Compare commits
269 Commits
Release-3.
...
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 | ||
![]() |
254d176266 | ||
![]() |
66deef52c8 | ||
![]() |
a5f29e93f5 | ||
![]() |
8f7793a795 | ||
![]() |
7f253bd6c1 | ||
![]() |
2969f61fe4 | ||
![]() |
7cbd494123 | ||
![]() |
ed15cc1730 | ||
![]() |
db8863c736 | ||
![]() |
13a049cf54 | ||
![]() |
4233d21e5b | ||
![]() |
f65e095e4d | ||
![]() |
f2c6745b8a | ||
![]() |
7ad58c7bcd | ||
![]() |
13ffc92bc3 | ||
![]() |
433905b33c | ||
![]() |
3a7eff1478 | ||
![]() |
ef46d1bf60 | ||
![]() |
654f7e6b01 | ||
![]() |
e853e2e4ac | ||
![]() |
4aec12c68f | ||
![]() |
1bdedd3b45 | ||
![]() |
a818e7b185 | ||
![]() |
5aed00dd0b | ||
![]() |
349425fe8a | ||
![]() |
9162b02ce9 | ||
![]() |
6c57729779 | ||
![]() |
ba9d13bf7b | ||
![]() |
56757973b6 | ||
![]() |
f1f4aeb4be | ||
![]() |
16bdfe4571 | ||
![]() |
804de05a0a | ||
![]() |
0fd4b828f2 | ||
![]() |
62891b8537 | ||
![]() |
ae02706c71 | ||
![]() |
c386af6813 | ||
![]() |
4c5df91d51 | ||
![]() |
a0f7c46cc9 | ||
![]() |
08c153abea | ||
![]() |
897ad7007f | ||
![]() |
13fb930676 | ||
![]() |
7f5fce001b | ||
![]() |
8af41b1d3c | ||
![]() |
90125d0f9a | ||
![]() |
919b6430c4 | ||
![]() |
7027f6b834 | ||
![]() |
cebd2c9763 | ||
![]() |
025db4ce3a | ||
![]() |
78f02c375e | ||
![]() |
4e14a57016 | ||
![]() |
b82895c489 | ||
![]() |
cf97a73485 | ||
![]() |
37b8e6c3f9 | ||
![]() |
c73f16fdfe | ||
![]() |
68df78a2a6 | ||
![]() |
af1e02b0bb | ||
![]() |
bca86c87e1 | ||
![]() |
a04dbf2c2d | ||
![]() |
4bcaa75fa4 | ||
![]() |
7deb2311f5 | ||
![]() |
4674594ee7 | ||
![]() |
730bad9728 | ||
![]() |
1f4900c363 | ||
![]() |
8e24eef265 | ||
![]() |
974c903d1c | ||
![]() |
9ec78752a0 | ||
![]() |
437f6a03a9 | ||
![]() |
94fefa0690 | ||
![]() |
91dc3604f5 | ||
![]() |
48ecb3e2b4 | ||
![]() |
59dfc847ae | ||
![]() |
cdfefed385 | ||
![]() |
98d2eadde2 | ||
![]() |
286b130f47 | ||
![]() |
b0b1549503 | ||
![]() |
277b4eec9a | ||
![]() |
927619bf47 | ||
![]() |
41b0c7768c | ||
![]() |
3b95931973 | ||
![]() |
13f98fa8ce | ||
![]() |
179a674b00 | ||
![]() |
ee4c9575ae | ||
![]() |
b615d2a423 | ||
![]() |
dc6998259e | ||
![]() |
b0953fb466 | ||
![]() |
1186926f30 | ||
![]() |
70db5d67ff | ||
![]() |
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 | ||
![]() |
d9727973c1 | ||
![]() |
0293762904 | ||
![]() |
95c6131ce7 | ||
![]() |
e326fe6f2d | ||
![]() |
2b64c90a0e | ||
![]() |
dd0d91c7e3 | ||
![]() |
a386142fa6 | ||
![]() |
cacc744411 | ||
![]() |
2d23578e0b | ||
![]() |
f8880066ea | ||
![]() |
a85423869f | ||
![]() |
469c02ad14 | ||
![]() |
1cd9a9098c | ||
![]() |
5ff14a54db | ||
![]() |
28e3d442e2 | ||
![]() |
bb0edcb62a | ||
![]() |
9a015a5c49 | ||
![]() |
9d20f60903 | ||
![]() |
5426496b4f | ||
![]() |
a549e41558 | ||
![]() |
a82c892a4e | ||
![]() |
9e9fb3ad7d | ||
![]() |
8cc3651c76 | ||
![]() |
4d879afca7 | ||
![]() |
afae221cb3 | ||
![]() |
b064bb61e9 | ||
![]() |
c839e4bc21 | ||
![]() |
7a9baeb350 | ||
![]() |
6d4041b2a1 | ||
![]() |
1932cbfbbc | ||
![]() |
8fecf5c145 | ||
![]() |
6131a9c4c1 | ||
![]() |
881d569d8e | ||
![]() |
6c18c197c6 | ||
![]() |
f47ec0d522 | ||
![]() |
4053196188 | ||
![]() |
5b40a85024 | ||
![]() |
36faba8ed3 | ||
![]() |
7d022c4f0d | ||
![]() |
b933bb6c50 | ||
![]() |
92bfcfdcf3 | ||
![]() |
3b754cfec4 | ||
![]() |
3689c01e4b | ||
![]() |
4b90fbd07a | ||
![]() |
1a225dca67 | ||
![]() |
226666c2bb | ||
![]() |
d4ef226911 | ||
![]() |
6491262491 | ||
![]() |
2c4d69bfc0 | ||
![]() |
f423969a8e | ||
![]() |
36cd4c370a | ||
![]() |
85f69782b2 | ||
![]() |
1f130c0891 | ||
![]() |
fdd1b40a9f | ||
![]() |
6993d58fdc | ||
![]() |
1845114d36 | ||
![]() |
bba1ffde38 |
209
CMakeLists.txt
209
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 3)
|
||||
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,174 +37,237 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
||||
include(CTest)
|
||||
include(CPack)
|
||||
|
||||
FIND_LIBRARY(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||
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()
|
||||
|
||||
|
||||
MESSAGE(STATUS "Detecting readline support")
|
||||
message(STATUS "Detecting readline support")
|
||||
if (READLINE_LIBRARY)
|
||||
MESSAGE(STATUS "Found: ${READLINE_LIBRARY}")
|
||||
SET (READLINE_LIB readline)
|
||||
ADD_DEFINITIONS(/DREADLINE_AVAILABLE)
|
||||
message(STATUS "Found: ${READLINE_LIBRARY}")
|
||||
set (READLINE_LIB readline)
|
||||
add_definitions(/DREADLINE_AVAILABLE)
|
||||
else(READLINE_LIBRARY)
|
||||
MESSAGE(STATUS "Not Found")
|
||||
SET (READLINE_LIB )
|
||||
SET (READLINE_FLAG )
|
||||
message(STATUS "Not Found")
|
||||
set (READLINE_LIB )
|
||||
set (READLINE_FLAG )
|
||||
endif(READLINE_LIBRARY)
|
||||
|
||||
IF(MSVC)
|
||||
ADD_DEFINITIONS(/W4)
|
||||
IF(CMAKE_CL_64)
|
||||
ADD_DEFINITIONS(/bigobj)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
# -Wno-missing-field-initializers is for boost on macos
|
||||
ADD_DEFINITIONS(-Wall -Wextra -Wno-missing-field-initializers -Wshadow)
|
||||
ENDIF()
|
||||
if(MSVC)
|
||||
add_definitions(/W4)
|
||||
if(CMAKE_CL_64)
|
||||
add_definitions(/bigobj)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic -std=c++0x)
|
||||
|
||||
if (APPLE)
|
||||
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.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)
|
||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||
endif()
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
SET(DYNAMIC_LOADER "dl")
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
list(APPEND LIBS "dl")
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
list(APPEND LIBS "pthread")
|
||||
add_definitions(-pthread)
|
||||
endif()
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
|
||||
list(APPEND LIBS ${READLINE_LIB})
|
||||
|
||||
if (MSVC)
|
||||
# Boost on MSVC does automatic linking
|
||||
SET(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
|
||||
else()
|
||||
SET(LIBS ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
|
||||
endif()
|
||||
|
||||
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_executable(chai src/main.cpp)
|
||||
target_link_libraries(chai ${LIBS})
|
||||
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} ${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)
|
||||
|
||||
IF(BUILD_TESTING)
|
||||
if(BUILD_TESTING)
|
||||
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
|
||||
|
||||
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}
|
||||
set_property(TEST ${UNIT_TESTS}
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
|
||||
IF (NOT UNIT_TEST_LIGHT)
|
||||
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} ${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()
|
||||
ENDIF(BUILD_TESTING)
|
||||
endif()
|
||||
endif(BUILD_TESTING)
|
||||
|
||||
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
|
||||
install(DIRECTORY include/chaiscript DESTINATION include
|
||||
install(DIRECTORY include/chaiscript DESTINATION include
|
||||
PATTERN "*.hpp"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
install(DIRECTORY unittests DESTINATION share/chaiscript
|
||||
install(DIRECTORY unittests DESTINATION share/chaiscript
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*.inc"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
install(DIRECTORY samples DESTINATION share/chaiscript
|
||||
install(DIRECTORY samples DESTINATION share/chaiscript
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
|
||||
|
||||
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
|
||||
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
|
||||
DESTINATION lib/pkgconfig)
|
||||
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
|
||||
DESTINATION lib/pkgconfig)
|
||||
|
||||
|
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"
|
||||
|
26
contrib/codeanalysis/is_prime.chai
Normal file
26
contrib/codeanalysis/is_prime.chai
Normal file
@@ -0,0 +1,26 @@
|
||||
def isprime(n)
|
||||
{
|
||||
for (auto i = 2; i < n; ++i)
|
||||
{
|
||||
if (n % i == 0) {return false}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
def primes(n)
|
||||
{
|
||||
auto count = 0
|
||||
for (auto i = 2; i <= n; ++i)
|
||||
{
|
||||
if (isprime(i)) {++count}
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
|
||||
auto N = 5000
|
||||
|
||||
print("primes: " + primes(N).to_string())
|
9
contrib/codeanalysis/profile_math.chai
Normal file
9
contrib/codeanalysis/profile_math.chai
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
var something = 0;
|
||||
|
||||
for (var i = 1; i < 10000; ++i)
|
||||
{
|
||||
something += int(3 % 2 * 4 + 2 / 16.0 - 100 + (10 ^ 19) / 64 + (3 & 12) - (4 | 14)) % i;
|
||||
}
|
||||
|
||||
print(something);
|
@@ -48,10 +48,10 @@ $language_data = array (
|
||||
'ESCAPE_CHAR' => '\\',
|
||||
'KEYWORDS' => array(
|
||||
1 => array(
|
||||
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally',
|
||||
'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
|
||||
|
@@ -7,6 +7,9 @@ if exists("b:current_syntax")
|
||||
finish
|
||||
end
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
syn case match
|
||||
|
||||
" syncing method
|
||||
@@ -16,11 +19,11 @@ syn sync fromstart
|
||||
syn region chaiscriptString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=chaiscriptSpecial,chaiscriptEval,@Spell
|
||||
|
||||
" Escape characters
|
||||
syn match chaiscriptSpecial contained "\\[\\abfnrtv\'\"]\|\\\d\{,3}"
|
||||
syn match chaiscriptSpecial contained "\\[\\abfnrtv\'\"]\|\\\d\{,3}"
|
||||
|
||||
" String evals
|
||||
syn region chaiscriptEval contained start="${" end="}"
|
||||
|
||||
syn region chaiscriptEval contained start="${" end="}"
|
||||
|
||||
" integer number
|
||||
syn match chaiscriptNumber "\<\d\+\>"
|
||||
|
||||
@@ -42,14 +45,14 @@ syn match chaiscriptNumber "\<0b[01]\+\>"
|
||||
" Various language features
|
||||
syn keyword chaiscriptCond if else
|
||||
syn keyword chaiscriptRepeat while for do
|
||||
syn keyword chaiscriptStatement break continue return
|
||||
syn keyword chaiscriptStatement break continue return switch case default
|
||||
syn keyword chaiscriptExceptions try catch throw
|
||||
|
||||
"Keyword
|
||||
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
|
||||
@@ -91,4 +94,6 @@ hi def link chaiscriptEval Special
|
||||
|
||||
let b:current_syntax = "chaiscript"
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
" vim: nowrap sw=2 sts=2 ts=8 noet
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
///
|
||||
/// \sa chaiscript
|
||||
/// \sa chaiscript::ChaiScript
|
||||
/// \sa ChaiScript_Language for Built in Functions
|
||||
/// \sa \ref LangGettingStarted
|
||||
/// \sa \ref LangKeywordRef
|
||||
/// \sa \ref LangInPlaceRef
|
||||
/// \sa \ref LangObjectSystemRef
|
||||
@@ -32,11 +34,13 @@
|
||||
///
|
||||
/// <hr>
|
||||
///
|
||||
/// \section gettingstarted Getting Started
|
||||
/// \section gettingstarted API Getting Started
|
||||
///
|
||||
/// \li \ref basics
|
||||
/// \li \ref compiling
|
||||
/// \li \ref eval
|
||||
/// \li \ref addingitems
|
||||
/// \li \ref operatoroverloading
|
||||
/// \li \ref helpermacro
|
||||
/// \li \ref pointerconversions
|
||||
/// \li \ref baseclasses
|
||||
@@ -50,6 +54,7 @@
|
||||
/// Basic simple example:
|
||||
///
|
||||
/// \code
|
||||
/// //main.cpp
|
||||
/// #include <chaiscript/chaiscript.hpp>
|
||||
///
|
||||
/// double function(int i, double j)
|
||||
@@ -67,6 +72,27 @@
|
||||
/// \endcode
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection compiling Compiling ChaiScript Applications
|
||||
///
|
||||
/// 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
|
||||
/// the dynamic loader. For example:
|
||||
///
|
||||
/// \code
|
||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
|
||||
/// \endcode
|
||||
///
|
||||
/// Alternatively, you may compile without threading support.
|
||||
///
|
||||
/// \code
|
||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -DCHAISCRIPT_NO_THREADS
|
||||
/// \endcode
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection eval Evaluating Scripts
|
||||
///
|
||||
/// Scripts can be evaluated with the () operator, eval method or eval_file method.
|
||||
@@ -114,7 +140,10 @@
|
||||
///
|
||||
/// \subsubsection addingobjects Adding Objects
|
||||
///
|
||||
/// Named objects can be created with the #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;
|
||||
@@ -166,8 +195,8 @@
|
||||
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
|
||||
///
|
||||
/// \code
|
||||
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod"));
|
||||
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod, "overloadedmethod"));
|
||||
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod");
|
||||
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod), "overloadedmethod");
|
||||
/// \endcode
|
||||
///
|
||||
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
|
||||
@@ -204,7 +233,31 @@
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa chaiscript::Module
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection operatoroverloading Operator Overloading
|
||||
///
|
||||
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
|
||||
///
|
||||
/// \code
|
||||
/// class MyClass {
|
||||
/// MyClass operator+(const MyClass &) const;
|
||||
/// };
|
||||
///
|
||||
/// chai.add(fun(&MyClass::operator+), "+");
|
||||
///
|
||||
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
|
||||
/// {
|
||||
/// std::stringstream ss;
|
||||
/// ss << t_lhs << t_rhs;
|
||||
/// return ss.str();
|
||||
/// }
|
||||
///
|
||||
/// chai.add(fun(append_string_int), "+");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection helpermacro Class Helper Macro
|
||||
///
|
||||
@@ -249,10 +302,10 @@
|
||||
/// <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 var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
|
||||
/// 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.
|
||||
///
|
||||
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
|
||||
@@ -263,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()
|
||||
/// {
|
||||
@@ -329,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");
|
||||
/// }
|
||||
@@ -342,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
|
||||
@@ -359,12 +412,14 @@
|
||||
///
|
||||
/// 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>
|
||||
///
|
||||
/// \subsection exceptions Exception Handling
|
||||
///
|
||||
/// \subsubsection exceptionsbasics Exception Handling Basics
|
||||
///
|
||||
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
|
||||
/// ChaiScript.
|
||||
///
|
||||
@@ -376,10 +431,12 @@
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
/// // Throw in C++, catch in ChaiScript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
|
||||
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
|
||||
///
|
||||
/// // Throw in ChaiScript, catch in C++
|
||||
/// try {
|
||||
/// chai("throw(1)");
|
||||
/// } catch (chaiscript::Boxed_Value bv) {
|
||||
@@ -388,6 +445,31 @@
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
|
||||
///
|
||||
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
|
||||
/// ChaiScript what possible exceptions are expected from the script being executed.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// chaiscript::ChaiScript chai;
|
||||
///
|
||||
/// try {
|
||||
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
/// } catch (const double e) {
|
||||
/// } catch (int) {
|
||||
/// } catch (float) {
|
||||
/// } catch (const std::string &) {
|
||||
/// } catch (const std::exception &e) {
|
||||
/// // This is the one what will be called in the specific throw() above
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa chaiscript::Exception_Handler for details on automatic exception unboxing
|
||||
/// \sa chaiscript::exception_specification
|
||||
|
||||
|
||||
|
||||
/// \page LangObjectSystemRef ChaiScript Language Object Model Reference
|
||||
///
|
||||
@@ -429,6 +511,114 @@
|
||||
/// In-place Map ::= "[" (string ":" expression)+ "]"
|
||||
/// \endcode
|
||||
|
||||
/// \page LangGettingStarted ChaiScript Language Getting Started
|
||||
///
|
||||
/// ChaiScript is a simple language that should feel familiar to anyone who knows
|
||||
/// C++ or ECMAScript (JavaScript).
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptloops Loops
|
||||
///
|
||||
/// Common looping constructs exist in ChaiScript
|
||||
///
|
||||
/// \code
|
||||
/// var i = 0;
|
||||
/// while (i < 10)
|
||||
/// {
|
||||
/// // do something
|
||||
/// ++i;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \code
|
||||
/// for (var i = 0; i < 10; ++i)
|
||||
/// {
|
||||
/// // do something
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref keywordfor
|
||||
/// \sa \ref keywordwhile
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptifs Conditionals
|
||||
///
|
||||
/// If statements work as expected
|
||||
///
|
||||
/// \code
|
||||
/// var b = true;
|
||||
///
|
||||
/// if (b) {
|
||||
/// // do something
|
||||
/// } else if (c < 10) {
|
||||
/// // do something else
|
||||
/// } else {
|
||||
/// // or do this
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref keywordif
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptfunctions Functions
|
||||
///
|
||||
/// Functions are defined with the def keyword
|
||||
///
|
||||
/// \code
|
||||
/// def myfun(x) { print(x); }
|
||||
///
|
||||
/// myfun(10);
|
||||
/// \endcode
|
||||
///
|
||||
/// Functions may have "guards" which determine if which is called.
|
||||
///
|
||||
/// \code
|
||||
/// eval> def myfun2(x) : x < 10 { print("less than 10"); }
|
||||
/// eval> def myfun2(x) : x >= 10 { print("10 or greater"); }
|
||||
/// eval> myfun2(5)
|
||||
/// less than 10
|
||||
/// eval> myfun2(12)
|
||||
/// 10 or greater
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref keyworddef
|
||||
/// \sa \ref keywordattr
|
||||
/// \sa \ref LangObjectSystemRef
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptfunctionobjects Function Objects
|
||||
///
|
||||
/// Functions are first class types in ChaiScript and can be used as variables.
|
||||
///
|
||||
/// \code
|
||||
/// eval> var p = print;
|
||||
/// eval> p(1);
|
||||
/// 1
|
||||
/// \endcode
|
||||
///
|
||||
/// They can also be passed to functions.
|
||||
///
|
||||
/// \code
|
||||
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
|
||||
/// eval> def dosomething(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
|
||||
/// eval> callfunc(dosomething, 1, 2);
|
||||
/// lhs: 1, rhs: 2
|
||||
/// \endcode
|
||||
///
|
||||
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
|
||||
///
|
||||
/// \code
|
||||
/// eval> callfunc(`+`, 1, 4);
|
||||
/// 5
|
||||
/// eval> callfunc(`*`, 3, 2);
|
||||
/// 6
|
||||
/// \endcode
|
||||
///
|
||||
/// <hr>
|
||||
/// \sa \ref LangKeywordRef
|
||||
/// \sa ChaiScript_Language for Built in Functions
|
||||
|
||||
|
||||
/// \page LangKeywordRef ChaiScript Language Keyword Reference
|
||||
///
|
||||
///
|
||||
@@ -558,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_pod_value.hpp"
|
||||
|
||||
#ifdef BOOST_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
#include "dispatchkit/boxed_number.hpp"
|
||||
|
||||
#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
|
||||
|
@@ -1,14 +1,17 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#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
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -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()
|
||||
: m_what(t_what)
|
||||
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();
|
||||
}
|
||||
|
@@ -1,93 +1,133 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "dynamic_object.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "boxed_pod_value.hpp"
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include "boxed_number.hpp"
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -21,189 +22,30 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// \brief Assigns a POD value from a Boxed_POD_Value. Helps support operators between
|
||||
/// disparate POD types.
|
||||
/// \param[in,out] p1 object to assign to
|
||||
/// \param[in] v Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_pod(P1 &p1, const Boxed_POD_Value &v)
|
||||
{
|
||||
if (v.isfloat)
|
||||
{
|
||||
return (p1 = P1(v.d));
|
||||
} else {
|
||||
return (p1 = P1(v.i));
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Constructs a new POD value object from a Boxed_POD_Value
|
||||
/// \param[in] v Boxed_POD_Value to copy into the new object
|
||||
/// \brief Constructs a new POD value object from a Boxed_Number
|
||||
/// \param[in] v Boxed_Number to copy into the new object
|
||||
/// \returns The newly created object.
|
||||
template<typename P1>
|
||||
P1 construct_pod(Boxed_POD_Value v)
|
||||
std::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
{
|
||||
if (v.isfloat)
|
||||
{
|
||||
return P1(v.d);
|
||||
} else {
|
||||
return P1(v.i);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Performs a bitwise and assignment (&=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to bitwise and assign to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.isfloat)
|
||||
{
|
||||
return p1 &= P1(r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("&= only valid for integer types");
|
||||
}
|
||||
|
||||
/// \brief Performs a xor assignment (^=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to xor assign to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.isfloat)
|
||||
{
|
||||
return p1 ^= P1(r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("^= only valid for integer types");
|
||||
}
|
||||
|
||||
/// \brief Performs a bitwise or assignment (|=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to bitwise or assign to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.isfloat)
|
||||
{
|
||||
return p1 |= P1(r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("&= only valid for integer types");
|
||||
}
|
||||
|
||||
/// \brief Performs an assign difference (-=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to difference assign to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.isfloat)
|
||||
{
|
||||
return p1 -= P1(r.d);
|
||||
} else {
|
||||
return p1 -= P1(r.i);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Performs an assign shift left (<<=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to assign shift left to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.isfloat)
|
||||
{
|
||||
return p1 <<= P1(r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("<<= only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
/// \brief Performs an assign product (*=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to assign product to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.isfloat)
|
||||
{
|
||||
return p1 *= P1(r.d);
|
||||
} else {
|
||||
return p1 *= P1(r.i);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Performs an assign quotient (/=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to assign quotient to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.isfloat)
|
||||
{
|
||||
return p1 /= P1(r.d);
|
||||
} else {
|
||||
return p1 /= P1(r.i);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Performs an assign remainder (%=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to assign remainder to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.isfloat)
|
||||
{
|
||||
return p1 %= P1(r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("%= only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
/// \brief Performs an assign shift right (>>=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to assign shift right to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.isfloat)
|
||||
{
|
||||
return p1 >>= P1(r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast(">>= only valid for integer types");
|
||||
}
|
||||
|
||||
/// \brief Performs an assign sum (+=) on the given object with the given Boxed_POD_Value
|
||||
/// \param[in,out] p1 object to sum assign to
|
||||
/// \param[in] r Boxed_POD_Value to assign from
|
||||
/// \returns Reference to p1, to support normal C assignment semantics
|
||||
template<typename P1>
|
||||
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.isfloat)
|
||||
{
|
||||
return p1 += P1(r.d);
|
||||
} else {
|
||||
return p1 += P1(r.i);
|
||||
}
|
||||
std::shared_ptr<P1> p(new P1());
|
||||
Boxed_Value bv(p);
|
||||
Boxed_Number nb(bv);
|
||||
nb = v;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Adds a copy constructor for the given type to the given Model
|
||||
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
||||
/// \param[in,out] m The Module to add the copy constructor to
|
||||
/// \tparam T The type to add a copy constructor for
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
template<typename T>
|
||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(constructor<T (const T &)>(), type);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
||||
@@ -223,76 +65,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/// \brief Add all arithmetic operators appropriate for integers for the templated type.
|
||||
/// Used during bootstrap, also available to users.
|
||||
/// \tparam T Type to create arithmetic operators for
|
||||
/// \param[in,out] m module to add arithmetic operators to
|
||||
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
|
||||
template<typename T>
|
||||
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
operators::assign_bitwise_and<T>(m);
|
||||
operators::assign_xor<T>(m);
|
||||
operators::assign_bitwise_or<T>(m);
|
||||
operators::assign_difference<T>(m);
|
||||
operators::assign_left_shift<T>(m);
|
||||
operators::assign_product<T>(m);
|
||||
operators::assign_quotient<T>(m);
|
||||
operators::assign_remainder<T>(m);
|
||||
operators::assign_right_shift<T>(m);
|
||||
operators::assign_sum<T>(m);
|
||||
|
||||
operators::prefix_decrement<T>(m);
|
||||
operators::prefix_increment<T>(m);
|
||||
operators::addition<T>(m);
|
||||
operators::unary_plus<T>(m);
|
||||
operators::subtraction<T>(m);
|
||||
operators::unary_minus<T>(m);
|
||||
operators::bitwise_and<T>(m);
|
||||
operators::bitwise_compliment<T>(m);
|
||||
operators::bitwise_xor<T>(m);
|
||||
operators::bitwise_or<T>(m);
|
||||
operators::division<T>(m);
|
||||
operators::left_shift<T>(m);
|
||||
operators::multiplication<T>(m);
|
||||
operators::remainder<T>(m);
|
||||
operators::right_shift<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Add all arithmetic operators appropriate for floating point numbers for the templated type.
|
||||
/// Used during bootstrap, also available to users.
|
||||
/// \tparam T Type to create arithmetic operators for
|
||||
/// \param[in,out] m module to add arithmetic operators to
|
||||
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
|
||||
template<typename T>
|
||||
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
operators::assign_difference<T>(m);
|
||||
operators::assign_product<T>(m);
|
||||
operators::assign_quotient<T>(m);
|
||||
operators::assign_sum<T>(m);
|
||||
|
||||
operators::addition<T>(m);
|
||||
operators::unary_plus<T>(m);
|
||||
operators::subtraction<T>(m);
|
||||
operators::unary_minus<T>(m);
|
||||
operators::division<T>(m);
|
||||
operators::multiplication<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Adds a copy constructor for the given type to the given Model
|
||||
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
||||
/// \param[in,out] m The Module to add the copy constructor to
|
||||
/// \tparam T The type to add a copy constructor for
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
template<typename T>
|
||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(constructor<T (const T &)>(), type);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Adds default and copy constructors for the given type
|
||||
/// \param[in] type The name of the type to add the constructors for.
|
||||
@@ -322,36 +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 assignment operator for T = POD.
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign_pod<T>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
@@ -360,52 +126,14 @@ namespace chaiscript
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<T>(), name);
|
||||
basic_constructors<T>(name, m);
|
||||
operators::assign<T>(m);
|
||||
oper_assign_pod<T>(m);
|
||||
m->add(constructor<T ()>(), name);
|
||||
construct_pod<T>(name, m);
|
||||
|
||||
m->add(fun(&detail::assign_sum_pod<T>), "+=");
|
||||
m->add(fun(&detail::assign_difference_pod<T>), "-=");
|
||||
m->add(fun(&detail::assign_product_pod<T>), "*=");
|
||||
m->add(fun(&detail::assign_quotient_pod<T>), "/=");
|
||||
|
||||
m->add(fun(&to_string<T>), "to_string");
|
||||
m->add(fun(&parse_string<T>), "to_" + name);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_integer_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
bootstrap_pod_type<T>(name, m);
|
||||
|
||||
m->add(fun(&detail::assign_bitwise_and_pod<T>), "&=");
|
||||
m->add(fun(&detail::assign_xor_pod<T>), "^=");
|
||||
m->add(fun(&detail::assign_bitwise_or_pod<T>), "|=");
|
||||
m->add(fun(&detail::assign_left_shift_pod<T>), "<<=");
|
||||
m->add(fun(&detail::assign_remainder_pod<T>), "%=");
|
||||
m->add(fun(&detail::assign_right_shift_pod<T>), ">>=");
|
||||
|
||||
opers_integer_arithmetic<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_float_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
bootstrap_pod_type<T>(name, m);
|
||||
opers_float_arithmetic<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* "clone" function for a shared_ptr type. This is used in the case
|
||||
@@ -415,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;
|
||||
}
|
||||
@@ -424,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -438,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())))
|
||||
@@ -480,22 +208,48 @@ namespace chaiscript
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add all arithmetic operators for PODs
|
||||
*/
|
||||
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&operators::addition<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
|
||||
m->add(fun(&operators::subtraction<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
|
||||
m->add(fun(&operators::bitwise_and<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "&");
|
||||
m->add(fun(&operators::bitwise_xor<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "^");
|
||||
m->add(fun(&operators::bitwise_or<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "|");
|
||||
m->add(fun(&operators::division<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
|
||||
m->add(fun(&operators::left_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "<<");
|
||||
m->add(fun(&operators::multiplication<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
|
||||
m->add(fun(&operators::remainder<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "%");
|
||||
m->add(fun(&operators::right_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), ">>");
|
||||
}
|
||||
m->add(fun(&Boxed_Number::equals), "==");
|
||||
m->add(fun(&Boxed_Number::less_than), "<");
|
||||
m->add(fun(&Boxed_Number::greater_than), ">");
|
||||
m->add(fun(&Boxed_Number::greater_than_equal), ">=");
|
||||
m->add(fun(&Boxed_Number::less_than_equal), "<=");
|
||||
m->add(fun(&Boxed_Number::not_equal), "!=");
|
||||
|
||||
m->add(fun(&Boxed_Number::pre_decrement), "--");
|
||||
m->add(fun(&Boxed_Number::pre_increment), "++");
|
||||
m->add(fun(&Boxed_Number::sum), "+");
|
||||
m->add(fun(&Boxed_Number::unary_plus), "+");
|
||||
m->add(fun(&Boxed_Number::unary_minus), "-");
|
||||
m->add(fun(&Boxed_Number::difference), "-");
|
||||
m->add(fun(&Boxed_Number::assign_bitwise_and), "&=");
|
||||
m->add(fun(&Boxed_Number::assign), "=");
|
||||
m->add(fun(&Boxed_Number::assign_bitwise_or), "|=");
|
||||
m->add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
|
||||
m->add(fun(&Boxed_Number::assign_remainder), "%=");
|
||||
m->add(fun(&Boxed_Number::assign_shift_left), "<<=");
|
||||
m->add(fun(&Boxed_Number::assign_shift_right), ">>=");
|
||||
m->add(fun(&Boxed_Number::bitwise_and), "&");
|
||||
m->add(fun(&Boxed_Number::bitwise_complement), "~");
|
||||
m->add(fun(&Boxed_Number::bitwise_xor), "^");
|
||||
m->add(fun(&Boxed_Number::bitwise_or), "|");
|
||||
m->add(fun(&Boxed_Number::assign_product), "*=");
|
||||
m->add(fun(&Boxed_Number::assign_quotient), "/=");
|
||||
m->add(fun(&Boxed_Number::assign_sum), "+=");
|
||||
m->add(fun(&Boxed_Number::assign_difference), "-=");
|
||||
m->add(fun(&Boxed_Number::quotient), "/");
|
||||
m->add(fun(&Boxed_Number::shift_left), "<<");
|
||||
m->add(fun(&Boxed_Number::product), "*");
|
||||
m->add(fun(&Boxed_Number::remainder), "%");
|
||||
m->add(fun(&Boxed_Number::shift_right), ">>");
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a bound function object. The first param is the function to bind
|
||||
@@ -533,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;
|
||||
}
|
||||
@@ -544,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())
|
||||
@@ -562,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;
|
||||
@@ -590,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:
|
||||
@@ -619,7 +373,7 @@ namespace chaiscript
|
||||
m->add(user_type<void>(), "void");
|
||||
m->add(user_type<bool>(), "bool");
|
||||
m->add(user_type<Boxed_Value>(), "Object");
|
||||
m->add(user_type<Boxed_POD_Value>(), "PODObject");
|
||||
m->add(user_type<Boxed_Number>(), "Number");
|
||||
m->add(user_type<Proxy_Function>(), "Function");
|
||||
m->add(user_type<std::exception>(), "exception");
|
||||
|
||||
@@ -638,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");
|
||||
@@ -646,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");
|
||||
@@ -669,16 +423,15 @@ 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");
|
||||
typedef bool (Type_Info::*typeinfocompare)(const Type_Info &) const;
|
||||
m->add(fun(typeinfocompare(&Type_Info::operator==)), "==");
|
||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
|
||||
|
||||
basic_constructors<bool>("bool", m);
|
||||
operators::assign<bool>(m);
|
||||
operators::equal<bool>(m);
|
||||
|
||||
m->add(fun(&to_string<const std::string &>), "internal_to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
|
||||
@@ -686,32 +439,43 @@ namespace chaiscript
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
m->add(fun(&what), "what");
|
||||
|
||||
bootstrap_float_type<double>("double", m);
|
||||
bootstrap_integer_type<int>("int", m);
|
||||
bootstrap_integer_type<size_t>("size_t", m);
|
||||
bootstrap_integer_type<char>("char", m);
|
||||
bootstrap_integer_type<boost::int64_t>("int64_t", m);
|
||||
bootstrap_pod_type<double>("double", m);
|
||||
bootstrap_pod_type<long double>("long_double", m);
|
||||
bootstrap_pod_type<float>("float", m);
|
||||
bootstrap_pod_type<int>("int", m);
|
||||
bootstrap_pod_type<long>("long", m);
|
||||
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
||||
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
||||
bootstrap_pod_type<size_t>("size_t", m);
|
||||
bootstrap_pod_type<char>("char", m);
|
||||
bootstrap_pod_type<std::int8_t>("int8_t", m);
|
||||
bootstrap_pod_type<std::int16_t>("int16_t", m);
|
||||
bootstrap_pod_type<std::int32_t>("int32_t", m);
|
||||
bootstrap_pod_type<std::int64_t>("int64_t", m);
|
||||
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
|
||||
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
|
||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
opers_comparison<Boxed_POD_Value>(m);
|
||||
opers_arithmetic_pod(m);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "bootstrap.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -147,6 +148,21 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
void insert(T &t_target, const T &t_other)
|
||||
{
|
||||
t_target.insert(t_other.begin(), t_other.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
||||
{
|
||||
t_target.insert(t_val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add Bidir_Range support for the given ContainerType
|
||||
*/
|
||||
@@ -227,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;
|
||||
}
|
||||
@@ -255,10 +271,9 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -390,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 &)>(boost::mem_fn(&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;
|
||||
}
|
||||
|
||||
@@ -464,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())) \
|
||||
@@ -511,20 +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 std::function<int (const String *, const String &, int)> find_func;
|
||||
|
||||
typedef boost::function<int (const String *, const String &, int)> find_func;
|
||||
|
||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find)))), "find");
|
||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_last_of)))), "find_last_of");
|
||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
|
||||
m->add(fun(find_func(boost::mem_fn(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;
|
||||
}
|
||||
|
@@ -1,11 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// 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
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -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 &>
|
||||
{
|
||||
};
|
||||
|
||||
|
818
include/chaiscript/dispatchkit/boxed_number.hpp
Normal file
818
include/chaiscript/dispatchkit/boxed_number.hpp
Normal file
@@ -0,0 +1,818 @@
|
||||
// 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_BOXED_NUMERIC_HPP_
|
||||
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "../language/chaiscript_algebraic.hpp"
|
||||
#include <sstream>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244 4018 4389 4146)
|
||||
#endif
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
class Boxed_Number
|
||||
{
|
||||
private:
|
||||
struct boolean
|
||||
{
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::equals:
|
||||
return const_var(t == u);
|
||||
case Operators::less_than:
|
||||
return const_var(t < u);
|
||||
case Operators::greater_than:
|
||||
return const_var(t > u);
|
||||
case Operators::less_than_equal:
|
||||
return const_var(t <= u);
|
||||
case Operators::greater_than_equal:
|
||||
return const_var(t >= u);
|
||||
case Operators::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
struct binary
|
||||
{
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::assign:
|
||||
t = u;
|
||||
break;
|
||||
case Operators::pre_increment:
|
||||
++t;
|
||||
break;
|
||||
case Operators::pre_decrement:
|
||||
--t;
|
||||
break;
|
||||
case Operators::assign_product:
|
||||
t *= u;
|
||||
break;
|
||||
case Operators::assign_sum:
|
||||
t += u;
|
||||
break;
|
||||
case Operators::assign_quotient:
|
||||
t /= u;
|
||||
break;
|
||||
case Operators::assign_difference:
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
return t_lhs;
|
||||
}
|
||||
};
|
||||
|
||||
struct binary_int
|
||||
{
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::assign_bitwise_and:
|
||||
t &= u;
|
||||
break;
|
||||
case Operators::assign_bitwise_or:
|
||||
t |= u;
|
||||
break;
|
||||
case Operators::assign_shift_left:
|
||||
t <<= u;
|
||||
break;
|
||||
case Operators::assign_shift_right:
|
||||
t >>= u;
|
||||
break;
|
||||
case Operators::assign_remainder:
|
||||
t %= u;
|
||||
break;
|
||||
case Operators::assign_bitwise_xor:
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return t_lhs;
|
||||
}
|
||||
};
|
||||
|
||||
struct const_binary_int
|
||||
{
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::shift_left:
|
||||
return const_var(t << u);
|
||||
case Operators::shift_right:
|
||||
return const_var(t >> u);
|
||||
case Operators::remainder:
|
||||
return const_var(t % u);
|
||||
case Operators::bitwise_and:
|
||||
return const_var(t & u);
|
||||
case Operators::bitwise_or:
|
||||
return const_var(t | u);
|
||||
case Operators::bitwise_xor:
|
||||
return const_var(t ^ u);
|
||||
case Operators::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
struct const_binary
|
||||
{
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::sum:
|
||||
return const_var(t + u);
|
||||
case Operators::quotient:
|
||||
return const_var(t / u);
|
||||
case Operators::product:
|
||||
return const_var(t * u);
|
||||
case Operators::difference:
|
||||
return const_var(t - u);
|
||||
case Operators::unary_minus:
|
||||
return const_var(-t);
|
||||
case Operators::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS, typename RHS, bool Float>
|
||||
struct Go
|
||||
{
|
||||
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
{
|
||||
return boolean::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 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 && !t_lhs.is_const()) {
|
||||
return binary_int::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::const_int_flag && t_oper < Operators::const_flag) {
|
||||
return const_binary_int::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 if (t_oper > Operators::const_flag) {
|
||||
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
struct Go<LHS, RHS, true>
|
||||
{
|
||||
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
{
|
||||
return boolean::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 if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
|
||||
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
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 chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS, bool Float>
|
||||
static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
const Type_Info &inp_ = t_rhs.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(double)) {
|
||||
return Go<LHS, double, true>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return Go<LHS, float, true>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return Go<LHS, long double, true>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(char)) {
|
||||
return Go<LHS, char, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
return Go<LHS, unsigned int, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return Go<LHS, std::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return Go<LHS, std::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return Go<LHS, std::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return Go<LHS, std::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return Go<LHS, std::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return Go<LHS, std::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return Go<LHS, std::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return Go<LHS, std::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
const Type_Info &inp_ = t_lhs.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return oper_rhs<int, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(double)) {
|
||||
return oper_rhs<double, true>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return oper_rhs<long double, true>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return oper_rhs<float, true>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(char)) {
|
||||
return oper_rhs<char, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
return oper_rhs<unsigned int, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return oper_rhs<std::int8_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return oper_rhs<std::int16_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return oper_rhs<std::int32_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return oper_rhs<std::int64_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return oper_rhs<std::uint8_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return oper_rhs<std::uint16_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return oper_rhs<std::uint32_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return oper_rhs<std::uint64_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else {
|
||||
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:
|
||||
Boxed_Number()
|
||||
: bv(Boxed_Value(0))
|
||||
{
|
||||
}
|
||||
|
||||
Boxed_Number(const Boxed_Value &v)
|
||||
: bv(v)
|
||||
{
|
||||
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
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator<(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator>(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator>=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator<=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator!=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
Boxed_Number operator--()
|
||||
{
|
||||
return oper(Operators::pre_decrement, this->bv, var(0));
|
||||
}
|
||||
|
||||
Boxed_Number operator++()
|
||||
{
|
||||
return oper(Operators::pre_increment, this->bv, var(0));
|
||||
}
|
||||
|
||||
Boxed_Number operator+(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::sum, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator+() const
|
||||
{
|
||||
return oper(Operators::unary_plus, this->bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
Boxed_Number operator-() const
|
||||
{
|
||||
return oper(Operators::unary_minus, this->bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
Boxed_Number operator-(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::difference, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator&=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
void validate_boxed_number(const Boxed_Value &v)
|
||||
{
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
if (inp_ == typeid(bool))
|
||||
{
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
if (!inp_.is_arithmetic())
|
||||
{
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Number operator=(const Boxed_Value &v)
|
||||
{
|
||||
validate_boxed_number(v);
|
||||
bv = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::assign, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator|=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator^=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator%=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator&(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator~() const
|
||||
{
|
||||
return oper(Operators::bitwise_complement, this->bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
Boxed_Number operator^(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator|(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator*=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_product, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator/=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator+=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator-=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator/(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::quotient, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::shift_left, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator*(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::product, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator%(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::remainder, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::shift_right, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
|
||||
{
|
||||
return oper(Operators::pre_decrement, t_lhs.bv, var(0));
|
||||
}
|
||||
|
||||
static Boxed_Number pre_increment(Boxed_Number t_lhs)
|
||||
{
|
||||
return oper(Operators::pre_increment, t_lhs.bv, var(0));
|
||||
}
|
||||
|
||||
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return oper(Operators::unary_plus, t_lhs.bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return oper(Operators::unary_minus, t_lhs.bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
return oper(t_oper, t_lhs, t_rhs);
|
||||
}
|
||||
|
||||
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
{
|
||||
return oper(t_oper, t_lhs, const_var(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Boxed_Value bv;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_Number>
|
||||
{
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,260 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_POD_VALUE_HPP_
|
||||
#define CHAISCRIPT_BOXED_POD_VALUE_HPP_
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
class Boxed_POD_Value
|
||||
{
|
||||
public:
|
||||
Boxed_POD_Value(const Boxed_Value &v)
|
||||
: d(0), i(0), isfloat(false)
|
||||
{
|
||||
if (v.get_type_info().is_undef())
|
||||
{
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
|
||||
if (inp_ == typeid(double))
|
||||
{
|
||||
d = boxed_cast<double>(v);
|
||||
isfloat = true;
|
||||
} else if (inp_ == typeid(float)) {
|
||||
d = boxed_cast<float>(v);
|
||||
isfloat = true;
|
||||
} else if (inp_ == typeid(bool)) {
|
||||
i = boxed_cast<bool>(v);
|
||||
} else if (inp_ == typeid(char)) {
|
||||
i = boxed_cast<char>(v);
|
||||
} else if (inp_ == typeid(int)) {
|
||||
i = boxed_cast<int>(v);
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
i = boxed_cast<unsigned int>(v);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
i = boxed_cast<long>(v);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
i = boxed_cast<unsigned long>(v);
|
||||
} else if (inp_ == typeid(boost::int8_t)) {
|
||||
i = boxed_cast<boost::int8_t>(v);
|
||||
} else if (inp_ == typeid(boost::int16_t)) {
|
||||
i = boxed_cast<boost::int16_t>(v);
|
||||
} else if (inp_ == typeid(boost::int32_t)) {
|
||||
i = boxed_cast<boost::int32_t>(v);
|
||||
} else if (inp_ == typeid(boost::int64_t)) {
|
||||
i = boxed_cast<boost::int64_t>(v);
|
||||
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||
i = boxed_cast<boost::uint8_t>(v);
|
||||
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||
i = boxed_cast<boost::uint16_t>(v);
|
||||
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||
i = boxed_cast<boost::uint32_t>(v);
|
||||
} else {
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Boxed_POD_Value &r) const
|
||||
{
|
||||
return ((isfloat)?d:i) == ((r.isfloat)?r.d:r.i);
|
||||
}
|
||||
|
||||
bool operator<(const Boxed_POD_Value &r) const
|
||||
{
|
||||
return ((isfloat)?d:i) < ((r.isfloat)?r.d:r.i);
|
||||
}
|
||||
|
||||
bool operator>(const Boxed_POD_Value &r) const
|
||||
{
|
||||
return ((isfloat)?d:i) > ((r.isfloat)?r.d:r.i);
|
||||
}
|
||||
|
||||
bool operator>=(const Boxed_POD_Value &r) const
|
||||
{
|
||||
return ((isfloat)?d:i) >= ((r.isfloat)?r.d:r.i);
|
||||
}
|
||||
|
||||
bool operator<=(const Boxed_POD_Value &r) const
|
||||
{
|
||||
return ((isfloat)?d:i) <= ((r.isfloat)?r.d:r.i);
|
||||
}
|
||||
|
||||
bool operator!=(const Boxed_POD_Value &r) const
|
||||
{
|
||||
return ((isfloat)?d:i) != ((r.isfloat)?r.d:r.i);
|
||||
}
|
||||
|
||||
Boxed_Value operator+(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i + r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((isfloat)?d:i) + ((r.isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator-(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i - r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((isfloat)?d:i) - ((r.isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator&(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return Boxed_Value(i & r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("& only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator^(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return Boxed_Value(i ^ r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("^ only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator|(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return Boxed_Value(i | r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("| only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator/(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i / r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((isfloat)?d:i) / ((r.isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator<<(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i << r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("<< only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value operator*(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i * r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((isfloat)?d:i) * ((r.isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value operator%(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i % r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast("% only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator>>(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!isfloat && !r.isfloat)
|
||||
{
|
||||
return smart_size(i >> r.i);
|
||||
}
|
||||
|
||||
throw exception::bad_boxed_cast(">> only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value smart_size(boost::int64_t t_i) const
|
||||
{
|
||||
if (t_i < boost::integer_traits<int>::const_min
|
||||
|| t_i > boost::integer_traits<int>::const_max)
|
||||
{
|
||||
return Boxed_Value(t_i);
|
||||
} else {
|
||||
return Boxed_Value(static_cast<int>(t_i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double d;
|
||||
boost::int64_t i;
|
||||
|
||||
bool isfloat;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_POD_Value>
|
||||
{
|
||||
typedef Boxed_POD_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return Boxed_POD_Value(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_POD_Value &> : Cast_Helper<Boxed_POD_Value>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_POD_Value> : Cast_Helper<Boxed_POD_Value>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -12,17 +12,11 @@
|
||||
#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
|
||||
{
|
||||
|
||||
/// \brief A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects
|
||||
/// \sa chaiscript::boxed_cast
|
||||
class Boxed_Value
|
||||
@@ -41,19 +35,12 @@ namespace chaiscript
|
||||
*/
|
||||
struct Data
|
||||
{
|
||||
template<typename T>
|
||||
static bool is_null(boost::any *a)
|
||||
{
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
|
||||
return ptr->get() == 0;
|
||||
}
|
||||
|
||||
Data(const Type_Info &ti,
|
||||
const boost::any &to,
|
||||
const chaiscript::detail::Any &to,
|
||||
bool tr,
|
||||
const boost::function<bool (boost::any*)> &t_is_null = boost::function<bool (boost::any*)>())
|
||||
: m_type_info(ti), m_obj(to),
|
||||
m_is_ref(tr), m_is_null(t_is_null)
|
||||
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),
|
||||
m_is_ref(tr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -62,7 +49,8 @@ namespace chaiscript
|
||||
m_type_info = rhs.m_type_info;
|
||||
m_obj = rhs.m_obj;
|
||||
m_is_ref = rhs.m_is_ref;
|
||||
m_is_null = rhs.m_is_null;
|
||||
m_data_ptr = rhs.m_data_ptr;
|
||||
m_const_data_ptr = rhs.m_const_data_ptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -72,73 +60,77 @@ 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;
|
||||
boost::function<bool (boost::any*)> m_is_null;
|
||||
std::vector<boost::shared_ptr<Data> > m_dependencies;
|
||||
};
|
||||
|
||||
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(),
|
||||
false)
|
||||
);
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
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,
|
||||
boost::function<bool (boost::any *)>(&Data::is_null<T>))
|
||||
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),
|
||||
true)
|
||||
chaiscript::detail::Any(obj),
|
||||
true,
|
||||
&obj.get()
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static boost::shared_ptr<Data> get(const T& t)
|
||||
static std::shared_ptr<Data> get(const 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(boost::shared_ptr<T>(new T(t))),
|
||||
chaiscript::detail::Any(p),
|
||||
false,
|
||||
boost::function<bool (boost::any *)>(&Data::is_null<T>))
|
||||
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(),
|
||||
false)
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -224,15 +216,10 @@ namespace chaiscript
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (m_data->m_is_null)
|
||||
{
|
||||
return m_data->m_is_null(&m_data->m_obj);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -247,30 +234,27 @@ namespace chaiscript
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
void clear_dependencies()
|
||||
void *get_ptr() const
|
||||
{
|
||||
m_data->m_dependencies.clear();
|
||||
return m_data->m_data_ptr;
|
||||
}
|
||||
|
||||
template<typename InItr>
|
||||
void add_dependencies(InItr begin, const InItr &end)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
if (begin->m_data != m_data)
|
||||
{
|
||||
m_data->m_dependencies.push_back(begin->m_data);
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
const void *get_const_ptr() const
|
||||
{
|
||||
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
|
||||
///
|
||||
@@ -297,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.
|
||||
@@ -308,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
|
||||
@@ -364,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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -11,13 +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"
|
||||
@@ -32,6 +31,71 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it is a reserved word
|
||||
*/
|
||||
class reserved_word_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
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() noexcept {}
|
||||
|
||||
std::string word() const
|
||||
{
|
||||
return m_word;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_word;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it already exists in current context
|
||||
*/
|
||||
class name_conflict_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
name_conflict_error(const std::string &t_name) throw()
|
||||
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~name_conflict_error() throw() {}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that a non-const object was added as a shared object
|
||||
*/
|
||||
class global_non_const : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
global_non_const() noexcept
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() noexcept {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// \brief Holds a collection of ChaiScript settings which can be applied to the ChaiScript runtime.
|
||||
/// Used to implement loadable module support.
|
||||
class Module
|
||||
@@ -55,6 +119,17 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
if (!t_bv.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
m_globals.push_back(std::make_pair(t_bv, t_name));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//Add a bit of chaiscript to eval during module implementation
|
||||
Module &eval(const std::string &str)
|
||||
@@ -63,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;
|
||||
@@ -76,11 +151,18 @@ namespace chaiscript
|
||||
apply(m_funcs.begin(), m_funcs.end(), t_engine);
|
||||
apply_eval(m_evals.begin(), m_evals.end(), t_eval);
|
||||
apply_single(m_conversions.begin(), m_conversions.end(), t_engine);
|
||||
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;
|
||||
std::vector<std::pair<Boxed_Value, std::string> > m_globals;
|
||||
std::vector<std::string> m_evals;
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
|
||||
@@ -89,7 +171,22 @@ namespace chaiscript
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
t.add(begin->first, begin->second);
|
||||
try {
|
||||
t.add(begin->first, begin->second);
|
||||
} catch (const chaiscript::exception::name_conflict_error &) {
|
||||
/// \todo Should we throw an error if there's a name conflict
|
||||
/// while applying a module?
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_globals(InItr begin, InItr end, T &t) const
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
t.add_global_const(begin->first, begin->second);
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
@@ -116,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
|
||||
{
|
||||
@@ -266,48 +363,6 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
namespace exception
|
||||
{
|
||||
/**
|
||||
* Exception thrown in the case that a multi method dispatch fails
|
||||
* because no matching function was found
|
||||
* at runtime due to either an arity_error, a guard_error or a bad_boxed_cast
|
||||
* exception
|
||||
*/
|
||||
class reserved_word_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
reserved_word_error(const std::string &t_word) throw()
|
||||
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~reserved_word_error() throw() {}
|
||||
|
||||
std::string word() const
|
||||
{
|
||||
return m_word;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_word;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that a non-const object was added as a shared object
|
||||
*/
|
||||
class global_non_const : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
global_non_const() throw()
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() throw() {}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -321,18 +376,21 @@ 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
|
||||
{
|
||||
std::map<std::string, std::vector<Proxy_Function> > m_functions;
|
||||
std::map<std::string, Proxy_Function> m_function_objects;
|
||||
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()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -353,10 +411,10 @@ namespace chaiscript
|
||||
/**
|
||||
* Add a new named Proxy_Function to the system
|
||||
*/
|
||||
bool add(const Proxy_Function &f, const std::string &name)
|
||||
void add(const Proxy_Function &f, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
return add_function(f, name);
|
||||
add_function(f, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,6 +438,7 @@ namespace chaiscript
|
||||
|
||||
add_object(name, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a named object to the current scope
|
||||
@@ -388,7 +447,15 @@ namespace chaiscript
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
stack.back()[name] = obj;
|
||||
|
||||
Scope &scope = stack.back();
|
||||
Scope::iterator itr = scope.find(name);
|
||||
if (itr != stack.back().end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
stack.back().insert(std::make_pair(name, obj));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,12 +466,17 @@ 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);
|
||||
|
||||
m_state.m_global_objects[name] = obj;
|
||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -430,28 +502,24 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps out the stack with a new stack
|
||||
* \returns the old stack
|
||||
* \param[in] s The new stack
|
||||
*/
|
||||
Stack set_stack(const Stack &s)
|
||||
{
|
||||
Stack old = m_stack_holder->stack;
|
||||
m_stack_holder->stack = s;
|
||||
return old;
|
||||
}
|
||||
|
||||
Stack new_stack() const
|
||||
/// Pushes a new stack on to the list of stacks
|
||||
void new_stack()
|
||||
{
|
||||
Stack s(new Stack::element_type());
|
||||
s->push_back(Scope());
|
||||
return s;
|
||||
m_stack_holder->stacks.push_back(s);
|
||||
}
|
||||
|
||||
void pop_stack()
|
||||
{
|
||||
m_stack_holder->stacks.pop_back();
|
||||
}
|
||||
|
||||
/// \returns the current stack
|
||||
Stack get_stack() const
|
||||
{
|
||||
return m_stack_holder->stack;
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -491,21 +559,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
// If all that failed, then check to see if it's a function
|
||||
std::vector<Proxy_Function> funcs = get_function(name);
|
||||
|
||||
if (funcs.empty())
|
||||
{
|
||||
throw std::range_error("Object not known: " + name);
|
||||
} else {
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
// Return the first item if there is only one,
|
||||
// no reason to take the cast of the extra level of dispatch
|
||||
return const_var(*funcs.begin());
|
||||
} else {
|
||||
return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
||||
}
|
||||
}
|
||||
return get_function_object(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -588,9 +642,26 @@ namespace chaiscript
|
||||
} else {
|
||||
return std::vector<Proxy_Function>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// \returns a function object (Boxed_Value wrapper) if it exists
|
||||
/// \throws std::range_error if it does not
|
||||
Boxed_Value get_function_object(const std::string &t_name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||
|
||||
std::map<std::string, Proxy_Function>::const_iterator itr = funs.find(t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
{
|
||||
return const_var(itr->second);
|
||||
} else {
|
||||
throw std::range_error("Object not found: " + t_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a function exists
|
||||
*/
|
||||
@@ -602,6 +673,78 @@ 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
|
||||
///
|
||||
std::map<std::string, Boxed_Value> get_scripting_objects() const
|
||||
{
|
||||
// We don't want the current context, but one up if it exists
|
||||
StackData &stack = (m_stack_holder->stacks.size()==1)?(*(m_stack_holder->stacks.back())):(*m_stack_holder->stacks[m_stack_holder->stacks.size()-2]);
|
||||
|
||||
std::map<std::string, Boxed_Value> retval;
|
||||
|
||||
// note: map insert doesn't overwrite existing values, which is why this works
|
||||
|
||||
for (StackData::reverse_iterator itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||
{
|
||||
retval.insert(itr->begin(), itr->end());
|
||||
}
|
||||
|
||||
// add the global values
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get a map of all functions that can be seen from a scripting context
|
||||
///
|
||||
std::map<std::string, Boxed_Value> get_function_objects() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||
|
||||
std::map<std::string, Boxed_Value> objs;
|
||||
|
||||
for (std::map<std::string, Proxy_Function>::const_iterator itr = funs.begin();
|
||||
itr != funs.end();
|
||||
++itr)
|
||||
{
|
||||
objs.insert(std::make_pair(itr->first, const_var(itr->second)));
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a vector of all registered functions
|
||||
*/
|
||||
@@ -665,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -760,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());
|
||||
}
|
||||
@@ -781,6 +923,29 @@ namespace chaiscript
|
||||
m_state = t_state;
|
||||
}
|
||||
|
||||
void save_function_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
m_stack_holder->call_params.insert(m_stack_holder->call_params.begin(), t_params.begin(), t_params.end());
|
||||
}
|
||||
|
||||
void new_function_call()
|
||||
{
|
||||
++m_stack_holder->call_depth;
|
||||
}
|
||||
|
||||
void pop_function_call()
|
||||
{
|
||||
--m_stack_holder->call_depth;
|
||||
|
||||
assert(m_stack_holder->call_depth >= 0);
|
||||
|
||||
if (m_stack_holder->call_depth == 0)
|
||||
{
|
||||
/// \todo Critical: this needs to be smarter, memory can expand quickly
|
||||
/// in tight loops involving function calls
|
||||
m_stack_holder->call_params.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -789,7 +954,17 @@ namespace chaiscript
|
||||
*/
|
||||
StackData &get_stack_data() const
|
||||
{
|
||||
return *(m_stack_holder->stack);
|
||||
return *(m_stack_holder->stacks.back());
|
||||
}
|
||||
|
||||
const std::map<std::string, Proxy_Function> &get_function_objects_int() const
|
||||
{
|
||||
return m_state.m_function_objects;
|
||||
}
|
||||
|
||||
std::map<std::string, Proxy_Function> &get_function_objects_int()
|
||||
{
|
||||
return m_state.m_function_objects;
|
||||
}
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
||||
@@ -811,10 +986,10 @@ namespace chaiscript
|
||||
const size_t rhssize = rhsparamtypes.size();
|
||||
|
||||
const Type_Info boxed_type = user_type<Boxed_Value>();
|
||||
const Type_Info boxed_pod_type = user_type<Boxed_POD_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)
|
||||
{
|
||||
@@ -906,16 +1081,15 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation detail for adding a function. Returns
|
||||
* true if the function was added, false if a function with the
|
||||
* same signature and name already exists.
|
||||
* Implementation detail for adding a function.
|
||||
* \throws exception::name_conflict_error if there's a function matching the given one being added
|
||||
*/
|
||||
bool add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||
void add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@@ -924,6 +1098,8 @@ namespace chaiscript
|
||||
std::map<std::string, std::vector<Proxy_Function> >::iterator itr
|
||||
= funcs.find(t_name);
|
||||
|
||||
std::map<std::string, Proxy_Function> &func_objs = get_function_objects_int();
|
||||
|
||||
if (itr != funcs.end())
|
||||
{
|
||||
std::vector<Proxy_Function> &vec = itr->second;
|
||||
@@ -933,19 +1109,21 @@ namespace chaiscript
|
||||
{
|
||||
if ((*t_f) == *(*itr2))
|
||||
{
|
||||
return false;
|
||||
throw chaiscript::exception::name_conflict_error(t_name);
|
||||
}
|
||||
}
|
||||
|
||||
vec.push_back(t_f);
|
||||
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
|
||||
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||
} else {
|
||||
std::vector<Proxy_Function> vec;
|
||||
vec.push_back(t_f);
|
||||
funcs.insert(std::make_pair(t_name, vec));
|
||||
func_objs[t_name] = t_f;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
@@ -954,12 +1132,17 @@ namespace chaiscript
|
||||
struct Stack_Holder
|
||||
{
|
||||
Stack_Holder()
|
||||
: stack(new StackData())
|
||||
: call_depth(0)
|
||||
{
|
||||
stack->push_back(Scope());
|
||||
Stack s(new StackData());
|
||||
s->push_back(Scope());
|
||||
stacks.push_back(s);
|
||||
}
|
||||
|
||||
Stack stack;
|
||||
std::deque<Stack> stacks;
|
||||
|
||||
std::list<Boxed_Value> call_params;
|
||||
int call_depth;
|
||||
};
|
||||
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -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 {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,6 +45,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
|
||||
|
||||
const Type_Info &base()
|
||||
{
|
||||
return m_base;
|
||||
@@ -63,6 +61,8 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Conversion() {}
|
||||
|
||||
private:
|
||||
Type_Info m_base;
|
||||
Type_Info m_derived;
|
||||
@@ -87,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();
|
||||
@@ -96,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)
|
||||
{
|
||||
@@ -112,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");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -136,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
|
||||
@@ -165,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);
|
||||
|
||||
@@ -219,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.
|
||||
@@ -249,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>();
|
||||
}
|
||||
@@ -275,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,12 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -44,20 +43,6 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct Dynamic_Object_Attribute
|
||||
{
|
||||
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
|
||||
Dynamic_Object &t_do)
|
||||
{
|
||||
if (t_do.get_type_name() != t_type_name)
|
||||
{
|
||||
throw exception::bad_boxed_cast("Dynamic object type mismatch");
|
||||
}
|
||||
|
||||
return t_do.get_attr(t_attr_name);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A Proxy_Function implementation designed for calling a function
|
||||
* that is automatically guarded based on the first param based on the
|
||||
@@ -66,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() {}
|
||||
|
||||
@@ -102,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};
|
||||
}
|
||||
|
||||
|
||||
@@ -137,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))
|
||||
@@ -176,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)
|
||||
{
|
||||
@@ -188,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;
|
||||
|
||||
};
|
||||
|
||||
@@ -207,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)
|
||||
{
|
||||
|
176
include/chaiscript/dispatchkit/exception_specification.hpp
Normal file
176
include/chaiscript/dispatchkit/exception_specification.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// 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_EXCEPTION_SPECIFICATION_HPP_
|
||||
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
|
||||
#include "boxed_cast.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv) = 0;
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
void throw_type(const Boxed_Value &bv)
|
||||
{
|
||||
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1>
|
||||
struct Exception_Handler_Impl1 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Exception_Handler_Impl2 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
struct Exception_Handler_Impl3 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T3>(bv);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
struct Exception_Handler_Impl4 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T3>(bv);
|
||||
throw_type<T4>(bv);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct Exception_Handler_Impl5 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T3>(bv);
|
||||
throw_type<T4>(bv);
|
||||
throw_type<T5>(bv);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
|
||||
///
|
||||
/// Exception specifications allow the user to tell ChaiScript what possible exceptions are expected from the script
|
||||
/// being executed. Exception_Handler objects are created with the chaiscript::exception_specification() function.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// chaiscript::ChaiScript chai;
|
||||
///
|
||||
/// try {
|
||||
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
/// } catch (const double e) {
|
||||
/// } catch (int) {
|
||||
/// } catch (float) {
|
||||
/// } catch (const std::string &) {
|
||||
/// } catch (const std::exception &e) {
|
||||
/// // This is the one what will be called in the specific throw() above
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// It is recommended that if catching the generic \c std::exception& type that you specifically catch
|
||||
/// the chaiscript::exception::eval_error type, so that there is no confusion.
|
||||
///
|
||||
/// \code
|
||||
/// try {
|
||||
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<const std::exception &>());
|
||||
/// } catch (const chaiscript::exception::eval_error &) {
|
||||
/// // Error in script parsing / execution
|
||||
/// } catch (const std::exception &e) {
|
||||
/// // Error explicitly thrown from script
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Similarly, if you are using the ChaiScript::eval form that unboxes the return value, then chaiscript::exception::bad_boxed_cast
|
||||
/// should be handled as well.
|
||||
///
|
||||
/// \code
|
||||
/// try {
|
||||
/// chai.eval<int>("1.0", chaiscript::exception_specification<const std::exception &>());
|
||||
/// } catch (const chaiscript::exception::eval_error &) {
|
||||
/// // Error in script parsing / execution
|
||||
/// } catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
/// // Error unboxing return value
|
||||
/// } catch (const std::exception &e) {
|
||||
/// // Error explicitly thrown from script
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
|
||||
/// \sa \ref exceptions
|
||||
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
|
||||
template<typename T1>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2, typename T3>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,22 +1,12 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// 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
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -34,27 +34,36 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<boost::shared_ptr<Ret> &>
|
||||
struct Handle_Return<Ret *>
|
||||
{
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(Ret *p)
|
||||
{
|
||||
return Boxed_Value(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -65,7 +74,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::cref(r));
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -135,6 +144,30 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Number>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Number &r)
|
||||
{
|
||||
return r.bv;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Number>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Number &r)
|
||||
{
|
||||
return r.bv;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
|
@@ -1,12 +1,14 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#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);
|
||||
|
@@ -1,27 +1,39 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// 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
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -12,53 +12,21 @@
|
||||
#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
|
||||
{
|
||||
class Boxed_POD_Value;
|
||||
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++
|
||||
@@ -74,7 +42,6 @@ namespace chaiscript
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
Boxed_Value bv = do_call(params);
|
||||
bv.add_dependencies(params.begin(), params.end());
|
||||
return bv;
|
||||
}
|
||||
|
||||
@@ -82,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> >();
|
||||
}
|
||||
|
||||
|
||||
@@ -139,10 +106,10 @@ namespace chaiscript
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
|| (!bv.get_type_info().is_undef()
|
||||
&& (ti.bare_equal(user_type<Boxed_POD_Value>())
|
||||
&& (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> >())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -176,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
|
||||
{
|
||||
@@ -188,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
|
||||
{ }
|
||||
};
|
||||
}
|
||||
@@ -207,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 = "",
|
||||
@@ -219,7 +186,12 @@ namespace chaiscript
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &rhs) const
|
||||
{
|
||||
return this == &rhs;
|
||||
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||
|
||||
return this == &rhs
|
||||
|| (prhs
|
||||
&& this->m_arity == prhs->m_arity
|
||||
&& !this->m_guard && !prhs->m_guard);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
@@ -293,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)
|
||||
{
|
||||
@@ -304,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;
|
||||
@@ -409,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();
|
||||
@@ -440,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() {}
|
||||
|
||||
@@ -461,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())
|
||||
@@ -483,7 +454,7 @@ namespace chaiscript
|
||||
return "";
|
||||
}
|
||||
|
||||
boost::function<Func> internal_function() const
|
||||
std::function<Func> internal_function() const
|
||||
{
|
||||
return m_f;
|
||||
}
|
||||
@@ -491,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;
|
||||
};
|
||||
|
||||
@@ -509,8 +480,8 @@ namespace chaiscript
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
@@ -518,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 {
|
||||
@@ -555,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);
|
||||
@@ -568,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;
|
||||
};
|
||||
}
|
||||
@@ -587,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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -610,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 {
|
||||
@@ -631,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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,16 +1,9 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// 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();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -9,15 +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/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
|
||||
{
|
||||
@@ -27,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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,38 +29,41 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||
const std::type_info *t_ti, const std::type_info *t_bareti)
|
||||
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||
m_is_void(t_is_void),
|
||||
m_type_info(t_ti), m_bare_type_info(t_bareti),
|
||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bareti),
|
||||
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
|
||||
m_is_undef(false)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info()
|
||||
: m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||
m_is_void(false), m_type_info(0), m_bare_type_info(0),
|
||||
: m_type_info(0), m_bare_type_info(0),
|
||||
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||
m_is_void(false), m_is_arithmetic(false),
|
||||
m_is_undef(true)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info(const Type_Info &ti)
|
||||
: m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
|
||||
m_is_pointer(ti.m_is_pointer),
|
||||
m_is_void(ti.m_is_void), m_type_info(ti.m_type_info),
|
||||
: m_type_info(ti.m_type_info),
|
||||
m_bare_type_info(ti.m_bare_type_info),
|
||||
m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
|
||||
m_is_pointer(ti.m_is_pointer),
|
||||
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
|
||||
m_is_undef(ti.m_is_undef)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info &operator=(const Type_Info &ti)
|
||||
{
|
||||
m_type_info = ti.m_type_info;
|
||||
m_bare_type_info = ti.m_bare_type_info;
|
||||
m_is_const = ti.m_is_const;
|
||||
m_is_reference = ti.m_is_reference;
|
||||
m_is_pointer = ti.m_is_pointer;
|
||||
m_is_void = ti.m_is_void;
|
||||
m_type_info = ti.m_type_info;
|
||||
m_bare_type_info = ti.m_bare_type_info;
|
||||
m_is_arithmetic = ti.m_is_arithmetic;
|
||||
m_is_undef = ti.m_is_undef;
|
||||
return *this;
|
||||
}
|
||||
@@ -97,6 +93,7 @@ namespace chaiscript
|
||||
bool is_const() const { return m_is_const; }
|
||||
bool is_reference() const { return m_is_reference; }
|
||||
bool is_void() const { return m_is_void; }
|
||||
bool is_arithmetic() const { return m_is_arithmetic; }
|
||||
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; }
|
||||
bool is_pointer() const { return m_is_pointer; }
|
||||
|
||||
@@ -121,12 +118,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
bool m_is_const;
|
||||
bool m_is_reference;
|
||||
bool m_is_pointer;
|
||||
bool m_is_void;
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
bool m_is_arithmetic;
|
||||
bool m_is_undef;
|
||||
};
|
||||
|
||||
@@ -140,67 +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,
|
||||
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,
|
||||
&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,
|
||||
&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,
|
||||
&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,
|
||||
&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));
|
||||
}
|
||||
};
|
||||
@@ -222,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();
|
||||
}
|
||||
@@ -237,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();
|
||||
}
|
||||
|
130
include/chaiscript/language/chaiscript_algebraic.hpp
Normal file
130
include/chaiscript/language/chaiscript_algebraic.hpp
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
struct Operators {
|
||||
enum Opers
|
||||
{
|
||||
boolean_flag,
|
||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
||||
non_const_flag,
|
||||
assign, pre_increment, pre_decrement, assign_product, assign_sum,
|
||||
assign_quotient, assign_difference,
|
||||
non_const_int_flag,
|
||||
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
|
||||
assign_remainder, assign_bitwise_xor,
|
||||
const_int_flag,
|
||||
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
|
||||
const_flag,
|
||||
sum, quotient, product, difference, unary_plus, unary_minus,
|
||||
invalid
|
||||
};
|
||||
|
||||
static const char *to_string(Opers t_oper) {
|
||||
const char *opers[] = {
|
||||
"",
|
||||
"==", "<", ">", "<=", ">=", "!=",
|
||||
"",
|
||||
"=", "++", "--", "*=", "+=",
|
||||
"/=", "-=",
|
||||
"",
|
||||
"&=", "|=", "<<=", ">>=",
|
||||
"%=", "^=",
|
||||
"",
|
||||
"<<", ">>", "%", "&", "|", "^", "~",
|
||||
"",
|
||||
"+", "/", "*", "-", "+", "-",
|
||||
""
|
||||
};
|
||||
return opers[t_oper];
|
||||
}
|
||||
|
||||
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
||||
{
|
||||
if (t_str == "==")
|
||||
{
|
||||
return equals;
|
||||
} else if (t_str == "<") {
|
||||
return less_than;
|
||||
} else if (t_str == ">") {
|
||||
return greater_than;
|
||||
} else if (t_str == "<=") {
|
||||
return less_than_equal;
|
||||
} else if (t_str == ">=") {
|
||||
return greater_than_equal;
|
||||
} else if (t_str == "!=") {
|
||||
return not_equal;
|
||||
} else if (t_str == "=") {
|
||||
return assign;
|
||||
} else if (t_str == "++") {
|
||||
return pre_increment;
|
||||
} else if (t_str == "--") {
|
||||
return pre_decrement;
|
||||
} else if (t_str == "*=") {
|
||||
return assign_product;
|
||||
} else if (t_str == "+=") {
|
||||
return assign_sum;
|
||||
} else if (t_str == "-=") {
|
||||
return assign_difference;
|
||||
} else if (t_str == "&=") {
|
||||
return assign_bitwise_and;
|
||||
} else if (t_str == "|=") {
|
||||
return assign_bitwise_or;
|
||||
} else if (t_str == "<<=") {
|
||||
return assign_shift_left;
|
||||
} else if (t_str == ">>=") {
|
||||
return assign_shift_right;
|
||||
} else if (t_str == "%=") {
|
||||
return assign_remainder;
|
||||
} else if (t_str == "^=") {
|
||||
return assign_bitwise_xor;
|
||||
} else if (t_str == "<<") {
|
||||
return shift_left;
|
||||
} else if (t_str == ">>") {
|
||||
return shift_right;
|
||||
} else if (t_str == "%") {
|
||||
return remainder;
|
||||
} else if (t_str == "&") {
|
||||
return bitwise_and;
|
||||
} else if (t_str == "|") {
|
||||
return bitwise_or;
|
||||
} else if (t_str == "^") {
|
||||
return bitwise_xor;
|
||||
} else if (t_str == "~") {
|
||||
return bitwise_complement;
|
||||
} else if (t_str == "+") {
|
||||
if (t_is_unary) {
|
||||
return unary_plus;
|
||||
} else {
|
||||
return sum;
|
||||
}
|
||||
} else if (t_str == "-") {
|
||||
if (t_is_unary) {
|
||||
return unary_minus;
|
||||
} else {
|
||||
return difference;
|
||||
}
|
||||
} else if (t_str == "/") {
|
||||
return quotient;
|
||||
} else if (t_str == "*") {
|
||||
return product;
|
||||
} else {
|
||||
return invalid;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
|
||||
|
@@ -1,28 +1,29 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#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
|
||||
{
|
||||
/// Signature of module entry point that all binary loadable modules must implement.
|
||||
typedef ModulePtr (*Create_Module_Func)();
|
||||
|
||||
|
||||
/// Types of AST nodes available to the parser and eval
|
||||
class AST_Node_Type {
|
||||
public:
|
||||
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Comparison, Additive, Multiplicative, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
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
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond
|
||||
};
|
||||
};
|
||||
|
||||
@@ -33,10 +34,10 @@ namespace chaiscript
|
||||
*/
|
||||
const char *ast_node_type_to_string(int ast_node_type) {
|
||||
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Comparison", "Additive", "Multiplicative", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"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"};
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
@@ -54,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.
|
||||
@@ -68,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
|
||||
*/
|
||||
@@ -146,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() {}
|
||||
@@ -212,6 +516,57 @@ namespace chaiscript
|
||||
|
||||
chaiscript::detail::Dispatch_Engine &m_de;
|
||||
};
|
||||
|
||||
/// Creates a new functon call and pops it on destruction
|
||||
struct Function_Push_Pop
|
||||
{
|
||||
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||
: m_de(t_de)
|
||||
{
|
||||
m_de.new_function_call();
|
||||
}
|
||||
|
||||
~Function_Push_Pop()
|
||||
{
|
||||
m_de.pop_function_call();
|
||||
}
|
||||
|
||||
void save_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
m_de.save_function_params(t_params);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// explicitly unimplemented copy and assignment
|
||||
Function_Push_Pop(const Function_Push_Pop &);
|
||||
Function_Push_Pop& operator=(const Function_Push_Pop &);
|
||||
|
||||
chaiscript::detail::Dispatch_Engine &m_de;
|
||||
};
|
||||
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Stack_Push_Pop
|
||||
{
|
||||
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||
: m_de(t_de)
|
||||
{
|
||||
m_de.new_stack();
|
||||
}
|
||||
|
||||
~Stack_Push_Pop()
|
||||
{
|
||||
m_de.pop_stack();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// explicitly unimplemented copy and assignment
|
||||
Stack_Push_Pop(const Stack_Push_Pop &);
|
||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &);
|
||||
|
||||
chaiscript::detail::Dispatch_Engine &m_de;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -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,9 @@
|
||||
#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
|
||||
{
|
||||
@@ -33,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
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -56,7 +62,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw exception::load_module_error(dlerror());
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,14 +81,27 @@ namespace chaiscript
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw exception::load_module_error(dlerror());
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
static T cast_symbol(void *p)
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
T func_ptr;
|
||||
void *in_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = p;
|
||||
return c.func_ptr;
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
@@ -166,7 +185,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +205,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,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;
|
||||
@@ -217,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -260,7 +279,11 @@ namespace chaiscript
|
||||
|
||||
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
|
||||
{
|
||||
return t_ast->eval(m_engine);
|
||||
try {
|
||||
return t_ast->eval(m_engine);
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
throw Boxed_Value(t_ee);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,34 +291,10 @@ namespace chaiscript
|
||||
* Evaluates the given string, used during eval() inside of a script
|
||||
*/
|
||||
const Boxed_Value internal_eval(const std::string &t_e) {
|
||||
return do_eval(t_e, "__EVAL__", true);
|
||||
}
|
||||
|
||||
void use(const std::string &t_filename)
|
||||
{
|
||||
for (size_t i = 0; i < m_usepaths.size(); ++i)
|
||||
{
|
||||
|
||||
try {
|
||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||
|
||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||
|
||||
if (m_used_files.count(appendedpath) == 0)
|
||||
{
|
||||
m_used_files.insert(appendedpath);
|
||||
l2.unlock();
|
||||
eval_file(appendedpath);
|
||||
}
|
||||
} catch (const exception::file_not_found_error &) {
|
||||
if (i == m_usepaths.size() - 1)
|
||||
{
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
// failed to load, try the next path
|
||||
}
|
||||
try {
|
||||
return do_eval(t_e, "__EVAL__", true);
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
throw Boxed_Value(t_ee);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,8 +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;
|
||||
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");
|
||||
@@ -320,23 +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::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&);
|
||||
@@ -345,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");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,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();
|
||||
@@ -384,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)
|
||||
{
|
||||
@@ -400,13 +399,112 @@ 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.
|
||||
///
|
||||
/// \param[in] t_filename Filename to load and evaluate
|
||||
void use(const std::string &t_filename)
|
||||
{
|
||||
for (size_t i = 0; i < m_usepaths.size(); ++i)
|
||||
{
|
||||
try {
|
||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||
|
||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||
|
||||
if (m_used_files.count(appendedpath) == 0)
|
||||
{
|
||||
m_used_files.insert(appendedpath);
|
||||
l2.unlock();
|
||||
eval_file(appendedpath);
|
||||
}
|
||||
|
||||
return; // return, we loaded it, or it was already loaded
|
||||
} catch (const exception::file_not_found_error &) {
|
||||
if (i == m_usepaths.size() - 1)
|
||||
{
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
// failed to load, try the next path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \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)
|
||||
{
|
||||
@@ -424,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:
|
||||
///
|
||||
@@ -446,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:
|
||||
@@ -465,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
|
||||
@@ -522,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;
|
||||
@@ -546,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
|
||||
}
|
||||
@@ -568,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
|
||||
@@ -598,61 +720,105 @@ namespace chaiscript
|
||||
/// \brief Evaluates a string. Equivalent to ChaiScript::eval.
|
||||
///
|
||||
/// \param[in] t_script Script to execute
|
||||
/// \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.
|
||||
Boxed_Value operator()(const std::string &t_script)
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||
{
|
||||
return do_eval(t_script);
|
||||
try {
|
||||
return do_eval(t_script);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
}
|
||||
throw bv;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Evaluates a string and returns a typesafe result.
|
||||
///
|
||||
/// \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)
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
return boxed_cast<T>(do_eval(t_input));
|
||||
try {
|
||||
return boxed_cast<T>(do_eval(t_input, t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
}
|
||||
throw bv;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Evaluates a string.
|
||||
///
|
||||
/// \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)
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
return do_eval(t_input);
|
||||
try {
|
||||
return do_eval(t_input, t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
}
|
||||
throw bv;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the result.
|
||||
/// \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.
|
||||
Boxed_Value eval_file(const std::string &t_filename) {
|
||||
return do_eval(load_file(t_filename), t_filename);
|
||||
/// \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);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
}
|
||||
throw bv;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result.
|
||||
/// \tparam T Type to extract from the result value of the script execution
|
||||
/// \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) {
|
||||
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
||||
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
try {
|
||||
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
}
|
||||
throw bv;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -66,6 +68,11 @@ namespace chaiscript
|
||||
|
||||
void setup_operators()
|
||||
{
|
||||
m_operators.push_back(AST_Node_Type::Ternary_Cond);
|
||||
std::vector<std::string> ternary_cond;
|
||||
ternary_cond.push_back("?");
|
||||
m_operator_matches.push_back(ternary_cond);
|
||||
|
||||
m_operators.push_back(AST_Node_Type::Logical_Or);
|
||||
std::vector<std::string> logical_or;
|
||||
logical_or.push_back("||");
|
||||
@@ -111,29 +118,27 @@ namespace chaiscript
|
||||
shift.push_back(">>");
|
||||
m_operator_matches.push_back(shift);
|
||||
|
||||
m_operators.push_back(AST_Node_Type::Additive);
|
||||
std::vector<std::string> additive;
|
||||
additive.push_back("+");
|
||||
additive.push_back("-");
|
||||
m_operator_matches.push_back(additive);
|
||||
//We share precedence here but then separate them later
|
||||
m_operators.push_back(AST_Node_Type::Addition);
|
||||
std::vector<std::string> addition;
|
||||
addition.push_back("+");
|
||||
addition.push_back("-");
|
||||
m_operator_matches.push_back(addition);
|
||||
|
||||
m_operators.push_back(AST_Node_Type::Multiplicative);
|
||||
std::vector<std::string> multiplicative;
|
||||
multiplicative.push_back("*");
|
||||
multiplicative.push_back("/");
|
||||
multiplicative.push_back("%");
|
||||
m_operator_matches.push_back(multiplicative);
|
||||
|
||||
m_operators.push_back(AST_Node_Type::Dot_Access);
|
||||
std::vector<std::string> dot_access;
|
||||
dot_access.push_back(".");
|
||||
m_operator_matches.push_back(dot_access);
|
||||
//We share precedence here but then separate them later
|
||||
m_operators.push_back(AST_Node_Type::Multiplication);
|
||||
std::vector<std::string> multiplication;
|
||||
multiplication.push_back("*");
|
||||
multiplication.push_back("/");
|
||||
multiplication.push_back("%");
|
||||
m_operator_matches.push_back(multiplication);
|
||||
|
||||
for ( int c = 0 ; c < detail::lengthof_alphabet ; ++c ) {
|
||||
for ( int a = 0 ; a < detail::max_alphabet ; a ++ ) {
|
||||
m_alphabet[a][c]=false;
|
||||
}
|
||||
}
|
||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('?')]=true;
|
||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('+')]=true;
|
||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('-')]=true;
|
||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('*')]=true;
|
||||
@@ -172,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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +265,7 @@ namespace chaiscript
|
||||
m_match_stack.push_back(t_t);
|
||||
}
|
||||
else {
|
||||
//todo: fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
|
||||
/// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
|
||||
m_match_stack.push_back(t_t);
|
||||
}
|
||||
}
|
||||
@@ -325,7 +341,6 @@ namespace chaiscript
|
||||
*/
|
||||
bool Float_() {
|
||||
bool retval = false;
|
||||
std::string::const_iterator start = m_input_pos;
|
||||
|
||||
if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) {
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) {
|
||||
@@ -341,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;
|
||||
@@ -352,7 +373,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a floating point value from input, without skipping initial whitespace
|
||||
* Reads a hex value from input, without skipping initial whitespace
|
||||
*/
|
||||
bool Hex_() {
|
||||
bool retval = false;
|
||||
@@ -369,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;
|
||||
@@ -384,8 +410,16 @@ 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 floating point value from input, without skipping initial whitespace
|
||||
* Reads a binary value from input, without skipping initial whitespace
|
||||
*/
|
||||
bool Binary_() {
|
||||
bool retval = false;
|
||||
@@ -417,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
|
||||
*/
|
||||
@@ -433,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))) {
|
||||
@@ -456,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;
|
||||
@@ -655,7 +846,6 @@ namespace chaiscript
|
||||
bool saw_interpolation_marker = false;
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
//for (std::string::iterator s = start + 1, end = m_input_pos - 1; s != end; ++s) {
|
||||
std::string::const_iterator s = start + 1, end = m_input_pos - 1;
|
||||
|
||||
while (s != end) {
|
||||
@@ -665,13 +855,11 @@ namespace chaiscript
|
||||
|
||||
if (is_interpolated) {
|
||||
//If we've seen previous interpolation, add on instead of making a new one
|
||||
AST_NodePtr plus(new eval::Str_AST_Node("+", AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(plus);
|
||||
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
|
||||
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
|
||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else {
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
@@ -681,9 +869,6 @@ namespace chaiscript
|
||||
//We've finished with the part of the string up to this point, so clear it
|
||||
match = "";
|
||||
|
||||
AST_NodePtr plus(new eval::Str_AST_Node("+", AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(plus);
|
||||
|
||||
std::string eval_match;
|
||||
|
||||
++s;
|
||||
@@ -718,7 +903,7 @@ namespace chaiscript
|
||||
|
||||
build_match(AST_NodePtr(new eval::Fun_Call_AST_Node()), tostr_stack_top);
|
||||
|
||||
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
|
||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else {
|
||||
throw exception::eval_error("Unclosed in-string eval", File_Position(prev_line, prev_col), *m_filename);
|
||||
@@ -765,13 +950,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
if (is_interpolated) {
|
||||
AST_NodePtr plus(new eval::Str_AST_Node("+", AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(plus);
|
||||
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
|
||||
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
|
||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else {
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
@@ -1428,6 +1610,90 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a case block from input
|
||||
*/
|
||||
bool Case() {
|
||||
bool retval = false;
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Keyword("case")) {
|
||||
retval = true;
|
||||
|
||||
if (!Char('(')) {
|
||||
throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
if (!(Operator() && Char(')'))) {
|
||||
throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
while (Eol()) {}
|
||||
|
||||
if (!Block()) {
|
||||
throw exception::eval_error("Incomplete 'case' block", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(new eval::Case_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else if (Keyword("default")) {
|
||||
while (Eol()) {}
|
||||
|
||||
if (!Block()) {
|
||||
throw exception::eval_error("Incomplete 'default' block", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(new eval::Default_AST_Node()), prev_stack_top);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a switch statement from input
|
||||
*/
|
||||
bool Switch() {
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Keyword("switch")) {
|
||||
|
||||
if (!Char('(')) {
|
||||
throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
if (!(Operator() && Char(')'))) {
|
||||
throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
while (Eol()) {}
|
||||
|
||||
if (Char('{')) {
|
||||
while (Eol()) {}
|
||||
|
||||
while (Case()) {
|
||||
while (Eol()) { } // eat
|
||||
}
|
||||
|
||||
while (Eol()) { } // eat
|
||||
|
||||
if (!Char('}')) {
|
||||
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(new eval::Switch_AST_Node()), prev_stack_top);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a curly-brace C-style block from input
|
||||
*/
|
||||
@@ -1486,14 +1752,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an identifier, then proceeds to check if it's a function or array call
|
||||
* Reads a dot expression(member access), then proceeds to check if it's a function or array call
|
||||
*/
|
||||
bool Id_Fun_Array() {
|
||||
bool Dot_Fun_Array() {
|
||||
bool retval = false;
|
||||
std::string::const_iterator prev_pos = m_input_pos;
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
if (Id(true)) {
|
||||
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
|
||||
Paren_Expression() || Inline_Container() || Id(true)) {
|
||||
retval = true;
|
||||
bool has_more = true;
|
||||
|
||||
@@ -1509,6 +1775,19 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(new eval::Fun_Call_AST_Node()), prev_stack_top);
|
||||
/// \todo Work around for method calls until we have a better solution
|
||||
if (!m_match_stack.back()->children.empty()) {
|
||||
if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Dot_Access) {
|
||||
AST_NodePtr dot_access = m_match_stack.back()->children[0];
|
||||
AST_NodePtr func_call = m_match_stack.back();
|
||||
m_match_stack.pop_back();
|
||||
func_call->children.erase(func_call->children.begin());
|
||||
func_call->children.insert(func_call->children.begin(), dot_access->children.back());
|
||||
dot_access->children.pop_back();
|
||||
dot_access->children.push_back(func_call);
|
||||
m_match_stack.push_back(dot_access);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Char('[')) {
|
||||
has_more = true;
|
||||
@@ -1519,6 +1798,14 @@ namespace chaiscript
|
||||
|
||||
build_match(AST_NodePtr(new eval::Array_Call_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else if (Symbol(".", true)) {
|
||||
has_more = true;
|
||||
if (!(Id(true))) {
|
||||
throw exception::eval_error("Incomplete array access", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(new eval::Dot_Access_AST_Node()), prev_stack_top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1533,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);
|
||||
}
|
||||
|
||||
@@ -1574,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;
|
||||
@@ -1592,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) {
|
||||
@@ -1613,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
|
||||
*/
|
||||
@@ -1675,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;
|
||||
}
|
||||
@@ -1683,8 +1998,7 @@ namespace chaiscript
|
||||
* Parses any of a group of 'value' style ast_node groups from input
|
||||
*/
|
||||
bool Value() {
|
||||
if (Var_Decl() || Lambda() || Id_Fun_Array() || Num(true) || Prefix() || Quoted_String(true) || Single_Quoted_String(true) ||
|
||||
Paren_Expression() || Inline_Container()) {
|
||||
if (Var_Decl() || Dot_Fun_Array() || Prefix()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -1703,7 +2017,7 @@ namespace chaiscript
|
||||
|
||||
bool Operator(size_t t_precedence = 0) {
|
||||
bool retval = false;
|
||||
|
||||
AST_NodePtr oper;
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (t_precedence < m_operators.size()) {
|
||||
@@ -1711,50 +2025,84 @@ namespace chaiscript
|
||||
retval = true;
|
||||
if (Operator_Helper(t_precedence)) {
|
||||
do {
|
||||
while (Eol()) {}
|
||||
if (!Operator(t_precedence+1)) {
|
||||
throw exception::eval_error("Incomplete "
|
||||
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
||||
File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
} while (Operator_Helper(t_precedence));
|
||||
|
||||
switch (m_operators[t_precedence]) {
|
||||
case(AST_Node_Type::Comparison) :
|
||||
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Dot_Access) :
|
||||
build_match(AST_NodePtr(new eval::Dot_Access_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Additive) :
|
||||
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Multiplicative) :
|
||||
build_match(AST_NodePtr(new eval::Multiplicative_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Shift) :
|
||||
build_match(AST_NodePtr(new eval::Shift_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Equality) :
|
||||
build_match(AST_NodePtr(new eval::Equality_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_And) :
|
||||
build_match(AST_NodePtr(new eval::Bitwise_And_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_Xor) :
|
||||
build_match(AST_NodePtr(new eval::Bitwise_Xor_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_Or) :
|
||||
build_match(AST_NodePtr(new eval::Bitwise_Or_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Logical_And) :
|
||||
build_match(AST_NodePtr(new eval::Logical_And_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Logical_Or) :
|
||||
build_match(AST_NodePtr(new eval::Logical_Or_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
default:
|
||||
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
switch (m_operators[t_precedence]) {
|
||||
case(AST_Node_Type::Comparison) :
|
||||
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Ternary_Cond) :
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
if (Symbol(":")) {
|
||||
if (!Operator(t_precedence+1)) {
|
||||
throw exception::eval_error("Incomplete "
|
||||
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
||||
File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
build_match(AST_NodePtr(new eval::Ternary_Cond_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else {
|
||||
throw exception::eval_error("Incomplete "
|
||||
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
||||
File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
break;
|
||||
case(AST_Node_Type::Addition) :
|
||||
oper = m_match_stack.at(m_match_stack.size()-2);
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
if (oper->text == "+") {
|
||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else if (oper->text == "-") {
|
||||
build_match(AST_NodePtr(new eval::Subtraction_AST_Node()), prev_stack_top);
|
||||
}
|
||||
break;
|
||||
case(AST_Node_Type::Multiplication) :
|
||||
oper = m_match_stack.at(m_match_stack.size()-2);
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
if (oper->text == "*") {
|
||||
build_match(AST_NodePtr(new eval::Multiplication_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else if (oper->text == "/") {
|
||||
build_match(AST_NodePtr(new eval::Division_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else if (oper->text == "%") {
|
||||
build_match(AST_NodePtr(new eval::Modulus_AST_Node()), prev_stack_top);
|
||||
}
|
||||
break;
|
||||
case(AST_Node_Type::Shift) :
|
||||
build_match(AST_NodePtr(new eval::Shift_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Equality) :
|
||||
build_match(AST_NodePtr(new eval::Equality_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_And) :
|
||||
build_match(AST_NodePtr(new eval::Bitwise_And_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_Xor) :
|
||||
build_match(AST_NodePtr(new eval::Bitwise_Xor_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_Or) :
|
||||
build_match(AST_NodePtr(new eval::Bitwise_Or_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Logical_And) :
|
||||
build_match(AST_NodePtr(new eval::Logical_And_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Logical_Or) :
|
||||
build_match(AST_NodePtr(new eval::Logical_Or_AST_Node()), prev_stack_top);
|
||||
break;
|
||||
default:
|
||||
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
} while (Operator_Helper(t_precedence));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1862,7 +2210,6 @@ namespace chaiscript
|
||||
bool saw_eol = true;
|
||||
|
||||
while (has_more) {
|
||||
has_more = false;
|
||||
int prev_line = m_line;
|
||||
int prev_col = m_col;
|
||||
if (Def()) {
|
||||
@@ -1905,6 +2252,14 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Switch()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Return()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
@@ -1921,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);
|
||||
@@ -1934,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;
|
||||
}
|
||||
@@ -1955,13 +2310,13 @@ 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())) {
|
||||
++m_input_pos;
|
||||
}
|
||||
// TODO: respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
|
||||
/// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
|
||||
}
|
||||
|
||||
if (Statements()) {
|
||||
|
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-2011, 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_ */
|
@@ -1,6 +1,6 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
@@ -8,80 +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(_module, _class_name, _constructors, _methods) \
|
||||
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
|
||||
chaiscript::utility::method_name_translator, _constructors, _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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2010 Jason Turner and Jonathan Turner. All Rights Reserved.
|
||||
Copyright 2009-2012 Jason Turner and Jonathan Turner. All Rights Reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
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 v2.3.3
|
||||
http://www.chaiscript.com
|
||||
(c) 2009-2010 Jason Turner and Jonathan Turner
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
[Introduction]
|
||||
|
||||
ChaiScript is 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(&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(&function, "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
@@ -1,3 +1,40 @@
|
||||
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)
|
||||
* Compile with -pedantic (#9)
|
||||
* Fix issues with multiple ChaiScript object types having the same attribute name (#15)
|
||||
* Prevent variable redeclaration in same scope (#22)
|
||||
* mgee: Boxed_Number improvements (#27)
|
||||
* Support switch statements (#34)
|
||||
* Fix uint16 comparions (#26)
|
||||
* Add ability to add const_var globals in Module objects (#14)
|
||||
* Add support for ternary operators ?:
|
||||
* Add headers to CMakeLists so they show up in IDEs
|
||||
* Add ability to get vector of defined objects and vector of defined functions
|
||||
* Fix memory leak in cyclical references
|
||||
* Clean up static analysis issues discovered
|
||||
* Fix vector construction to be consistent with map construction
|
||||
* Increased unit tests to 161
|
||||
* Performance enhancements
|
||||
|
||||
Changes since 3.0.0
|
||||
* Numeric operations performance increased approximately 10x
|
||||
* Looping operations performance increased up to 2x
|
||||
* Engine start up time decreased
|
||||
* Several parsing bugs related to index operators fixed
|
||||
* Added full support for all C algebraic types: double, long double, float, int, long, char,
|
||||
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
|
||||
* Enhanced support for capturing of exceptions thrown from ChaiScript in C++
|
||||
|
||||
Changes since 2.3.3
|
||||
|
||||
* Code simplifications
|
||||
|
@@ -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
|
44
src/main.cpp
44
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
|
||||
|
||||
@@ -215,21 +229,11 @@ int main(int argc, char *argv[])
|
||||
case eInteractive : interactive(chai); break;
|
||||
case eCommand : val = chai.eval(arg); break;
|
||||
case eFile : val = chai.eval_file(arg); break;
|
||||
default : std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
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())
|
||||
@@ -49,49 +51,54 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
m->add(chaiscript::base_class<std::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( 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( 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
|
||||
|
@@ -7,11 +7,22 @@ class TestBaseType
|
||||
public:
|
||||
TestBaseType() {}
|
||||
TestBaseType(int) {}
|
||||
TestBaseType(int *) {}
|
||||
virtual ~TestBaseType() {}
|
||||
virtual int func() { return 0; }
|
||||
|
||||
};
|
||||
|
||||
enum TestEnum
|
||||
{
|
||||
TestValue1 = 1
|
||||
};
|
||||
|
||||
int to_int(TestEnum t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
class TestDerivedType : public TestBaseType
|
||||
{
|
||||
public:
|
||||
@@ -24,9 +35,14 @@ std::string hello_world()
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
int *get_new_int()
|
||||
{
|
||||
return new int(1);
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -44,6 +60,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType (int *)>(), "TestBaseType");
|
||||
|
||||
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
||||
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
||||
@@ -52,10 +69,19 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
|
||||
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
||||
|
||||
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
||||
|
||||
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
|
||||
|
||||
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
|
||||
|
||||
m->add(chaiscript::fun(&to_int), "to_int");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#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)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user