Compare commits
281 Commits
Release-5.
...
v5.5.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7478d57264 | ||
![]() |
bab3701c2f | ||
![]() |
e225654289 | ||
![]() |
019ea57cb6 | ||
![]() |
60fe242fb6 | ||
![]() |
6c10f18e4c | ||
![]() |
d5a221a468 | ||
![]() |
6ec3afc687 | ||
![]() |
049cd12127 | ||
![]() |
8b34066dd5 | ||
![]() |
9fb74762ad | ||
![]() |
7b7e7176f5 | ||
![]() |
81146d6b0f | ||
![]() |
423e872720 | ||
![]() |
1e8c0ab93e | ||
![]() |
c90fe16858 | ||
![]() |
161652b5d9 | ||
![]() |
cc5bf45b3b | ||
![]() |
28124e4b33 | ||
![]() |
db207b345b | ||
![]() |
684d724103 | ||
![]() |
283152a880 | ||
![]() |
dc3ef087e2 | ||
![]() |
032ba63b8a | ||
![]() |
cf49b1b30c | ||
![]() |
63a083b47b | ||
![]() |
4a3315cfd1 | ||
![]() |
8a30581eaf | ||
![]() |
a51281a5be | ||
![]() |
e0919f7228 | ||
![]() |
fa5966bd04 | ||
![]() |
f4f2391801 | ||
![]() |
5daf837037 | ||
![]() |
99396ba05c | ||
![]() |
f5304ac75c | ||
![]() |
3f460fdd20 | ||
![]() |
4f972bcf67 | ||
![]() |
5d5e881971 | ||
![]() |
5515d058bb | ||
![]() |
79c5f71975 | ||
![]() |
c876a89030 | ||
![]() |
20c0e6016e | ||
![]() |
dd12785b72 | ||
![]() |
87cee688a8 | ||
![]() |
e2cf8a48be | ||
![]() |
7c766f87a4 | ||
![]() |
e85be6eb3d | ||
![]() |
7b42d5307a | ||
![]() |
43d6f0cf16 | ||
![]() |
86e26966c1 | ||
![]() |
9e8b833d11 | ||
![]() |
48c97bce9c | ||
![]() |
021e2a7949 | ||
![]() |
78cd980067 | ||
![]() |
58d9e69479 | ||
![]() |
935e9de19e | ||
![]() |
f547b4bb10 | ||
![]() |
87e40237d3 | ||
![]() |
5619f2602d | ||
![]() |
5986531bba | ||
![]() |
8ecc11c275 | ||
![]() |
81dc4949d2 | ||
![]() |
9a7d03df05 | ||
![]() |
4f5a6da280 | ||
![]() |
e4b9be6e09 | ||
![]() |
0a7e7b3a0d | ||
![]() |
e1b80abac4 | ||
![]() |
b6e8605aee | ||
![]() |
0e381e333e | ||
![]() |
8c31255012 | ||
![]() |
01cf906e18 | ||
![]() |
e55700b86b | ||
![]() |
81184cbbd7 | ||
![]() |
c00c38bc22 | ||
![]() |
ae1897e2ea | ||
![]() |
93c1cfde99 | ||
![]() |
2321f1d709 | ||
![]() |
cfd4a73a89 | ||
![]() |
04782b6a33 | ||
![]() |
5861c45fc1 | ||
![]() |
d62a452a9d | ||
![]() |
3ccb155358 | ||
![]() |
6c2ccf3869 | ||
![]() |
f02a9fa885 | ||
![]() |
0036ebfe5d | ||
![]() |
7b28f9ef57 | ||
![]() |
bd8a78eccc | ||
![]() |
9436533ddb | ||
![]() |
243f4001d1 | ||
![]() |
3bd2a9c00d | ||
![]() |
fde90ad980 | ||
![]() |
308eb34d05 | ||
![]() |
4a70ffe599 | ||
![]() |
52179d8333 | ||
![]() |
eed90b521d | ||
![]() |
166f3501c3 | ||
![]() |
29b1fca76c | ||
![]() |
8d36b66c89 | ||
![]() |
f78fb77128 | ||
![]() |
bb08cc3699 | ||
![]() |
6692607507 | ||
![]() |
6bea42c1c0 | ||
![]() |
251790f144 | ||
![]() |
4ee9ba9c96 | ||
![]() |
a71903f185 | ||
![]() |
3fe80d70c6 | ||
![]() |
9c05779fac | ||
![]() |
a6e3fd5b42 | ||
![]() |
6a3f19d575 | ||
![]() |
9b7e4d2e78 | ||
![]() |
f546e46582 | ||
![]() |
fa1f4b795b | ||
![]() |
cb1c7730cf | ||
![]() |
3a775097dd | ||
![]() |
5692dfc58a | ||
![]() |
c5f6c549ec | ||
![]() |
14a280713f | ||
![]() |
e7b6ee6cf9 | ||
![]() |
32a9aa9c3c | ||
![]() |
f57a14e3de | ||
![]() |
4018c873dc | ||
![]() |
b4ea27d28a | ||
![]() |
e5d723621f | ||
![]() |
46e7d0ab99 | ||
![]() |
d5378f50af | ||
![]() |
be9632d0ad | ||
![]() |
61cd633084 | ||
![]() |
c35b35e4f8 | ||
![]() |
bcb7172037 | ||
![]() |
3c552db548 | ||
![]() |
37982cbdaa | ||
![]() |
28a016b51d | ||
![]() |
c0bf6ee99d | ||
![]() |
f29af4618a | ||
![]() |
ee17a184c2 | ||
![]() |
6eab8ddfe1 | ||
![]() |
a7e8c6fe1f | ||
![]() |
5f2796868b | ||
![]() |
c2d08457ad | ||
![]() |
d3084ed136 | ||
![]() |
62b8977abe | ||
![]() |
b87c37032b | ||
![]() |
7932cb18f3 | ||
![]() |
706b5aaa45 | ||
![]() |
41bf96c42e | ||
![]() |
67b5d989cb | ||
![]() |
fcc9bd9bbb | ||
![]() |
825c28521e | ||
![]() |
5da1475082 | ||
![]() |
c9a244019e | ||
![]() |
2bd1910c70 | ||
![]() |
4ace508339 | ||
![]() |
926e962fc0 | ||
![]() |
caf4495cff | ||
![]() |
6b0e0dc7ae | ||
![]() |
65b0846e41 | ||
![]() |
296769ee24 | ||
![]() |
d9bdad714f | ||
![]() |
12de955a47 | ||
![]() |
a652a7e564 | ||
![]() |
611692646f | ||
![]() |
96acf5e833 | ||
![]() |
656b438002 | ||
![]() |
56b036052f | ||
![]() |
7fade8e841 | ||
![]() |
db8be03cee | ||
![]() |
372cf73548 | ||
![]() |
0213039ee7 | ||
![]() |
e8fcb3f68b | ||
![]() |
8d8df1f5bd | ||
![]() |
f40f9d8441 | ||
![]() |
8879a89490 | ||
![]() |
e4a3b3f620 | ||
![]() |
d6c8b36eeb | ||
![]() |
de86e79df2 | ||
![]() |
8d96abe730 | ||
![]() |
c021cc931c | ||
![]() |
782c3040cc | ||
![]() |
4dbe9df21e | ||
![]() |
a1fc7416e1 | ||
![]() |
bf0737a35c | ||
![]() |
00c8bf4973 | ||
![]() |
593ce462f7 | ||
![]() |
304e34002b | ||
![]() |
385465cf3f | ||
![]() |
27307b17d1 | ||
![]() |
4bdf854a9c | ||
![]() |
0162757158 | ||
![]() |
b0a882d57e | ||
![]() |
d22fb19e0e | ||
![]() |
8b134c65d1 | ||
![]() |
ee35eb1512 | ||
![]() |
ebbcc5cbdb | ||
![]() |
dbd9534bd9 | ||
![]() |
daf5480c48 | ||
![]() |
1f2c9b0c77 | ||
![]() |
a38d89cb41 | ||
![]() |
3d76e980cc | ||
![]() |
cb42bffbf9 | ||
![]() |
b2b9efebe3 | ||
![]() |
b97c5c13c1 | ||
![]() |
8c70fff02b | ||
![]() |
9cf5064a3b | ||
![]() |
af44da916a | ||
![]() |
20b40d3970 | ||
![]() |
1e0cd4f63a | ||
![]() |
04131d208b | ||
![]() |
9c35ede59a | ||
![]() |
8aedd80e1a | ||
![]() |
52bb08f4d5 | ||
![]() |
71348b7967 | ||
![]() |
3a6caeb1c5 | ||
![]() |
3f78af9a3d | ||
![]() |
31a4900765 | ||
![]() |
eb1a1c0275 | ||
![]() |
8724e0cb80 | ||
![]() |
a195fac4ca | ||
![]() |
2a2a469a1b | ||
![]() |
ac21c8b063 | ||
![]() |
5272a64be9 | ||
![]() |
3b1213a2b0 | ||
![]() |
b872a50acc | ||
![]() |
c6a1d1ea75 | ||
![]() |
36466a4ac5 | ||
![]() |
e667b4df5f | ||
![]() |
7cebc8d748 | ||
![]() |
189ae82cb7 | ||
![]() |
bf83969723 | ||
![]() |
5cb78ecd68 | ||
![]() |
41f6ca18ea | ||
![]() |
a26d628e5c | ||
![]() |
d5fef3121a | ||
![]() |
16f09794cf | ||
![]() |
26722d648d | ||
![]() |
95e3093df3 | ||
![]() |
510d550d64 | ||
![]() |
73b3762f7a | ||
![]() |
d44de49fb1 | ||
![]() |
21e3d1cc0a | ||
![]() |
1708024372 | ||
![]() |
101225aa68 | ||
![]() |
6e71409a52 | ||
![]() |
feb344e744 | ||
![]() |
494a67c9a0 | ||
![]() |
1a48dd9480 | ||
![]() |
12d842ca5a | ||
![]() |
9ac58a942e | ||
![]() |
d0ce78061c | ||
![]() |
e68599920a | ||
![]() |
58a8854009 | ||
![]() |
1e1385bc52 | ||
![]() |
ae1221d46d | ||
![]() |
9d59098015 | ||
![]() |
6fea178f5d | ||
![]() |
81edebc074 | ||
![]() |
4fc51dfe05 | ||
![]() |
241ca75204 | ||
![]() |
88f7bffc4f | ||
![]() |
1f1656a6c2 | ||
![]() |
47e44d2f9e | ||
![]() |
2afc09dad4 | ||
![]() |
95b69b7572 | ||
![]() |
1858885010 | ||
![]() |
f338066298 | ||
![]() |
d068ce472c | ||
![]() |
380b94a8d2 | ||
![]() |
dd79534de1 | ||
![]() |
fd72b2951a | ||
![]() |
48f538438d | ||
![]() |
c9995480e6 | ||
![]() |
e298333ac6 | ||
![]() |
d225e09d5d | ||
![]() |
e4f4b64cc8 | ||
![]() |
59df213e66 | ||
![]() |
691e002f90 | ||
![]() |
47ab27fd11 | ||
![]() |
0ea8931b21 | ||
![]() |
f24d376fa5 | ||
![]() |
4754462048 | ||
![]() |
7917ea02dc | ||
![]() |
abcc6c9e3e |
25
.decent_ci-Linux.yaml
Normal file
25
.decent_ci-Linux.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
compilers:
|
||||
- name: "clang"
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: AddressSanitizer
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: ThreadSanitizer
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.8"
|
||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: cppcheck
|
||||
compiler_extra_flags: --enable=all -I include --inline-suppr
|
||||
|
8
.decent_ci-MacOS.yaml
Normal file
8
.decent_ci-MacOS.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
compilers:
|
||||
- name: clang
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
- name: clang
|
||||
build_type: Debug
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
skip_packaging: true
|
||||
|
22
.decent_ci-Windows.yaml
Normal file
22
.decent_ci-Windows.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
compilers:
|
||||
- name: Visual Studio
|
||||
version: 14
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
skip_packaging: true
|
||||
- name: Visual Studio
|
||||
version: 14
|
||||
architecture: Win64
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
skip_packaging: true
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
architecture: Win64
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
|
4
.decent_ci.yaml
Normal file
4
.decent_ci.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
results_repository : ChaiScript/ChaiScript-BuildResults
|
||||
results_path : _posts
|
||||
results_base_url : https://chaiscript.github.io/ChaiScript-BuildResults
|
||||
aging_pull_requests_notification: true
|
31
.travis.yml
Normal file
31
.travis.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
env:
|
||||
- GCC_VER=4.6
|
||||
- GCC_VER=4.8
|
||||
before_install:
|
||||
- sudo pip install cpp-coveralls
|
||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -qq g++-4.8
|
||||
- if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; else export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi
|
||||
script:
|
||||
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug .
|
||||
- make -j2
|
||||
- make test
|
||||
- mkdir gcov
|
||||
- find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \;
|
||||
- $GCOV -d -o gcov gcov/*.gcda
|
||||
- coveralls -n -E ".*\.cpp"
|
||||
after_script:
|
||||
- contrib/codeanalysis/runcppcheck.sh
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- jason@emptycrate.com
|
||||
on_success: always
|
||||
on_failure: always
|
||||
env:
|
||||
global:
|
||||
secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
|
320
CMakeLists.txt
320
CMakeLists.txt
@@ -2,10 +2,74 @@ cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(chaiscript)
|
||||
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||
option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE)
|
||||
# MINGW does not yet support C++11's concurrency features
|
||||
if(MINGW)
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" FALSE)
|
||||
else()
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
||||
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
|
||||
|
||||
if(ENABLE_COVERAGE)
|
||||
add_definitions(--coverage -O0)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} --coverage")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
option(ENABLE_THREAD_SANITIZER "Enable thread sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_THREAD_SANITIZER)
|
||||
add_definitions(-fsanitize=thread -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=thread")
|
||||
endif()
|
||||
|
||||
option(ENABLE_ADDRESS_SANITIZER "Enable address sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_ADDRESS_SANITIZER)
|
||||
add_definitions(-fsanitize=address -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_MEMORY_SANITIZER)
|
||||
add_definitions(-fsanitize=memory -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=memory")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNDEFINED_SANITIZER "Enable undefined behavior sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_UNDEFINED_SANITIZER)
|
||||
add_definitions(-fsanitize=undefined -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
option(ENABLE_LTO "Enable Link Time Optimization" FALSE)
|
||||
|
||||
if (ENABLE_LTO)
|
||||
add_definitions(-flto)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
|
||||
endif()
|
||||
|
||||
option(PROFILE_GENERATE "Generate profile data" FALSE)
|
||||
if (PROFILE_GENERATE)
|
||||
add_definitions(-fprofile-generate)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-generate")
|
||||
endif()
|
||||
|
||||
option(PROFILE_USE "Use profile data" FALSE)
|
||||
if (PROFILE_USE)
|
||||
add_definitions(-fprofile-use)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-use")
|
||||
endif()
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.git")
|
||||
@@ -17,8 +81,9 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 1)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 1)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||
set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com")
|
||||
@@ -39,7 +104,9 @@ include(CPack)
|
||||
|
||||
include(cmake/CheckCXX11Features.cmake)
|
||||
|
||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||
if(NOT MINGW)
|
||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||
endif()
|
||||
|
||||
if(HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
message(STATUS "Variadic Template support detected")
|
||||
@@ -51,94 +118,130 @@ enable_testing()
|
||||
|
||||
|
||||
message(STATUS "Detecting readline support")
|
||||
if (READLINE_LIBRARY)
|
||||
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 )
|
||||
endif(READLINE_LIBRARY)
|
||||
if(READLINE_LIBRARY)
|
||||
message(STATUS "Found: ${READLINE_LIBRARY}")
|
||||
set(READLINE_LIB readline)
|
||||
add_definitions(/DREADLINE_AVAILABLE)
|
||||
else()
|
||||
message(STATUS "Not Found")
|
||||
set(READLINE_LIB)
|
||||
set(READLINE_FLAG)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
|
||||
if(GCC_VERSION VERSION_LESS 4.8)
|
||||
set(CPP11_FLAG "-std=c++0x")
|
||||
else()
|
||||
set(CPP11_FLAG "-std=c++11")
|
||||
endif()
|
||||
else()
|
||||
set(CPP11_FLAG "-std=c++11")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(/W4)
|
||||
if(CMAKE_CL_64)
|
||||
add_definitions(/bigobj)
|
||||
endif()
|
||||
add_definitions(/W4 /w44640)
|
||||
add_definitions(/bigobj)
|
||||
# Note on MSVC compiler flags.
|
||||
# The code base selective disables warnings as necessary when the compiler is complaining too much
|
||||
# about something that is perfectly valid, or there is simply no technical way around it
|
||||
# This particular warning, C4503 is in regards to the decorated names that MSVC generates internally.
|
||||
# The error did not come up until the move to C++11, but the compiler doesn't give enough information
|
||||
# to determine where the error is coming from, and the internet provides no real information for
|
||||
# how to workaround or fix the error. So I'm disabling it globally.
|
||||
add_definitions(/wd4503)
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic -std=c++0x)
|
||||
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic ${CPP11_FLAG})
|
||||
|
||||
if (APPLE)
|
||||
if(APPLE)
|
||||
add_definitions(-Wno-sign-compare)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER MATCHES ".*clang")
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
option(USE_LIBCXX "Use clang's libcxx" TRUE)
|
||||
|
||||
if (USE_LIBCXX)
|
||||
if(USE_LIBCXX)
|
||||
add_definitions(-stdlib=libc++)
|
||||
set (EXTRA_LINKER_FLAGS -std=c++0x -stdlib=libc++)
|
||||
else ()
|
||||
set (EXTRA_LINKER_FLAGS -std=c++0x )
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG} -stdlib=libc++")
|
||||
else()
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
|
||||
endif()
|
||||
else()
|
||||
set (EXTRA_LINKER_FLAGS )
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
|
||||
endif()
|
||||
|
||||
# limitations in MinGW require us to make an optimized build
|
||||
# for the sake of object sizes or something
|
||||
if(MINGW OR CYGWIN)
|
||||
add_definitions(-O3)
|
||||
endif()
|
||||
|
||||
include_directories(include)
|
||||
|
||||
|
||||
set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/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(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
else()
|
||||
if(NOT MULTITHREAD_SUPPORT_ENABLED)
|
||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||
endif()
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
list(APPEND LIBS "dl")
|
||||
if(CMAKE_HOST_UNIX)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
list(APPEND LIBS "dl")
|
||||
endif()
|
||||
|
||||
if(MULTITHREAD_SUPPORT_ENABLED)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE GCC_FULL_VERSION)
|
||||
if(GCC_FULL_VERSION MATCHES "4.8.1.*ubuntu")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--no-as-needed -pthread")
|
||||
else()
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -pthread")
|
||||
endif()
|
||||
else()
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -pthread")
|
||||
endif()
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
list(APPEND LIBS "pthread")
|
||||
add_definitions(-pthread)
|
||||
endif()
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
list(APPEND LIBS ${READLINE_LIB})
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
|
||||
if (CMAKE_COMPILER_2005)
|
||||
# vs2005 is a bit too loud about possible loss of data warnings
|
||||
# ADD_DEFINITIONS(/wd4244)
|
||||
endif()
|
||||
|
||||
add_library(chaiscript_stdlib MODULE src/chaiscript_stdlib.cpp)
|
||||
target_link_libraries(chaiscript_stdlib ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib.cpp)
|
||||
target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
||||
target_link_libraries(chai ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_dependencies(chai chaiscript_stdlib)
|
||||
target_link_libraries(chai ${LIBS})
|
||||
add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
|
||||
|
||||
if (BUILD_SAMPLES)
|
||||
if(BUILD_SAMPLES)
|
||||
add_executable(example samples/example.cpp)
|
||||
target_link_libraries(example ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(example ${LIBS})
|
||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||
target_link_libraries(memory_leak_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
add_executable(inheritance samples/inheritance.cpp)
|
||||
target_link_libraries(inheritance ${LIBS})
|
||||
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
||||
target_link_libraries(fun_call_performance ${LIBS})
|
||||
endif()
|
||||
|
||||
|
||||
if (BUILD_MODULES)
|
||||
if(BUILD_MODULES)
|
||||
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||
target_link_libraries(stl_extra ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(stl_extra ${LIBS})
|
||||
|
||||
add_library(reflection MODULE src/reflection.cpp)
|
||||
target_link_libraries(reflection ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
set(MODULES stl_extra reflection)
|
||||
set(MODULES stl_extra)
|
||||
endif()
|
||||
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||
@@ -148,60 +251,77 @@ list(SORT UNIT_TESTS)
|
||||
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)
|
||||
|
||||
set_property(TEST ${UNIT_TESTS}
|
||||
PROPERTY ENVIRONMENT
|
||||
add_test(version_check chai -c "if(\"\\\${ version() };\\\${version_major()};\\\${version_minor()};\\\${version_patch()}\" != \"${CHAI_VERSION};${CPACK_PACKAGE_VERSION_MAJOR};${CPACK_PACKAGE_VERSION_MINOR};${CPACK_PACKAGE_VERSION_PATCH}\") { exit(-1) }")
|
||||
set_property(TEST version_check
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
|
||||
if (NOT UNIT_TEST_LIGHT)
|
||||
|
||||
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()
|
||||
|
||||
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)
|
||||
# commented out because uniform initializer syntax is not working properly in MSVC 2013
|
||||
add_executable(utility_test unittests/utility_test.cpp)
|
||||
target_link_libraries(utility_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(utility_test ${LIBS})
|
||||
add_test(NAME Utility_Test COMMAND utility_test)
|
||||
|
||||
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
|
||||
target_link_libraries(dynamic_object_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(dynamic_object_test ${LIBS})
|
||||
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
|
||||
|
||||
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
|
||||
target_link_libraries(functor_creation_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(functor_creation_test ${LIBS})
|
||||
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
|
||||
|
||||
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
|
||||
target_link_libraries(functor_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(functor_cast_test ${LIBS})
|
||||
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
|
||||
|
||||
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
|
||||
target_link_libraries(boxed_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(boxed_cast_test ${LIBS})
|
||||
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
|
||||
|
||||
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
|
||||
target_link_libraries(object_lifetime_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(object_lifetime_test ${LIBS})
|
||||
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
|
||||
|
||||
add_executable(object_lifetime_test2 unittests/object_lifetime_test2.cpp)
|
||||
target_link_libraries(object_lifetime_test2 ${LIBS})
|
||||
add_test(NAME Object_Lifetime_Test2 COMMAND object_lifetime_test2)
|
||||
|
||||
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
|
||||
target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(function_ordering_test ${LIBS})
|
||||
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
|
||||
|
||||
add_executable(type_info_test unittests/type_info_test.cpp)
|
||||
target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(type_info_test ${LIBS})
|
||||
add_test(NAME Type_Info_Test COMMAND type_info_test)
|
||||
|
||||
add_executable(type_name_test unittests/type_name_test.cpp)
|
||||
target_link_libraries(type_name_test ${LIBS})
|
||||
add_test(NAME Type_Name_Test COMMAND type_name_test)
|
||||
|
||||
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS})
|
||||
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
|
||||
|
||||
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
|
||||
target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(short_comparison_test ${LIBS})
|
||||
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
|
||||
|
||||
add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp)
|
||||
target_link_libraries(cpp_lambda_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(cpp_lambda_test ${LIBS})
|
||||
add_test(NAME cpp_lambda_test COMMAND cpp_lambda_test)
|
||||
|
||||
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
|
||||
@@ -214,7 +334,11 @@ if(BUILD_TESTING)
|
||||
|
||||
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_test(NAME Simultaneous_ChaiScript_Test COMMAND simultaneous_chaiscript_test)
|
||||
|
||||
add_executable(heap_allocated_chaiscript_test unittests/heap_allocated_chaiscript_test.cpp)
|
||||
target_link_libraries(heap_allocated_chaiscript_test ${LIBS})
|
||||
add_test(NAME Heap_Allocated_ChaiScript_Test COMMAND heap_allocated_chaiscript_test)
|
||||
|
||||
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
|
||||
target_link_libraries(c_linkage_test ${LIBS})
|
||||
@@ -224,7 +348,11 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(integer_literal_test ${LIBS})
|
||||
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp)
|
||||
target_link_libraries(arithmetic_conversions_test ${LIBS})
|
||||
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_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)
|
||||
@@ -232,40 +360,44 @@ if(BUILD_TESTING)
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
|
||||
unittests/multifile_test_module.cpp)
|
||||
target_link_libraries(multifile_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
add_test(NAME MultiFile_Test COMMAND multifile_test)
|
||||
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(test_module ${LIBS})
|
||||
|
||||
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||
endif()
|
||||
endif(BUILD_TESTING)
|
||||
endif()
|
||||
|
||||
install(TARGETS chai chaiscript_stdlib-${CHAI_VERSION} ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||
|
||||
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
|
||||
install(DIRECTORY include/chaiscript DESTINATION include
|
||||
PATTERN "*.hpp"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
PATTERN "*.hpp"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
install(DIRECTORY unittests DESTINATION share/chaiscript
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*.inc"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*.inc"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
install(DIRECTORY samples DESTINATION share/chaiscript
|
||||
PATTERN "*.chai"
|
||||
PATTERN "*/.svn*" EXCLUDE
|
||||
PATTERN "*/.git*" EXCLUDE
|
||||
PATTERN "*~" EXCLUDE)
|
||||
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"
|
||||
|
1861
Doxyfile.in
1861
Doxyfile.in
File diff suppressed because it is too large
Load Diff
10
contrib/codeanalysis/heterogenous_array_loop.chai
Normal file
10
contrib/codeanalysis/heterogenous_array_loop.chai
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
var my_array=["1", 4, 6.6l, 10ul, "1000", 100, 10.9f ];
|
||||
|
||||
for (var j = 0; j < 10000; ++j)
|
||||
{
|
||||
for (var i = 0; i < 6; ++i)
|
||||
{
|
||||
to_string(my_array[i]);
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
def isprime(n)
|
||||
{
|
||||
for (auto i = 2; i < n; ++i)
|
||||
for (var i = 2; i < n; ++i)
|
||||
{
|
||||
if (n % i == 0) {return false}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ def isprime(n)
|
||||
|
||||
def primes(n)
|
||||
{
|
||||
auto count = 0
|
||||
for (auto i = 2; i <= n; ++i)
|
||||
var count = 0
|
||||
for (var i = 2; i <= n; ++i)
|
||||
{
|
||||
if (isprime(i)) {++count}
|
||||
}
|
||||
@@ -21,6 +21,6 @@ def primes(n)
|
||||
}
|
||||
|
||||
|
||||
auto N = 5000
|
||||
var N = 5000
|
||||
|
||||
print("primes: " + primes(N).to_string())
|
||||
|
16
contrib/codeanalysis/runcppcheck.sh
Executable file
16
contrib/codeanalysis/runcppcheck.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
pushd ..
|
||||
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
|
||||
tar -xvf cppcheck-1.66.tar.bz2
|
||||
cd cppcheck-1.66
|
||||
CXX=g++-4.8 make -j2
|
||||
popd
|
||||
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
|
||||
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
|
||||
echo -n '{ "body": " ' > output.json
|
||||
echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json
|
||||
echo -n '"}' >> output.json
|
||||
if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; else curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/issues/${TRAVIS_PULL_REQUEST}/comments; fi
|
||||
|
||||
|
@@ -38,7 +38,7 @@
|
||||
************************************************************************************/
|
||||
|
||||
$language_data = array (
|
||||
'LANG_NAME' => 'Chaiscript',
|
||||
'LANG_NAME' => 'ChaiScript',
|
||||
'COMMENT_SINGLE' => array(1 => '//'),
|
||||
'COMMENT_MULTI' => array('/*' => '*/'),
|
||||
//Regular Expressions
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_HPP_
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
|
||||
|
||||
/// \mainpage
|
||||
/// <a href="http://www.chaiscript.com">ChaiScript</a> is a scripting language designed specifically for integration with C++. It provides
|
||||
/// @mainpage
|
||||
/// [ChaiScript](http://www.chaiscript.com") is a scripting language designed specifically for integration with C++. It provides
|
||||
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
|
||||
///
|
||||
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
|
||||
@@ -18,42 +18,42 @@
|
||||
///
|
||||
/// The end user parts of the API are extremely simple both in size and ease of use.
|
||||
///
|
||||
/// Currently, all source control and project management aspects of ChaiScript occur on <a href="http://www.github.com/ChaiScript/ChaiScript">github</a>.
|
||||
/// Currently, all source control and project management aspects of ChaiScript occur on [github](http://www.github.com/ChaiScript/ChaiScript").
|
||||
///
|
||||
/// <hr>
|
||||
/// ------------------------------------------------------------
|
||||
///
|
||||
/// \sa chaiscript
|
||||
/// \sa chaiscript::ChaiScript
|
||||
/// \sa ChaiScript_Language for Built in Functions
|
||||
/// \sa \ref LangGettingStarted
|
||||
/// \sa \ref LangKeywordRef
|
||||
/// \sa \ref LangInPlaceRef
|
||||
/// \sa \ref LangObjectSystemRef
|
||||
/// \sa http://www.chaiscript.com
|
||||
/// \sa http://www.github.com/ChaiScript/ChaiScript
|
||||
/// @sa chaiscript
|
||||
/// @sa chaiscript::ChaiScript
|
||||
/// @sa ChaiScript_Language for Built in Functions
|
||||
/// @sa @ref LangGettingStarted
|
||||
/// @sa @ref LangKeywordRef
|
||||
/// @sa @ref LangInPlaceRef
|
||||
/// @sa @ref LangObjectSystemRef
|
||||
/// @sa http://www.chaiscript.com
|
||||
/// @sa http://www.github.com/ChaiScript/ChaiScript
|
||||
///
|
||||
/// <hr>
|
||||
/// -----------------------------------------------------------
|
||||
///
|
||||
/// \section gettingstarted API 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
|
||||
/// \li \ref functionobjects
|
||||
/// \li \ref threading
|
||||
/// \li \ref exceptions
|
||||
/// - @ref basics
|
||||
/// - @ref compiling
|
||||
/// - @ref eval
|
||||
/// - @ref adding_items
|
||||
/// - @ref operatoroverloading
|
||||
/// - @ref add_class
|
||||
/// - @ref pointer_conversions
|
||||
/// - @ref baseclasses
|
||||
/// - @ref functionobjects
|
||||
/// - @ref threading
|
||||
/// - @ref exceptions
|
||||
///
|
||||
///
|
||||
/// \subsection basics Basics
|
||||
/// @subsection basics Basics
|
||||
///
|
||||
/// Basic simple example:
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~{.cpp}
|
||||
/// //main.cpp
|
||||
/// #include <chaiscript/chaiscript.hpp>
|
||||
///
|
||||
@@ -69,111 +69,115 @@
|
||||
///
|
||||
/// double d = chai.eval<double>("function(3, 4.75);");
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection compiling Compiling ChaiScript Applications
|
||||
/// ------------------------------------------------------
|
||||
///
|
||||
/// ChaiScript is a header only library with only one dependecy: The
|
||||
/// @subsection compiling Compiling ChaiScript Applications
|
||||
///
|
||||
/// ChaiScript is a header only library with only one dependency: The
|
||||
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
||||
///
|
||||
/// \subsubsection compilinggcc Compiling with GCC
|
||||
/// @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
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// ------------------------------------------
|
||||
///
|
||||
/// @subsection eval Evaluating Scripts
|
||||
///
|
||||
/// Scripts can be evaluated with the () operator, eval method or eval_file method.
|
||||
///
|
||||
/// \subsubsection parenoperator () Operator
|
||||
/// @subsubsection parenoperator () Operator
|
||||
///
|
||||
/// operator() can be used as a handy shortcut for evaluating ChaiScript snippets.
|
||||
/// \code
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai("print(\"hello world\")");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa chaiscript::ChaiScript::operator()(const std::string &)
|
||||
///
|
||||
/// \subsubsection evalmethod Method 'eval'
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai("print(@"hello world@")");
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// The eval method is somewhat more verbose and can be used to get typesafely return values
|
||||
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
|
||||
///
|
||||
/// @subsubsection evalmethod Method 'eval'
|
||||
///
|
||||
/// The eval method is somewhat more verbose and can be used to get type safely return values
|
||||
/// from the script.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.eval("callsomefunc()");
|
||||
/// int result = chai.eval<int>("1 + 3");
|
||||
/// // result now equals 4
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa chaiscript::ChaiScript::eval
|
||||
/// @sa chaiscript::ChaiScript::eval
|
||||
///
|
||||
/// \subsubsection evalfilemethod Method 'eval_file'
|
||||
/// @subsubsection evalfilemethod Method 'eval_file'
|
||||
///
|
||||
/// The 'eval_file' method loads a file from disk and executes the script in it
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.eval_file("myfile.chai");
|
||||
/// std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa chaiscript::ChaiScript::eval_file
|
||||
/// @sa chaiscript::ChaiScript::eval_file
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection addingitems Adding Items to ChaiScript
|
||||
/// --------------------------------------------------
|
||||
///
|
||||
/// @subsection adding_items Adding Items to ChaiScript
|
||||
///
|
||||
/// ChaiScript supports 4 basic things that can be added: objects, functions, type infos and Modules
|
||||
///
|
||||
/// \subsubsection addingobjects Adding Objects
|
||||
/// @subsubsection adding_objects Adding Objects
|
||||
///
|
||||
/// 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
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// using namespace chaiscript;
|
||||
/// ChaiScript chai;
|
||||
/// int i = 5;
|
||||
/// chai.add(var(i), "i");
|
||||
/// chai("print(i)");
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// Immutable objects can be created with the chaiscript::const_var function.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// chai.add(const_var(i), "i");
|
||||
/// chai("i = 5"); // exception throw, cannot assign const var
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// Named variables can only be accessed from the context they are created in.
|
||||
/// If you want a global variable, it must be const, and created with the
|
||||
/// chaiscript::ChaiScript::add_global_const function.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// chai.add_global_const(const_var(i), "i");
|
||||
/// chai("def somefun() { print(i); }; sumfun();");
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// \subsubsection addingfunctions Adding Functions
|
||||
/// @subsubsection adding_functions Adding Functions
|
||||
///
|
||||
/// Functions, methods and members are all added using the same function: chaiscript::fun.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// using namespace chaiscript;
|
||||
///
|
||||
/// class MyClass {
|
||||
@@ -190,26 +194,26 @@
|
||||
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
||||
/// chai.add(fun(&MyClass::method), "method");
|
||||
/// chai.add(fun(&MyClass::staticmethod), "staticmethod");
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// 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.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// MyClass obj;
|
||||
/// chai.add(fun(&MyClass::method, &obj), "method");
|
||||
/// chai("method()"); // equiv to obj.method()
|
||||
/// chai.add(fun(&MyClass::method2, &obj, 3), "method2");
|
||||
/// chai("method2()"); // equiv to obj.method2(3)
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// \subsubsection addingtypeinfo Adding Type Info
|
||||
/// @subsubsection addingtypeinfo Adding Type Info
|
||||
///
|
||||
/// ChaiScript will automatically support any type implicitly provided to it in the form
|
||||
/// of objects and function parameters / return types. However, it can be nice to let ChaiScript
|
||||
@@ -219,27 +223,28 @@
|
||||
///
|
||||
/// Continuing with the example "MyClass" from above:
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// chai.add(user_type<MyClass>(), "MyClass");
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \subsubsection addingmodules Adding Modules
|
||||
/// @subsubsection adding_modules Adding Modules
|
||||
///
|
||||
/// Modules are holders for collections of ChaiScript registrations.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// ModulePtr module = get_sum_module();
|
||||
/// chai.add(module);
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa chaiscript::Module
|
||||
/// @sa chaiscript::Module
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection operatoroverloading Operator Overloading
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @subsection operatoroverloading Operator Overloading
|
||||
///
|
||||
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// class MyClass {
|
||||
/// MyClass operator+(const MyClass &) const;
|
||||
/// };
|
||||
@@ -254,17 +259,18 @@
|
||||
/// }
|
||||
///
|
||||
/// chai.add(fun(append_string_int), "+");
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
/// @sa @ref adding_functions
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection helpermacro Class Helper Macro
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @subsection add_class Class Helper Utility
|
||||
///
|
||||
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
|
||||
/// of the CHAISCRIPT_CLASS helper macro.
|
||||
/// of the add_class helper utility.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// class Test
|
||||
/// {
|
||||
/// public:
|
||||
@@ -277,40 +283,40 @@
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
///
|
||||
/// chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||
///
|
||||
/// CHAISCRIPT_CLASS( m,
|
||||
/// Test,
|
||||
/// (Test ())
|
||||
/// (Test (const Test &)),
|
||||
/// ((function))
|
||||
/// ((function2))
|
||||
/// ((function3))
|
||||
/// ((functionOverload)(std::string (Test::*)(double)))
|
||||
/// ((functionOverload)(std::string (Test::*)(int)))
|
||||
/// ((operator=))
|
||||
/// );
|
||||
///
|
||||
/// chaiscript::utility::add_class<chaiscript::Test>(*m,
|
||||
/// "Test",
|
||||
/// { constructor<Test()>(),
|
||||
/// constructor<Test(const Test &)>() },
|
||||
/// { {fun(&Test::function), "function"},
|
||||
/// {fun(&Test::function2), "function2"},
|
||||
/// {fun(&Test::function2), "function3"}
|
||||
/// {fun(static_cast<std::string Test::*(double)>(&Test::functionOverload)), "functionOverload"}
|
||||
/// {fun(static_cast<std::string Test::*(int)>(&Test::functionOverload)), "functionOverload"} }
|
||||
/// );
|
||||
///
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(m);
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa \ref addingmodules
|
||||
/// @sa @ref adding_modules
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection pointerconversions Pointer / Object Conversions
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @subsection pointer_conversions Pointer / Object Conversions
|
||||
///
|
||||
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
|
||||
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
|
||||
///
|
||||
/// 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).
|
||||
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted 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.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// void fun1(const int *);
|
||||
/// void fun2(int *);
|
||||
/// void fun3(int);
|
||||
@@ -350,18 +356,19 @@
|
||||
/// chai("fun9(i)");
|
||||
/// chai("fun10(i)");
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
|
||||
/// available and tested.
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection baseclasses Base Classes
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @subsection baseclasses Base Classes
|
||||
///
|
||||
/// ChaiScript supports handling of passing a derived class object to a function expecting a base class object.
|
||||
/// For the process to work, the base/derived relationship must be registered with the engine.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// class Base {};
|
||||
/// class Derived : public Base {};
|
||||
/// void myfunction(Base *b);
|
||||
@@ -375,16 +382,17 @@
|
||||
/// chai.add(chaiscript::fun(&myfunction), "myfunction");
|
||||
/// chai("myfunction(d)");
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// <hr>
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// \subsection functionobjects Function Objects
|
||||
///
|
||||
/// Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion
|
||||
/// @subsection functionobjects Function Objects
|
||||
///
|
||||
/// Functions are first class objects in ChaiScript and ChaiScript supports automatic conversion
|
||||
/// between ChaiScript functions and std::function objects.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// void callafunc(const std::function<void (const std::string &)> &t_func)
|
||||
/// {
|
||||
/// t_func("bob");
|
||||
@@ -400,11 +408,12 @@
|
||||
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
|
||||
/// f(); // call the ChaiScript function dump_system, from C++
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// <hr>
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// \subsection threading Threading
|
||||
///
|
||||
/// @subsection threading Threading
|
||||
///
|
||||
/// Thread safety is automatically handled within the ChaiScript system. Objects can be added
|
||||
/// and scripts executed from multiple threads. For each thread that executes scripts, a new
|
||||
@@ -414,16 +423,17 @@
|
||||
///
|
||||
/// Disabling thread safety increases performance in many cases.
|
||||
///
|
||||
/// <hr>
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// \subsection exceptions Exception Handling
|
||||
///
|
||||
/// @subsection exceptions Exception Handling
|
||||
///
|
||||
/// \subsubsection exceptionsbasics Exception Handling Basics
|
||||
/// @subsubsection exceptionsbasics Exception Handling Basics
|
||||
///
|
||||
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
|
||||
/// ChaiScript.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// void throwexception()
|
||||
/// {
|
||||
/// throw std::runtime_error("err");
|
||||
@@ -444,19 +454,19 @@
|
||||
/// // i == 1
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
|
||||
/// @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
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// chaiscript::ChaiScript chai;
|
||||
///
|
||||
/// try {
|
||||
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
/// 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) {
|
||||
@@ -464,19 +474,19 @@
|
||||
/// } 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
|
||||
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
|
||||
/// @sa chaiscript::exception_specification
|
||||
|
||||
|
||||
|
||||
/// \page LangObjectSystemRef ChaiScript Language Object Model Reference
|
||||
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
|
||||
///
|
||||
///
|
||||
/// ChaiScript has an object system built in, for types defined within the ChaiScript system.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~
|
||||
/// attr Rectangle::height
|
||||
/// attr Rectangle::width
|
||||
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
|
||||
@@ -485,67 +495,84 @@
|
||||
/// var rect = Rectangle()
|
||||
/// rect.height = 30
|
||||
/// print(rect.area())
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// \sa \ref keywordattr
|
||||
/// \sa \ref keyworddef
|
||||
/// Since ChaiScript 5.4.0 it has been possible to use the "class" keyword to simplify this code.
|
||||
///
|
||||
/// ~~~~~~~~~
|
||||
/// class Rectangle {
|
||||
/// attr height
|
||||
/// attr width
|
||||
/// def Rectangle() { this.height = 10; this.width = 20 }
|
||||
/// def area() { this.height * this.width }
|
||||
/// }
|
||||
///
|
||||
/// var rect = Rectangle()
|
||||
/// rect.height = 30
|
||||
/// print(rect.area())
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// @sa @ref keywordattr
|
||||
/// @sa @ref keyworddef
|
||||
|
||||
/// \page LangInPlaceRef ChaiScript Language In-Place Creation Reference
|
||||
/// \section inplacevector Vector
|
||||
/// @page LangInPlaceRef ChaiScript Language In-Place Creation Reference
|
||||
/// @section inplacevector Vector
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~
|
||||
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// \section inplacerangedvector Ranged Vector
|
||||
/// @section inplacerangedvector Ranged Vector
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~~
|
||||
/// In-place Ranged Vector ::= "[" value ".." value "]"
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// Creates a vector over a range (eg. 1..10)
|
||||
///
|
||||
/// \section inplacemap Map
|
||||
/// @section inplacemap Map
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// In-place Map ::= "[" (string ":" expression)+ "]"
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
|
||||
/// \page LangGettingStarted ChaiScript Language Getting Started
|
||||
/// @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
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @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
|
||||
/// @sa @ref keywordfor
|
||||
/// @sa @ref keywordwhile
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptifs Conditionals
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section chaiscriptifs Conditionals
|
||||
///
|
||||
/// If statements work as expected
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// var b = true;
|
||||
///
|
||||
/// if (b) {
|
||||
@@ -555,103 +582,109 @@
|
||||
/// } else {
|
||||
/// // or do this
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa \ref keywordif
|
||||
/// @sa @ref keywordif
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptfunctions Functions
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @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
|
||||
/// @sa @ref keyworddef
|
||||
/// @sa @ref keywordattr
|
||||
/// @sa @ref LangObjectSystemRef
|
||||
///
|
||||
/// <hr>
|
||||
/// \section chaiscriptfunctionobjects Function Objects
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @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);
|
||||
/// eval> def do_something(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
|
||||
/// eval> callfunc(do_something, 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
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @sa @ref LangKeywordRef
|
||||
/// @sa ChaiScript_Language for Built in Functions
|
||||
|
||||
|
||||
/// \page LangKeywordRef ChaiScript Language Keyword Reference
|
||||
/// @page LangKeywordRef ChaiScript Language Keyword Reference
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordattr attr
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordattr attr
|
||||
/// Defines a ChaiScript object attribute
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// Attribute Definition ::= "attr" class_name "::" attribute_name
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa \ref LangObjectSystemRef
|
||||
/// @sa @ref LangObjectSystemRef
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordbreak break
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordbreak break
|
||||
/// Stops execution of a looping block.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// Break Statement ::= "break"
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa \ref keywordfor
|
||||
/// \sa \ref keywordwhile
|
||||
/// @sa @ref keywordfor
|
||||
/// @sa @ref keywordwhile
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keyworddef def
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keyworddef def
|
||||
/// Begins a function or method definition
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [arg ("," arg)*] ")" [":" guard] block
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// annotation: meta-annotation on function, currently used as documentation. Optional.
|
||||
/// identifier: name of function. Required.
|
||||
@@ -667,50 +700,56 @@
|
||||
/// Method definitions for known types extend those types with new methods. This includes C++ and ChaiScript defined types.
|
||||
/// Method definitions for unknown types implicitly define the named type.
|
||||
///
|
||||
/// \sa \ref LangObjectSystemRef
|
||||
/// @sa @ref LangObjectSystemRef
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordelse else
|
||||
/// \sa \ref keywordif
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordelse else
|
||||
/// @sa @ref keywordif
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordfor for
|
||||
/// \code
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordfor for
|
||||
/// ~~~~~~~~
|
||||
/// For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block
|
||||
/// \endcode
|
||||
/// This loop can be broken using the \ref keywordbreak command.
|
||||
/// ~~~~~~~~
|
||||
/// This loop can be broken using the @ref keywordbreak command.
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordfun fun
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordfun fun
|
||||
/// Begins an anonymous function declaration (sometimes called a lambda).
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// Lambda ::= "fun" "(" [variable] ("," variable)* ")" block
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \b Examples:
|
||||
/// _Example_
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// // Generate an anonymous function object that adds 2 to its parameter
|
||||
/// var f = fun(x) { x + 2; }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa \ref keyworddef for more details on ChaiScript functions
|
||||
/// @sa @ref keyworddef for more details on ChaiScript functions
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordif if
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordif if
|
||||
/// Begins a conditional block of code that only executes if the condition evaluates as true.
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// If Block ::= "if" "(" condition ")" block
|
||||
/// Else If Block ::= "else if" "(" condition ")" block
|
||||
/// Else Block ::= "else" block
|
||||
/// \endcode
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// _Example_
|
||||
///
|
||||
/// ~~~~~~~~
|
||||
/// if (true) {
|
||||
/// // do something
|
||||
/// } else if (false) {
|
||||
@@ -718,35 +757,38 @@
|
||||
/// } else {
|
||||
/// // otherwise do this
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordtry try
|
||||
/// \code
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordtry try
|
||||
/// ~~~~~~~~
|
||||
/// Try Block ::= "try" block
|
||||
/// ("catch" ["(" variable ")"] [":" guards] block)+
|
||||
/// ["finally" block]
|
||||
/// \endcode
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa ChaiScript_Language::throw
|
||||
/// @sa ChaiScript_Language::throw
|
||||
///
|
||||
/// <hr>
|
||||
/// \section keywordwhile while
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordwhile while
|
||||
///
|
||||
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~
|
||||
/// While Block ::= "while" "(" condition ")" block
|
||||
/// \endcode
|
||||
/// This loop can be broken using the \ref keywordbreak command.
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// This loop can be broken using the @ref keywordbreak command.
|
||||
|
||||
|
||||
/// \namespace chaiscript
|
||||
/// \brief Namespace chaiscript contains every API call that the average user will be concerned with.
|
||||
/// @namespace chaiscript
|
||||
/// @brief Namespace chaiscript contains every API call that the average user will be concerned with.
|
||||
|
||||
/// \namespace chaiscript::detail
|
||||
/// \brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
||||
/// @namespace chaiscript::detail
|
||||
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||
@@ -9,13 +9,25 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CHAISCRIPT_MSVC _MSC_VER
|
||||
#define CHAISCRIPT_HAS_DECLSPEc
|
||||
#define CHAISCRIPT_HAS_DECLSPEC
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define CHAISCRIPT_WINDOWS
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
/// Currently only g++>=4.8supports this natively
|
||||
/// \todo Make this support other compilers when possible
|
||||
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__)
|
||||
#define CHAISCRIPT_OVERRIDE override
|
||||
#else
|
||||
#define CHAISCRIPT_OVERRIDE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
@@ -23,6 +35,19 @@
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#define CHAISCRIPT_NOEXCEPT throw()
|
||||
#define CHAISCRIPT_CONSTEXPR
|
||||
#else
|
||||
#define CHAISCRIPT_NOEXCEPT noexcept
|
||||
#define CHAISCRIPT_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
namespace chaiscript {
|
||||
static const int version_major = 5;
|
||||
static const int version_minor = 5;
|
||||
static const int version_patch = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -7,11 +7,19 @@
|
||||
#ifndef CHAISCRIPT_STDLIB_HPP_
|
||||
#define CHAISCRIPT_STDLIB_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
#include "dispatchkit/boxed_value.hpp"
|
||||
|
||||
/// \file
|
||||
/// @file
|
||||
///
|
||||
/// This file generates the standard library that normal ChaiScript usage requires.
|
||||
|
||||
@@ -38,7 +46,5 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||
@@ -64,16 +64,59 @@ namespace chaiscript
|
||||
|
||||
using std::recursive_mutex;
|
||||
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
|
||||
/// 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(void *t_key)
|
||||
: m_key(t_key)
|
||||
{
|
||||
}
|
||||
|
||||
~Thread_Storage()
|
||||
{
|
||||
t().erase(m_key);
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
{
|
||||
return &(t()[m_key]);
|
||||
}
|
||||
|
||||
inline T &operator*() const
|
||||
{
|
||||
return t()[m_key];
|
||||
}
|
||||
|
||||
void *m_key;
|
||||
|
||||
private:
|
||||
static std::unordered_map<void*, T> &t()
|
||||
{
|
||||
thread_local static std::unordered_map<void *, T> my_t;
|
||||
return my_t;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// This version is used if the compiler does not support thread_local
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
|
||||
Thread_Storage(void *)
|
||||
{
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
{
|
||||
return get_tls().get();
|
||||
@@ -88,40 +131,33 @@ namespace chaiscript
|
||||
private:
|
||||
std::shared_ptr<T> get_tls() const
|
||||
{
|
||||
|
||||
unique_lock<mutex> lock(m_mutex);
|
||||
|
||||
|
||||
auto itr = m_instances.find(std::this_thread::get_id());
|
||||
|
||||
if (itr != m_instances.end()) { return itr->second; }
|
||||
|
||||
|
||||
std::shared_ptr<T> new_instance(new T());
|
||||
|
||||
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
|
||||
|
||||
return new_instance;
|
||||
|
||||
|
||||
/*
|
||||
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;
|
||||
};
|
||||
#endif // threading enabled but no tls
|
||||
|
||||
#else
|
||||
#else // threading disabled
|
||||
template<typename T>
|
||||
class unique_lock
|
||||
{
|
||||
public:
|
||||
unique_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -129,6 +165,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
shared_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
@@ -148,6 +185,10 @@ namespace chaiscript
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
Thread_Storage(void *)
|
||||
{
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
{
|
||||
return &obj;
|
||||
|
@@ -7,6 +7,8 @@
|
||||
#ifndef CHAISCRIPT_ANY_HPP_
|
||||
#define CHAISCRIPT_ANY_HPP_
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
namespace exception
|
||||
@@ -19,15 +21,15 @@ namespace chaiscript {
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_any_cast() noexcept
|
||||
bad_any_cast() CHAISCRIPT_NOEXCEPT
|
||||
: m_what("bad any cast")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_any_cast() noexcept {}
|
||||
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
virtual const char * what() const noexcept
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
@@ -42,40 +44,52 @@ namespace chaiscript {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
Data(const std::type_info &t_type)
|
||||
: m_type(t_type)
|
||||
{
|
||||
}
|
||||
|
||||
Data &operator=(const Data &) = delete;
|
||||
|
||||
virtual ~Data() {}
|
||||
|
||||
virtual void *data() = 0;
|
||||
virtual const std::type_info &type() const = 0;
|
||||
virtual std::shared_ptr<Data> clone() const = 0;
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<Data> clone() const = 0;
|
||||
const std::type_info &m_type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
Data_Impl(const T &t_type)
|
||||
: m_type(typeid(T)),
|
||||
m_data(t_type)
|
||||
explicit Data_Impl(T t_type)
|
||||
: Data(typeid(T)),
|
||||
m_data(std::move(t_type))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void *data()
|
||||
virtual ~Data_Impl() {}
|
||||
|
||||
virtual void *data() CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
const std::type_info &type() const
|
||||
std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_type;
|
||||
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
|
||||
}
|
||||
|
||||
std::shared_ptr<Data> clone() const
|
||||
{
|
||||
return std::shared_ptr<Data>(new Data_Impl<T>(m_data));
|
||||
}
|
||||
Data_Impl &operator=(const Data_Impl&) = delete;
|
||||
|
||||
const std::type_info &m_type;
|
||||
T m_data;
|
||||
};
|
||||
|
||||
std::shared_ptr<Data> m_data;
|
||||
std::unique_ptr<Data> m_data;
|
||||
|
||||
public:
|
||||
// construct/copy/destruct
|
||||
@@ -91,12 +105,19 @@ namespace chaiscript {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any(const ValueType &t_value)
|
||||
#if _MSC_VER != 1800
|
||||
Any(Any &&) = default;
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
#endif
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<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);
|
||||
@@ -104,13 +125,6 @@ namespace chaiscript {
|
||||
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
|
||||
{
|
||||
@@ -120,7 +134,6 @@ namespace chaiscript {
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -131,9 +144,7 @@ namespace chaiscript {
|
||||
// modifiers
|
||||
Any & swap(Any &t_other)
|
||||
{
|
||||
std::shared_ptr<Data> data = t_other.m_data;
|
||||
t_other.m_data = m_data;
|
||||
m_data = data;
|
||||
std::swap(t_other.m_data, m_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@@ -1,14 +1,22 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Info;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
@@ -21,26 +29,26 @@ namespace chaiscript
|
||||
class bad_boxed_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) noexcept
|
||||
: from(t_from), to(&t_to), m_what(t_what)
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
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(Type_Info t_from, const std::type_info &t_to)
|
||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const std::string &t_what) noexcept
|
||||
: to(0), m_what(t_what)
|
||||
bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
: to(nullptr), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_cast() noexcept {}
|
||||
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
virtual const char * what() const noexcept
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||
@@ -14,79 +14,20 @@ namespace chaiscript
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<int>
|
||||
struct Placeholder
|
||||
{
|
||||
};
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
struct Placeholder
|
||||
{
|
||||
static std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)> placeholder() {
|
||||
return std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)>(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,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)
|
||||
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
|
||||
{
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(f, innerparams..., Placeholder<maxcount - count + 1>::value());
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(std::forward<F>(f), innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,37 +35,42 @@ namespace chaiscript
|
||||
struct Bind_First<0, maxcount, Sig>
|
||||
{
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
|
||||
{
|
||||
return std::bind(f, innerparams...);
|
||||
return std::bind(std::forward<F>(f), innerparams...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<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)
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(std::function<Ret (P1, Param...)> &&f, O&& o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(std::move(f), std::forward<O>(o));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,19 +1,39 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "proxy_functions_detail.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "../utility/utility.hpp"
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -26,13 +46,9 @@ namespace chaiscript
|
||||
/// \param[in] v Boxed_Number to copy into the new object
|
||||
/// \returns The newly created object.
|
||||
template<typename P1>
|
||||
std::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
|
||||
{
|
||||
std::shared_ptr<P1> p(new P1());
|
||||
Boxed_Value bv(p);
|
||||
Boxed_Number nb(bv);
|
||||
nb = v;
|
||||
return p;
|
||||
return std::make_shared<P1>(v.get_as<P1>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,9 +109,7 @@ 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)
|
||||
{
|
||||
@@ -104,10 +118,8 @@ namespace chaiscript
|
||||
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)
|
||||
{
|
||||
@@ -116,12 +128,10 @@ namespace chaiscript
|
||||
ss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
*/
|
||||
|
||||
|
||||
/// Add all common functions for a POD type. All operators, and
|
||||
/// common conversions
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -135,22 +145,18 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* "clone" function for a shared_ptr type. This is used in the case
|
||||
* where you do not want to make a deep copy of an object during cloning
|
||||
* but want to instead maintain the shared_ptr. It is needed internally
|
||||
* for handling of Proxy_Function object (that is,
|
||||
* function variables.
|
||||
*/
|
||||
/// "clone" function for a shared_ptr type. This is used in the case
|
||||
/// where you do not want to make a deep copy of an object during cloning
|
||||
/// but want to instead maintain the shared_ptr. It is needed internally
|
||||
/// for handling of Proxy_Function object (that is,
|
||||
/// function variables.
|
||||
template<typename Type>
|
||||
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
*/
|
||||
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
template<typename Type>
|
||||
std::shared_ptr<typename std::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
|
||||
@@ -160,11 +166,9 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
* object pointed to, instead maintains the shared_ptr concept.
|
||||
* Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
*/
|
||||
/// Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
/// object pointed to, instead maintains the shared_ptr concept.
|
||||
/// Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
|
||||
{
|
||||
@@ -178,10 +182,8 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class consisting of only static functions. All default bootstrapping occurs
|
||||
* from this class.
|
||||
*/
|
||||
/// Class consisting of only static functions. All default bootstrapping occurs
|
||||
/// from this class.
|
||||
class Bootstrap
|
||||
{
|
||||
private:
|
||||
@@ -200,18 +202,16 @@ namespace chaiscript
|
||||
|
||||
static void print(const std::string &s)
|
||||
{
|
||||
std::cout << s;
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
}
|
||||
|
||||
static void println(const std::string &s)
|
||||
{
|
||||
std::cout << s << std::endl;
|
||||
puts(s.c_str());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add all arithmetic operators for PODs
|
||||
*/
|
||||
/// Add all arithmetic operators for PODs
|
||||
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&Boxed_Number::equals), "==");
|
||||
@@ -251,11 +251,8 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a bound function object. The first param is the function to bind
|
||||
* the remaining parameters are the args to bind into the
|
||||
* result
|
||||
*/
|
||||
/// Create a bound function object. The first param is the function to bind
|
||||
/// the remaining parameters are the args to bind into the result
|
||||
static Boxed_Value bind_function(const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
@@ -265,32 +262,21 @@ namespace chaiscript
|
||||
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
|
||||
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(f,
|
||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a call can be made that consists of the first parameter
|
||||
* (the function) with the remaining parameters as its arguments.
|
||||
*/
|
||||
static Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() < 1)
|
||||
{
|
||||
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
|
||||
}
|
||||
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return bool(pf->get_guard());
|
||||
if (pf->get_guard()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -315,23 +301,13 @@ namespace chaiscript
|
||||
static void throw_exception(const Boxed_Value &bv) {
|
||||
throw bv;
|
||||
}
|
||||
|
||||
static std::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(
|
||||
std::shared_ptr<chaiscript::detail::Dispatch_Engine> e
|
||||
= std::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
|
||||
{
|
||||
e->add(user_type<void>(), "void");
|
||||
return e;
|
||||
}
|
||||
|
||||
static std::string what(const std::exception &e)
|
||||
{
|
||||
return e.what();
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean specialization of internal to_string function
|
||||
*/
|
||||
/// Boolean specialization of internal to_string function
|
||||
static std::string bool_to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
@@ -358,12 +334,44 @@ namespace chaiscript
|
||||
return vbv;
|
||||
}
|
||||
|
||||
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
if (auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf))
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
if (auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf))
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
return pf->get_parse_tree();
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||
/// \param[in,out] m Module to add bootstrapped functions to
|
||||
@@ -379,10 +387,9 @@ namespace chaiscript
|
||||
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
||||
|
||||
|
||||
|
||||
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
|
||||
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
|
||||
|
||||
@@ -411,9 +418,12 @@ namespace chaiscript
|
||||
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
||||
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
||||
m->add(fun(&Boxed_Value::is_type), "is_type");
|
||||
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
|
||||
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
|
||||
|
||||
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
||||
m->add(user_type<Type_Info>(), "Type_Info");
|
||||
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
|
||||
|
||||
|
||||
operators::equal<Type_Info>(m);
|
||||
@@ -433,8 +443,8 @@ namespace chaiscript
|
||||
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");
|
||||
m->add(fun<std::string (const std::string &t_ss)>([](const std::string &s) -> std::string { return s; }), "to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "to_string");
|
||||
m->add(fun(&unknown_assign), "=");
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
m->add(fun(&what), "what");
|
||||
@@ -465,18 +475,76 @@ namespace chaiscript
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))),
|
||||
"bind");
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(&bind_function)), "bind");
|
||||
|
||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&call_exists, std::placeholders::_1))),
|
||||
"call_exists");
|
||||
|
||||
m->add(fun(&Boxed_Value::type_match), "type_match");
|
||||
|
||||
|
||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||
|
||||
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
|
||||
"eval_error",
|
||||
{ },
|
||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<std::shared_ptr<const chaiscript::AST_Node>>);
|
||||
return retval;
|
||||
})), "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::to_string), "to_string"},
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_node.children.begin(), t_node.children.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
|
||||
return retval;
|
||||
})), "children"},
|
||||
{fun(&AST_Node::replace_child), "replace_child"}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
|
||||
"ChaiScript_Parser",
|
||||
{ constructor<parser::ChaiScript_Parser ()>() },
|
||||
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
|
||||
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
|
||||
);
|
||||
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
@@ -1,24 +1,33 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
/**
|
||||
* \file
|
||||
* This file contains utility functions for registration of STL container
|
||||
* classes. The methodology used is based on the SGI STL concepts.
|
||||
* http://www.sgi.com/tech/stl/table_of_contents.html
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// This file contains utility functions for registration of STL container
|
||||
/// classes. The methodology used is based on the SGI STL concepts.
|
||||
/// http://www.sgi.com/tech/stl/table_of_contents.html
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include "bootstrap.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -26,11 +35,10 @@ namespace chaiscript
|
||||
{
|
||||
namespace standard_library
|
||||
{
|
||||
/**
|
||||
* Bidir_Range, based on the D concept of ranges.
|
||||
* \todo Update the Range code to base its capabilities on
|
||||
* the user_typetraits of the iterator passed in
|
||||
*/
|
||||
|
||||
/// Bidir_Range, based on the D concept of ranges.
|
||||
/// \todo Update the Range code to base its capabilities on
|
||||
/// the user_typetraits of the iterator passed in
|
||||
template<typename Container>
|
||||
struct Bidir_Range
|
||||
{
|
||||
@@ -149,6 +157,12 @@ namespace chaiscript
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
size_t count(const T &t_target, const typename T::key_type &t_key)
|
||||
{
|
||||
return t_target.count(t_key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert(T &t_target, const T &t_other)
|
||||
{
|
||||
@@ -163,9 +177,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add Bidir_Range support for the given ContainerType
|
||||
*/
|
||||
/// Add Bidir_Range support for the given ContainerType
|
||||
template<typename Bidir_Type>
|
||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -173,7 +185,7 @@ namespace chaiscript
|
||||
|
||||
copy_constructor<Bidir_Type>(type + "_Range", m);
|
||||
|
||||
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range");
|
||||
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
|
||||
m->add(fun(&Bidir_Type::empty), "empty");
|
||||
m->add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||
@@ -184,14 +196,13 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm for inserting at a specific position into a container
|
||||
*/
|
||||
|
||||
/// Algorithm for inserting at a specific position into a container
|
||||
template<typename Type>
|
||||
void insert_at(Type &container, int pos, const typename Type::value_type &v)
|
||||
{
|
||||
typename Type::iterator itr = container.begin();
|
||||
typename Type::iterator end = container.end();
|
||||
auto itr = container.begin();
|
||||
auto end = container.end();
|
||||
|
||||
if (pos < 0 || std::distance(itr, end) < pos)
|
||||
{
|
||||
@@ -202,14 +213,13 @@ namespace chaiscript
|
||||
container.insert(itr, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm for erasing a specific position from a container
|
||||
*/
|
||||
|
||||
/// Algorithm for erasing a specific position from a container
|
||||
template<typename Type>
|
||||
void erase_at(Type &container, int pos)
|
||||
{
|
||||
typename Type::iterator itr = container.begin();
|
||||
typename Type::iterator end = container.end();
|
||||
auto itr = container.begin();
|
||||
auto end = container.end();
|
||||
|
||||
if (pos < 0 || std::distance(itr, end) < (pos-1))
|
||||
{
|
||||
@@ -219,7 +229,7 @@ namespace chaiscript
|
||||
std::advance(itr, pos);
|
||||
container.erase(itr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
@@ -230,10 +240,9 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add random_access_container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||
*/
|
||||
|
||||
/// Add random_access_container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -252,10 +261,9 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add assignable concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/Assignable.html
|
||||
*/
|
||||
|
||||
/// Add assignable concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -264,23 +272,21 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/Container.html
|
||||
*/
|
||||
|
||||
/// Add container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Container.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun( std::function<int (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
|
||||
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
|
||||
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
|
||||
m->add(fun<size_t (const ContainerType *)>([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m->add(fun<bool (const ContainerType *)>([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m->add(fun<void (ContainerType *)>([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add default constructable concept to the given Type
|
||||
* http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
*/
|
||||
|
||||
/// Add default constructable concept to the given Type
|
||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
template<typename Type>
|
||||
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -290,10 +296,9 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add sequence concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/Sequence.html
|
||||
*/
|
||||
|
||||
/// Add sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -311,10 +316,9 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add back insertion sequence concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
*/
|
||||
|
||||
/// Add back insertion sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -330,25 +334,26 @@ namespace chaiscript
|
||||
push_back_name = "push_back";
|
||||
}
|
||||
|
||||
typedef void (ContainerType::*pushback)(const typename ContainerType::value_type &);
|
||||
m->add(fun(static_cast<pushback>(&ContainerType::push_back)), push_back_name);
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
m->add(fun(static_cast<push_back>(&ContainerType::push_back)), push_back_name);
|
||||
m->add(fun(&ContainerType::pop_back), "pop_back");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*Front insertion sequence
|
||||
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
*/
|
||||
|
||||
/// Front insertion sequence
|
||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*frontptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*constfrontptr)() const;
|
||||
typedef void (ContainerType::*pushptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*popptr)();
|
||||
|
||||
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<constfrontptr>(&ContainerType::front)), "front");
|
||||
|
||||
std::string push_front_name;
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||
@@ -363,10 +368,9 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* bootstrap a given PairType
|
||||
* http://www.sgi.com/tech/stl/pair.html
|
||||
*/
|
||||
|
||||
/// bootstrap a given PairType
|
||||
/// http://www.sgi.com/tech/stl/pair.html
|
||||
template<typename PairType>
|
||||
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -386,10 +390,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add pair associative container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||
*/
|
||||
|
||||
/// Add pair associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||
|
||||
template<typename ContainerType>
|
||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -398,18 +402,17 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add unique associative container concept to the given ContainerType
|
||||
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
*/
|
||||
|
||||
/// Add unique associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count), "count");
|
||||
m->add(fun(detail::count<ContainerType>), "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(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
|
||||
m->add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
@@ -425,10 +428,9 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a MapType container
|
||||
* http://www.sgi.com/tech/stl/Map.html
|
||||
*/
|
||||
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename MapType>
|
||||
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -447,10 +449,9 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* hopefully working List type
|
||||
* http://www.sgi.com/tech/stl/List.html
|
||||
*/
|
||||
|
||||
/// hopefully working List type
|
||||
/// http://www.sgi.com/tech/stl/List.html
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -467,17 +468,19 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a vector type with associated concepts
|
||||
* http://www.sgi.com/tech/stl/Vector.html
|
||||
*/
|
||||
|
||||
/// Create a vector type with associated concepts
|
||||
/// http://www.sgi.com/tech/stl/Vector.html
|
||||
template<typename VectorType>
|
||||
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<VectorType>(), type);
|
||||
|
||||
typedef typename VectorType::reference (VectorType::*frontptr)();
|
||||
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
|
||||
|
||||
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||
|
||||
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
@@ -490,33 +493,33 @@ namespace chaiscript
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
m->eval("def Vector::`==`(rhs) : type_match(rhs, this) { \
|
||||
if ( rhs.size() != this.size() ) { \
|
||||
return false; \
|
||||
} else { \
|
||||
auto r1 = range(this); \
|
||||
auto r2 = range(rhs); \
|
||||
while (!r1.empty()) \
|
||||
{ \
|
||||
if (!eq(r1.front(), r2.front())) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
r1.pop_front(); \
|
||||
r2.pop_front(); \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
}");
|
||||
m->eval(R"(
|
||||
def Vector::`==`(rhs) : type_match(rhs, this) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
} else {
|
||||
auto r1 = range(this);
|
||||
auto r2 = range(rhs);
|
||||
while (!r1.empty())
|
||||
{
|
||||
if (!eq(r1.front(), r2.front()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
r1.pop_front();
|
||||
r2.pop_front();
|
||||
}
|
||||
true;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a String container
|
||||
* http://www.sgi.com/tech/stl/basic_string.html
|
||||
*/
|
||||
/// Add a String container
|
||||
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||
template<typename String>
|
||||
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -527,7 +530,7 @@ namespace chaiscript
|
||||
random_access_container_type<String>(type, m);
|
||||
sequence_type<String>(type, m);
|
||||
default_constructible_type<String>(type, m);
|
||||
container_type<String>(type, m);
|
||||
// container_type<String>(type, m);
|
||||
assignable_type<String>(type, m);
|
||||
input_range_type<String>(type, m);
|
||||
|
||||
@@ -541,19 +544,23 @@ namespace chaiscript
|
||||
}
|
||||
m->add(fun(&String::push_back), push_back_name);
|
||||
|
||||
typedef std::function<int (const String *, const String &, int)> find_func;
|
||||
typedef std::function<size_t (const String *, const String &, size_t)> find_func;
|
||||
|
||||
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find(f, pos); } )), "find");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->rfind(f, pos); } ) ), "rfind");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_first_of(f, pos); } ) ), "find_first_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_last_of(f, pos); } ) ), "find_last_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find(f, pos); } )), "find");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ) ), "rfind");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ) ), "find_first_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ) ), "find_last_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of");
|
||||
|
||||
m->add(fun( std::function<void (String *)>( [](String *s) { return s->clear(); } ) ), "clear");
|
||||
m->add(fun( std::function<bool (const String *)>( [](const String *s) { return s->empty(); } ) ), "empty");
|
||||
m->add(fun( std::function<size_t (const String *)>( [](const String *s) { return s->size(); } ) ), "size");
|
||||
|
||||
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");
|
||||
m->add(fun( std::function<String (const String *, size_t, size_t)>( [](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ) ), "substr");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -563,3 +570,5 @@ namespace chaiscript
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -1,20 +1,30 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace detail {
|
||||
namespace exception {
|
||||
class bad_any_cast;
|
||||
} // namespace exception
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -62,10 +72,10 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
|
||||
{
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv);
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
|
||||
|
||||
@@ -76,14 +86,21 @@ namespace chaiscript
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
|
||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
||||
{
|
||||
try {
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv));
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
|
||||
} catch (...) {
|
||||
try {
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
|
||||
// try going the other way - down the inheritance graph
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it's not polymorphic, just throw the error, don't waste the time on the
|
||||
|
@@ -1,73 +1,69 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Type_Conversions;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Cast_Helper_Inner helper classes
|
||||
|
||||
/**
|
||||
* Generic Cast_Helper_Inner, for casting to any type
|
||||
*/
|
||||
template<typename T>
|
||||
T* throw_if_null(T *t)
|
||||
{
|
||||
if (t) return t;
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
}
|
||||
|
||||
/// Generic Cast_Helper_Inner, for casting to any type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
|
||||
} else {
|
||||
return ob.get().cast<std::reference_wrapper<const Result> >();
|
||||
}
|
||||
return *(static_cast<const Result *>(throw_if_null(ob.get_const_ptr())));
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
|
||||
} else {
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
|
||||
{
|
||||
};
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const * type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -88,15 +84,12 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a * type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -107,49 +100,43 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a & type
|
||||
*/
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result &cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
return ob.get().cast<std::reference_wrapper<Result> >();
|
||||
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
|
||||
} else {
|
||||
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
|
||||
return r;
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
|
||||
{
|
||||
typedef typename std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
|
||||
{
|
||||
typedef typename std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@@ -160,9 +147,7 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
@@ -174,9 +159,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const std::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 std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
@@ -189,23 +172,32 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a Boxed_Value type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a Boxed_Value type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
typedef const Boxed_Value & Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return ob;
|
||||
return ob;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const Boxed_Value & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a Boxed_Value & type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value &>
|
||||
{
|
||||
typedef Boxed_Value& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return const_cast<Boxed_Value &>(ob);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
@@ -215,11 +207,9 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
*/
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
@@ -250,17 +240,15 @@ namespace chaiscript
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
|
||||
*/
|
||||
/// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
|
||||
template<typename T>
|
||||
struct Cast_Helper
|
||||
{
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob);
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -1,22 +1,36 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, 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 <cstdint>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "../language/chaiscript_algebraic.hpp"
|
||||
#include "any.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
// Due to the nature of generating every possible arithmetic operation, there
|
||||
// are going to be warnings generated on every platform regarding size and sign,
|
||||
// this is OK, so we're disabling size/and sign type warnings
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244 4018 4389 4146)
|
||||
#pragma warning(disable : 4244 4018 4389 4146 4365)
|
||||
#endif
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
@@ -49,7 +63,6 @@ namespace chaiscript
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -145,7 +158,6 @@ namespace chaiscript
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -171,7 +183,6 @@ namespace chaiscript
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -222,7 +233,7 @@ namespace chaiscript
|
||||
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();
|
||||
const auto &inp_ = t_rhs.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
@@ -309,7 +320,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
std::string to_string_aux(const Boxed_Value &v) const
|
||||
static std::string to_string_aux(const Boxed_Value &v)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << *static_cast<const Source *>(v.get_const_ptr());
|
||||
@@ -323,10 +334,10 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Boxed_Number(const Boxed_Value &v)
|
||||
: bv(v)
|
||||
Boxed_Number(Boxed_Value v)
|
||||
: bv(std::move(v))
|
||||
{
|
||||
validate_boxed_number(v);
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
@@ -335,6 +346,46 @@ namespace chaiscript
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
Boxed_Number get_as(const Type_Info &inp_) const
|
||||
{
|
||||
if (inp_.bare_equal_type_info(typeid(int))) {
|
||||
return Boxed_Number(get_as<int>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(double))) {
|
||||
return Boxed_Number(get_as<double>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(float))) {
|
||||
return Boxed_Number(get_as<float>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long double))) {
|
||||
return Boxed_Number(get_as<long double>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(char))) {
|
||||
return Boxed_Number(get_as<char>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
|
||||
return Boxed_Number(get_as<unsigned int>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long))) {
|
||||
return Boxed_Number(get_as<long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
|
||||
return Boxed_Number(get_as<unsigned long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
|
||||
return Boxed_Number(get_as<int8_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {
|
||||
return Boxed_Number(get_as<int16_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int32_t))) {
|
||||
return Boxed_Number(get_as<int32_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int64_t))) {
|
||||
return Boxed_Number(get_as<int64_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint8_t))) {
|
||||
return Boxed_Number(get_as<uint8_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint16_t))) {
|
||||
return Boxed_Number(get_as<uint16_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint32_t))) {
|
||||
return Boxed_Number(get_as<uint32_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint64_t))) {
|
||||
return Boxed_Number(get_as<uint64_t>());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Target> Target get_as() const
|
||||
{
|
||||
const Type_Info &inp_ = bv.get_type_info();
|
||||
@@ -482,7 +533,7 @@ namespace chaiscript
|
||||
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
void validate_boxed_number(const Boxed_Value &v)
|
||||
static void validate_boxed_number(const Boxed_Value &v)
|
||||
{
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
if (inp_ == typeid(bool))
|
||||
@@ -775,38 +826,32 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
/// 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)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
/// 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
|
||||
*/
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
@@ -1,18 +1,21 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
|
||||
#include <map>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "any.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -22,24 +25,21 @@ namespace chaiscript
|
||||
class Boxed_Value
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* used for explicitly creating a "void" object
|
||||
*/
|
||||
/// used for explicitly creating a "void" object
|
||||
struct Void_Type
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* structure which holds the internal state of a Boxed_Value
|
||||
*/
|
||||
/// structure which holds the internal state of a Boxed_Value
|
||||
/// \todo Get rid of Any and merge it with this, reducing an allocation in the process
|
||||
struct Data
|
||||
{
|
||||
Data(const Type_Info &ti,
|
||||
const chaiscript::detail::Any &to,
|
||||
chaiscript::detail::Any to,
|
||||
bool tr,
|
||||
const void *t_void_ptr)
|
||||
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?0:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
m_is_ref(tr)
|
||||
{
|
||||
}
|
||||
@@ -52,18 +52,28 @@ namespace chaiscript
|
||||
m_data_ptr = rhs.m_data_ptr;
|
||||
m_const_data_ptr = rhs.m_const_data_ptr;
|
||||
|
||||
if (rhs.m_attrs)
|
||||
{
|
||||
m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*rhs.m_attrs));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Data()
|
||||
{
|
||||
}
|
||||
Data(const Data &) = delete;
|
||||
|
||||
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
|
||||
Data(Data &&) = default;
|
||||
Data &operator=(Data &&rhs) = default;
|
||||
#endif
|
||||
|
||||
|
||||
Type_Info m_type_info;
|
||||
chaiscript::detail::Any m_obj;
|
||||
void *m_data_ptr;
|
||||
const void *m_const_data_ptr;
|
||||
bool m_is_ref;
|
||||
std::unique_ptr<std::map<std::string, Boxed_Value>> m_attrs;
|
||||
};
|
||||
|
||||
struct Object_Data
|
||||
@@ -95,32 +105,53 @@ namespace chaiscript
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj)
|
||||
{
|
||||
auto ptr = obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(T *t)
|
||||
{
|
||||
return get(std::ref(*t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const T *t)
|
||||
{
|
||||
return get(std::cref(*t));
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
|
||||
{
|
||||
auto p = &obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(obj),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
true,
|
||||
&obj.get()
|
||||
p
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const T& t)
|
||||
static std::shared_ptr<Data> get(T t)
|
||||
{
|
||||
auto p = std::make_shared<T>(t);
|
||||
auto p = std::make_shared<T>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(p),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
p.get()
|
||||
ptr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -137,115 +168,114 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Basic Boxed_Value constructor
|
||||
*/
|
||||
template<typename T>
|
||||
explicit Boxed_Value(T t)
|
||||
: m_data(Object_Data::get(t))
|
||||
/// Basic Boxed_Value constructor
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
|
||||
explicit Boxed_Value(T &&t)
|
||||
: m_data(Object_Data::get(std::forward<T>(t)))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor - each copy shares the same data pointer
|
||||
*/
|
||||
Boxed_Value(const Boxed_Value &t_so)
|
||||
: m_data(t_so.m_data)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Unknown-type constructor
|
||||
*/
|
||||
/// Unknown-type constructor
|
||||
Boxed_Value()
|
||||
: m_data(Object_Data::get())
|
||||
: m_data(Object_Data::get())
|
||||
{
|
||||
}
|
||||
|
||||
~Boxed_Value()
|
||||
{
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Boxed_Value(Boxed_Value&&) = default;
|
||||
Boxed_Value& operator=(Boxed_Value&&) = default;
|
||||
#endif
|
||||
|
||||
Boxed_Value(const Boxed_Value&) = default;
|
||||
Boxed_Value& operator=(const Boxed_Value&) = default;
|
||||
|
||||
void swap(Boxed_Value &rhs)
|
||||
{
|
||||
std::swap(m_data, rhs.m_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* copy the values stored in rhs.m_data to m_data
|
||||
* m_data pointers are not shared in this case
|
||||
*/
|
||||
/// Copy the values stored in rhs.m_data to m_data.
|
||||
/// m_data pointers are not shared in this case
|
||||
Boxed_Value assign(const Boxed_Value &rhs)
|
||||
{
|
||||
(*m_data) = (*rhs.m_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* shared data assignment, same as copy construction
|
||||
*/
|
||||
Boxed_Value &operator=(const Boxed_Value &rhs)
|
||||
{
|
||||
Boxed_Value temp(rhs);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Type_Info &get_type_info() const
|
||||
const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the object is uninitialized
|
||||
*/
|
||||
bool is_undef() const
|
||||
/// return true if the object is uninitialized
|
||||
bool is_undef() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info.is_undef();
|
||||
}
|
||||
|
||||
bool is_const() const
|
||||
bool is_const() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info.is_const();
|
||||
}
|
||||
|
||||
bool is_type(const Type_Info &ti) const
|
||||
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
bool is_null() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0);
|
||||
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
||||
}
|
||||
|
||||
const chaiscript::detail::Any & get() const
|
||||
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_obj;
|
||||
}
|
||||
|
||||
bool is_ref() const
|
||||
bool is_ref() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
|
||||
bool is_pointer() const
|
||||
bool is_pointer() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
void *get_ptr() const
|
||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
}
|
||||
|
||||
const void *get_const_ptr() const
|
||||
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
}
|
||||
|
||||
Boxed_Value get_attr(const std::string &t_name)
|
||||
{
|
||||
if (!m_data->m_attrs)
|
||||
{
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>());
|
||||
}
|
||||
|
||||
return (*m_data->m_attrs)[t_name];
|
||||
}
|
||||
|
||||
Boxed_Value ©_attrs(const Boxed_Value &t_obj)
|
||||
{
|
||||
if (t_obj.m_data->m_attrs)
|
||||
{
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*t_obj.m_data->m_attrs));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// \returns true if the two Boxed_Values share the same internal type
|
||||
static bool type_match(Boxed_Value l, Boxed_Value r)
|
||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
@@ -254,19 +284,20 @@ namespace chaiscript
|
||||
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, std::shared_ptr, or std::reference_type
|
||||
/// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
|
||||
/// a copy is not made.
|
||||
/// \param t The value to box
|
||||
///
|
||||
/// @param t The value to box
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
///
|
||||
/// ~~~{.cpp}
|
||||
/// int i;
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::var(i), "i");
|
||||
/// chai.add(chaiscript::var(&i), "ip");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingobjects
|
||||
/// ~~~
|
||||
///
|
||||
/// @sa @ref adding_objects
|
||||
template<typename T>
|
||||
Boxed_Value var(T t)
|
||||
{
|
||||
@@ -281,7 +312,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(std::shared_ptr<typename std::add_const<T>::type >(new T(t)));
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
|
||||
}
|
||||
|
||||
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
@@ -339,7 +370,8 @@ namespace chaiscript
|
||||
/// chai.add(chaiscript::const_var(Green), "Green");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingobjects
|
||||
/// \todo support C++11 strongly typed enums
|
||||
/// \sa \ref adding_objects
|
||||
template<typename T>
|
||||
Boxed_Value const_var(const T &t)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,287 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
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) noexcept
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() noexcept {}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
|
||||
|
||||
const Type_Info &base()
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
const Type_Info &derived()
|
||||
{
|
||||
return m_derived;
|
||||
}
|
||||
|
||||
protected:
|
||||
Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived)
|
||||
: m_base(t_base), m_derived(t_derived)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Conversion() {}
|
||||
|
||||
private:
|
||||
Type_Info m_base;
|
||||
Type_Info m_derived;
|
||||
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived)
|
||||
{
|
||||
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
|
||||
{
|
||||
if (t_derived.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_derived.is_const())
|
||||
{
|
||||
std::shared_ptr<const Base> data
|
||||
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<Base> data
|
||||
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_derived.is_const())
|
||||
{
|
||||
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
|
||||
const Base &data = dynamic_cast<const Base &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
|
||||
Base &data = dynamic_cast<Base &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Dynamic_Conversions
|
||||
{
|
||||
public:
|
||||
static inline Dynamic_Conversions &get()
|
||||
{
|
||||
static Dynamic_Conversions obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
static std::shared_ptr<Dynamic_Conversion> create()
|
||||
{
|
||||
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
|
||||
/// and in the global notion of the static conversion object
|
||||
/// someday this will almost certainly have to change. Maybe it is time for ChaiScript
|
||||
/// to become a library?
|
||||
Dynamic_Conversions::get().add_conversion(conversion);
|
||||
return conversion;
|
||||
}
|
||||
|
||||
template<typename InItr>
|
||||
void cleanup(InItr begin, const InItr &end)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
if (begin->unique())
|
||||
{
|
||||
m_conversions.erase(begin->get());
|
||||
}
|
||||
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
m_conversions.insert(conversion.get());
|
||||
}
|
||||
|
||||
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return find(base, derived) != m_conversions.end();
|
||||
}
|
||||
|
||||
|
||||
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
std::set<Dynamic_Conversion *>::const_iterator itr =
|
||||
find(base, derived);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Dynamic_Conversions() {}
|
||||
|
||||
std::set<Dynamic_Conversion *>::const_iterator find(
|
||||
const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
|
||||
itr != m_conversions.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
|
||||
return m_conversions.end();
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<Dynamic_Conversion *> m_conversions;
|
||||
};
|
||||
}
|
||||
|
||||
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.
|
||||
///
|
||||
/// Create a new base class registration for applying to a module or to the chaiscript engine
|
||||
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
|
||||
/// if you have a type that is introduced in a loadable module and is used by multiple modules
|
||||
/// (through a tertiary dll that is shared between the modules, static linking the new type
|
||||
/// into both loadable modules would not be portable), you need to register the base type
|
||||
/// relationship in all modules that use the newly added type in a polymorphic way.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// class Base
|
||||
/// {};
|
||||
/// class Derived : public Base
|
||||
/// {};
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<Base, Derived>());
|
||||
/// \endcode
|
||||
///
|
||||
/// \todo Move share static type registration code into a mechanism that allows it to be properly
|
||||
/// shared by all modules
|
||||
template<typename Base, typename Derived>
|
||||
Dynamic_Cast_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
|
||||
return detail::Dynamic_Conversions::create<Base, Derived>();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename Base, typename Derived>
|
||||
bool dynamic_cast_converts()
|
||||
{
|
||||
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
|
||||
}
|
||||
|
||||
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
|
||||
{
|
||||
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
|
||||
}
|
||||
|
||||
template<typename Base>
|
||||
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
|
||||
{
|
||||
try {
|
||||
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@@ -1,12 +1,33 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -15,8 +36,8 @@ namespace chaiscript
|
||||
class Dynamic_Object
|
||||
{
|
||||
public:
|
||||
Dynamic_Object(const std::string &t_type_name)
|
||||
: m_type_name(t_type_name)
|
||||
Dynamic_Object(std::string t_type_name)
|
||||
: m_type_name(std::move(t_type_name))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -30,7 +51,7 @@ namespace chaiscript
|
||||
return m_attrs[t_attr_name];
|
||||
}
|
||||
|
||||
std::map<std::string, Boxed_Value> get_attrs()
|
||||
std::map<std::string, Boxed_Value> get_attrs() const
|
||||
{
|
||||
return m_attrs;
|
||||
}
|
||||
@@ -43,30 +64,28 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* A Proxy_Function implementation designed for calling a function
|
||||
* that is automatically guarded based on the first param based on the
|
||||
* param's type name
|
||||
*/
|
||||
/// A Proxy_Function implementation designed for calling a function
|
||||
/// that is automatically guarded based on the first param based on the
|
||||
/// param's type name
|
||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
const std::string &t_type_name,
|
||||
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)
|
||||
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
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,
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
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(new Type_Info(t_ti))
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
@@ -74,10 +93,12 @@ namespace chaiscript
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const
|
||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
|
||||
if (df)
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
{
|
||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||
} else {
|
||||
@@ -85,47 +106,41 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
return m_func->call_match(vals);
|
||||
return m_func->call_match(vals, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return m_func->get_arity();
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti))
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
return (*m_func)(params);
|
||||
return (*m_func)(params, t_conversions);
|
||||
} else {
|
||||
throw exception::guard_error();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv) const
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti);
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -140,14 +155,13 @@ namespace chaiscript
|
||||
return types;
|
||||
}
|
||||
|
||||
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti)
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
static Type_Info doti = user_type<Dynamic_Object>();
|
||||
if (bv.get_type_info().bare_equal(doti))
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
@@ -163,12 +177,12 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti)
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
return dynamic_object_typename_match(bvs[0], name, ti);
|
||||
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -176,7 +190,9 @@ namespace chaiscript
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
std::unique_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -191,10 +207,10 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Constructor(
|
||||
const std::string &t_type_name,
|
||||
std::string t_type_name,
|
||||
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)
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
|
||||
m_type_name(std::move(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)");
|
||||
@@ -202,8 +218,8 @@ namespace chaiscript
|
||||
|
||||
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
||||
{
|
||||
std::vector<Type_Info>::const_iterator begin = tl.begin();
|
||||
std::vector<Type_Info>::const_iterator end = tl.end();
|
||||
auto begin = tl.begin();
|
||||
auto end = tl.end();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
@@ -215,7 +231,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Dynamic_Object_Constructor() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
if (dc)
|
||||
@@ -226,36 +242,27 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals;
|
||||
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
|
||||
return m_func->call_match(new_vals);
|
||||
return m_func->call_match(new_vals, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
// "this" is not considered part of the arity
|
||||
return m_func->get_arity() - 1;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_params;
|
||||
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
||||
new_params.push_back(bv);
|
||||
auto bv = var(Dynamic_Object(m_type_name));
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
|
||||
(*m_func)(new_params);
|
||||
(*m_func)(new_params, t_conversions);
|
||||
|
||||
return bv;
|
||||
}
|
||||
|
@@ -1,79 +1,102 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this a variadic template
|
||||
struct Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv) = 0;
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||
|
||||
virtual ~Exception_Handler_Base() {}
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
void throw_type(const Boxed_Value &bv)
|
||||
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||
{
|
||||
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
||||
try { T t = t_engine.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)
|
||||
virtual ~Exception_Handler_Impl1() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T1>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Exception_Handler_Impl2 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
virtual ~Exception_Handler_Impl2() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
struct Exception_Handler_Impl3 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
virtual ~Exception_Handler_Impl3() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T3>(bv);
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
throw_type<T3>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
struct Exception_Handler_Impl4 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
virtual ~Exception_Handler_Impl4() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T3>(bv);
|
||||
throw_type<T4>(bv);
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
throw_type<T3>(bv, t_engine);
|
||||
throw_type<T4>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct Exception_Handler_Impl5 : Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv)
|
||||
virtual ~Exception_Handler_Impl5() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv);
|
||||
throw_type<T2>(bv);
|
||||
throw_type<T3>(bv);
|
||||
throw_type<T4>(bv);
|
||||
throw_type<T5>(bv);
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
throw_type<T3>(bv, t_engine);
|
||||
throw_type<T4>(bv, t_engine);
|
||||
throw_type<T5>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -1,128 +1,123 @@
|
||||
// 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)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
#include "boxed_cast.hpp"
|
||||
#include "function_call_detail.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Type_Conversions;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
/**
|
||||
* Build a function caller that knows how to dispatch on a set of functions
|
||||
* example:
|
||||
* std::function<void (int)> f =
|
||||
* build_function_caller(dispatchkit.get_function("print"));
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] funcs the set of functions to dispatch on.
|
||||
*/
|
||||
/// Build a function caller that knows how to dispatch on a set of functions
|
||||
/// example:
|
||||
/// std::function<void (int)> f =
|
||||
/// build_function_caller(dispatchkit.get_function("print"));
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] funcs the set of functions to dispatch on.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs)
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
{
|
||||
FunctionType *p=0;
|
||||
return detail::build_function_caller_helper(p, funcs);
|
||||
FunctionType *p=nullptr;
|
||||
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a function caller for a particular Proxy_Function object
|
||||
* useful in the case that a function is being pass out from scripting back
|
||||
* into code
|
||||
* example:
|
||||
* void my_function(Proxy_Function f)
|
||||
* {
|
||||
* std::function<void (int)> local_f =
|
||||
* build_function_caller(f);
|
||||
* }
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] func A function to execute.
|
||||
*/
|
||||
/// Build a function caller for a particular Proxy_Function object
|
||||
/// useful in the case that a function is being pass out from scripting back
|
||||
/// into code
|
||||
/// example:
|
||||
/// void my_function(Proxy_Function f)
|
||||
/// {
|
||||
/// std::function<void (int)> local_f =
|
||||
/// build_function_caller(f);
|
||||
/// }
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] func A function to execute.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func)
|
||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
||||
{
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
funcs.push_back(func);
|
||||
return functor<FunctionType>(funcs);
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({func}), t_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
* and creating a typesafe C++ function caller from it.
|
||||
*/
|
||||
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
/// and creating a typesafe C++ function caller from it.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv)
|
||||
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function &
|
||||
*/
|
||||
/// Cast helper to handle automatic casting to const std::function &
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
return dispatch::functor<Signature>(ob, t_conversions);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob);
|
||||
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast helper to handle automatic casting to std::function
|
||||
*/
|
||||
/// Cast helper to handle automatic casting to std::function
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
return dispatch::functor<Signature>(ob, t_conversions);
|
||||
} else {
|
||||
return Cast_Helper_Inner<std::function<Signature> >::cast(ob);
|
||||
return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function
|
||||
*/
|
||||
/// Cast helper to handle automatic casting to const std::function
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
return dispatch::functor<Signature>(ob, t_conversions);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob);
|
||||
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,14 +1,23 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -17,31 +26,42 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/**
|
||||
* Internal helper class for handling the return
|
||||
* value of a build_function_caller
|
||||
*/
|
||||
template<typename Ret>
|
||||
/// Internal helper class for handling the return
|
||||
/// value of a build_function_caller
|
||||
template<typename Ret, bool is_arithmetic>
|
||||
struct Function_Caller_Ret
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params));
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization for arithmetic return types
|
||||
*/
|
||||
template<typename Ret>
|
||||
struct Function_Caller_Ret<Ret, true>
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Specialization for void return types
|
||||
*/
|
||||
template<>
|
||||
struct Function_Caller_Ret<void>
|
||||
struct Function_Caller_Ret<void, false>
|
||||
{
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params);
|
||||
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,28 +71,30 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs)
|
||||
: m_funcs(t_funcs)
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
|
||||
: m_funcs(std::move(t_funcs)),
|
||||
m_conversions(t_conversions)
|
||||
{
|
||||
}
|
||||
|
||||
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, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::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)...
|
||||
}, m_conversions
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
Type_Conversions m_conversions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs)
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
@@ -88,7 +110,7 @@ namespace chaiscript
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_Conversions()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,20 +1,26 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Number;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
@@ -42,6 +48,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
|
@@ -1,13 +1,14 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
#define CHAISCRIPT_OPERATORS_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -15,442 +16,446 @@ namespace chaiscript
|
||||
{
|
||||
namespace operators
|
||||
{
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign(L l, R r)
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign(L l, R r) -> L&
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_bitwise_and(L l, R r)
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_xor(L l, R r)
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_xor(L l, R r) -> decltype((l^=r))
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_bitwise_or(L l, R r)
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_difference(L l, R r)
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_difference(L l, R r) -> decltype(( l -= r))
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_left_shift(L l, R r)
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_product(L l, R r)
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_product(L l, R r) -> decltype(( l *= r ))
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_quotient(L l, R r)
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_remainder(L l, R r)
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_right_shift(L l, R r)
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_sum(L l, R r)
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign_sum(L l, R r) -> L&
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret prefix_decrement(L l)
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
template<typename L>
|
||||
auto prefix_decrement(L l) -> decltype(( --l ))
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret prefix_increment(L l)
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
template<typename L>
|
||||
auto prefix_increment(L l) -> decltype(( ++l ))
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret equal(L l, R r)
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto equal(L l, R r) -> decltype(( l == r ))
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret greater_than(L l, R r)
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto greater_than(L l, R r) -> decltype(( l > r ))
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret greater_than_equal(L l, R r)
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret less_than(L l, R r)
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto less_than(L l, R r) -> decltype(( l < r ))
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret less_than_equal(L l, R r)
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret logical_compliment(L l)
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
template<typename L>
|
||||
auto logical_compliment(L l) -> decltype(( !l ))
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret not_equal(L l, R r)
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto not_equal(L l, R r) -> decltype(( l != r ))
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret addition(L l, R r)
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto addition(L l, R r) -> decltype(( l + r ))
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_plus(L l)
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
template<typename L>
|
||||
auto unary_plus(L l) -> decltype(( +l ))
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret subtraction(L l, R r)
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto subtraction(L l, R r) -> decltype(( l - r ))
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_minus(L l)
|
||||
{
|
||||
template<typename L>
|
||||
auto unary_minus(L l) -> decltype(( -l ))
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
return (-l);
|
||||
return (-l);
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
return (-l);
|
||||
return (-l);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_and(L l, R r)
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto bitwise_and(L l, R r) -> decltype(( l & r ))
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret bitwise_compliment(L l)
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
template<typename L>
|
||||
auto bitwise_compliment(L l) -> decltype(( ~l ))
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_xor(L l, R r)
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_or(L l, R r)
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto bitwise_or(L l, R r) -> decltype(( l | r ))
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret division(L l, R r)
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto division(L l, R r) -> decltype(( l / r ))
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret left_shift(L l, R r)
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto left_shift(L l, R r) -> decltype(( l << r ))
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret multiplication(L l, R r)
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto multiplication(L l, R r) -> decltype(( l * r ))
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret remainder(L l, R r)
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret right_shift(L l, R r)
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto remainder(L l, R r) -> decltype(( l % r ))
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto right_shift(L l, R r) -> decltype(( l >> r ))
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign<T &, T &, const T&>), "=");
|
||||
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
|
||||
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
|
||||
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
|
||||
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
|
||||
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
|
||||
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
|
||||
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
|
||||
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
|
||||
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&prefix_decrement<T &, T &>), "--");
|
||||
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&prefix_increment<T &, T &>), "++");
|
||||
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&equal<bool, const T&, const T&>), "==");
|
||||
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
|
||||
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
|
||||
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&less_than<bool, const T&, const T&>), "<");
|
||||
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
|
||||
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&logical_compliment<bool, const T &>), "!");
|
||||
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(¬_equal<bool, const T &, const T &>), "!=");
|
||||
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&addition<T, const T &, const T &>), "+");
|
||||
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&unary_plus<T, const T &>), "+");
|
||||
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&subtraction<T, const T &, const T &>), "-");
|
||||
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&unary_minus<T, const T &>), "-");
|
||||
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
|
||||
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_compliment<T, const T &>), "~");
|
||||
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
|
||||
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
|
||||
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&division<T, const T &, const T &>), "/");
|
||||
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
|
||||
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&multiplication<T, const T &, const T &>), "*");
|
||||
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&remainder<T, const T &, const T &>), "%");
|
||||
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
|
||||
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace chaiscript
|
||||
template<typename Class, typename ... Params>
|
||||
std::shared_ptr<Class> constructor_(Params ... params)
|
||||
{
|
||||
return std::shared_ptr<Class>(new Class(params...));
|
||||
return std::make_shared<Class>(params...);
|
||||
}
|
||||
|
||||
template<typename Class, typename ... Params >
|
||||
@@ -48,7 +48,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Proxy_Function constructor()
|
||||
{
|
||||
T *f = 0;
|
||||
T *f = nullptr;
|
||||
return (dispatch::detail::build_constructor_(f));
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
@@ -9,21 +9,36 @@
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
||||
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "proxy_functions_detail.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
struct arity_error;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Boxed_Number;
|
||||
struct AST_Node;
|
||||
|
||||
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
@@ -39,42 +54,45 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
virtual ~Proxy_Function_Base() {}
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||
{
|
||||
Boxed_Value bv = do_call(params);
|
||||
Boxed_Value bv = do_call(params, t_conversions);
|
||||
return bv;
|
||||
}
|
||||
|
||||
/// Returns a vector containing all of the types of the parameters the function returns/takes
|
||||
/// 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
|
||||
/// value contains exactly 1 Type_Info object: the return type
|
||||
/// \returns the types of all parameters.
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
|
||||
bool has_arithmetic_param() const
|
||||
{
|
||||
return m_has_arithmetic_param;
|
||||
}
|
||||
|
||||
virtual std::vector<std::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
||||
{
|
||||
return std::vector<std::shared_ptr<const Proxy_Function_Base> >();
|
||||
}
|
||||
|
||||
|
||||
//! Return true if the function is a possible match
|
||||
//! to the passed in values
|
||||
bool filter(const std::vector<Boxed_Value> &vals) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
int arity = get_arity();
|
||||
|
||||
if (arity < 0)
|
||||
if (m_arity < 0)
|
||||
{
|
||||
return true;
|
||||
} else if (size_t(arity) == vals.size()) {
|
||||
if (arity == 0)
|
||||
} else if (size_t(m_arity) == vals.size()) {
|
||||
if (m_arity == 0)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return compare_first_type(vals[0]);
|
||||
return compare_first_type(vals[0], t_conversions);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
@@ -82,34 +100,22 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \returns the number of arguments the function takes or -1 if it is variadic
|
||||
virtual int get_arity() const = 0;
|
||||
int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const = 0;
|
||||
|
||||
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
|
||||
: m_types(t_types)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv) const
|
||||
{
|
||||
const std::vector<Type_Info> &types = get_param_types();
|
||||
|
||||
if (types.size() < 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const Type_Info &ti = types[1];
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
|| (!bv.get_type_info().is_undef()
|
||||
&& (ti.bare_equal(user_type<Boxed_Number>())
|
||||
|| ti.bare_equal(bv.get_type_info())
|
||||
|| chaiscript::detail::dynamic_cast_converts(ti, bv.get_type_info())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| t_conversions.converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -119,8 +125,38 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const = 0;
|
||||
|
||||
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
|
||||
: m_types(std::move(t_types)), m_has_arithmetic_param(false), m_arity(t_arity)
|
||||
{
|
||||
for (size_t i = 1; i < m_types.size(); ++i)
|
||||
{
|
||||
if (m_types[i].is_arithmetic())
|
||||
{
|
||||
m_has_arithmetic_param = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
const std::vector<Type_Info> &types = get_param_types();
|
||||
|
||||
if (types.size() < 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const Type_Info &ti = types[1];
|
||||
return compare_type_to_param(ti, bv, t_conversions);
|
||||
|
||||
}
|
||||
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
|
||||
{
|
||||
if (tis.size() - 1 != bvs.size())
|
||||
{
|
||||
@@ -139,13 +175,15 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
std::vector<Type_Info> m_types;
|
||||
bool m_has_arithmetic_param;
|
||||
int m_arity;
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Common typedef used for passing of any registered function in ChaiScript
|
||||
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
|
||||
/// \brief Const version of Proxy_Function. Points to a const Proxy_Function. This is how most registered functions
|
||||
/// are handled internally.
|
||||
typedef std::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
|
||||
@@ -155,11 +193,11 @@ namespace chaiscript
|
||||
class guard_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
guard_error() noexcept
|
||||
guard_error() CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("Guard evaluation failed")
|
||||
{ }
|
||||
|
||||
virtual ~guard_error() noexcept
|
||||
virtual ~guard_error() CHAISCRIPT_NOEXCEPT
|
||||
{ }
|
||||
};
|
||||
}
|
||||
@@ -174,17 +212,19 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dynamic_Proxy_Function(
|
||||
const std::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
|
||||
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 = "",
|
||||
const Proxy_Function &t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity)),
|
||||
m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard), m_parsenode(t_parsenode)
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity), t_arity),
|
||||
m_f(std::move(t_f)), m_arity(t_arity), m_description(std::move(t_description)), m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &rhs) const
|
||||
virtual ~Dynamic_Proxy_Function() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||
|
||||
@@ -194,19 +234,12 @@ namespace chaiscript
|
||||
&& !this->m_guard && !prhs->m_guard);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (m_arity < 0 || vals.size() == size_t(m_arity))
|
||||
&& test_guard(vals);
|
||||
&& test_guard(vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Proxy_Function() {}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
Proxy_Function get_guard() const
|
||||
{
|
||||
@@ -218,18 +251,18 @@ namespace chaiscript
|
||||
return m_parsenode;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
||||
{
|
||||
|
||||
if (test_guard(params))
|
||||
if (test_guard(params, t_conversions))
|
||||
{
|
||||
return m_f(params);
|
||||
} else {
|
||||
@@ -242,12 +275,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (m_guard)
|
||||
{
|
||||
try {
|
||||
return boxed_cast<bool>((*m_guard)(params));
|
||||
return boxed_cast<bool>((*m_guard)(params, t_conversions));
|
||||
} catch (const exception::arity_error &) {
|
||||
return false;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
@@ -302,30 +335,25 @@ namespace chaiscript
|
||||
public:
|
||||
Bound_Function(const Const_Proxy_Function &t_f,
|
||||
const std::vector<Boxed_Value> &t_args)
|
||||
: Proxy_Function_Base(build_param_type_info(t_f, t_args)),
|
||||
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
|
||||
: Proxy_Function_Base(build_param_type_info(t_f, t_args), (t_f->get_arity()<0?-1:static_cast<int>(build_param_type_info(t_f, t_args).size())-1)),
|
||||
m_f(t_f), m_args(t_args)
|
||||
{
|
||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||
}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_f) const
|
||||
virtual bool operator==(const Proxy_Function_Base &t_f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return &t_f == this;
|
||||
}
|
||||
|
||||
virtual ~Bound_Function() {}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_f->call_match(build_param_list(vals));
|
||||
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return (*m_f)(build_param_list(params));
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Const_Proxy_Function> fs;
|
||||
fs.push_back(m_f);
|
||||
@@ -335,10 +363,8 @@ namespace chaiscript
|
||||
|
||||
std::vector<Boxed_Value> build_param_list(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
typedef std::vector<Boxed_Value>::const_iterator pitr;
|
||||
|
||||
pitr parg = params.begin();
|
||||
pitr barg = m_args.begin();
|
||||
auto parg = params.begin();
|
||||
auto barg = m_args.begin();
|
||||
|
||||
std::vector<Boxed_Value> args;
|
||||
|
||||
@@ -366,12 +392,7 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "Bound: " + m_f->annotation();
|
||||
}
|
||||
@@ -400,15 +421,42 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (*m_f)(build_param_list(params));
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
Const_Proxy_Function m_f;
|
||||
std::vector<Boxed_Value> m_args;
|
||||
int m_arity;
|
||||
};
|
||||
|
||||
class Proxy_Function_Impl_Base : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Impl_Base() {}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (int(vals.size()) != get_arity())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -417,41 +465,25 @@ namespace chaiscript
|
||||
* type checking of Boxed_Value parameters, in a type safe manner
|
||||
*/
|
||||
template<typename Func>
|
||||
class Proxy_Function_Impl : public Proxy_Function_Base
|
||||
class Proxy_Function_Impl : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
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)
|
||||
Proxy_Function_Impl(std::function<Func> f)
|
||||
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
||||
m_f(std::move(f)), m_dummy_func(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Proxy_Function_Impl *pimpl = dynamic_cast<const Proxy_Function_Impl<Func> *>(&t_func);
|
||||
return pimpl != 0;
|
||||
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
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())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals);
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
{
|
||||
return "";
|
||||
return dynamic_cast<const Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
|
||||
}
|
||||
|
||||
std::function<Func> internal_function() const
|
||||
@@ -460,9 +492,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params);
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -478,14 +510,14 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
: Proxy_Function_Base(param_types(), 1),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Attribute_Access<T, Class> * aa
|
||||
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
|
||||
@@ -497,13 +529,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@@ -513,23 +539,23 @@ namespace chaiscript
|
||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
const Boxed_Value &bv = params[0];
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv);
|
||||
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv);
|
||||
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
}
|
||||
} else {
|
||||
@@ -557,13 +583,13 @@ namespace chaiscript
|
||||
class dispatch_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
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(std::vector<Boxed_Value> t_parameters,
|
||||
std::vector<Const_Proxy_Function> t_functions)
|
||||
: std::runtime_error("Error with function dispatch"), parameters(std::move(t_parameters)), functions(std::move(t_functions))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dispatch_error() noexcept {}
|
||||
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::vector<Boxed_Value> parameters;
|
||||
std::vector<Const_Proxy_Function> functions;
|
||||
@@ -572,23 +598,136 @@ namespace chaiscript
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
{
|
||||
if (t_func->get_arity() != static_cast<int>(plist.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||
|
||||
assert(plist.size() == types.size() - 1);
|
||||
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
{
|
||||
if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i], t_conversions)
|
||||
|| (types[i+1].is_arithmetic() && plist[i].get_type_info().is_arithmetic()))
|
||||
{
|
||||
// types continue to match
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// all types match
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
|
||||
InItr matching_func(end);
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
if (types_match_except_for_arithmetic(*begin, plist, t_conversions))
|
||||
{
|
||||
if (matching_func == end)
|
||||
{
|
||||
matching_func = begin;
|
||||
} else {
|
||||
// More than one function matches, not attempting
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
}
|
||||
|
||||
++begin;
|
||||
}
|
||||
|
||||
if (matching_func == end)
|
||||
{
|
||||
// no appropriate function to attempt arithmetic type conversion on
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
|
||||
|
||||
std::vector<Boxed_Value> newplist;
|
||||
const std::vector<Type_Info> &tis = (*matching_func)->get_param_types();
|
||||
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
{
|
||||
if (tis[i+1].is_arithmetic()
|
||||
&& plist[i].get_type_info().is_arithmetic()) {
|
||||
newplist.push_back(Boxed_Number(plist[i]).get_as(tis[i+1]).bv);
|
||||
} else {
|
||||
newplist.push_back(plist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return (*(*matching_func))(newplist, t_conversions);
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
//parameter failed to cast
|
||||
} catch (const exception::arity_error &) {
|
||||
//invalid num params
|
||||
} catch (const exception::guard_error &) {
|
||||
//guard failed to allow the function to execute
|
||||
}
|
||||
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
|
||||
std::multimap<size_t, const Proxy_Function_Base *> ordered_funcs;
|
||||
|
||||
for (const auto &func : funcs)
|
||||
{
|
||||
size_t numdiffs = 0;
|
||||
const auto arity = func->get_arity();
|
||||
|
||||
if (arity == -1)
|
||||
{
|
||||
numdiffs = plist.size();
|
||||
} else if (arity == static_cast<int>(plist.size())) {
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
{
|
||||
if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info()))
|
||||
{
|
||||
++numdiffs;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
ordered_funcs.insert(std::make_pair(numdiffs, func.get()));
|
||||
}
|
||||
|
||||
for (const auto &func : ordered_funcs )
|
||||
{
|
||||
try {
|
||||
if ((*begin)->filter(plist))
|
||||
if (func.second->filter(plist, t_conversions))
|
||||
{
|
||||
return (*(*begin))(plist);
|
||||
return (*(func.second))(plist, t_conversions);
|
||||
}
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
//parameter failed to cast, try again
|
||||
@@ -598,22 +737,9 @@ namespace chaiscript
|
||||
//guard failed to allow the function to execute,
|
||||
//try again
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
{
|
||||
return dispatch::dispatch(funcs.begin(), funcs.end(), plist);
|
||||
return detail::dispatch_with_conversions(funcs.cbegin(), funcs.cend(), plist, t_conversions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,21 +1,31 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include <string>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
@@ -32,7 +42,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~arity_error() noexcept {}
|
||||
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
int got;
|
||||
int expected;
|
||||
@@ -50,8 +60,8 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Params>
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
|
||||
{
|
||||
return std::vector<Type_Info> { chaiscript::detail::Get_Type_Info<Ret>::get(),
|
||||
chaiscript::detail::Get_Type_Info<Params>::get()... };
|
||||
/// \note somehow this is responsible for a large part of the code generation
|
||||
return { user_type<Ret>(), user_type<Params>()... };
|
||||
}
|
||||
|
||||
|
||||
@@ -59,14 +69,13 @@ namespace chaiscript
|
||||
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)
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, int generation, const Type_Conversions &t_conversions)
|
||||
{
|
||||
boxed_cast<Param>(params[generation]);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1);
|
||||
boxed_cast<Param>(params[generation], &t_conversions);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,24 +83,23 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, int)
|
||||
static void do_try(const std::vector<Boxed_Value> &, int, const Type_Conversions &)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarly used to prevent
|
||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0);
|
||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
@@ -105,41 +113,48 @@ namespace chaiscript
|
||||
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
struct Call_Func<Ret, 0, Params...>
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this
|
||||
#endif
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> &, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams))...);
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
* The function attempts to unbox each paramter to the expected type.
|
||||
* The function attempts to unbox each parameter to the expected type.
|
||||
* if any unboxing fails the execution of the function fails and
|
||||
* the bad_boxed_cast is passed up to the caller.
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
Ret call_func(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
{
|
||||
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params);
|
||||
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params, t_conversions);
|
||||
}
|
||||
|
||||
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,9 +171,9 @@ namespace chaiscript
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params));
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -166,9 +181,9 @@ namespace chaiscript
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
call_func(fun, params);
|
||||
call_func(fun, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
}
|
||||
};
|
||||
|
@@ -1,14 +1,18 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "bind_first.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -36,13 +40,17 @@ namespace chaiscript
|
||||
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);
|
||||
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
|
||||
/// std::function for member function pointers seems to be broken in MSVC
|
||||
return std::function<Ret(Class &, Args...)>(std::mem_fn(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);
|
||||
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
|
||||
/// std::function for member function pointers seems to be broken in MSVC
|
||||
return std::function<Ret (const Class &, Args...)>(std::mem_fn(func));
|
||||
}
|
||||
|
||||
template<bool Object>
|
||||
@@ -51,6 +59,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
static Proxy_Function go(T t)
|
||||
{
|
||||
/// \todo is it possible to reduce the number of templates generated here?
|
||||
return Proxy_Function(
|
||||
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
|
||||
}
|
||||
@@ -68,23 +77,6 @@ namespace 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
|
||||
/// 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 std::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member
|
||||
/// \param[in] t Function / member to expose
|
||||
///
|
||||
@@ -104,13 +96,32 @@ namespace chaiscript
|
||||
/// chai.add(fun(&MyClass::memberdata), "memberdata");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T>
|
||||
Proxy_Function fun(T t)
|
||||
{
|
||||
return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
|
||||
}
|
||||
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a std::function object
|
||||
/// \param[in] f std::function to expose to ChaiScript
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// std::function<int (char, float, std::string)> f = get_some_function();
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(fun(f), "some_function");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T>
|
||||
Proxy_Function fun(const std::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
|
||||
/// \param[in] t Function / member to expose
|
||||
/// \param[in] q Value to bind to first parameter
|
||||
@@ -128,7 +139,7 @@ namespace chaiscript
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T, typename Q>
|
||||
Proxy_Function fun(T t, const Q &q)
|
||||
{
|
||||
@@ -154,7 +165,7 @@ namespace chaiscript
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T, typename Q, typename R>
|
||||
Proxy_Function fun(T t, const Q &q, const R &r)
|
||||
{
|
||||
|
443
include/chaiscript/dispatchkit/type_conversions.hpp
Normal file
443
include/chaiscript/dispatchkit/type_conversions.hpp
Normal file
@@ -0,0 +1,443 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
|
||||
class bad_boxed_type_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &from) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0;
|
||||
|
||||
const Type_Info &to() const
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
const Type_Info &from() const
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
|
||||
: m_to(t_to), m_from(t_from)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Type_Conversion_Base() {}
|
||||
|
||||
private:
|
||||
Type_Info m_to;
|
||||
Type_Info m_from;
|
||||
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
std::shared_ptr<const To> data
|
||||
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<To> data
|
||||
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = dynamic_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
|
||||
To &data = dynamic_cast<To &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
class Type_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
||||
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
|
||||
m_func(std::move(t_func))
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
/// \todo better handling of errors from the conversion function
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
private:
|
||||
Callable m_func;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class Type_Conversions
|
||||
{
|
||||
public:
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||
{
|
||||
return *t_lhs != *t_rhs && t_lhs->before(*t_rhs);
|
||||
}
|
||||
};
|
||||
|
||||
Type_Conversions()
|
||||
: m_num_types(0),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Conversions(const Type_Conversions &t_other)
|
||||
: m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
||||
{
|
||||
auto &cache = *m_thread_cache;
|
||||
if (cache.size() != m_num_types)
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
cache = m_convertableTypes;
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
/// \todo error if a conversion already exists
|
||||
m_conversions.insert(conversion);
|
||||
m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()});
|
||||
m_num_types = m_convertableTypes.size();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool convertable_type() const
|
||||
{
|
||||
return thread_cache().count(user_type<T>().bare_type_info()) != 0;
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
bool converts() const
|
||||
{
|
||||
return converts(user_type<To>(), user_type<From>());
|
||||
}
|
||||
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
const auto &types = thread_cache();
|
||||
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0)
|
||||
{
|
||||
return has_conversion(to, from) || has_conversion(from, to);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
void enable_conversion_saves(bool t_val)
|
||||
{
|
||||
m_conversion_saves->enabled = t_val;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> take_saves()
|
||||
{
|
||||
std::vector<Boxed_Value> ret;
|
||||
std::swap(ret, m_conversion_saves->saves);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool has_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
return find(to, from) != m_conversions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::Type_Conversion_Base> get_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr = find(to, from);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
return std::find_if(m_conversions.begin(), m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
return conversion->to().bare_equal(to) && conversion->from().bare_equal(from);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> get_conversions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
|
||||
struct Conversion_Saves
|
||||
{
|
||||
Conversion_Saves()
|
||||
: enabled(false)
|
||||
{}
|
||||
|
||||
bool enabled;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||
std::set<const std::type_info *, Less_Than> m_convertableTypes;
|
||||
std::atomic_size_t m_num_types;
|
||||
chaiscript::detail::threading::Thread_Storage<std::set<const std::type_info *, Less_Than>> m_thread_cache;
|
||||
chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||
|
||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
///
|
||||
/// Create a new to class registration for applying to a module or to the ChaiScript engine
|
||||
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
|
||||
/// if you have a type that is introduced in a loadable module and is used by multiple modules
|
||||
/// (through a tertiary dll that is shared between the modules, static linking the new type
|
||||
/// into both loadable modules would not be portable), you need to register the type
|
||||
/// relationship in all modules that use the newly added type in a polymorphic way.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// class Base
|
||||
/// {};
|
||||
/// class Derived : public Base
|
||||
/// {};
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::to_class<Base, Derived>());
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Type_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
|
||||
return std::make_shared<detail::Dynamic_Conversion_Impl<Base, Derived>>();
|
||||
}
|
||||
|
||||
template<typename Callable>
|
||||
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to,
|
||||
const Callable &t_func)
|
||||
{
|
||||
return std::make_shared<detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
|
||||
}
|
||||
|
||||
template<typename From, typename To, typename Callable>
|
||||
Type_Conversion type_conversion(const Callable &t_function)
|
||||
{
|
||||
auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
return chaiscript::Boxed_Value(t_function(detail::Cast_Helper<const From &>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return std::make_shared<detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
Type_Conversion type_conversion()
|
||||
{
|
||||
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
auto &&from = detail::Cast_Helper<From>::cast(t_bv, nullptr);
|
||||
To to(from);
|
||||
return chaiscript::Boxed_Value(to);
|
||||
};
|
||||
|
||||
return std::make_shared<detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@@ -1,16 +1,17 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||
#define CHAISCRIPT_TYPE_INFO_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -24,11 +25,12 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// \brief Compile time deduced information about a type
|
||||
class Type_Info
|
||||
{
|
||||
public:
|
||||
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_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),
|
||||
@@ -37,65 +39,57 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info()
|
||||
: m_type_info(0), m_bare_type_info(0),
|
||||
CHAISCRIPT_CONSTEXPR Type_Info()
|
||||
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
||||
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_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)
|
||||
{
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Type_Info(Type_Info&&) = default;
|
||||
Type_Info& operator=(Type_Info&&) = default;
|
||||
#endif
|
||||
|
||||
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_is_arithmetic = ti.m_is_arithmetic;
|
||||
m_is_undef = ti.m_is_undef;
|
||||
return *this;
|
||||
}
|
||||
Type_Info(const Type_Info&) = default;
|
||||
Type_Info& operator=(const Type_Info&) = default;
|
||||
|
||||
bool operator<(const Type_Info &ti) const
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_type_info < ti.m_type_info;
|
||||
}
|
||||
|
||||
bool operator==(const Type_Info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return ti.m_type_info == m_type_info
|
||||
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
|
||||
}
|
||||
|
||||
bool operator==(const std::type_info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_type_info != 0 && (*m_type_info) == ti;
|
||||
return m_type_info != nullptr && (*m_type_info) == ti;
|
||||
}
|
||||
|
||||
bool bare_equal(const Type_Info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return ti.m_bare_type_info == m_bare_type_info
|
||||
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
||||
}
|
||||
|
||||
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; }
|
||||
CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_bare_type_info != nullptr
|
||||
&& (*m_bare_type_info) == ti;
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@@ -107,7 +101,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::string bare_name() const
|
||||
std::string bare_name() const
|
||||
{
|
||||
if (m_bare_type_info)
|
||||
{
|
||||
@@ -117,6 +111,11 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
|
||||
{
|
||||
return m_bare_type_info;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
@@ -138,7 +137,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
constexpr static Type_Info get()
|
||||
CHAISCRIPT_CONSTEXPR static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -153,7 +152,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
constexpr static Type_Info get()
|
||||
CHAISCRIPT_CONSTEXPR static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -168,7 +167,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
constexpr static Type_Info get()
|
||||
CHAISCRIPT_CONSTEXPR static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -183,7 +182,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
constexpr static Type_Info get()
|
||||
CHAISCRIPT_CONSTEXPR static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -198,7 +197,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
constexpr static Type_Info get()
|
||||
CHAISCRIPT_CONSTEXPR static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -208,11 +207,6 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Stripped_Type
|
||||
{
|
||||
typedef typename Bare_Type<typename detail::Get_Type_Info<T>::type>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Creates a Type_Info object representing the type passed in
|
||||
@@ -225,7 +219,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type(const T &/*t*/)
|
||||
CHAISCRIPT_CONSTEXPR Type_Info user_type(const T &/*t*/)
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
@@ -240,7 +234,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type()
|
||||
CHAISCRIPT_CONSTEXPR Type_Info user_type()
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
@@ -1,11 +1,13 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
|
||||
@@ -126,5 +128,5 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
|
||||
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
|
||||
|
||||
|
@@ -1,14 +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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
#define CHAISCRIPT_COMMON_HPP_
|
||||
#define CHAISCRIPT_COMMON_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../dispatchkit/boxed_value.hpp"
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "../dispatchkit/type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
struct AST_Node;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -21,23 +35,22 @@ namespace chaiscript
|
||||
public:
|
||||
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary
|
||||
};
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* Helper lookup to get the name of each node type
|
||||
*/
|
||||
|
||||
/// Helper lookup to get the name of each node type
|
||||
const char *ast_node_type_to_string(int ast_node_type) {
|
||||
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition"};
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
@@ -55,27 +68,27 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<const AST_Node> AST_NodePtr_Const;
|
||||
|
||||
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
namespace exception
|
||||
{
|
||||
/**
|
||||
* Errors generated during parsing or evaluation
|
||||
*/
|
||||
|
||||
/// Errors generated during parsing or evaluation
|
||||
struct eval_error : public std::runtime_error {
|
||||
std::string reason;
|
||||
File_Position start_position;
|
||||
File_Position end_position;
|
||||
std::string filename;
|
||||
std::string detail;
|
||||
std::vector<AST_NodePtr> call_stack;
|
||||
std::vector<AST_NodePtr_Const> call_stack;
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
@@ -83,18 +96,18 @@ namespace chaiscript
|
||||
eval_error(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
|
||||
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
|
||||
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why) noexcept
|
||||
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||
reason(t_why)
|
||||
{}
|
||||
@@ -105,23 +118,23 @@ namespace chaiscript
|
||||
|
||||
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 << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
||||
ss << '\n' << detail << '\n';
|
||||
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 << '\n';
|
||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << std::endl;
|
||||
ss << '\n';
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual ~eval_error() noexcept {}
|
||||
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
private:
|
||||
|
||||
@@ -251,15 +264,13 @@ namespace chaiscript
|
||||
std::stringstream ss;
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:" << std::endl;
|
||||
ss << " " << t_functions.size() << " overloads available:\n";
|
||||
|
||||
for (std::vector<chaiscript::Const_Proxy_Function>::const_iterator itr = t_functions.begin();
|
||||
itr != t_functions.end();
|
||||
++itr)
|
||||
for (const auto & t_function : t_functions)
|
||||
{
|
||||
ss << " " << format_types((*itr), t_dot_notation, t_ss) << std::endl;
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -279,7 +290,7 @@ namespace chaiscript
|
||||
{
|
||||
std::string paramstr;
|
||||
|
||||
for (std::vector<Boxed_Value>::const_iterator itr = t_parameters.begin();
|
||||
for (auto itr = t_parameters.begin();
|
||||
itr != t_parameters.end();
|
||||
++itr)
|
||||
{
|
||||
@@ -377,15 +388,14 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors generated when loading a file
|
||||
*/
|
||||
|
||||
/// Errors generated when loading a file
|
||||
struct file_not_found_error : public std::runtime_error {
|
||||
file_not_found_error(const std::string &t_filename) noexcept
|
||||
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
{ }
|
||||
|
||||
virtual ~file_not_found_error() noexcept {}
|
||||
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -407,39 +417,34 @@ namespace chaiscript
|
||||
|
||||
oss << text;
|
||||
|
||||
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||
oss << this->children[j]->pretty_print();
|
||||
for (auto & elem : this->children) {
|
||||
oss << elem->pretty_print();
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the contents of an AST node, including its children, recursively
|
||||
*/
|
||||
std::string to_string(std::string t_prepend = "") {
|
||||
|
||||
/// Prints the contents of an AST node, including its children, recursively
|
||||
std::string to_string(const std::string &t_prepend = "") const {
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
|
||||
|
||||
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||
<< this->text << " : " << this->start.line << ", " << this->start.column << '\n';
|
||||
|
||||
for (size_t j = 0; j < this->children.size(); ++j) {
|
||||
oss << this->children[j]->to_string(t_prepend + " ");
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string internal_to_string() {
|
||||
return to_string();
|
||||
}
|
||||
|
||||
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
|
||||
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) const
|
||||
{
|
||||
try {
|
||||
return eval_internal(t_e);
|
||||
} catch (exception::eval_error &ee) {
|
||||
ee.call_stack.push_back(shared_from_this());
|
||||
throw ee;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,19 +455,19 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname,
|
||||
AST_Node(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),
|
||||
text(std::move(t_ast_node_text)), identifier(t_id), filename(t_fname),
|
||||
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
|
||||
{
|
||||
}
|
||||
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
|
||||
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
|
||||
AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
|
||||
text(std::move(t_ast_node_text)), identifier(t_id), filename(t_fname) {}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &)
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const
|
||||
{
|
||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
||||
}
|
||||
@@ -478,25 +483,33 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Special type for returned values
|
||||
*/
|
||||
|
||||
/// Special type for returned values
|
||||
struct Return_Value {
|
||||
Boxed_Value retval;
|
||||
|
||||
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type indicating a call to 'break'
|
||||
*/
|
||||
|
||||
/// Special type indicating a call to 'break'
|
||||
struct Break_Loop {
|
||||
Break_Loop() { }
|
||||
};
|
||||
|
||||
|
||||
/// Special type indicating a call to 'continue'
|
||||
struct Continue_Loop {
|
||||
Continue_Loop() { }
|
||||
};
|
||||
|
||||
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Scope_Push_Pop
|
||||
{
|
||||
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
|
||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
||||
|
||||
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||
: m_de(t_de)
|
||||
{
|
||||
@@ -510,16 +523,16 @@ namespace chaiscript
|
||||
|
||||
|
||||
private:
|
||||
// explicitly unimplemented copy and assignment
|
||||
Scope_Push_Pop(const Scope_Push_Pop &);
|
||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &);
|
||||
|
||||
chaiscript::detail::Dispatch_Engine &m_de;
|
||||
};
|
||||
|
||||
/// Creates a new functon call and pops it on destruction
|
||||
/// Creates a new function call and pops it on destruction
|
||||
struct Function_Push_Pop
|
||||
{
|
||||
Function_Push_Pop(const Function_Push_Pop &) = delete;
|
||||
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
||||
|
||||
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||
: m_de(t_de)
|
||||
{
|
||||
@@ -536,11 +549,13 @@ namespace chaiscript
|
||||
m_de.save_function_params(t_params);
|
||||
}
|
||||
|
||||
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
m_de.save_function_params(std::move(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;
|
||||
};
|
||||
@@ -548,6 +563,9 @@ namespace chaiscript
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Stack_Push_Pop
|
||||
{
|
||||
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
|
||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
||||
|
||||
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||
: m_de(t_de)
|
||||
{
|
||||
@@ -561,9 +579,6 @@ namespace chaiscript
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -571,5 +586,5 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||
|
||||
|
@@ -1,23 +1,40 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||
#define CHAISCRIPT_ENGINE_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "../dispatchkit/boxed_cast_helper.hpp"
|
||||
#include "../dispatchkit/boxed_value.hpp"
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "../dispatchkit/type_conversions.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
|
||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
@@ -28,9 +45,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include "chaiscript_prelude.chai"
|
||||
#include "chaiscript_parser.hpp"
|
||||
#include "../dispatchkit/exception_specification.hpp"
|
||||
#include "chaiscript_parser.hpp"
|
||||
#include "chaiscript_prelude.chai"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -39,12 +56,12 @@ namespace chaiscript
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &t_reason) noexcept
|
||||
load_module_error(const std::string &t_reason) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~load_module_error() noexcept
|
||||
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -52,7 +69,7 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
@@ -123,32 +140,32 @@ namespace chaiscript
|
||||
struct Loadable_Module
|
||||
{
|
||||
template<typename T>
|
||||
static std::wstring towstring(const T &t_str)
|
||||
static std::wstring to_wstring(const T &t_str)
|
||||
{
|
||||
return std::wstring(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string tostring(const T &t_str)
|
||||
static std::string to_string(const T &t_str)
|
||||
{
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
template<typename T>
|
||||
static std::wstring toproperstring(const T &t_str)
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
return towstring(t_str);
|
||||
return to_wstring(t_str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string toproperstring(const T &t_str)
|
||||
static std::string to_proper_string(const T &t_str)
|
||||
{
|
||||
return tostring(t_str);
|
||||
return to_string(t_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string GetErrorMessage(DWORD t_err)
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
typedef LPWSTR StringType;
|
||||
@@ -157,9 +174,9 @@ namespace chaiscript
|
||||
typedef LPSTR StringType;
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = 0;
|
||||
StringType lpMsgBuf = nullptr;
|
||||
|
||||
FormatMessage(
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
@@ -167,25 +184,23 @@ namespace chaiscript
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(StringType)&lpMsgBuf,
|
||||
0, NULL );
|
||||
|
||||
if (lpMsgBuf)
|
||||
0, NULL ) != 0 && lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
LocalFree(lpMsgBuf);
|
||||
return tostring(retval);
|
||||
return to_string(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(toproperstring(t_filename).c_str()))
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +220,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,10 +270,7 @@ namespace chaiscript
|
||||
|
||||
chaiscript::detail::Dispatch_Engine m_engine;
|
||||
|
||||
|
||||
/**
|
||||
* Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
*/
|
||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||
{
|
||||
try {
|
||||
@@ -270,7 +282,7 @@ namespace chaiscript
|
||||
return Boxed_Value();
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::eval::detail::Return_Value &rv) {
|
||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
}
|
||||
}
|
||||
@@ -287,9 +299,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluates the given string, used during eval() inside of a script
|
||||
*/
|
||||
|
||||
/// Evaluates the given string, used during eval() inside of a script
|
||||
const Boxed_Value internal_eval(const std::string &t_e) {
|
||||
try {
|
||||
return do_eval(t_e, "__EVAL__", true);
|
||||
@@ -298,16 +309,12 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current evaluation m_engine
|
||||
*/
|
||||
/// Returns the current evaluation m_engine
|
||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() {
|
||||
return m_engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
*/
|
||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
void build_eval_system(const ModulePtr &t_lib) {
|
||||
m_engine.add_reserved_word("def");
|
||||
m_engine.add_reserved_word("fun");
|
||||
@@ -323,6 +330,7 @@ namespace chaiscript
|
||||
m_engine.add_reserved_word("break");
|
||||
m_engine.add_reserved_word("true");
|
||||
m_engine.add_reserved_word("false");
|
||||
m_engine.add_reserved_word("class");
|
||||
m_engine.add_reserved_word("_");
|
||||
|
||||
if (t_lib)
|
||||
@@ -337,11 +345,23 @@ namespace chaiscript
|
||||
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(Proxy_Function(new dispatch::Dynamic_Proxy_Function(
|
||||
[this](const std::vector<Boxed_Value> &t_params) {
|
||||
return m_engine.call_exists(t_params);
|
||||
})), "call_exists");
|
||||
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type");
|
||||
m_engine.add(fun<void (const Type_Info &, const Type_Info &, const std::function<Boxed_Value (const Boxed_Value &)> &)> (
|
||||
[=](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
|
||||
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
|
||||
}
|
||||
), "add_type_conversion");
|
||||
|
||||
typedef void (ChaiScript::*load_mod_1)(const std::string&);
|
||||
|
||||
typedef std::string (ChaiScript::*load_mod_1)(const std::string&);
|
||||
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
|
||||
|
||||
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
|
||||
@@ -351,20 +371,27 @@ namespace chaiscript
|
||||
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
|
||||
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
|
||||
|
||||
do_eval(ChaiScript_Prelude::chaiscript_prelude, "standard prelude");
|
||||
m_engine.add(fun(&ChaiScript::version_major, this), "version_major");
|
||||
m_engine.add(fun(&ChaiScript::version_minor, this), "version_minor");
|
||||
m_engine.add(fun(&ChaiScript::version_patch, this), "version_patch");
|
||||
m_engine.add(fun(&ChaiScript::version, this), "version");
|
||||
|
||||
m_engine.add(fun(&ChaiScript::add_global_const, this), "add_global_const");
|
||||
m_engine.add(fun(&ChaiScript::add_global, this), "add_global");
|
||||
|
||||
do_eval(ChaiScript_Prelude::chaiscript_prelude(), "standard prelude");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for loading a file
|
||||
*/
|
||||
std::string load_file(const std::string &t_filename) {
|
||||
|
||||
/// Helper function for loading a file
|
||||
static std::string load_file(const std::string &t_filename) {
|
||||
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
||||
|
||||
if (!infile.is_open()) {
|
||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
std::streampos size = infile.tellg();
|
||||
const auto size = infile.tellg();
|
||||
infile.seekg(0, std::ios::beg);
|
||||
|
||||
assert(size >= 0);
|
||||
@@ -373,7 +400,7 @@ namespace chaiscript
|
||||
{
|
||||
return std::string();
|
||||
} else {
|
||||
std::vector<char> v(static_cast<unsigned int>(size));
|
||||
std::vector<char> v(static_cast<size_t>(size));
|
||||
infile.read(&v[0], size);
|
||||
return std::string(v.begin(), v.end());
|
||||
}
|
||||
@@ -385,9 +412,9 @@ namespace chaiscript
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript(const ModulePtr &t_lib,
|
||||
const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||
const std::vector<std::string> &t_usepaths = std::vector<std::string>())
|
||||
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths)
|
||||
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_modulepaths(std::move(t_modulepaths)), m_usepaths(std::move(t_usepaths))
|
||||
{
|
||||
if (m_modulepaths.empty())
|
||||
{
|
||||
@@ -409,9 +436,9 @@ namespace chaiscript
|
||||
///
|
||||
/// \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)
|
||||
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_modulepaths(std::move(t_modulepaths)), m_usepaths(std::move(t_usepaths))
|
||||
{
|
||||
if (m_modulepaths.empty())
|
||||
{
|
||||
@@ -423,8 +450,7 @@ namespace chaiscript
|
||||
m_usepaths.push_back("");
|
||||
}
|
||||
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
// If on Unix, add the path of the current executable to the module search path
|
||||
// as windows would do
|
||||
|
||||
@@ -440,7 +466,7 @@ namespace chaiscript
|
||||
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('/');
|
||||
const size_t lastslash = dllpath.rfind('/');
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
dllpath.erase(lastslash);
|
||||
@@ -448,23 +474,55 @@ namespace chaiscript
|
||||
|
||||
// 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());
|
||||
const 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
|
||||
m_modulepaths.insert(m_modulepaths.begin(), dllpath+"/");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib");
|
||||
load_module("chaiscript_stdlib-" + version());
|
||||
|
||||
build_eval_system(ModulePtr());
|
||||
}
|
||||
|
||||
int version_major() const
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
|
||||
int version_minor() const
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
|
||||
int version_patch() const
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
|
||||
std::string version() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << version_major() << "." << version_minor() << "." << version_patch();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string get_type_name(const Type_Info &ti) const
|
||||
{
|
||||
return m_engine.get_type_name(ti);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string get_type_name() const
|
||||
{
|
||||
return get_type_name(user_type<T>());
|
||||
}
|
||||
|
||||
|
||||
/// \brief Loads and parses a file. If the file is already, it is not reloaded
|
||||
@@ -474,31 +532,30 @@ namespace chaiscript
|
||||
/// \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)
|
||||
for (const auto &path : m_usepaths)
|
||||
{
|
||||
try {
|
||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||
const auto appendedpath = path + 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);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::unique_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);
|
||||
}
|
||||
l2.lock();
|
||||
m_used_files.insert(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
|
||||
}
|
||||
}
|
||||
|
||||
// failed to load by any name
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
/// \brief Adds a constant object that is available in all contexts and to all threads
|
||||
@@ -512,6 +569,17 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Adds a mutable 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
|
||||
/// \warning The user is responsible for making sure the object is thread-safe if necessary
|
||||
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
||||
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
m_engine.add_global(t_bv, t_name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
||||
/// \sa ChaiScript::get_state
|
||||
/// \sa ChaiScript::set_state
|
||||
@@ -601,7 +669,7 @@ namespace chaiscript
|
||||
/// chai.add(chaiscript::var(&obj), "obj"); // Add a pointer to a locally defined object
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingitems
|
||||
/// \sa \ref adding_items
|
||||
template<typename T>
|
||||
ChaiScript &add(const T &t_t, const std::string &t_name)
|
||||
{
|
||||
@@ -618,7 +686,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||
/// \endcode
|
||||
ChaiScript &add(const Dynamic_Cast_Conversion &d)
|
||||
ChaiScript &add(const Type_Conversion &d)
|
||||
{
|
||||
m_engine.add(d);
|
||||
return *this;
|
||||
@@ -645,36 +713,39 @@ namespace chaiscript
|
||||
/// (the symbol mentioned above), an exception is thrown.
|
||||
///
|
||||
/// \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::string load_module(const std::string &t_module_name)
|
||||
{
|
||||
std::vector<exception::load_module_error> errors;
|
||||
std::string version_stripped_name = t_module_name;
|
||||
size_t version_pos = version_stripped_name.find("-"+version());
|
||||
if (version_pos != std::string::npos)
|
||||
{
|
||||
version_stripped_name.erase(version_pos);
|
||||
}
|
||||
|
||||
std::vector<std::string> prefixes;
|
||||
prefixes.push_back("lib");
|
||||
prefixes.push_back("");
|
||||
std::vector<std::string> prefixes{"lib", "cyg", ""};
|
||||
|
||||
std::vector<std::string> postfixes;
|
||||
postfixes.push_back(".dll");
|
||||
postfixes.push_back(".so");
|
||||
postfixes.push_back("");
|
||||
std::vector<std::string> postfixes{".dll", ".so", ""};
|
||||
|
||||
for (size_t i = 0; i < m_modulepaths.size(); ++i)
|
||||
for (auto & elem : m_modulepaths)
|
||||
{
|
||||
for (auto & prefix : prefixes)
|
||||
{
|
||||
for (size_t j = 0; j < prefixes.size(); ++j)
|
||||
{
|
||||
for (size_t k = 0; k < postfixes.size(); ++k)
|
||||
{
|
||||
try {
|
||||
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
|
||||
load_module(t_module_name, name);
|
||||
return;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
}
|
||||
for (auto & postfix : postfixes)
|
||||
{
|
||||
try {
|
||||
const auto name = elem + prefix + t_module_name + postfix;
|
||||
// std::cerr << "trying location: " << name << '\n';
|
||||
load_module(version_stripped_name, name);
|
||||
return name;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
// std::cerr << "error: " << e.what() << '\n';
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string errstring;
|
||||
|
||||
@@ -731,9 +802,9 @@ namespace chaiscript
|
||||
return do_eval(t_script);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw bv;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,20 +825,28 @@ namespace chaiscript
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
try {
|
||||
return boxed_cast<T>(do_eval(t_input, t_filename));
|
||||
return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw bv;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||
{
|
||||
return m_engine.boxed_cast<Type>(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
|
||||
/// \param[in] t_filename Optional filename to report to the user for where the error occurred. Useful
|
||||
/// in special cases where you are loading a file internally instead of using eval_file
|
||||
///
|
||||
/// \return result of the script execution
|
||||
@@ -779,9 +858,9 @@ namespace chaiscript
|
||||
return do_eval(t_input, t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw bv;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,13 +874,13 @@ namespace chaiscript
|
||||
return do_eval(load_file(t_filename), t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw bv;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result.
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe 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
|
||||
@@ -812,12 +891,12 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
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));
|
||||
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw bv;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
struct ChaiScript_Prelude {
|
||||
constexpr static const char *chaiscript_prelude=R""(
|
||||
static std::string chaiscript_prelude() { return R""(
|
||||
|
||||
def lt(l, r) {
|
||||
if (call_exists(`<`, l, r)) {
|
||||
@@ -40,9 +40,9 @@ 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);
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
|
||||
{
|
||||
eval(type_name(x))(x).copy_var_attrs(x);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,11 +56,6 @@ 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());
|
||||
@@ -136,8 +131,8 @@ def insert_at(container, pos, x)
|
||||
|
||||
# Returns the reverse of the given container
|
||||
def reverse(container) {
|
||||
auto retval = new(container);
|
||||
auto r = range(container);
|
||||
auto retval := new(container);
|
||||
auto r := range(container);
|
||||
while (!r.empty()) {
|
||||
retval.push_back(r.back());
|
||||
r.pop_back();
|
||||
@@ -147,10 +142,16 @@ def reverse(container) {
|
||||
|
||||
# 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);
|
||||
{
|
||||
clone(r);
|
||||
}
|
||||
|
||||
def range(r) : call_exists(range_internal, r)
|
||||
{
|
||||
var ri := range_internal(r);
|
||||
ri.get_var_attr("internal_obj") := r;
|
||||
ri;
|
||||
}
|
||||
|
||||
# The retro attribute that contains the underlying range
|
||||
attr retro::m_range;
|
||||
@@ -200,19 +201,19 @@ def retro::empty()
|
||||
|
||||
# Performs the second value function over the container first value
|
||||
def for_each(container, func) : call_exists(range, container) {
|
||||
var t_range = 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 back_inserter(container) {
|
||||
bind(push_back, container, _);
|
||||
}
|
||||
|
||||
def contains(container, item, compare_func) : call_exists(range, container) {
|
||||
auto t_range = range(container);
|
||||
auto t_range := range(container);
|
||||
while (!t_range.empty()) {
|
||||
if ( compare_func(t_range.front(), item) ) {
|
||||
return true;
|
||||
@@ -220,15 +221,15 @@ def contains(container, item, compare_func) : call_exists(range, container) {
|
||||
|
||||
t_range.pop_front();
|
||||
}
|
||||
return false;
|
||||
false;
|
||||
}
|
||||
|
||||
def contains(container, item) {
|
||||
return contains(container, item, eq)
|
||||
contains(container, item, eq)
|
||||
}
|
||||
|
||||
def map(container, func, inserter) : call_exists(range, container) {
|
||||
auto range = range(container);
|
||||
auto range := range(container);
|
||||
while (!range.empty()) {
|
||||
inserter(func(range.front()));
|
||||
range.pop_front();
|
||||
@@ -237,7 +238,7 @@ def map(container, func, inserter) : call_exists(range, container) {
|
||||
|
||||
# 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);
|
||||
auto retval := new(container);
|
||||
map(container, func, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
@@ -245,7 +246,7 @@ def map(container, func) {
|
||||
# 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);
|
||||
auto range := range(container);
|
||||
while (!range.empty()) {
|
||||
retval = (func(range.front(), retval));
|
||||
range.pop_front();
|
||||
@@ -266,8 +267,8 @@ def product(container) {
|
||||
# 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);
|
||||
auto inserter := back_inserter(retval);
|
||||
auto range := range(y);
|
||||
while (!range.empty()) {
|
||||
inserter(range.front());
|
||||
range.pop_front();
|
||||
@@ -277,7 +278,7 @@ def concat(x, y) : call_exists(clone, x) {
|
||||
|
||||
|
||||
def take(container, num, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto r := range(container);
|
||||
auto i = num;
|
||||
while ((i > 0) && (!r.empty())) {
|
||||
inserter(r.front());
|
||||
@@ -289,14 +290,14 @@ def take(container, num, inserter) : call_exists(range, container) {
|
||||
|
||||
# Returns a new container with the given number of elements taken from the container
|
||||
def take(container, num) {
|
||||
auto retval = new(container);
|
||||
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);
|
||||
auto r := range(container);
|
||||
while ((!r.empty()) && f(r.front())) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
@@ -306,14 +307,14 @@ def take_while(container, f, inserter) : call_exists(range, container) {
|
||||
|
||||
# Returns a new container with the given elements match the second value function
|
||||
def take_while(container, f) {
|
||||
auto retval = new(container);
|
||||
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 r := range(container);
|
||||
auto i = num;
|
||||
while ((i > 0) && (!r.empty())) {
|
||||
r.pop_front();
|
||||
@@ -328,14 +329,14 @@ def drop(container, num, inserter) : call_exists(range, container) {
|
||||
|
||||
# Returns a new container with the given number of elements dropped from the given container
|
||||
def drop(container, num) {
|
||||
auto retval = new(container);
|
||||
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);
|
||||
auto r := range(container);
|
||||
while ((!r.empty())&& f(r.front())) {
|
||||
r.pop_front();
|
||||
}
|
||||
@@ -348,7 +349,7 @@ def drop_while(container, f, inserter) : call_exists(range, container) {
|
||||
|
||||
# Returns a new container with the given elements dropped that match the second value function
|
||||
def drop_while(container, f) {
|
||||
auto retval = new(container);
|
||||
auto retval := new(container);
|
||||
drop_while(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
@@ -356,7 +357,7 @@ def drop_while(container, f) {
|
||||
|
||||
# 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 r := range(container);
|
||||
auto retval = r.front();
|
||||
r.pop_front();
|
||||
retval = func(retval, r.front());
|
||||
@@ -372,7 +373,7 @@ def reduce(container, func) : container.size() >= 2 && call_exists(range, contai
|
||||
# Returns a string of the elements in container delimited by the second value string
|
||||
def join(container, delim) {
|
||||
auto retval = "";
|
||||
auto range = range(container);
|
||||
auto range := range(container);
|
||||
if (!range.empty()) {
|
||||
retval += to_string(range.front());
|
||||
range.pop_front();
|
||||
@@ -387,7 +388,7 @@ def join(container, delim) {
|
||||
|
||||
|
||||
def filter(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto r := range(container);
|
||||
while (!r.empty()) {
|
||||
if (f(r.front())) {
|
||||
inserter(r.front());
|
||||
@@ -399,7 +400,7 @@ def filter(container, f, inserter) : call_exists(range, container) {
|
||||
|
||||
# Returns a new Vector which match the second value function
|
||||
def filter(container, f) {
|
||||
auto retval = new(container);
|
||||
auto retval := new(container);
|
||||
filter(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
@@ -416,7 +417,7 @@ def generate_range(x, y, inserter) {
|
||||
|
||||
# Returns a new Vector which represents the range from the first value to the second value
|
||||
def generate_range(x, y) {
|
||||
auto retval = Vector();
|
||||
auto retval := Vector();
|
||||
generate_range(x,y,back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
@@ -429,8 +430,8 @@ def collate(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);
|
||||
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();
|
||||
@@ -441,7 +442,7 @@ def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y)
|
||||
|
||||
# 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();
|
||||
auto retval := Vector();
|
||||
zip_with(f,x,y,back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
@@ -455,37 +456,37 @@ def zip(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));
|
||||
find(this, substr, size_t(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));
|
||||
rfind(this, substr, size_t(-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));
|
||||
find_first_of(this, list, size_t(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));
|
||||
find_last_of(this, list, size_t(-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));
|
||||
find_first_not_of(this, list, size_t(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));
|
||||
find_last_not_of(this, list, size_t(-1));
|
||||
}
|
||||
|
||||
|
||||
@@ -505,7 +506,7 @@ def string::trim() {
|
||||
|
||||
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
|
||||
auto range = range(container);
|
||||
auto range := range(container);
|
||||
while (!range.empty()) {
|
||||
if (compare_func(range.front(), value)) {
|
||||
return range;
|
||||
@@ -513,16 +514,17 @@ def find(container, value, compare_func) : call_exists(range, container) && is_t
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
return range;
|
||||
range;
|
||||
}
|
||||
|
||||
|
||||
def find(container, value) {
|
||||
return find(container, value, eq)
|
||||
find(container, value, eq)
|
||||
}
|
||||
|
||||
|
||||
)"";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
namespace ChaiScript_Language
|
||||
{
|
||||
|
||||
/// \page LangStandardLibraryRef ChaiScript Language Standard Libary Reference
|
||||
/// \page LangStandardLibraryRef ChaiScript Language Standard Library Reference
|
||||
///
|
||||
/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
|
||||
/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
|
||||
@@ -112,7 +112,7 @@ class Map
|
||||
};
|
||||
|
||||
|
||||
/// \brief A concept implemented by string, Vector and Map. It is convertable to Range, default constructable and back_insertable
|
||||
/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
|
||||
class Container
|
||||
{
|
||||
public:
|
||||
@@ -153,10 +153,10 @@ void print(Object o);
|
||||
|
||||
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
|
||||
///
|
||||
/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string
|
||||
/// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string
|
||||
/// using the chaiscript::boxed_cast and chaiscript::var functions.
|
||||
///
|
||||
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the
|
||||
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
|
||||
/// std::string of the same name.
|
||||
///
|
||||
/// \note Object and function notations are equivalent in ChaiScript. This means that
|
||||
@@ -519,7 +519,7 @@ class Function
|
||||
/// \brief Returns a vector of Type_Info objects that represent the param types for this function.
|
||||
/// The first value in the list is the return type.
|
||||
///
|
||||
/// If this function is a conglomeration of several functions (get_contained_values().size() > 0)
|
||||
/// If this function is a conglomerate of several functions (get_contained_values().size() > 0)
|
||||
/// then the function returns as many Type_Info objects as it can. If the functions contained all have
|
||||
/// the same arity, then it represents the arity. If they have different arities, it returns only
|
||||
/// one value - the return type.
|
||||
@@ -534,7 +534,7 @@ class Function
|
||||
/// \endcode
|
||||
Vector get_param_types() const;
|
||||
|
||||
/// \brief Returns true if the function has a guard to it. Always returns falls for a conglomerate function
|
||||
/// \brief Returns true if the function has a guard to it. Always returns false for a conglomerate function
|
||||
bool has_guard() const;
|
||||
|
||||
/// \brief Calls the function with the given set of parameters and returns the value;
|
||||
|
@@ -1,14 +1,19 @@
|
||||
// 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)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
|
||||
#include "../chaiscript.hpp"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "../dispatchkit/type_info.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
@@ -16,24 +21,46 @@ namespace chaiscript
|
||||
namespace utility
|
||||
{
|
||||
|
||||
/// Single step command for registering a class with ChaiScript
|
||||
///
|
||||
/// \param[in,out] t_module Model to add class to
|
||||
/// \param[in] t_class_name Name of the class being registered
|
||||
/// \param[in] t_constructors Vector of constructors to add
|
||||
/// \param[in] t_funcs Vector of methods to add
|
||||
///
|
||||
/// \example Adding a basic class to ChaiScript in one step
|
||||
///
|
||||
/// \code
|
||||
/// chaiscript::utility::add_class<test>(*m,
|
||||
/// "test",
|
||||
/// { constructor<test ()>(),
|
||||
/// constructor<test (const test &)>() },
|
||||
/// { {fun(&test::function), "function"},
|
||||
/// {fun(&test::function2), "function2"},
|
||||
/// {fun(&test::function3), "function3"},
|
||||
/// {fun(static_cast<std::string(test::*)(double)>(&test::functionoverload)), "functionoverload" },
|
||||
/// {fun(static_cast<std::string(test::*)(int)>(&test::functionoverload)), "functionoverload" },
|
||||
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
|
||||
/// }
|
||||
/// );
|
||||
///
|
||||
template<typename Class, typename ModuleType>
|
||||
void add_class(ModuleType &t_module,
|
||||
const std::string &t_classname,
|
||||
const std::string &t_class_name,
|
||||
const std::vector<chaiscript::Proxy_Function> &t_constructors,
|
||||
const std::vector<std::pair<chaiscript::Proxy_Function, std::string>> &t_funcs)
|
||||
{
|
||||
t_module.add(chaiscript::user_type<Class>(), t_classname);
|
||||
t_module.add(chaiscript::user_type<Class>(), t_class_name);
|
||||
|
||||
for(const chaiscript::Proxy_Function &ctor: t_constructors)
|
||||
{
|
||||
t_module.add(ctor, t_classname);
|
||||
t_module.add(ctor, t_class_name);
|
||||
}
|
||||
|
||||
for(auto fun: t_funcs)
|
||||
for(const auto &fun: t_funcs)
|
||||
{
|
||||
t_module.add(fun.first, fun.second);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,7 @@
|
||||
Copyright 2009-2012 Jason Turner and Jonathan Turner. All Rights Reserved.
|
||||
Copyright 2009-2014 Jason Turner
|
||||
Copyright 2009-2012 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:
|
||||
|
10
readme.md
10
readme.md
@@ -1,8 +1,14 @@
|
||||
Master Status: [](https://travis-ci.org/ChaiScript/ChaiScript) [](https://coveralls.io/r/ChaiScript/ChaiScript?branch=master)
|
||||
|
||||
Develop Status: [](https://travis-ci.org/ChaiScript/ChaiScript) [](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop)
|
||||
|
||||
|
||||
ChaiScript
|
||||
|
||||
http://www.chaiscript.com
|
||||
|
||||
(c) 2009-2012 Jason Turner and Jonathan Turner
|
||||
(c) 2009-2012 Jonathan Turner
|
||||
(c) 2009-2014 Jason Turner
|
||||
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
@@ -10,6 +16,8 @@ Release under the BSD license, see "license.txt" for details.
|
||||
Introduction
|
||||
============
|
||||
|
||||
[](https://gitter.im/ChaiScript/ChaiScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
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
|
||||
|
131
releasenotes.md
Normal file
131
releasenotes.md
Normal file
@@ -0,0 +1,131 @@
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.5.1
|
||||
|
||||
### Changes since 5.5.0
|
||||
* 30% performance increase
|
||||
* Fix handling of object stack, resulting in greatly reduced memory usage
|
||||
* Code cleanups
|
||||
|
||||
### Changes since 5.4.0
|
||||
* 2x performance increase
|
||||
* Significant code cleanups
|
||||
* Throw exception if user attempts to call function on null object
|
||||
* Allow user defined type conversions
|
||||
* Fix object lifetime for nested function calls made at the global scope
|
||||
* Fix returning of boolean values from function calls
|
||||
|
||||
|
||||
### Changes since 5.3.1
|
||||
* Decreased compile time and build size
|
||||
* Make "reflection" module built in (losing some of the time / build size gains)
|
||||
* Add new "class" syntax for ChaiScript defined methods and attributes see: [unittests/class.chai](unittests/class.chai) for examples
|
||||
* Minor performance enhancements
|
||||
* major to_string performance enhancements
|
||||
* Provide API for retrieving registered type name #124
|
||||
* Added strong reference to container to range object #132
|
||||
|
||||
|
||||
### Changes since 5.3.0
|
||||
* Add automatic conversion of arithmetic return types, following the same
|
||||
rules as conversion of arithmetic types when passing parameters
|
||||
* Add automatic casting up the inheritence hierarchy when possible.
|
||||
* Enable travis.ci testing
|
||||
* Allow users to add globals from within script
|
||||
* Various static analysis fixes
|
||||
* Code modernization to C++11
|
||||
* Unofficial support for Haiku added
|
||||
* Fix #121 - Inability to compile on cygwin
|
||||
* Formatting fixes and spelling corrections
|
||||
* Apply "include what you use" https://code.google.com/p/include-what-you-use/
|
||||
* Apply clang-modernize
|
||||
* Various threading fixes
|
||||
* Performance improvements
|
||||
|
||||
### Changes since 5.2.0
|
||||
* Official support for MSVC with C++11. All major platforms and compilers are now support for C++11 release
|
||||
|
||||
### Changes since 4.2.0
|
||||
* Enhanced unit tests
|
||||
* Add `continue` statement, fix various use cases for `for` loops
|
||||
* Fix use of suffixed numbers in vector initialization
|
||||
* Code cleanups
|
||||
* Eliminate global data, which makes code more portable and thread safe
|
||||
* Fix issue #79
|
||||
* Merge pretty_print fixes from @mgee #82
|
||||
* Compiler warning fixes for latest compiler releases
|
||||
* Fix threading problems
|
||||
* Fix linking error on MacOS Mavericks #88
|
||||
* Allow non-const globals
|
||||
* Make sure user cannot name a variable with `::` in it #91
|
||||
* Fix various string / map / vector `size` and `count` calls for compilers which have weird overloads for them. #90 #93 #95
|
||||
* Make module search path relative to the currently running executable
|
||||
* Build and work with wstring windows builds
|
||||
* fix for some new line cases in the middle of a vector initialization from jespada
|
||||
|
||||
### Changes since 5.1.0
|
||||
* Add support for automatic conversion of arithmetic types when possible
|
||||
and when no ambiguous method dispatch exists.
|
||||
|
||||
### 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
|
||||
* Fully integrate documentation with source code in doxygen style comments
|
||||
* Unit tests increased from 114 to 137
|
||||
* Automatic conversion between boost::function objects and ChaiScript functions
|
||||
* Many bug fixes
|
||||
* Minor performance improvements
|
||||
* Namespace reorganization to make end user code more accessible
|
||||
* clang support
|
||||
* VisualStudio 2010 Support
|
||||
* Support for C++ base classes and automatic upcasting
|
||||
* Remove __ reserved identifiers
|
||||
* Better code organization to reduce #ifdefs
|
||||
* clanmills: command line options for chai eval
|
||||
* clanmills: parser cleanups and code reduction
|
||||
* Function introspection and reflection
|
||||
* Correct function dispatch order to account for base classes and provide a defined order of dispatch
|
||||
* Predictable object lifetime that emulates C++ stack lifetime
|
||||
* emarcotte: pkgconfig support
|
||||
* standardize on method/member naming and indentation
|
||||
* 64bit Visual Studio support
|
||||
* Better support for const objects
|
||||
* Drastic reduction of runtime exceptions - making debug builds orders of magnitude faster
|
||||
* Support for platforms with no loadable module support
|
||||
* Add helper macro for registering class
|
@@ -1,63 +0,0 @@
|
||||
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
|
||||
* Fully integrate documentation with source code in doxygen style comments
|
||||
* Unit tests increased from 114 to 137
|
||||
* Automatic conversion between boost::function objects and ChaiScript functions
|
||||
* Many bug fixes
|
||||
* Minor performance improvements
|
||||
* Namespace reorganization to make end user code more accessible
|
||||
* clang support
|
||||
* VisualStudio 2010 Support
|
||||
* Support for C++ base classes and automatic upcasting
|
||||
* Remove __ reserved identifiers
|
||||
* Better code organization to reduce #ifdefs
|
||||
* clanmills: command line options for chai eval
|
||||
* clanmills: parser cleanups and code reduction
|
||||
* Function introspection and reflection
|
||||
* Correct function dispatch order to account for base classes and provide a defined order of dispatch
|
||||
* Predictable object lifetime that emulates C++ stack lifetime
|
||||
* emarcotte: pkgconfig support
|
||||
* standardize on method/member naming and indentation
|
||||
* 64bit Visual Studio support
|
||||
* Better support for const objects
|
||||
* Drastic reduction of runtime exceptions - making debug builds orders of magnitude faster
|
||||
* Support for platforms with no loadable module support
|
||||
* Add helper macro for registering class
|
@@ -5,6 +5,7 @@
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
@@ -12,12 +13,12 @@
|
||||
|
||||
void log(const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << '\n';
|
||||
}
|
||||
|
||||
void log(const std::string &module, const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
@@ -27,12 +28,12 @@ void bound_log(const std::string &msg)
|
||||
|
||||
void hello_world(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
std::cout << "Hello World" << std::endl;
|
||||
std::cout << "Hello World\n";
|
||||
}
|
||||
|
||||
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
std::cout << "Hello Constructor" << std::endl;
|
||||
std::cout << "Hello Constructor\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +42,9 @@ struct System
|
||||
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)
|
||||
const std::function<std::string (const std::string &)> &t_func)
|
||||
{
|
||||
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func);
|
||||
m_callbacks[t_name] = t_func;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +62,7 @@ struct System
|
||||
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
|
||||
{
|
||||
std::cout << *p << std::endl;
|
||||
std::cout << *p << '\n';
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char * /*argv*/[]) {
|
||||
@@ -121,7 +122,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//the templated version of eval:
|
||||
int i = chai.eval<int>("5+5");
|
||||
|
||||
std::cout << "5+5: " << i << std::endl;
|
||||
std::cout << "5+5: " << i << '\n';
|
||||
|
||||
//Add a new variable
|
||||
chai("var scripti = 15");
|
||||
@@ -129,14 +130,14 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//We can even get a handle to the variables in the system
|
||||
int &scripti = chai.eval<int &>("scripti");
|
||||
|
||||
std::cout << "scripti: " << scripti << std::endl;
|
||||
std::cout << "scripti: " << scripti << '\n';
|
||||
scripti *= 2;
|
||||
std::cout << "scripti (updated): " << scripti << std::endl;
|
||||
std::cout << "scripti (updated): " << scripti << '\n';
|
||||
chai("print(\"Scripti from chai: \" + to_string(scripti))");
|
||||
|
||||
//To do: Add examples of handling Boxed_Values directly when needed
|
||||
|
||||
//Creating a functor on the stack and using it immediatly
|
||||
//Creating a functor on the stack and using it immediately
|
||||
int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||
|
||||
std::stringstream ss;
|
||||
|
@@ -1,13 +1,13 @@
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
print(i)
|
||||
print(i)
|
||||
}
|
||||
|
||||
for (var i = 10; i >= 0; i -= 2) {
|
||||
print(i)
|
||||
print(i)
|
||||
}
|
||||
|
||||
var i = 0
|
||||
|
||||
for (; i < 5; ++i) {
|
||||
print(i)
|
||||
print(i)
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
//functions of zero params don't need them:
|
||||
def meet {
|
||||
print("Hello")
|
||||
print("Hello")
|
||||
}
|
||||
|
||||
def greet(x) {
|
||||
print("Hello, " + x.to_string())
|
||||
print("Hello, " + x.to_string())
|
||||
}
|
||||
|
||||
//but you need parens for invocation:
|
||||
|
4
samples/fun_call_performance.chai
Normal file
4
samples/fun_call_performance.chai
Normal file
@@ -0,0 +1,4 @@
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
puts(helloWorld("Bob12345"))
|
||||
}
|
||||
|
407
samples/fun_call_performance.cpp
Normal file
407
samples/fun_call_performance.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
|
||||
char *mystrdup(const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc(len + 1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len + 1, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d, s, len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
std::string retval;
|
||||
std::cout << p;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char*){}
|
||||
void using_history(){}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
std::vector<std::string>(*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = t_path;
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
return{ exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\" };
|
||||
}
|
||||
#else
|
||||
|
||||
std::string exepath;
|
||||
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
Dl_info rInfo;
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
if (!dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
exepath = std::string(rInfo.dli_fname);
|
||||
}
|
||||
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void help(int n) {
|
||||
if (n >= 0) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
|
||||
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
|
||||
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "usage : chai [option]+" << std::endl;
|
||||
std::cout << "option:" << std::endl;
|
||||
std::cout << " -h | --help" << std::endl;
|
||||
std::cout << " -i | --interactive" << std::endl;
|
||||
std::cout << " -c | --command cmd" << std::endl;
|
||||
std::cout << " -v | --version" << std::endl;
|
||||
std::cout << " - --stdin" << std::endl;
|
||||
std::cout << " filepath" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void version(int){
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
||||
}
|
||||
|
||||
std::string helloWorld(const std::string &t_name)
|
||||
{
|
||||
return "Hello " + t_name + "!";
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
throw std::runtime_error("no exception throw");
|
||||
}
|
||||
|
||||
std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if (!std::cin.eof()) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if (input_raw) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos + 1, std::string::npos);
|
||||
}
|
||||
|
||||
retval = val;
|
||||
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if (retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// We have to wrap exit with our own because Clang has a hard time with
|
||||
// function pointers to functions with special attributes (system exit being marked NORETURN)
|
||||
void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript& chai)
|
||||
{
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
std::string input = get_next_command();
|
||||
try {
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
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]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.push_back("");
|
||||
if (usepath)
|
||||
{
|
||||
usepaths.push_back(usepath);
|
||||
}
|
||||
|
||||
std::vector<std::string> modulepaths;
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
|
||||
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths);
|
||||
|
||||
chai.add(chaiscript::fun(&myexit), "exit");
|
||||
chai.add(chaiscript::fun(&myexit), "quit");
|
||||
chai.add(chaiscript::fun(&help), "help");
|
||||
chai.add(chaiscript::fun(&version), "version");
|
||||
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
|
||||
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
|
||||
|
||||
chai.add(chaiscript::fun(&helloWorld), "helloWorld");
|
||||
|
||||
clock_t begin = clock();
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
std::string str = helloWorld("Bob12345");
|
||||
fwrite(str.c_str(), 1, str.size(), stdout);
|
||||
}
|
||||
|
||||
clock_t end = clock();
|
||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
|
||||
//begin = clock();
|
||||
|
||||
////for (int i = 0; i < 1000; i++)
|
||||
////{
|
||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
||||
////}
|
||||
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
|
||||
|
||||
//end = clock();
|
||||
//elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
//printf("**MyProgram::time= %lf\n", elapsed_secs);
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (i == 0 && argc > 1) {
|
||||
++i;
|
||||
}
|
||||
|
||||
std::string arg(i ? argv[i] : "--interactive");
|
||||
|
||||
enum {
|
||||
eInteractive
|
||||
, eCommand
|
||||
, eFile
|
||||
} mode = eCommand;
|
||||
|
||||
if (arg == "-c" || arg == "--command") {
|
||||
if ((i + 1) >= argc) {
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
arg = argv[++i];
|
||||
}
|
||||
}
|
||||
else if (arg == "-" || arg == "--stdin") {
|
||||
arg = "";
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
arg += line + '\n';
|
||||
}
|
||||
}
|
||||
else if (arg == "-v" || arg == "--version") {
|
||||
arg = "version(0)";
|
||||
}
|
||||
else if (arg == "-h" || arg == "--help") {
|
||||
arg = "help(-1)";
|
||||
}
|
||||
else if (arg == "-i" || arg == "--interactive") {
|
||||
mode = eInteractive;
|
||||
}
|
||||
else if (arg.find('-') == 0) {
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
mode = eFile;
|
||||
}
|
||||
|
||||
chaiscript::Boxed_Value val;
|
||||
try {
|
||||
switch (mode) {
|
||||
case eInteractive: interactive(chai); break;
|
||||
case eCommand: val = chai.eval(arg); break;
|
||||
case eFile: {
|
||||
begin = clock();
|
||||
|
||||
val = chai.eval_file(arg);
|
||||
|
||||
end = clock();
|
||||
double elapsed_secs1 = double(end - begin) / CLOCKS_PER_SEC;
|
||||
printf("**C++::time= %.10f\n", elapsed_secs);
|
||||
printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
|
||||
break;
|
||||
}
|
||||
default: std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
var i = 0
|
||||
if (i == 0) {
|
||||
print("i is 0")
|
||||
print("i is 0")
|
||||
}
|
||||
else if (i == 1) {
|
||||
print("i is 1")
|
||||
print("i is 1")
|
||||
}
|
||||
else {
|
||||
print("i is not 0 or 1")
|
||||
print("i is not 0 or 1")
|
||||
}
|
||||
|
134
samples/inheritance.cpp
Normal file
134
samples/inheritance.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
class BaseClass
|
||||
{
|
||||
public:
|
||||
BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~BaseClass() {}
|
||||
|
||||
virtual std::string doSomething(float, double) const = 0;
|
||||
|
||||
|
||||
void setValue(const std::string &t_val) {
|
||||
if (validateValue(t_val))
|
||||
{
|
||||
m_value = t_val;
|
||||
}
|
||||
}
|
||||
|
||||
std::string getValue() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool validateValue(const std::string &t_val) = 0;
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
class ChaiScriptDerived : public BaseClass
|
||||
{
|
||||
public:
|
||||
ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &t_funcs)
|
||||
{
|
||||
// using the range-checked .at() methods to give us an exception
|
||||
// instead of a crash if the user passed in too-few params
|
||||
tie(t_funcs.at(0), m_doSomethingImpl);
|
||||
tie(t_funcs.at(1), m_validateValueImpl);
|
||||
}
|
||||
|
||||
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
assert(m_doSomethingImpl);
|
||||
return m_doSomethingImpl(*this, f, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
assert(m_validateValueImpl);
|
||||
return m_validateValueImpl(*this, t_val);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Param>
|
||||
void tie(const chaiscript::Boxed_Value &t_func, Param &t_param)
|
||||
{
|
||||
t_param = chaiscript::boxed_cast<Param>(t_func);
|
||||
}
|
||||
|
||||
std::function<std::string (const ChaiScriptDerived&, float, double)> m_doSomethingImpl;
|
||||
std::function<bool (ChaiScriptDerived&, const std::string &t_val)> m_validateValueImpl;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
||||
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
||||
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
|
||||
chai.add(chaiscript::constructor<ChaiScriptDerived (const std::vector<chaiscript::Boxed_Value> &)>(), "ChaiScriptDerived");
|
||||
chai.add(chaiscript::base_class<BaseClass, ChaiScriptDerived>());
|
||||
chai.add(chaiscript::user_type<BaseClass>(), "BaseClass");
|
||||
chai.add(chaiscript::user_type<ChaiScriptDerived>(), "ChaiScriptDerived");
|
||||
|
||||
std::string script = R""(
|
||||
def MakeDerived() {
|
||||
return ChaiScriptDerived(
|
||||
// create a dynamically created array and pass it in to the constructor
|
||||
[
|
||||
fun(this, f, d) {
|
||||
// see here that we are calling back into the 'this' pointer
|
||||
return "${this.getValue()}${f * d}";
|
||||
},
|
||||
|
||||
fun(this, new_val) {
|
||||
if (new_val.size() < 5) {
|
||||
true;
|
||||
} else {
|
||||
print("String ${new_val} is too long");
|
||||
false;
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
var myderived := MakeDerived(); // avoid a copy by using reference assignment :=
|
||||
|
||||
)"";
|
||||
|
||||
chai.eval(script);
|
||||
|
||||
BaseClass &myderived = chai.eval<ChaiScriptDerived&>("myderived");
|
||||
|
||||
// at this point in the code myderived is both a ChaiScript variable and a C++ variable. In both cases
|
||||
// it is a derivation of BaseClass, and the implementation is provided via ChaiScript functors
|
||||
// assigned in the MakeDerived() factory function
|
||||
//
|
||||
// Notice that our validateValue() function has a requirement that the new string be < 5 characters long
|
||||
|
||||
myderived.setValue("1234");
|
||||
assert(myderived.getValue() == "1234");
|
||||
|
||||
// chaiscript defined function will print out an error message and refuse to allow the setting
|
||||
myderived.setValue("12345");
|
||||
assert(myderived.getValue() == "1234");
|
||||
|
||||
|
||||
chai.eval("myderived.setValue(\"new\")"); // set the value via chaiscript
|
||||
assert(myderived.getValue() == "new");
|
||||
|
||||
// call the other derived method via chaiscript and return the value to c++ land:
|
||||
std::string retval = chai.eval<std::string>("myderived.doSomething(2,4.3)");
|
||||
assert(retval == "new8.6");
|
||||
|
||||
// The whole process is fully orthogonal
|
||||
}
|
||||
|
||||
|
@@ -1,20 +1,20 @@
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
print("i: " + i.to_string())
|
||||
if (i == 5) {
|
||||
break
|
||||
}
|
||||
print("i: " + i.to_string())
|
||||
if (i == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var j = 0
|
||||
|
||||
while (true) {
|
||||
while (true) {
|
||||
++j;
|
||||
if (j == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
while (true) {
|
||||
++j;
|
||||
if (j == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
print("j: " + j.to_string())
|
||||
|
@@ -24,7 +24,7 @@ std::string get_next_command() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void fuction(void)
|
||||
void function(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -35,28 +35,28 @@ class test
|
||||
chaiscript::ChaiScript::State backupState;
|
||||
|
||||
public:
|
||||
test()
|
||||
: chai(chaiscript::Std_Lib::library())
|
||||
{
|
||||
backupState = chai.get_state();
|
||||
}
|
||||
~test(){}
|
||||
test()
|
||||
: chai(chaiscript::Std_Lib::library())
|
||||
{
|
||||
backupState = chai.get_state();
|
||||
}
|
||||
~test(){}
|
||||
|
||||
void ResetState()
|
||||
{
|
||||
chai.set_state(backupState);
|
||||
chai.add(chaiscript::fun(&fuction),"Whatever()");
|
||||
}
|
||||
void ResetState()
|
||||
{
|
||||
chai.set_state(backupState);
|
||||
chai.add(chaiscript::fun(&function),"Whatever()");
|
||||
}
|
||||
|
||||
void RunFile(std::string sFile)
|
||||
{
|
||||
try {
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
void RunFile(std::string sFile)
|
||||
{
|
||||
try {
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -70,12 +70,12 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
std::string command = "";
|
||||
|
||||
//
|
||||
// this loop increases memoryusage, if RunFile is not called (just hittin enter)
|
||||
// this loop increases memory usage, if RunFile is not called (just hitting enter)
|
||||
// as soon RunFile gets called, memory will be freed.
|
||||
//
|
||||
// scenario1 - RunFile gets called every Loop: memoryusage does not change
|
||||
// scenario2 - RunFile gets never called (just hitting enter): memoryusage increases every loop
|
||||
// scenario3 - RunFile gets in changing intervals: memoryusage goes up and down, but never as
|
||||
// scenario1 - RunFile gets called every Loop: memory usage does not change
|
||||
// scenario2 - RunFile gets never called (just hitting enter): memory usage increases every loop
|
||||
// scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as
|
||||
// low as in case 1 scenario3 :
|
||||
|
||||
while(command != "quit")
|
||||
|
@@ -2,7 +2,7 @@ var x = -(1 + 2 - 3 * 4 / 2)
|
||||
print("Answer: " + x.to_string())
|
||||
|
||||
if (x >= 2 && x <= 4) {
|
||||
print("x is between 2 and 4")
|
||||
print("x is between 2 and 4")
|
||||
}
|
||||
|
||||
|
||||
|
@@ -5,7 +5,7 @@ def for_each(container, function)
|
||||
while (!range.empty())
|
||||
{
|
||||
function(range.front());
|
||||
range.popFront();
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,10 +6,10 @@
|
||||
*/
|
||||
var x = 4
|
||||
def do_it() {
|
||||
var x = 1
|
||||
print(x)
|
||||
var y = fun(x) { x + 1 }
|
||||
print(y(9))
|
||||
var x = 1
|
||||
print(x)
|
||||
var y = fun(x) { x + 1 }
|
||||
print(y(9))
|
||||
}
|
||||
do_it()
|
||||
print(x)
|
||||
|
@@ -11,6 +11,6 @@ var size = vec.size()
|
||||
print("Vector Size: " + size.to_string());
|
||||
|
||||
while (i < size) {
|
||||
print(i.to_string() + ": " + to_string(vec[i]))
|
||||
i = i + 1
|
||||
print(i.to_string() + ": " + to_string(vec[i]))
|
||||
i = i + 1
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
var i = 0
|
||||
while (i < 10) {
|
||||
print("i: " + i.to_string())
|
||||
i = i + 1
|
||||
print("i: " + i.to_string())
|
||||
i = i + 1
|
||||
}
|
||||
|
@@ -9,6 +9,11 @@
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_chaiscript_stdlib()
|
||||
{
|
||||
@@ -16,6 +21,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_chaiscr
|
||||
}
|
||||
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
166
src/main.cpp
166
src/main.cpp
@@ -1,7 +1,7 @@
|
||||
// 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)
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
@@ -15,41 +15,145 @@
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
|
||||
char *mystrdup (const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d,s,len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
std::string retval;
|
||||
std::cout << p ;
|
||||
std::getline(std::cin, retval);
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
return std::cin.eof() ? NULL : _strdup(retval.c_str());
|
||||
#else
|
||||
return std::cin.eof() ? NULL : strdup(retval.c_str());
|
||||
#endif
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char*){}
|
||||
void using_history(){}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
std::vector<std::string> (*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = t_path;
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||
}
|
||||
#else
|
||||
|
||||
std::string exepath;
|
||||
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
if ( !dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname ) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
exepath = std::string(rInfo.dli_fname);
|
||||
}
|
||||
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void help(int n) {
|
||||
if ( n >= 0 ) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
|
||||
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
|
||||
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
|
||||
std::cout << "Additionally, you can inspect the runtime system using:\n";
|
||||
std::cout << " dump_system() - outputs all functions registered to the system\n";
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||
} else {
|
||||
std::cout << "usage : chai [option]+" << std::endl;
|
||||
std::cout << "option:" << std::endl;
|
||||
std::cout << " -h | --help" << std::endl;
|
||||
std::cout << " -i | --interactive" << std::endl;
|
||||
std::cout << " -c | --command cmd" << std::endl;
|
||||
std::cout << " -v | --version" << std::endl;
|
||||
std::cout << " - --stdin" << std::endl;
|
||||
std::cout << " filepath" << std::endl;
|
||||
std::cout << "usage : chai [option]+\n";
|
||||
std::cout << "option:" << '\n';
|
||||
std::cout << " -h | --help" << '\n';
|
||||
std::cout << " -i | --interactive" << '\n';
|
||||
std::cout << " -c | --command cmd" << '\n';
|
||||
std::cout << " -v | --version" << '\n';
|
||||
std::cout << " - --stdin" << '\n';
|
||||
std::cout << " filepath" << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void version(int){
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << '\n';
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
@@ -127,7 +231,7 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
@@ -137,19 +241,17 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
std::cout << '\n';
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << std::endl;
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::vector<std::string> usepaths;
|
||||
std::vector<std::string> modulepaths;
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
@@ -164,12 +266,16 @@ int main(int argc, char *argv[])
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.push_back("");
|
||||
if (usepath)
|
||||
{
|
||||
usepaths.push_back(usepath);
|
||||
}
|
||||
|
||||
std::vector<std::string> modulepaths;
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
@@ -199,7 +305,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if ( arg == "-c" || arg == "--command" ) {
|
||||
if ( (i+1) >= argc ) {
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
std::cout << "insufficient input following " << arg << '\n';
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
arg = argv[++i];
|
||||
@@ -217,7 +323,7 @@ int main(int argc, char *argv[])
|
||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
||||
mode = eInteractive ;
|
||||
} else if ( arg.find('-') == 0 ) {
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
std::cout << "unrecognised argument " << arg << '\n';
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
mode = eFile;
|
||||
@@ -229,16 +335,16 @@ 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;
|
||||
default : std::cout << "Unrecognized execution mode\n"; return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
std::cout << '\n';
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
std::cout << e.what() << '\n';
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@@ -1,104 +0,0 @@
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
// but this is the best way to do it for cross platform compatibility
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
|
||||
|
||||
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return bool(pf->get_parse_tree());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
return pf->get_parse_tree();
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
|
||||
{
|
||||
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||
|
||||
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<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
|
||||
"eval_error",
|
||||
{ },
|
||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{fun(&chaiscript::exception::eval_error::call_stack), "call_stack"} }
|
||||
);
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
|
||||
"File_Position",
|
||||
{ constructor<File_Position()>(),
|
||||
constructor<File_Position(int, int)>() },
|
||||
{ {fun(&File_Position::line), "line"},
|
||||
{fun(&File_Position::column), "column"} }
|
||||
);
|
||||
|
||||
chaiscript::utility::add_class<AST_Node>(*m,
|
||||
"AST_Node",
|
||||
{ },
|
||||
{ {fun(&AST_Node::text), "text"},
|
||||
{fun(&AST_Node::identifier), "identifier"},
|
||||
{fun(&AST_Node::filename), "filename"},
|
||||
{fun(&AST_Node::start), "start"},
|
||||
{fun(&AST_Node::end), "end"},
|
||||
{fun(&AST_Node::internal_to_string), "internal_to_string"},
|
||||
{fun(&AST_Node::children), "children"},
|
||||
{fun(&AST_Node::replace_child), "replace_child"}
|
||||
}
|
||||
);
|
||||
|
||||
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
|
||||
"ChaiScript_Parser",
|
||||
{ constructor<parser::ChaiScript_Parser ()>() },
|
||||
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
|
||||
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
|
||||
);
|
||||
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
@@ -1,3 +1,8 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
@@ -11,11 +16,19 @@
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||
{
|
||||
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||
}
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
|
@@ -2,15 +2,50 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
TestBaseType() {}
|
||||
TestBaseType(int) {}
|
||||
TestBaseType(int *) {}
|
||||
TestBaseType() : val(10), const_val(15) { }
|
||||
TestBaseType(int) : val(10), const_val(15) {}
|
||||
TestBaseType(int *) : val(10), const_val(15) {}
|
||||
virtual ~TestBaseType() {}
|
||||
virtual int func() { return 0; }
|
||||
|
||||
int base_only_func() { return -9; }
|
||||
|
||||
const TestBaseType &constMe() const { return *this; }
|
||||
|
||||
int val;
|
||||
const int const_val;
|
||||
|
||||
private:
|
||||
TestBaseType &operator=(const TestBaseType &);
|
||||
};
|
||||
|
||||
class Type2
|
||||
{
|
||||
public:
|
||||
Type2(TestBaseType t_bt)
|
||||
: m_bt(std::move(t_bt)),
|
||||
m_str("Hello World")
|
||||
{
|
||||
}
|
||||
|
||||
int get_val() const
|
||||
{
|
||||
return m_bt.val;
|
||||
}
|
||||
|
||||
const char *get_str() const
|
||||
{
|
||||
return m_str.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
TestBaseType m_bt;
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
enum TestEnum
|
||||
@@ -27,9 +62,34 @@ class TestDerivedType : public TestBaseType
|
||||
{
|
||||
public:
|
||||
virtual ~TestDerivedType() {}
|
||||
virtual int func() { return 1; }
|
||||
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
|
||||
int derived_only_func() { return 19; }
|
||||
|
||||
private:
|
||||
TestDerivedType &operator=(const TestDerivedType &);
|
||||
};
|
||||
|
||||
class TestMoreDerivedType : public TestDerivedType
|
||||
{
|
||||
public:
|
||||
virtual ~TestMoreDerivedType() {}
|
||||
};
|
||||
|
||||
std::shared_ptr<TestBaseType> derived_type_factory()
|
||||
{
|
||||
return std::make_shared<TestDerivedType>();
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> more_derived_type_factory()
|
||||
{
|
||||
return std::make_shared<TestMoreDerivedType>();
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> null_factory()
|
||||
{
|
||||
return std::shared_ptr<TestBaseType>();
|
||||
}
|
||||
|
||||
std::string hello_world()
|
||||
{
|
||||
return "Hello World";
|
||||
@@ -47,6 +107,10 @@ int *get_new_int()
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
|
||||
{
|
||||
@@ -56,6 +120,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
|
||||
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
|
||||
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
|
||||
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::user_type<Type2>(), "Type2");
|
||||
|
||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
@@ -65,23 +131,52 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
||||
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
||||
|
||||
m->add(chaiscript::constructor<TestMoreDerivedType ()>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::constructor<TestMoreDerivedType (const TestMoreDerivedType &)>(), "TestMoreDerivedType");
|
||||
|
||||
/// \todo automatic chaining of base classes?
|
||||
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
|
||||
m->add(chaiscript::base_class<TestBaseType, TestMoreDerivedType>());
|
||||
m->add(chaiscript::base_class<TestDerivedType, TestMoreDerivedType>());
|
||||
|
||||
m->add(chaiscript::fun(&TestDerivedType::derived_only_func), "derived_only_func");
|
||||
|
||||
m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory");
|
||||
m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory");
|
||||
m->add(chaiscript::fun(&null_factory), "null_factory");
|
||||
|
||||
m->add(chaiscript::fun(&TestDerivedType::func), "func");
|
||||
|
||||
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
||||
m->add(chaiscript::fun(&TestBaseType::val), "val");
|
||||
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
|
||||
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_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");
|
||||
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
|
||||
|
||||
m->add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { return Type2(t_bt); }));
|
||||
|
||||
m->add(chaiscript::fun(&Type2::get_val), "get_val");
|
||||
m->add(chaiscript::fun(&Type2::get_str), "get_str");
|
||||
m->add(chaiscript::type_conversion<const char *, std::string>());
|
||||
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@@ -1,7 +1,7 @@
|
||||
var i = 0
|
||||
while (i < 10) {
|
||||
if (++i == 5) {
|
||||
break
|
||||
}
|
||||
if (++i == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert_equal(5, i);
|
||||
|
@@ -1,4 +1,3 @@
|
||||
load_module("reflection")
|
||||
|
||||
def deep()
|
||||
{
|
||||
|
@@ -1,17 +1,17 @@
|
||||
def bob(x, y, z) {
|
||||
x + y + z
|
||||
x + y + z
|
||||
}
|
||||
|
||||
def bob(x, y) {
|
||||
x - y
|
||||
x - y
|
||||
}
|
||||
|
||||
def bob(x) {
|
||||
-x
|
||||
-x
|
||||
}
|
||||
|
||||
def bob() {
|
||||
10
|
||||
10
|
||||
}
|
||||
|
||||
assert_equal(10, bob())
|
||||
|
@@ -1,4 +1,3 @@
|
||||
load_module("reflection")
|
||||
var parser := ChaiScript_Parser()
|
||||
var parse_success = parser.parse("3 + 4", "INPUT")
|
||||
var a := parser.ast()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
def sam() {
|
||||
return 5
|
||||
return 5
|
||||
}
|
||||
|
||||
assert_equal(5, sam())
|
||||
|
@@ -1,4 +1,4 @@
|
||||
def greet {
|
||||
return("hello")
|
||||
return("hello")
|
||||
}
|
||||
|
||||
|
70
unittests/arithmetic_conversions_test.cpp
Normal file
70
unittests/arithmetic_conversions_test.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Tests to make sure that type conversions happen only when they should
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
void f1(int)
|
||||
{
|
||||
}
|
||||
|
||||
void f4(std::string)
|
||||
{
|
||||
}
|
||||
|
||||
void f2(int)
|
||||
{
|
||||
}
|
||||
|
||||
void f3(double)
|
||||
{
|
||||
}
|
||||
|
||||
void f_func_return(const std::function<unsigned int (unsigned long)> &f)
|
||||
{
|
||||
// test the ability to return an unsigned with auto conversion
|
||||
f(4);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&f1), "f1");
|
||||
chai.add(chaiscript::fun(&f2), "f2");
|
||||
chai.add(chaiscript::fun(&f3), "f2");
|
||||
chai.add(chaiscript::fun(&f1), "f3");
|
||||
chai.add(chaiscript::fun(&f4), "f3");
|
||||
|
||||
chai.add(chaiscript::fun(&f_func_return), "func_return");
|
||||
|
||||
// no overloads
|
||||
chai.eval("f1(0)");
|
||||
chai.eval("f1(0l)");
|
||||
chai.eval("f1(0ul)");
|
||||
chai.eval("f1(0ll)");
|
||||
chai.eval("f1(0ull)");
|
||||
chai.eval("f1(0.0)");
|
||||
chai.eval("f1(0.0f)");
|
||||
chai.eval("f1(0.0l)");
|
||||
|
||||
// expected overloads
|
||||
chai.eval("f2(1)");
|
||||
chai.eval("f2(1.0)");
|
||||
|
||||
// 1 non-arithmetic overload
|
||||
chai.eval("f2(1.0)");
|
||||
|
||||
// various options for returning with conversions from chaiscript
|
||||
chai.eval("func_return(fun(x) { return 5u; })");
|
||||
chai.eval("func_return(fun(x) { return 5; })");
|
||||
chai.eval("func_return(fun(x) { return 5.0f; })");
|
||||
|
||||
// this is the one call we expect to fail, ambiguous overloads
|
||||
try {
|
||||
chai.eval("f2(1.0l)");
|
||||
} catch (const std::exception &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// if the last one did not throw, we failed
|
||||
return EXIT_FAILURE;
|
||||
}
|
@@ -15,16 +15,16 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
use(ret);
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
|
||||
if (expectedpass) {
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << std::endl;
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << std::endl;
|
||||
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << '\n';
|
||||
return false;
|
||||
} catch (...) {
|
||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion." << std::endl;
|
||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
if (!ret)
|
||||
{
|
||||
std::cerr << "Error with type conversion test. From: "
|
||||
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
|
||||
<< " To: "
|
||||
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not" << std::endl;
|
||||
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
|
||||
<< " To: "
|
||||
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not\n";
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -264,21 +264,21 @@ bool pointer_test(const T& default_value, const T& new_value)
|
||||
|
||||
|
||||
if (p != (*result) ) {
|
||||
std::cerr << "Pointer passed in different than one returned" << std::endl;
|
||||
std::cerr << "Pointer passed in different than one returned\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*p != *(*result) ) {
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?" << std::endl;
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
std::cerr << "Bad boxed cast performing ** to ** test" << std::endl;
|
||||
std::cerr << "Bad boxed cast performing ** to ** test\n";
|
||||
return false;
|
||||
} catch (...) {
|
||||
std::cerr << "Unknown exception performing ** to ** test" << std::endl;
|
||||
std::cerr << "Unknown exception performing ** to ** test\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
11
unittests/break_for.chai
Normal file
11
unittests/break_for.chai
Normal file
@@ -0,0 +1,11 @@
|
||||
var j = 0;
|
||||
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
if (i == 5) {
|
||||
break
|
||||
}
|
||||
|
||||
j = i
|
||||
}
|
||||
|
||||
assert_equal(4, j);
|
@@ -1,7 +1,7 @@
|
||||
auto i = 0
|
||||
while (i < 10) {
|
||||
if (++i == 5) {
|
||||
break
|
||||
}
|
||||
if (++i == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert_equal(5, i);
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int dosomething(int i)
|
||||
int do_something(int i)
|
||||
{
|
||||
return i % 2;
|
||||
}
|
||||
@@ -13,8 +13,8 @@ int main()
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&dosomething), "dosomething");
|
||||
chai.add(chaiscript::fun(&do_something), "do_something");
|
||||
|
||||
return chai.eval<int>("dosomething(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
|
||||
return chai.eval<int>("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
|
||||
|
||||
}
|
||||
|
27
unittests/class.chai
Normal file
27
unittests/class.chai
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
class Vector3
|
||||
{
|
||||
// you can use attr, auto or var in this context
|
||||
attr x
|
||||
auto y
|
||||
var z
|
||||
|
||||
def Vector3(x,y,z)
|
||||
{
|
||||
this.x = x
|
||||
this.y = y
|
||||
this.z = z
|
||||
}
|
||||
|
||||
def doSomething(mult)
|
||||
{
|
||||
return this.x * this.y * this.z * mult
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
auto v = Vector3(1,2,3)
|
||||
assert_equal(1, v.x)
|
||||
assert_equal(v.doSomething(2), 12)
|
||||
|
16
unittests/continue_for.chai
Normal file
16
unittests/continue_for.chai
Normal file
@@ -0,0 +1,16 @@
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
|
||||
for (var i = 0; i < 10; ++i)
|
||||
{
|
||||
j = i
|
||||
if (i > 5)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
k = i
|
||||
}
|
||||
|
||||
assert_equal(5, k);
|
||||
assert_equal(9, j);
|
14
unittests/continue_while.chai
Normal file
14
unittests/continue_while.chai
Normal file
@@ -0,0 +1,14 @@
|
||||
var i = 0
|
||||
var j = 0
|
||||
|
||||
while (i < 10) {
|
||||
if (++i > 5)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
j = i;
|
||||
}
|
||||
|
||||
assert_equal(10, i);
|
||||
assert_equal(5, j);
|
@@ -8,7 +8,7 @@ void assert_equal(const LHS &lhs, const RHS &rhs)
|
||||
{
|
||||
return;
|
||||
} else {
|
||||
std::cout << "Got: " << lhs << " expected " << rhs << std::endl;
|
||||
std::cout << "Got: " << lhs << " expected " << rhs << '\n';
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@@ -9,14 +9,14 @@ int test_generic()
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"));");
|
||||
} catch (const chaiscript::Boxed_Value &bv) {
|
||||
const std::exception &e = chaiscript::boxed_cast<const std::exception &>(bv);
|
||||
const std::exception &e = chai.boxed_cast<const std::exception &>(bv);
|
||||
if (e.what() == std::string("error"))
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_generic failed" << std::endl;
|
||||
std::cout << "test_generic failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ int test_1()
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_1 failed" << std::endl;
|
||||
std::cout << "test_1 failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ int test_2()
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_2 failed" << std::endl;
|
||||
std::cout << "test_2 failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -61,22 +61,22 @@ int test_5()
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
} catch (const double) {
|
||||
std::cout << "test_5 failed with double" << std::endl;
|
||||
std::cout << "test_5 failed with double\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (int) {
|
||||
std::cout << "test_5 failed with int" << std::endl;
|
||||
std::cout << "test_5 failed with int\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (float) {
|
||||
std::cout << "test_5 failed with float" << std::endl;
|
||||
std::cout << "test_5 failed with float\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::string &) {
|
||||
std::cout << "test_5 failed with string" << std::endl;
|
||||
std::cout << "test_5 failed with string\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::exception &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::cout << "test_5 failed" << std::endl;
|
||||
std::cout << "test_5 failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -87,22 +87,22 @@ int test_unhandled()
|
||||
try {
|
||||
chai.eval("throw(\"error\")", chaiscript::exception_specification<int, double, float, const std::exception &>());
|
||||
} catch (double) {
|
||||
std::cout << "test_unhandled failed with double" << std::endl;
|
||||
std::cout << "test_unhandled failed with double\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (int) {
|
||||
std::cout << "test_unhandled failed with int" << std::endl;
|
||||
std::cout << "test_unhandled failed with int\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (float) {
|
||||
std::cout << "test_unhandled failed with float" << std::endl;
|
||||
std::cout << "test_unhandled failed with float\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::exception &) {
|
||||
std::cout << "test_unhandled failed with std::exception" << std::endl;
|
||||
std::cout << "test_unhandled failed with std::exception\n";
|
||||
return EXIT_FAILURE;
|
||||
} catch (const chaiscript::Boxed_Value &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::cout << "test_unhandled failed" << std::endl;
|
||||
std::cout << "test_unhandled failed\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,3 @@
|
||||
load_module("reflection")
|
||||
|
||||
def deep()
|
||||
{
|
||||
|
@@ -19,7 +19,7 @@ int main()
|
||||
// Dot notation
|
||||
|
||||
try {
|
||||
// non-existant function
|
||||
// non-existent function
|
||||
chai.eval("\"test\".test_one()");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
@@ -51,7 +51,7 @@ int main()
|
||||
// regular notation
|
||||
|
||||
try {
|
||||
// non-existant function
|
||||
// non-existent function
|
||||
chai.eval("test_one(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
|
@@ -5,3 +5,57 @@ for (auto i = 0; i < 5; ++i) {
|
||||
}
|
||||
|
||||
assert_equal([0,1,2,3,4], ret);
|
||||
|
||||
|
||||
var j = 0;
|
||||
|
||||
for (;j<10; ++j)
|
||||
{
|
||||
}
|
||||
|
||||
assert_equal(10, j);
|
||||
|
||||
|
||||
var k = 0;
|
||||
|
||||
for (;k<10; )
|
||||
{
|
||||
++k;
|
||||
}
|
||||
|
||||
assert_equal(10, k);
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var l = 0;
|
||||
|
||||
for (;;l = 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
assert_equal(0, l)
|
||||
|
||||
def isNotFive(x)
|
||||
{
|
||||
if (x != 5)
|
||||
{
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var m;
|
||||
|
||||
for (m = 0; isNotFive(m); m = m + 1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
assert_equal(5, m);
|
||||
|
||||
|
10
unittests/global_in_script.chai
Normal file
10
unittests/global_in_script.chai
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
var i = 5
|
||||
add_global(i, "j")
|
||||
|
||||
def myFun()
|
||||
{
|
||||
assert_equal(j, 5)
|
||||
}
|
||||
|
||||
myFun();
|
10
unittests/heap_allocated_chaiscript_test.cpp
Normal file
10
unittests/heap_allocated_chaiscript_test.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript *chai = new chaiscript::ChaiScript();
|
||||
delete chai;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@@ -6,3 +6,35 @@ auto t = TestDerivedType();
|
||||
assert_equal(t0.func(), 0);
|
||||
assert_equal(t.func(), 1);
|
||||
|
||||
assert_equal(10, t0.val);
|
||||
assert_equal(15, t0.const_val);
|
||||
|
||||
assert_equal(10, t.val);
|
||||
assert_equal(15, t.const_val);
|
||||
|
||||
t.val = 23;
|
||||
assert_equal(23, t.val)
|
||||
|
||||
// test_derived_factory returns a TestDerivedType contained
|
||||
// in a shared_ptr<TestBaseType>. This is testing our ability
|
||||
// to detect that and do the down casting for the user automatically
|
||||
// at runtime
|
||||
|
||||
assert_equal(t.derived_only_func(), 19);
|
||||
|
||||
var d := derived_type_factory();
|
||||
assert_equal(d.derived_only_func(), 19);
|
||||
|
||||
var t2 = TestMoreDerivedType();
|
||||
assert_equal(t2.derived_only_func(), 19);
|
||||
assert_equal(t2.base_only_func(), -9);
|
||||
|
||||
var md := more_derived_type_factory();
|
||||
assert_equal(md.derived_only_func(), 19);
|
||||
assert_equal(md.base_only_func(), -9);
|
||||
|
||||
assert_equal(md.func(), 1);
|
||||
assert_equal(t2.func(), 1);
|
||||
assert_equal(d.func(), 1);
|
||||
|
||||
|
||||
|
@@ -1,5 +1,3 @@
|
||||
// Tests to make sure that the order in which function dispatches occur is correct
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#define TEST_LITERAL(v) test_literal(v, #v)
|
||||
@@ -9,7 +7,7 @@ bool test_literal(T val, const std::string &str)
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
T val2 = chai.eval<T>(str);
|
||||
std::cout << "Comparing : " << val << " " << val2 << std::endl;
|
||||
std::cout << "Comparing : " << val << " " << val2 << '\n';
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
|
@@ -1,2 +1,4 @@
|
||||
load_module("test_module")
|
||||
assert_equal("Hello World", hello_world());
|
||||
|
||||
|
||||
|
5
unittests/map_count.chai
Normal file
5
unittests/map_count.chai
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
assert_equal(1, ["a":1].count("a"))
|
||||
assert_equal(0, ["A":1].count("a"))
|
||||
|
||||
|
11
unittests/member_variable_access.chai
Normal file
11
unittests/member_variable_access.chai
Normal file
@@ -0,0 +1,11 @@
|
||||
load_module("test_module")
|
||||
|
||||
var t0 = TestBaseType()
|
||||
t0.val = 13
|
||||
|
||||
assert_equal(15, t0.const_val)
|
||||
assert_equal(13, t0.val)
|
||||
assert_equal(15, t0.constMe().const_val)
|
||||
assert_equal(13, t0.constMe().val)
|
||||
|
||||
|
@@ -1,17 +1,17 @@
|
||||
def bob(x, y, z) {
|
||||
x + y + z
|
||||
x + y + z
|
||||
}
|
||||
|
||||
def bob(x, y) {
|
||||
x - y
|
||||
x - y
|
||||
}
|
||||
|
||||
def bob(x) {
|
||||
-x
|
||||
-x
|
||||
}
|
||||
|
||||
def bob() {
|
||||
10
|
||||
10
|
||||
}
|
||||
|
||||
assert_equal(10, bob())
|
||||
|
@@ -1,9 +1,3 @@
|
||||
// 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>
|
||||
@@ -24,19 +18,26 @@ int expected_value(int num_iters)
|
||||
|
||||
void do_work(chaiscript::ChaiScript &c, int id)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "MyVar" << rand();
|
||||
c.add(chaiscript::var(5), ss.str());
|
||||
ss.str("");
|
||||
ss << id;
|
||||
c.use("multithreaded_work.inc");
|
||||
c("do_chai_work(4000, " + ss.str() + ");");
|
||||
try{
|
||||
std::stringstream ss;
|
||||
ss << "MyVar" << rand();
|
||||
c.add(chaiscript::var(5), ss.str());
|
||||
ss.str("");
|
||||
ss << id;
|
||||
c.use("multithreaded_work.inc");
|
||||
c("do_chai_work(4000, " + ss.str() + ");");
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << "exception: " << e.what() << " thread: " << id;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef max // Why Microsoft? why?
|
||||
#undef max
|
||||
#endif
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
@@ -44,7 +45,7 @@ int main()
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -80,6 +81,7 @@ int main()
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < num_threads; ++i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
13
unittests/null_object_access.chai
Normal file
13
unittests/null_object_access.chai
Normal file
@@ -0,0 +1,13 @@
|
||||
load_module("test_module")
|
||||
|
||||
auto o := null_factory();
|
||||
|
||||
try {
|
||||
o.func();
|
||||
} catch (e) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
assert_true(false);
|
||||
|
||||
|
@@ -29,12 +29,19 @@ int main()
|
||||
{
|
||||
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||
|
||||
/*
|
||||
chaiscript::utility::add_class<Test>(*m,
|
||||
"Test",
|
||||
{ chaiscript::constructor<Test ()>(),
|
||||
chaiscript::constructor<Test (const Test &)>() },
|
||||
{ {chaiscript::fun(&Test::count), "count"} }
|
||||
);
|
||||
*/
|
||||
|
||||
m->add(chaiscript::user_type<Test>(), "Test");
|
||||
m->add(chaiscript::constructor<Test()>(), "Test");
|
||||
m->add(chaiscript::constructor<Test(const Test &)>(), "Test");
|
||||
m->add(chaiscript::fun(&Test::count), "count");
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(m);
|
||||
|
69
unittests/object_lifetime_test2.cpp
Normal file
69
unittests/object_lifetime_test2.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
template<typename T>
|
||||
struct Vector2
|
||||
{
|
||||
Vector2() : x(0), y(0) {};
|
||||
Vector2(T px, T py) : x(px), y(py) {};
|
||||
Vector2(const Vector2& cp) : x(cp.x), y(cp.y) {};
|
||||
|
||||
Vector2& operator+=(const Vector2& vec_r)
|
||||
{
|
||||
x += vec_r.x;
|
||||
y += vec_r.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2 operator+(const Vector2& vec_r)
|
||||
{
|
||||
return Vector2(*this += vec_r);
|
||||
}
|
||||
|
||||
void operator=(const Vector2& ver_r)
|
||||
{
|
||||
x = ver_r.x;
|
||||
y = ver_r.y;
|
||||
}
|
||||
|
||||
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
|
||||
Vector2<float> GetValue()
|
||||
{
|
||||
return Vector2<float>(10,15);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript _script(chaiscript::Std_Lib::library());
|
||||
|
||||
//Registering stuff
|
||||
_script.add(chaiscript::user_type<Vector2<float>>(), "Vector2f");
|
||||
_script.add(chaiscript::constructor<Vector2<float> ()>(), "Vector2f");
|
||||
_script.add(chaiscript::constructor<Vector2<float> (float, float)>(), "Vector2f");
|
||||
_script.add(chaiscript::constructor<Vector2<float> (const Vector2<float>&)>(), "Vector2f");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::x), "x");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::y), "y");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::operator +), "+");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::operator +=), "+=");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::operator =), "=");
|
||||
_script.add(chaiscript::fun(&GetValue), "getValue");
|
||||
|
||||
_script.eval(R"(
|
||||
var test = 0.0
|
||||
var test2 = Vector2f(10,10)
|
||||
|
||||
test = getValue().x
|
||||
print(test)
|
||||
print(test2.x)
|
||||
)");
|
||||
|
||||
if (_script.eval<std::string>("to_string(test)") != "10") { return EXIT_FAILURE; }
|
||||
if (_script.eval<std::string>("to_string(test2.x)") != "10") { return EXIT_FAILURE; }
|
||||
|
||||
|
||||
//_script.eval_file("object_lifetime_test2.inc");
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user