Compare commits
225 Commits
Release-5.
...
v5.3.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 | ||
![]() |
455324bf13 | ||
![]() |
deef33640c | ||
![]() |
85ba42849b | ||
![]() |
58f3256389 | ||
![]() |
f1a4c4c427 | ||
![]() |
afd27a4b01 | ||
![]() |
6bb90f9d6d | ||
![]() |
4c65e45598 | ||
![]() |
57c6d72a79 | ||
![]() |
923369a4f4 | ||
![]() |
964342bff3 | ||
![]() |
c5a86401aa | ||
![]() |
623c64299a | ||
![]() |
abcc6c9e3e | ||
![]() |
9832d1ce39 | ||
![]() |
ed7bdfb172 | ||
![]() |
87c9006174 | ||
![]() |
204ab53afc | ||
![]() |
d47cd63fec | ||
![]() |
193151f52e | ||
![]() |
6642e02496 | ||
![]() |
8f7226051e | ||
![]() |
d84b4c0b37 | ||
![]() |
46d1c50923 | ||
![]() |
9e3c2960aa | ||
![]() |
84e17b8d06 | ||
![]() |
9fd4a1b9f5 | ||
![]() |
32fab64882 | ||
![]() |
8cb49e9494 | ||
![]() |
441cdf0935 | ||
![]() |
f0016d978a | ||
![]() |
1155720b14 | ||
![]() |
7052234650 | ||
![]() |
c2934caad6 | ||
![]() |
f5b7be3743 | ||
![]() |
d8f881239f | ||
![]() |
199b1f5233 | ||
![]() |
0a436398dd | ||
![]() |
9f309fcbe9 | ||
![]() |
4e33e969dc | ||
![]() |
f27739cf71 | ||
![]() |
08d9d9e28e | ||
![]() |
935276fccd | ||
![]() |
f8feaf6ea8 | ||
![]() |
dfcc415c31 | ||
![]() |
927235d871 | ||
![]() |
a6924bcc9e | ||
![]() |
a3b50d4151 | ||
![]() |
bf4f90a4ff | ||
![]() |
45f07f9924 | ||
![]() |
d3b8daeff0 | ||
![]() |
39d817469c | ||
![]() |
7a25625fdd | ||
![]() |
5e6a51ba63 | ||
![]() |
a8ea5f151d | ||
![]() |
6cda1140c4 | ||
![]() |
5a76d98692 | ||
![]() |
949f54b9c4 | ||
![]() |
f6e53dd42d | ||
![]() |
d55439a7ac | ||
![]() |
953c4e4847 | ||
![]() |
3bccf4d977 |
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=
|
269
CMakeLists.txt
269
CMakeLists.txt
@@ -2,10 +2,47 @@ cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(chaiscript)
|
||||
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" 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, reflection)" 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_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()
|
||||
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")
|
||||
@@ -13,12 +50,13 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.txt")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 3)
|
||||
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")
|
||||
@@ -37,93 +75,143 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
||||
include(CTest)
|
||||
include(CPack)
|
||||
|
||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||
include(cmake/CheckCXX11Features.cmake)
|
||||
|
||||
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")
|
||||
else()
|
||||
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
|
||||
|
||||
message(STATUS "Detecting readline support")
|
||||
if (READLINE_LIBRARY)
|
||||
if(READLINE_LIBRARY)
|
||||
message(STATUS "Found: ${READLINE_LIBRARY}")
|
||||
set (READLINE_LIB readline)
|
||||
set(READLINE_LIB readline)
|
||||
add_definitions(/DREADLINE_AVAILABLE)
|
||||
else(READLINE_LIBRARY)
|
||||
else()
|
||||
message(STATUS "Not Found")
|
||||
set (READLINE_LIB )
|
||||
set (READLINE_FLAG )
|
||||
endif(READLINE_LIBRARY)
|
||||
set(READLINE_LIB)
|
||||
set(READLINE_FLAG)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(/W4)
|
||||
if(CMAKE_CL_64)
|
||||
add_definitions(/bigobj)
|
||||
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()
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic -std=c++0x)
|
||||
set(CPP11_FLAG "-std=c++11")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
if(MSVC)
|
||||
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 -Wnon-virtual-dtor -pedantic ${CPP11_FLAG})
|
||||
|
||||
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.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
else()
|
||||
if(NOT MULTITHREAD_SUPPORT_ENABLED)
|
||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||
endif()
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
set(DYNAMIC_LOADER "dl")
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
if(CMAKE_HOST_UNIX)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
list(APPEND LIBS "dl")
|
||||
endif()
|
||||
|
||||
set(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
|
||||
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()
|
||||
|
||||
add_definitions(-pthread)
|
||||
endif()
|
||||
|
||||
if (CMAKE_COMPILER_2005)
|
||||
# vs2005 is a bit too loud about possible loss of data warnings
|
||||
# ADD_DEFINITIONS(/wd4244)
|
||||
endif()
|
||||
|
||||
add_library(chaiscript_stdlib MODULE src/chaiscript_stdlib.cpp)
|
||||
target_link_libraries(chaiscript_stdlib ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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}")
|
||||
|
||||
|
||||
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})
|
||||
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})
|
||||
target_link_libraries(reflection ${LIBS})
|
||||
set(MODULES stl_extra reflection)
|
||||
endif()
|
||||
|
||||
@@ -134,10 +222,18 @@ list(SORT UNIT_TESTS)
|
||||
if(BUILD_TESTING)
|
||||
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
|
||||
|
||||
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}/"
|
||||
)
|
||||
|
||||
|
||||
foreach(filename ${UNIT_TESTS})
|
||||
message(STATUS "Adding test ${filename}")
|
||||
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
||||
endforeach(filename)
|
||||
endforeach()
|
||||
|
||||
set_property(TEST ${UNIT_TESTS}
|
||||
PROPERTY ENVIRONMENT
|
||||
@@ -145,65 +241,110 @@ if(BUILD_TESTING)
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
|
||||
if (NOT UNIT_TEST_LIGHT)
|
||||
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(function_ordering_test unittests/function_ordering_test.cpp)
|
||||
target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(function_ordering_test ${LIBS})
|
||||
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
|
||||
|
||||
add_executable(type_info_test unittests/type_info_test.cpp)
|
||||
target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(type_info_test ${LIBS})
|
||||
add_test(NAME Type_Info_Test COMMAND type_info_test)
|
||||
|
||||
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS})
|
||||
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
|
||||
|
||||
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
|
||||
target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(short_comparison_test ${LIBS})
|
||||
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
|
||||
|
||||
add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp)
|
||||
target_link_libraries(cpp_lambda_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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)
|
||||
target_link_libraries(expected_eval_errors_test ${LIBS})
|
||||
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
|
||||
|
||||
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(set_state_test unittests/set_state_test.cpp)
|
||||
target_link_libraries(set_state_test ${LIBS})
|
||||
add_test(NAME Set_State_Test COMMAND set_state_test)
|
||||
|
||||
add_executable(simultaneous_chaiscript_test unittests/simultaneous_chaiscript_test.cpp)
|
||||
target_link_libraries(simultaneous_chaiscript_test ${LIBS})
|
||||
add_test(NAME Simultaneous_ChaiScript_Test COMMAND simultaneous_chaiscript_test)
|
||||
|
||||
add_executable(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})
|
||||
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
|
||||
|
||||
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
|
||||
target_link_libraries(integer_literal_test ${LIBS})
|
||||
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
||||
|
||||
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)
|
||||
set_property(TEST Multithreaded_Test
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(multifile_test
|
||||
unittests/multifile_test_main.cpp
|
||||
unittests/multifile_test_chai.cpp
|
||||
unittests/multifile_test_module.cpp
|
||||
)
|
||||
target_link_libraries(multifile_test ${LIBS})
|
||||
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
|
||||
|
635
Doxyfile.in
635
Doxyfile.in
File diff suppressed because it is too large
Load Diff
103
cmake/CheckCXX11Features.cmake
Normal file
103
cmake/CheckCXX11Features.cmake
Normal file
@@ -0,0 +1,103 @@
|
||||
# Checks for C++11 features
|
||||
# CXX11_FEATURE_LIST - a list containing all supported features
|
||||
# HAS_CXX11_AUTO - auto keyword
|
||||
# HAS_CXX11_NULLPTR - nullptr
|
||||
# HAS_CXX11_LAMBDA - lambdas
|
||||
# HAS_CXX11_STATIC_ASSERT - static_assert()
|
||||
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
|
||||
# HAS_CXX11_DECLTYPE - decltype keyword
|
||||
# HAS_CXX11_CSTDINT_H - cstdint header
|
||||
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
|
||||
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
|
||||
# HAS_CXX11_CONSTEXPR - constexpr keyword
|
||||
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
|
||||
# HAS_CXX11_FUNC - __func__ preprocessor constant
|
||||
#
|
||||
# Original script by Rolf Eike Beer
|
||||
# Modifications by Andreas Weis
|
||||
#
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
|
||||
SET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_CXX_FLAGS "-std=c++0x")
|
||||
endif()
|
||||
|
||||
MACRO(CXX11_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
|
||||
IF (NOT DEFINED ${RESULT_VAR})
|
||||
SET(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11/cxx11_${FEATURE_NAME}")
|
||||
|
||||
IF (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
|
||||
ELSE (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\"")
|
||||
ENDIF (${FEATURE_NUMBER})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME}")
|
||||
|
||||
SET(_SRCFILE "${_SRCFILE_BASE}.cpp")
|
||||
SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
IF (CROSS_COMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ELSE (CROSS_COMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}")
|
||||
IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ENDIF (CROSS_COMPILING)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
|
||||
IF (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ELSE (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ENDIF (_TMP_RESULT)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
|
||||
IF (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- works")
|
||||
LIST(APPEND CXX11_FEATURE_LIST ${RESULT_VAR})
|
||||
ELSE (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- not supported")
|
||||
ENDIF (${RESULT_VAR})
|
||||
SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
|
||||
ENDIF (NOT DEFINED ${RESULT_VAR})
|
||||
ENDMACRO(CXX11_CHECK_FEATURE)
|
||||
|
||||
CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)
|
||||
CXX11_CHECK_FEATURE("nullptr" 2431 HAS_CXX11_NULLPTR)
|
||||
CXX11_CHECK_FEATURE("lambda" 2927 HAS_CXX11_LAMBDA)
|
||||
CXX11_CHECK_FEATURE("static_assert" 1720 HAS_CXX11_STATIC_ASSERT)
|
||||
CXX11_CHECK_FEATURE("rvalue_references" 2118 HAS_CXX11_RVALUE_REFERENCES)
|
||||
CXX11_CHECK_FEATURE("decltype" 2343 HAS_CXX11_DECLTYPE)
|
||||
CXX11_CHECK_FEATURE("cstdint" "" HAS_CXX11_CSTDINT_H)
|
||||
CXX11_CHECK_FEATURE("long_long" 1811 HAS_CXX11_LONG_LONG)
|
||||
CXX11_CHECK_FEATURE("variadic_templates" 2555 HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
CXX11_CHECK_FEATURE("constexpr" 2235 HAS_CXX11_CONSTEXPR)
|
||||
CXX11_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX11_SIZEOF_MEMBER)
|
||||
CXX11_CHECK_FEATURE("__func__" 2340 HAS_CXX11_FUNC)
|
||||
|
||||
SET(CXX11_FEATURE_LIST ${CXX11_FEATURE_LIST} CACHE STRING "C++11 feature support list")
|
||||
MARK_AS_ADVANCED(FORCE CXX11_FEATURE_LIST)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS ${CHECK_CXX11_OLD_CMAKE_CXX_FLAGS})
|
||||
UNSET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS)
|
||||
|
8
cmake/c++11-test-__func__-N2340.cpp
Normal file
8
cmake/c++11-test-__func__-N2340.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!__func__) { return 1; }
|
||||
if(std::strlen(__func__) <= 0) { return 1; }
|
||||
return 0;
|
||||
}
|
12
cmake/c++11-test-auto-N2546.cpp
Normal file
12
cmake/c++11-test-auto-N2546.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
auto i = 5;
|
||||
auto f = 3.14159f;
|
||||
auto d = 3.14159;
|
||||
bool ret = (
|
||||
(sizeof(f) < sizeof(d)) &&
|
||||
(sizeof(i) == sizeof(int))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
19
cmake/c++11-test-constexpr-N2235.cpp
Normal file
19
cmake/c++11-test-constexpr-N2235.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
constexpr int square(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
constexpr int the_answer()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int test_arr[square(3)];
|
||||
bool ret = (
|
||||
(square(the_answer()) == 1764) &&
|
||||
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
10
cmake/c++11-test-cstdint.cpp
Normal file
10
cmake/c++11-test-cstdint.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <cstdint>
|
||||
int main()
|
||||
{
|
||||
bool test =
|
||||
(sizeof(int8_t) == 1) &&
|
||||
(sizeof(int16_t) == 2) &&
|
||||
(sizeof(int32_t) == 4) &&
|
||||
(sizeof(int64_t) == 8);
|
||||
return test ? 0 : 1;
|
||||
}
|
11
cmake/c++11-test-decltype-N2343.cpp
Normal file
11
cmake/c++11-test-decltype-N2343.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
bool check_size(int i)
|
||||
{
|
||||
return sizeof(int) == sizeof(decltype(i));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool ret = check_size(42);
|
||||
return ret ? 0 : 1;
|
||||
}
|
5
cmake/c++11-test-lambda-N2927.cpp
Normal file
5
cmake/c++11-test-lambda-N2927.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
return ([&ret]() -> int { return ret; })();
|
||||
}
|
7
cmake/c++11-test-long_long-N1811.cpp
Normal file
7
cmake/c++11-test-long_long-N1811.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
int main(void)
|
||||
{
|
||||
long long l;
|
||||
unsigned long long ul;
|
||||
|
||||
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
|
||||
}
|
5
cmake/c++11-test-nullptr-N2431.cpp
Normal file
5
cmake/c++11-test-nullptr-N2431.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int* test = nullptr;
|
||||
return test ? 1 : 0;
|
||||
}
|
5
cmake/c++11-test-nullptr-N2431_fail_compile.cpp
Normal file
5
cmake/c++11-test-nullptr-N2431_fail_compile.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int i = nullptr;
|
||||
return 1;
|
||||
}
|
15
cmake/c++11-test-rvalue_references-N2118.cpp
Normal file
15
cmake/c++11-test-rvalue_references-N2118.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
int foo(int& lvalue)
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int foo(int&& rvalue)
|
||||
{
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 42;
|
||||
return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1;
|
||||
}
|
14
cmake/c++11-test-sizeof_member-N2253.cpp
Normal file
14
cmake/c++11-test-sizeof_member-N2253.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
struct foo {
|
||||
char bar;
|
||||
int baz;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool ret = (
|
||||
(sizeof(foo::bar) == 1) &&
|
||||
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
|
||||
(sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
5
cmake/c++11-test-static_assert-N1720.cpp
Normal file
5
cmake/c++11-test-static_assert-N1720.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(0 < 1, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
5
cmake/c++11-test-static_assert-N1720_fail_compile.cpp
Normal file
5
cmake/c++11-test-static_assert-N1720_fail_compile.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(1 < 0, "this should fail");
|
||||
return 0;
|
||||
}
|
23
cmake/c++11-test-variadic_templates-N2555.cpp
Normal file
23
cmake/c++11-test-variadic_templates-N2555.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
int Accumulate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
int Accumulate(T v, Ts... vs)
|
||||
{
|
||||
return v + Accumulate(vs...);
|
||||
}
|
||||
|
||||
template<int... Is>
|
||||
int CountElements()
|
||||
{
|
||||
return sizeof...(Is);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int acc = Accumulate(1, 2, 3, 4, -5);
|
||||
int count = CountElements<1,2,3,4,5>();
|
||||
return ((acc == 5) && (count == 5)) ? 0 : 1;
|
||||
}
|
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.64/cppcheck-1.65.tar.bz2
|
||||
tar -xvf cppcheck-1.65.tar.bz2
|
||||
cd cppcheck-1.65
|
||||
make -j2
|
||||
popd
|
||||
../cppcheck-1.65/cppcheck --enable=all -I include --inline-suppr --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,108 +69,115 @@
|
||||
///
|
||||
/// double d = chai.eval<double>("function(3, 4.75);");
|
||||
/// }
|
||||
/// \endcode
|
||||
/// ~~~~~~~
|
||||
///
|
||||
/// <hr>
|
||||
/// \subsection compiling Compiling ChaiScript Applications
|
||||
/// ------------------------------------------------------
|
||||
///
|
||||
/// @subsection compiling Compiling ChaiScript Applications
|
||||
///
|
||||
/// ChaiScript is a header only library with only one dependecy: The
|
||||
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
||||
///
|
||||
/// \subsubsection compilinggcc Compiling with GCC
|
||||
/// @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
|
||||
///
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai("print(\"hello world\")");
|
||||
/// \endcode
|
||||
/// chai("print(@"hello world@")");
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// \sa chaiscript::ChaiScript::operator()(const std::string &)
|
||||
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
|
||||
///
|
||||
/// \subsubsection evalmethod Method 'eval'
|
||||
/// @subsubsection evalmethod Method 'eval'
|
||||
///
|
||||
/// The eval method is somewhat more verbose and can be used to get typesafely 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.
|
||||
/// 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 {
|
||||
@@ -187,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
|
||||
@@ -216,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;
|
||||
/// };
|
||||
@@ -251,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:
|
||||
@@ -274,30 +283,30 @@
|
||||
///
|
||||
/// 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.
|
||||
@@ -307,7 +316,7 @@
|
||||
///
|
||||
/// 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);
|
||||
@@ -347,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);
|
||||
@@ -372,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");
|
||||
@@ -397,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
|
||||
@@ -411,16 +423,17 @@
|
||||
///
|
||||
/// Disabling thread safety increases performance in many cases.
|
||||
///
|
||||
/// <hr>
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// \subsection exceptions Exception Handling
|
||||
///
|
||||
/// \subsubsection exceptionsbasics Exception Handling Basics
|
||||
/// @subsection exceptions Exception Handling
|
||||
///
|
||||
/// @subsubsection exceptionsbasics Exception Handling Basics
|
||||
///
|
||||
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
|
||||
/// ChaiScript.
|
||||
///
|
||||
/// \code
|
||||
/// ~~~~~~~~{.cpp}
|
||||
/// void throwexception()
|
||||
/// {
|
||||
/// throw std::runtime_error("err");
|
||||
@@ -441,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) {
|
||||
@@ -461,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 }
|
||||
@@ -482,67 +495,69 @@
|
||||
/// var rect = Rectangle()
|
||||
/// rect.height = 30
|
||||
/// print(rect.area())
|
||||
/// \endcode
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// \sa \ref keywordattr
|
||||
/// \sa \ref keyworddef
|
||||
/// @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) {
|
||||
@@ -552,103 +567,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.
|
||||
@@ -664,50 +685,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) {
|
||||
@@ -715,35 +742,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 = 3;
|
||||
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,12 +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_THREADING_HPP_
|
||||
#define CHAISCRIPT_THREADING_HPP_
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@@ -62,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();
|
||||
@@ -99,16 +144,20 @@ namespace chaiscript
|
||||
return new_instance;
|
||||
}
|
||||
|
||||
mutable mutex m_mutex;
|
||||
mutable std::map<std::thread::id, std::shared_ptr<T> > m_instances;
|
||||
};
|
||||
|
||||
#else
|
||||
mutable mutex m_mutex;
|
||||
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
|
||||
};
|
||||
#endif // threading enabled but no tls
|
||||
|
||||
#else // threading disabled
|
||||
template<typename T>
|
||||
class unique_lock
|
||||
{
|
||||
public:
|
||||
unique_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -116,6 +165,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
shared_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
@@ -135,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
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
@@ -42,6 +44,7 @@ namespace chaiscript {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
virtual ~Data() {}
|
||||
virtual void *data() = 0;
|
||||
virtual const std::type_info &type() const = 0;
|
||||
virtual std::shared_ptr<Data> clone() const = 0;
|
||||
@@ -50,27 +53,31 @@ namespace chaiscript {
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
Data_Impl(const T &t_type)
|
||||
Data_Impl(T t_type)
|
||||
: m_type(typeid(T)),
|
||||
m_data(t_type)
|
||||
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
|
||||
const std::type_info &type() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
std::shared_ptr<Data> clone() const
|
||||
std::shared_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
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;
|
||||
};
|
||||
@@ -93,8 +100,8 @@ namespace chaiscript {
|
||||
|
||||
template<typename ValueType>
|
||||
Any(const ValueType &t_value)
|
||||
: m_data(std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value)))
|
||||
{
|
||||
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
|
||||
}
|
||||
|
||||
Any & operator=(const Any &t_any)
|
||||
|
@@ -1,14 +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_BAD_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Info;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
@@ -22,25 +29,25 @@ namespace chaiscript
|
||||
{
|
||||
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)
|
||||
std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
: from(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
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: from(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
|
||||
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_
|
||||
|
@@ -1,19 +1,37 @@
|
||||
// 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 "dynamic_cast_conversion.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"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -269,28 +287,17 @@ namespace chaiscript
|
||||
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;
|
||||
}
|
||||
@@ -316,14 +323,6 @@ namespace chaiscript
|
||||
throw bv;
|
||||
}
|
||||
|
||||
static std::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(
|
||||
std::shared_ptr<chaiscript::detail::Dispatch_Engine> e
|
||||
= std::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
|
||||
{
|
||||
e->add(user_type<void>(), "void");
|
||||
return e;
|
||||
}
|
||||
|
||||
static std::string what(const std::exception &e)
|
||||
{
|
||||
return e.what();
|
||||
@@ -379,7 +378,6 @@ 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==), "==");
|
||||
|
||||
|
||||
@@ -423,6 +421,7 @@ namespace chaiscript
|
||||
m->add(fun(&Type_Info::is_void), "is_type_void");
|
||||
m->add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||
m->add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
||||
m->add(fun(&Type_Info::name), "cpp_name");
|
||||
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
@@ -442,6 +441,7 @@ namespace chaiscript
|
||||
bootstrap_pod_type<long double>("long_double", m);
|
||||
bootstrap_pod_type<float>("float", m);
|
||||
bootstrap_pod_type<int>("int", m);
|
||||
bootstrap_pod_type<long>("long", m);
|
||||
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
||||
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
||||
bootstrap_pod_type<size_t>("size_t", m);
|
||||
@@ -470,9 +470,6 @@ namespace chaiscript
|
||||
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");
|
||||
|
||||
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,9 +157,27 @@ namespace chaiscript
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Add Bidir_Range support for the given ContainerType
|
||||
*/
|
||||
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)
|
||||
{
|
||||
t_target.insert(t_other.begin(), t_other.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
||||
{
|
||||
t_target.insert(t_val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Add Bidir_Range support for the given ContainerType
|
||||
template<typename Bidir_Type>
|
||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@@ -170,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)
|
||||
{
|
||||
@@ -188,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))
|
||||
{
|
||||
@@ -216,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()))
|
||||
{
|
||||
@@ -238,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()))
|
||||
{
|
||||
@@ -250,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<size_t (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
|
||||
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
|
||||
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
@@ -276,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()))
|
||||
{
|
||||
@@ -297,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()))
|
||||
{
|
||||
@@ -316,17 +334,16 @@ 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()))
|
||||
{
|
||||
@@ -349,10 +366,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()))
|
||||
{
|
||||
@@ -372,10 +388,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()))
|
||||
{
|
||||
@@ -384,22 +400,35 @@ 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(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
|
||||
m->add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
std::string insert_name;
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value))
|
||||
{
|
||||
insert_name = "insert_ref";
|
||||
} else {
|
||||
insert_name = "insert";
|
||||
}
|
||||
|
||||
m->add(fun(&detail::insert_ref<ContainerType>), insert_name);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
@@ -418,10 +447,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()))
|
||||
{
|
||||
@@ -438,10 +466,9 @@ 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()))
|
||||
{
|
||||
@@ -484,10 +511,8 @@ namespace chaiscript
|
||||
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()))
|
||||
{
|
||||
@@ -498,7 +523,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);
|
||||
|
||||
@@ -512,18 +537,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 *, size_t, size_t)>( [](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ) ), "substr");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -533,3 +563,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 "dynamic_cast_conversion.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Dynamic_Cast_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 Dynamic_Cast_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,15 +86,22 @@ namespace chaiscript
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
|
||||
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
|
||||
{
|
||||
try {
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << std::endl;
|
||||
// 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));
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
|
||||
} catch (...) {
|
||||
try {
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << std::endl;
|
||||
// try going the other way - down the inheritance graph
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_down_cast<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
|
||||
// attempted dynamic_cast
|
||||
|
@@ -1,18 +1,24 @@
|
||||
// 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 Dynamic_Cast_Conversions;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Cast_Helper_Inner helper classes
|
||||
@@ -25,7 +31,7 @@ namespace chaiscript
|
||||
{
|
||||
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 Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -67,7 +73,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -96,7 +102,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -115,7 +121,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result &cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -135,7 +141,7 @@ namespace chaiscript
|
||||
{
|
||||
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 Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
@@ -149,7 +155,7 @@ namespace chaiscript
|
||||
{
|
||||
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 Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@@ -197,7 +203,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef const Boxed_Value & Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
@@ -258,9 +264,9 @@ namespace chaiscript
|
||||
{
|
||||
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 Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob);
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -1,21 +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 <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 Dynamic_Cast_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
|
||||
@@ -48,7 +63,6 @@ namespace chaiscript
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,7 +158,6 @@ namespace chaiscript
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -170,7 +183,6 @@ namespace chaiscript
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -301,6 +313,19 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Target, typename Source>
|
||||
Target get_as_aux() const
|
||||
{
|
||||
return static_cast<Target>(*static_cast<const Source *>(bv.get_const_ptr()));
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
static std::string to_string_aux(const Boxed_Value &v)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << *static_cast<const Source *>(v.get_const_ptr());
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
@@ -315,6 +340,133 @@ namespace chaiscript
|
||||
validate_boxed_number(v);
|
||||
}
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
: bv(Boxed_Value(t))
|
||||
{
|
||||
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();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return get_as_aux<Target, int>();
|
||||
} else if (inp_ == typeid(double)) {
|
||||
return get_as_aux<Target, double>();
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return get_as_aux<Target, float>();
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return get_as_aux<Target, long double>();
|
||||
} else if (inp_ == typeid(char)) {
|
||||
return get_as_aux<Target, char>();
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
return get_as_aux<Target, unsigned int>();
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return get_as_aux<Target, long>();
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return get_as_aux<Target, unsigned long>();
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return get_as_aux<Target, std::int8_t>();
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return get_as_aux<Target, std::int16_t>();
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return get_as_aux<Target, std::int32_t>();
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return get_as_aux<Target, std::int64_t>();
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return get_as_aux<Target, std::uint8_t>();
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return get_as_aux<Target, std::uint16_t>();
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return get_as_aux<Target, std::uint32_t>();
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return get_as_aux<Target, std::uint64_t>();
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
const Type_Info &inp_ = bv.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return to_string_aux<int>(bv);
|
||||
} else if (inp_ == typeid(double)) {
|
||||
return to_string_aux<double>(bv);
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return to_string_aux<float>(bv);
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return to_string_aux<long double>(bv);
|
||||
} else if (inp_ == typeid(char)) {
|
||||
return to_string_aux<int>(Boxed_Value(get_as_aux<int, char>()));
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
return to_string_aux<unsigned int>(bv);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return to_string_aux<long>(bv);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return to_string_aux<unsigned long>(bv);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return to_string_aux<int>(Boxed_Value(get_as_aux<int, std::int8_t>()));
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return to_string_aux<std::int16_t>(bv);
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return to_string_aux<std::int32_t>(bv);
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return to_string_aux<std::int64_t>(bv);
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, std::uint8_t>()));
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return to_string_aux<std::uint16_t>(bv);
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return to_string_aux<std::uint32_t>(bv);
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return to_string_aux<std::uint64_t>(bv);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
@@ -381,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))
|
||||
@@ -682,7 +834,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
@@ -705,7 +857,7 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
@@ -1,18 +1,20 @@
|
||||
// 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 "any.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -22,24 +24,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,
|
||||
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(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)
|
||||
{
|
||||
}
|
||||
@@ -137,26 +136,20 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Basic Boxed_Value constructor
|
||||
*/
|
||||
/// Basic Boxed_Value constructor
|
||||
template<typename T>
|
||||
explicit Boxed_Value(T t)
|
||||
: m_data(Object_Data::get(t))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor - each copy shares the same data pointer
|
||||
*/
|
||||
/// 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())
|
||||
{
|
||||
@@ -171,19 +164,15 @@ namespace chaiscript
|
||||
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
|
||||
*/
|
||||
/// shared data assignment, same as copy construction
|
||||
Boxed_Value &operator=(const Boxed_Value &rhs)
|
||||
{
|
||||
Boxed_Value temp(rhs);
|
||||
@@ -196,9 +185,7 @@ namespace chaiscript
|
||||
return m_data->m_type_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the object is uninitialized
|
||||
*/
|
||||
/// return true if the object is uninitialized
|
||||
bool is_undef() const
|
||||
{
|
||||
return m_data->m_type_info.is_undef();
|
||||
@@ -216,7 +203,7 @@ namespace chaiscript
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
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
|
||||
@@ -254,19 +241,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)
|
||||
{
|
||||
@@ -339,7 +327,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)
|
||||
{
|
||||
|
@@ -1,29 +1,49 @@
|
||||
// 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_DISPATCHKIT_HPP_
|
||||
#define CHAISCRIPT_DISPATCHKIT_HPP_
|
||||
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Number;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript {
|
||||
namespace dispatch {
|
||||
class Dynamic_Proxy_Function;
|
||||
class Proxy_Function_Base;
|
||||
struct Placeholder_Object;
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
|
||||
/// \namespace chaiscript::dispatch
|
||||
@@ -39,12 +59,12 @@ namespace chaiscript
|
||||
class reserved_word_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
reserved_word_error(const std::string &t_word) noexcept
|
||||
reserved_word_error(const std::string &t_word) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~reserved_word_error() noexcept {}
|
||||
virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::string word() const
|
||||
{
|
||||
@@ -53,9 +73,31 @@ namespace chaiscript
|
||||
|
||||
private:
|
||||
std::string m_word;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it contains illegal characters
|
||||
*/
|
||||
class illegal_name_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
illegal_name_error(const std::string &t_name) throw()
|
||||
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~illegal_name_error() throw() {}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it already exists in current context
|
||||
*/
|
||||
@@ -86,12 +128,12 @@ namespace chaiscript
|
||||
class global_non_const : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
global_non_const() noexcept
|
||||
global_non_const() CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() noexcept {}
|
||||
virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,7 +198,6 @@ namespace chaiscript
|
||||
|
||||
~Module()
|
||||
{
|
||||
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -167,7 +208,7 @@ namespace chaiscript
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply(InItr begin, InItr end, T &t) const
|
||||
static void apply(InItr begin, InItr end, T &t)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
@@ -182,7 +223,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_globals(InItr begin, InItr end, T &t) const
|
||||
static void apply_globals(InItr begin, InItr end, T &t)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
@@ -192,7 +233,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_single(InItr begin, InItr end, T &t) const
|
||||
static void apply_single(InItr begin, InItr end, T &t)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
@@ -202,7 +243,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_eval(InItr begin, InItr end, T &t) const
|
||||
static void apply_eval(InItr begin, InItr end, T &t)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
@@ -231,7 +272,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const
|
||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
try {
|
||||
const Dispatch_Function &dispatchfun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
@@ -243,17 +284,17 @@ namespace chaiscript
|
||||
|
||||
virtual ~Dispatch_Function() {}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
function_vec::const_iterator begin = m_funcs.begin();
|
||||
auto begin = m_funcs.begin();
|
||||
const function_vec::const_iterator end = m_funcs.end();
|
||||
|
||||
if (begin != end)
|
||||
@@ -279,16 +320,14 @@ namespace chaiscript
|
||||
return -1; // unknown arity
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
function_vec::const_iterator begin = m_funcs.begin();
|
||||
function_vec::const_iterator end = m_funcs.end();
|
||||
auto begin = m_funcs.begin();
|
||||
auto end = m_funcs.end();
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
if ((*begin)->call_match(vals))
|
||||
if ((*begin)->call_match(vals, t_conversions))
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
@@ -299,15 +338,15 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "Multiple method dispatch function wrapper.";
|
||||
}
|
||||
|
||||
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 Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params);
|
||||
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -317,7 +356,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
function_vec::const_iterator begin = t_funcs.begin();
|
||||
auto begin = t_funcs.begin();
|
||||
const function_vec::const_iterator end = t_funcs.end();
|
||||
|
||||
if (begin != end)
|
||||
@@ -326,7 +365,7 @@ namespace chaiscript
|
||||
|
||||
++begin;
|
||||
|
||||
bool sizemismatch = false;
|
||||
bool size_mismatch = false;
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
@@ -334,7 +373,7 @@ namespace chaiscript
|
||||
|
||||
if (param_types.size() != type_infos.size())
|
||||
{
|
||||
sizemismatch = true;
|
||||
size_mismatch = true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < type_infos.size() && i < param_types.size(); ++i)
|
||||
@@ -350,7 +389,7 @@ namespace chaiscript
|
||||
|
||||
assert(type_infos.size() > 0 && " type_info vector size is < 0, this is only possible if something else is broken");
|
||||
|
||||
if (sizemismatch)
|
||||
if (size_mismatch)
|
||||
{
|
||||
type_infos.resize(1);
|
||||
}
|
||||
@@ -390,13 +429,21 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
Dispatch_Engine()
|
||||
: m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
: m_stack_holder(this),
|
||||
m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
~Dispatch_Engine()
|
||||
{
|
||||
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
||||
}
|
||||
|
||||
/// \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 chaiscript::boxed_cast<Type>(bv, &m_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,8 +451,7 @@ namespace chaiscript
|
||||
*/
|
||||
void add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_conversions.push_back(d);
|
||||
return detail::Dynamic_Conversions::get().add_conversion(d);
|
||||
m_conversions.add_conversion(d);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,13 +489,13 @@ namespace chaiscript
|
||||
/**
|
||||
* Adds a named object to the current scope
|
||||
*/
|
||||
void add_object(const std::string &name, const Boxed_Value &obj)
|
||||
void add_object(const std::string &name, const Boxed_Value &obj) const
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
|
||||
Scope &scope = stack.back();
|
||||
Scope::iterator itr = scope.find(name);
|
||||
auto itr = scope.find(name);
|
||||
if (itr != stack.back().end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
@@ -479,6 +525,25 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new global (non-const) shared object, between all the threads
|
||||
*/
|
||||
void add_global(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new scope to the stack
|
||||
*/
|
||||
@@ -551,7 +616,7 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = m_state.m_global_objects.find(name);
|
||||
auto itr = m_state.m_global_objects.find(name);
|
||||
if (itr != m_state.m_global_objects.end())
|
||||
{
|
||||
return itr->second;
|
||||
@@ -581,7 +646,7 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
Type_Name_Map::const_iterator itr = m_state.m_types.find(name);
|
||||
auto itr = m_state.m_types.find(name);
|
||||
|
||||
if (itr != m_state.m_types.end())
|
||||
{
|
||||
@@ -600,13 +665,11 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
for (Type_Name_Map::const_iterator itr = m_state.m_types.begin();
|
||||
itr != m_state.m_types.end();
|
||||
++itr)
|
||||
for (const auto & elem : m_state.m_types)
|
||||
{
|
||||
if (itr->second.bare_equal(ti))
|
||||
if (elem.second.bare_equal(ti))
|
||||
{
|
||||
return itr->first;
|
||||
return elem.first;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,7 +696,7 @@ namespace chaiscript
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &funs = get_functions_int();
|
||||
|
||||
std::map<std::string, std::vector<Proxy_Function> >::const_iterator itr
|
||||
auto itr
|
||||
= funs.find(t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
@@ -652,7 +715,7 @@ namespace chaiscript
|
||||
|
||||
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||
|
||||
std::map<std::string, Proxy_Function>::const_iterator itr = funs.find(t_name);
|
||||
auto itr = funs.find(t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
{
|
||||
@@ -673,20 +736,43 @@ namespace chaiscript
|
||||
return functions.find(name) != functions.end();
|
||||
}
|
||||
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
return scope;
|
||||
}
|
||||
|
||||
/// \brief Sets all of the locals for the current thread state.
|
||||
///
|
||||
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||
///
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
scope = t_locals;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Get a map of all objects that can be seen from the current scope in a scripting context
|
||||
///
|
||||
std::map<std::string, Boxed_Value> get_scripting_objects() const
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
|
||||
// We don't want the current context, but one up if it exists
|
||||
StackData &stack = (m_stack_holder->stacks.size()==1)?(*(m_stack_holder->stacks.back())):(*m_stack_holder->stacks[m_stack_holder->stacks.size()-2]);
|
||||
StackData &stack = (s.stacks.size()==1)?(*(s.stacks.back())):(*s.stacks[s.stacks.size()-2]);
|
||||
|
||||
std::map<std::string, Boxed_Value> retval;
|
||||
|
||||
// note: map insert doesn't overwrite existing values, which is why this works
|
||||
|
||||
for (StackData::reverse_iterator itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||
for (auto itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||
{
|
||||
retval.insert(itr->begin(), itr->end());
|
||||
}
|
||||
@@ -713,11 +799,9 @@ namespace chaiscript
|
||||
|
||||
std::map<std::string, Boxed_Value> objs;
|
||||
|
||||
for (std::map<std::string, Proxy_Function>::const_iterator itr = funs.begin();
|
||||
itr != funs.end();
|
||||
++itr)
|
||||
for (const auto & fun : funs)
|
||||
{
|
||||
objs.insert(std::make_pair(itr->first, const_var(itr->second)));
|
||||
objs.insert(std::make_pair(fun.first, const_var(fun.second)));
|
||||
}
|
||||
|
||||
return objs;
|
||||
@@ -735,15 +819,11 @@ namespace chaiscript
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &functions = get_functions_int();
|
||||
|
||||
for (std::map<std::string, std::vector<Proxy_Function> >::const_iterator itr = functions.begin();
|
||||
itr != functions.end();
|
||||
++itr)
|
||||
for (const auto & function : functions)
|
||||
{
|
||||
for (std::vector<Proxy_Function>::const_iterator itr2 = itr->second.begin();
|
||||
itr2 != itr->second.end();
|
||||
++itr2)
|
||||
for (const auto & internal_func : function.second)
|
||||
{
|
||||
rets.push_back(std::make_pair(itr->first, *itr2));
|
||||
rets.push_back(std::make_pair(function.first, internal_func));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,11 +837,16 @@ namespace chaiscript
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
const Dynamic_Cast_Conversions &conversions() const
|
||||
{
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
std::vector<Proxy_Function> functions = get_function(t_name);
|
||||
|
||||
return dispatch::dispatch(functions.begin(), functions.end(), params);
|
||||
return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name) const
|
||||
@@ -830,6 +915,22 @@ namespace chaiscript
|
||||
std::cout << ") " << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a call can be made that consists of the first parameter
|
||||
* (the function) with the remaining parameters as its arguments.
|
||||
*/
|
||||
Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() < 1)
|
||||
{
|
||||
throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
|
||||
Const_Proxy_Function f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump all system info to stdout
|
||||
*/
|
||||
@@ -886,7 +987,7 @@ namespace chaiscript
|
||||
return get_type_name(obj.get_type_info());
|
||||
}
|
||||
|
||||
State get_state()
|
||||
State get_state() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_global_object_mutex);
|
||||
@@ -904,7 +1005,8 @@ namespace chaiscript
|
||||
|
||||
void save_function_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
m_stack_holder->call_params.insert(m_stack_holder->call_params.begin(), t_params.begin(), t_params.end());
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
s.call_params.insert(s.call_params.begin(), t_params.begin(), t_params.end());
|
||||
}
|
||||
|
||||
void new_function_call()
|
||||
@@ -914,15 +1016,16 @@ namespace chaiscript
|
||||
|
||||
void pop_function_call()
|
||||
{
|
||||
--m_stack_holder->call_depth;
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
--s.call_depth;
|
||||
|
||||
assert(m_stack_holder->call_depth >= 0);
|
||||
assert(s.call_depth >= 0);
|
||||
|
||||
if (m_stack_holder->call_depth == 0)
|
||||
if (s.call_depth == 0)
|
||||
{
|
||||
/// \todo Critical: this needs to be smarter, memory can expand quickly
|
||||
/// in tight loops involving function calls
|
||||
m_stack_holder->call_params.clear();
|
||||
s.call_params.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1056,6 +1159,10 @@ namespace chaiscript
|
||||
*/
|
||||
void validate_object_name(const std::string &name) const
|
||||
{
|
||||
if (name.find("::") != std::string::npos) {
|
||||
throw chaiscript::exception::illegal_name_error(name);
|
||||
}
|
||||
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
||||
@@ -1074,7 +1181,7 @@ namespace chaiscript
|
||||
|
||||
std::map<std::string, std::vector<Proxy_Function> > &funcs = get_functions_int();
|
||||
|
||||
std::map<std::string, std::vector<Proxy_Function> >::iterator itr
|
||||
auto itr
|
||||
= funcs.find(t_name);
|
||||
|
||||
std::map<std::string, Proxy_Function> &func_objs = get_function_objects_int();
|
||||
@@ -1095,6 +1202,14 @@ namespace chaiscript
|
||||
vec.push_back(t_f);
|
||||
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
|
||||
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||
} else if (t_f->has_arithmetic_param()) {
|
||||
// if the function is the only function but it also contains
|
||||
// arithmetic operators, we must wrap it in a dispatch function
|
||||
// to allow for automatic arithmetic type conversions
|
||||
std::vector<Proxy_Function> vec;
|
||||
vec.push_back(t_f);
|
||||
funcs.insert(std::make_pair(t_name, vec));
|
||||
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||
} else {
|
||||
std::vector<Proxy_Function> vec;
|
||||
vec.push_back(t_f);
|
||||
@@ -1124,7 +1239,7 @@ namespace chaiscript
|
||||
int call_depth;
|
||||
};
|
||||
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
|
||||
|
@@ -1,16 +1,24 @@
|
||||
// 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_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#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
|
||||
{
|
||||
@@ -20,22 +28,22 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) noexcept
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() noexcept {}
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,13 +52,14 @@ namespace chaiscript
|
||||
class Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
|
||||
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0;
|
||||
|
||||
const Type_Info &base()
|
||||
const Type_Info &base() const
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
const Type_Info &derived()
|
||||
const Type_Info &derived() const
|
||||
{
|
||||
return m_derived;
|
||||
}
|
||||
@@ -69,26 +78,21 @@ namespace chaiscript
|
||||
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived)
|
||||
if (t_from.get_type_info().bare_equal(user_type<From>()))
|
||||
{
|
||||
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
|
||||
{
|
||||
if (t_derived.is_pointer())
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_derived.is_const())
|
||||
if (t_from.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));
|
||||
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();
|
||||
@@ -96,8 +100,8 @@ namespace chaiscript
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<Base> data
|
||||
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived));
|
||||
std::shared_ptr<To> data
|
||||
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
@@ -108,83 +112,109 @@ namespace chaiscript
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_derived.is_const())
|
||||
if (t_from.is_const())
|
||||
{
|
||||
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
|
||||
const Base &data = dynamic_cast<const Base &>(d);
|
||||
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 {
|
||||
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
|
||||
Base &data = dynamic_cast<Base &>(d);
|
||||
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_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Dynamic_Conversions
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
static inline Dynamic_Conversions &get()
|
||||
Dynamic_Conversion_Impl()
|
||||
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
|
||||
{
|
||||
static Dynamic_Conversions obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Dynamic_Cast_Conversions
|
||||
{
|
||||
public:
|
||||
Dynamic_Cast_Conversions()
|
||||
{
|
||||
}
|
||||
|
||||
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
|
||||
: m_conversions(t_other.get_conversions())
|
||||
{
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Dynamic_Conversion> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
m_conversions.insert(conversion);
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
static std::shared_ptr<Dynamic_Conversion> create()
|
||||
bool dynamic_cast_converts() const
|
||||
{
|
||||
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;
|
||||
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
|
||||
}
|
||||
|
||||
template<typename InItr>
|
||||
void cleanup(InItr begin, const InItr &end)
|
||||
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
if (begin->unique())
|
||||
{
|
||||
m_conversions.erase(begin->get());
|
||||
return has_conversion(base, derived) || has_conversion(derived, base);
|
||||
}
|
||||
|
||||
++begin;
|
||||
template<typename Base>
|
||||
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
|
||||
{
|
||||
try {
|
||||
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
template<typename Derived>
|
||||
Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
m_conversions.insert(conversion.get());
|
||||
try {
|
||||
return get_conversion(base.get_type_info(), user_type<Derived>())->convert_down(base);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
std::shared_ptr<detail::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 =
|
||||
auto itr =
|
||||
find(base, derived);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
@@ -196,12 +226,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
Dynamic_Conversions() {}
|
||||
|
||||
std::set<Dynamic_Conversion *>::const_iterator find(
|
||||
std::set<std::shared_ptr<detail::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();
|
||||
for (auto itr = m_conversions.begin();
|
||||
itr != m_conversions.end();
|
||||
++itr)
|
||||
{
|
||||
@@ -214,11 +242,17 @@ namespace chaiscript
|
||||
return m_conversions.end();
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<Dynamic_Conversion *> m_conversions;
|
||||
};
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::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
|
||||
@@ -242,8 +276,6 @@ namespace chaiscript
|
||||
/// 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()
|
||||
{
|
||||
@@ -253,34 +285,9 @@ namespace chaiscript
|
||||
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>();
|
||||
return std::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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 Dynamic_Cast_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;
|
||||
}
|
||||
@@ -52,21 +73,21 @@ namespace chaiscript
|
||||
{
|
||||
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)
|
||||
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))
|
||||
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,7 +95,9 @@ namespace chaiscript
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const
|
||||
Dynamic_Object_Function &operator=(const 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)
|
||||
@@ -85,47 +108,47 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_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
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
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 Dynamic_Cast_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 Dynamic_Cast_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 +163,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::shared_ptr<Type_Info> &ti, const Dynamic_Cast_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 +185,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::shared_ptr<Type_Info> &ti, const Dynamic_Cast_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;
|
||||
}
|
||||
@@ -177,6 +199,8 @@ namespace chaiscript
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -191,10 +215,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)
|
||||
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 +226,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 +239,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 +250,36 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals;
|
||||
new_vals.push_back(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
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
// "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 Dynamic_Cast_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);
|
||||
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,101 @@
|
||||
// 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
|
||||
{
|
||||
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,19 +1,28 @@
|
||||
// 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 Dynamic_Cast_Conversions;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -29,10 +38,10 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs)
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,11 +59,11 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func)
|
||||
functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
funcs.push_back(func);
|
||||
return functor<FunctionType>(funcs);
|
||||
return functor<FunctionType>(funcs, t_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,9 +72,9 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv)
|
||||
functor(const Boxed_Value &bv, const Dynamic_Cast_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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +87,13 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -97,13 +106,13 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -116,13 +125,13 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_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 "dynamic_cast_conversion.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -17,31 +26,44 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/**
|
||||
* Internal helper class for handling the return
|
||||
* value of a build_function_caller
|
||||
*/
|
||||
template<typename Ret>
|
||||
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 Dynamic_Cast_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 Dynamic_Cast_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 Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params);
|
||||
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,28 +73,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 Dynamic_Cast_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>::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;
|
||||
Dynamic_Cast_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 Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
@@ -88,7 +112,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:Dynamic_Cast_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
|
||||
|
@@ -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_OPERATORS_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
|
||||
|
||||
|
||||
@@ -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,22 +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 Dynamic_Cast_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
|
||||
{
|
||||
@@ -40,9 +54,10 @@ 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::Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
Boxed_Value bv = do_call(params);
|
||||
Boxed_Value bv = do_call(params, t_conversions);
|
||||
return bv;
|
||||
}
|
||||
|
||||
@@ -53,17 +68,21 @@ namespace chaiscript
|
||||
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 Dynamic_Cast_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 Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
int arity = get_arity();
|
||||
|
||||
@@ -75,7 +94,7 @@ namespace chaiscript
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return compare_first_type(vals[0]);
|
||||
return compare_first_type(vals[0], t_conversions);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
@@ -87,30 +106,15 @@ namespace chaiscript
|
||||
|
||||
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 Dynamic_Cast_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.dynamic_cast_converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -120,8 +124,38 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_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)
|
||||
: m_types(std::move(t_types)), m_has_arithmetic_param(false)
|
||||
{
|
||||
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 Dynamic_Cast_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())
|
||||
{
|
||||
@@ -140,6 +174,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
std::vector<Type_Info> m_types;
|
||||
bool m_has_arithmetic_param;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,11 +192,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
|
||||
{ }
|
||||
};
|
||||
}
|
||||
@@ -175,17 +211,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())
|
||||
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)),
|
||||
m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard), m_parsenode(t_parsenode)
|
||||
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);
|
||||
|
||||
@@ -195,16 +233,13 @@ 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 Dynamic_Cast_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
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
@@ -219,18 +254,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 Dynamic_Cast_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 {
|
||||
@@ -243,12 +278,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_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 &) {
|
||||
@@ -309,24 +344,19 @@ namespace chaiscript
|
||||
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 Dynamic_Cast_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);
|
||||
@@ -336,10 +366,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;
|
||||
|
||||
@@ -367,12 +395,12 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "Bound: " + m_f->annotation();
|
||||
}
|
||||
@@ -401,9 +429,9 @@ 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 Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (*m_f)(build_param_list(params));
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -421,36 +449,36 @@ namespace chaiscript
|
||||
class Proxy_Function_Impl : public Proxy_Function_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_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 operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Proxy_Function_Impl *pimpl = dynamic_cast<const Proxy_Function_Impl<Func> *>(&t_func);
|
||||
return pimpl != 0;
|
||||
return pimpl != nullptr;
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return static_cast<int>(m_types.size()) - 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (int(vals.size()) != get_arity())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals);
|
||||
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "";
|
||||
}
|
||||
@@ -461,9 +489,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 Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
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:
|
||||
@@ -486,7 +514,7 @@ namespace chaiscript
|
||||
|
||||
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);
|
||||
@@ -499,12 +527,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@@ -514,23 +542,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 Dynamic_Cast_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 {
|
||||
@@ -558,19 +586,109 @@ namespace chaiscript
|
||||
class dispatch_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
dispatch_error(const std::vector<Boxed_Value> &t_bvs)
|
||||
: std::runtime_error("Error with function dispatch"), parameters(t_bvs)
|
||||
dispatch_error(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;
|
||||
};
|
||||
}
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Dynamic_Cast_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 Dynamic_Cast_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
|
||||
@@ -579,14 +697,15 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
if ((*begin)->filter(plist))
|
||||
if ((*begin)->filter(plist, t_conversions))
|
||||
{
|
||||
return (*(*begin))(plist);
|
||||
return (*(*begin))(plist, t_conversions);
|
||||
}
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
//parameter failed to cast, try again
|
||||
@@ -599,7 +718,7 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
|
||||
throw exception::dispatch_error(plist);
|
||||
return detail::dispatch_with_conversions(orig, end, plist, t_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,9 +728,9 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return dispatch::dispatch(funcs.begin(), funcs.end(), plist);
|
||||
return dispatch::dispatch(funcs.begin(), funcs.end(), 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 Dynamic_Cast_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;
|
||||
@@ -43,6 +53,29 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename ... Rest>
|
||||
struct Build_Param_Type_List;
|
||||
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Build_Param_Type_List<Param, Rest...>
|
||||
{
|
||||
static void build(std::vector<Type_Info> &t_params)
|
||||
{
|
||||
t_params.push_back(chaiscript::detail::Get_Type_Info<Param>::get());
|
||||
Build_Param_Type_List<Rest...>::build(t_params);
|
||||
}
|
||||
};
|
||||
|
||||
// 0th case
|
||||
template<>
|
||||
struct Build_Param_Type_List<>
|
||||
{
|
||||
static void build(std::vector<Type_Info> &)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to return a list of all param types
|
||||
* it contains.
|
||||
@@ -50,8 +83,12 @@ 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()... };
|
||||
/// \todo this code was previously using { chaiscript::detail::Get_Type_Info<Ret>::get()... }
|
||||
/// but this seems to indicate another bug with MSVC's uniform initializer lists
|
||||
std::vector<Type_Info> params;
|
||||
params.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
|
||||
Build_Param_Type_List<Params...>::build(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,14 +96,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 Dynamic_Cast_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,13 +110,12 @@ 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 Dynamic_Cast_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
|
||||
@@ -88,10 +123,10 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_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,21 +140,28 @@ 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 Dynamic_Cast_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 Dynamic_Cast_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
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -130,11 +172,11 @@ namespace chaiscript
|
||||
*/
|
||||
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 Dynamic_Cast_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));
|
||||
@@ -143,7 +185,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -157,9 +198,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params));
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -167,9 +208,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 Dynamic_Cast_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)
|
||||
{
|
||||
|
@@ -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
|
||||
{
|
||||
@@ -28,7 +29,7 @@ namespace chaiscript
|
||||
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),
|
||||
@@ -38,7 +39,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
Type_Info()
|
||||
: m_type_info(0), m_bare_type_info(0),
|
||||
: 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)
|
||||
@@ -81,7 +82,7 @@ namespace chaiscript
|
||||
|
||||
bool operator==(const std::type_info &ti) const
|
||||
{
|
||||
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
|
||||
@@ -90,11 +91,17 @@ namespace chaiscript
|
||||
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
||||
}
|
||||
|
||||
bool bare_equal_type_info(const std::type_info &ti) const
|
||||
{
|
||||
return m_bare_type_info != nullptr
|
||||
&& (*m_bare_type_info) == ti;
|
||||
}
|
||||
|
||||
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_undef() const { return m_is_undef || m_bare_type_info == nullptr; }
|
||||
bool is_pointer() const { return m_is_pointer; }
|
||||
|
||||
std::string name() const
|
||||
@@ -138,7 +145,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
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 +160,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
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 +175,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
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 +190,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
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 +205,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
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,
|
||||
@@ -225,7 +232,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
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 +247,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
Type_Info user_type()
|
||||
CHAISCRIPT_CONSTEXPR Type_Info user_type()
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
@@ -1,12 +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_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
|
@@ -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_
|
||||
|
||||
#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
|
||||
};
|
||||
};
|
||||
|
||||
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"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
@@ -55,69 +68,245 @@ 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;
|
||||
|
||||
|
||||
/// \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;
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_ss)),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) 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))
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_parameters, t_ss)),
|
||||
reason(t_why)
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) 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)
|
||||
{}
|
||||
|
||||
virtual ~eval_error() noexcept {}
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << what();
|
||||
if (call_stack.size() > 0) {
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")" << std::endl;
|
||||
ss << std::endl << detail << std::endl;
|
||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||
for (size_t j = 1; j < call_stack.size(); ++j) {
|
||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
|
||||
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
ss << std::endl;
|
||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static int id(const T& t)
|
||||
{
|
||||
return t->identifier;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string pretty(const T& t)
|
||||
{
|
||||
return t->pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string fname(const T& t)
|
||||
{
|
||||
return *t->filename;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string startpos(const T& t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << t->start.line << ", " << t->start.column;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::string format_why(const std::string &t_why)
|
||||
{
|
||||
return "Error: \"" + t_why + "\"";
|
||||
}
|
||||
|
||||
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
||||
static std::string format_types(const Const_Proxy_Function &t_func,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
int arity = t_func->get_arity();
|
||||
std::vector<Type_Info> types = t_func->get_param_types();
|
||||
|
||||
std::string retval;
|
||||
if (arity == -1)
|
||||
{
|
||||
retval = "(...)";
|
||||
if (t_dot_notation)
|
||||
{
|
||||
retval = "(Object)." + retval;
|
||||
}
|
||||
} else if (types.size() <= 1) {
|
||||
retval = "()";
|
||||
} else {
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
|
||||
std::string paramstr;
|
||||
|
||||
for (size_t index = 1;
|
||||
index != types.size();
|
||||
++index)
|
||||
{
|
||||
paramstr += (types[index].is_const()?"const ":"");
|
||||
paramstr += t_ss.get_type_name(types[index]);
|
||||
|
||||
if (index == 1 && t_dot_notation)
|
||||
{
|
||||
paramstr += ").(";
|
||||
if (types.size() == 2)
|
||||
{
|
||||
paramstr += ", ";
|
||||
}
|
||||
} else {
|
||||
paramstr += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
ss << paramstr.substr(0, paramstr.size() - 2);
|
||||
|
||||
ss << ")";
|
||||
retval = ss.str();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||
|
||||
if (dynfun)
|
||||
{
|
||||
Proxy_Function f = dynfun->get_guard();
|
||||
|
||||
if (f)
|
||||
{
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
|
||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||
if (dynfunguard)
|
||||
{
|
||||
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||
}
|
||||
}
|
||||
|
||||
retval += "\n Defined at " + format_location(dynfun->get_parse_tree());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_guard(const T &t)
|
||||
{
|
||||
return t->pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_location(const T &t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "(" << *t->filename << " " << t->start.line << ", " << t->start.column << ")";
|
||||
|
||||
return oss.str();
|
||||
|
||||
}
|
||||
|
||||
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "With parameters: (";
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:" << std::endl;
|
||||
|
||||
for (const auto & t_function : t_functions)
|
||||
{
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
|
||||
}
|
||||
|
||||
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
|
||||
if (!t_parameters.empty())
|
||||
{
|
||||
std::string paramstr;
|
||||
|
||||
for (const Boxed_Value &bv: t_parameters)
|
||||
for (auto itr = t_parameters.begin();
|
||||
itr != t_parameters.end();
|
||||
++itr)
|
||||
{
|
||||
paramstr += (itr->is_const()?"const ":"");
|
||||
paramstr += t_ss.type_name(*itr);
|
||||
|
||||
if (itr == t_parameters.begin() && t_dot_notation)
|
||||
{
|
||||
paramstr += ").(";
|
||||
if (t_parameters.size() == 1)
|
||||
{
|
||||
paramstr += (bv.is_const()?"const ":"");
|
||||
paramstr += t_ss.type_name(bv);
|
||||
paramstr += ", ";
|
||||
}
|
||||
} else {
|
||||
paramstr += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
ss << paramstr.substr(0, paramstr.size() - 2);
|
||||
}
|
||||
@@ -148,14 +337,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
ss << " ";
|
||||
|
||||
ss << format_parameters(t_parameters, t_ss);
|
||||
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||
ss << " ";
|
||||
|
||||
ss << format_filename(t_fname);
|
||||
@@ -167,14 +356,16 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
ss << " ";
|
||||
|
||||
ss << format_parameters(t_parameters, t_ss);
|
||||
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||
ss << " ";
|
||||
|
||||
return ss.str();
|
||||
@@ -196,15 +387,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 {}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -220,16 +410,28 @@ namespace chaiscript
|
||||
std::vector<AST_NodePtr> children;
|
||||
AST_NodePtr annotation;
|
||||
|
||||
/**
|
||||
* Prints the contents of an AST node, including its children, recursively
|
||||
*/
|
||||
std::string to_string(std::string t_prepend = "") {
|
||||
virtual std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
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(const std::string &t_prepend = "") {
|
||||
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) {
|
||||
for (size_t j = 0; j < this->children.size(); ++j) {
|
||||
oss << this->children[j]->to_string(t_prepend + " ");
|
||||
}
|
||||
return oss.str();
|
||||
@@ -245,7 +447,7 @@ namespace chaiscript
|
||||
return eval_internal(t_e);
|
||||
} catch (exception::eval_error &ee) {
|
||||
ee.call_stack.push_back(shared_from_this());
|
||||
throw ee;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,15 +458,15 @@ 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() {}
|
||||
|
||||
@@ -284,22 +486,27 @@ 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
|
||||
{
|
||||
@@ -323,7 +530,7 @@ namespace chaiscript
|
||||
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(chaiscript::detail::Dispatch_Engine &t_de)
|
||||
|
@@ -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/dynamic_cast_conversion.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.hpp"
|
||||
#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 {
|
||||
@@ -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");
|
||||
@@ -337,11 +344,14 @@ 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(std::bind(&chaiscript::detail::Dispatch_Engine::call_exists, std::ref(m_engine), std::placeholders::_1))),
|
||||
"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");
|
||||
|
||||
|
||||
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,13 +361,20 @@ 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, "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()) {
|
||||
@@ -385,9 +402,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 +426,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 +440,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
|
||||
|
||||
@@ -454,18 +470,38 @@ namespace chaiscript
|
||||
dllpath = std::string(&buf.front(), pathlen);
|
||||
}
|
||||
|
||||
m_modulepaths.push_back(dllpath+"/");
|
||||
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();
|
||||
}
|
||||
|
||||
/// \brief Loads and parses a file. If the file is already, it is not reloaded
|
||||
/// The use paths specified at ChaiScript construction time are searched for the
|
||||
@@ -479,14 +515,15 @@ namespace chaiscript
|
||||
try {
|
||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||
|
||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||
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
|
||||
@@ -512,6 +549,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
|
||||
@@ -522,8 +570,12 @@ namespace chaiscript
|
||||
std::set<std::string> active_loaded_modules;
|
||||
};
|
||||
|
||||
/// \brief Returns a state object that represents the current state of the system
|
||||
/// \return Current state of the system
|
||||
/// \brief Returns a state object that represents the current state of the global system
|
||||
///
|
||||
/// The global system includes the reserved words, global const objects, functions and types.
|
||||
/// local variables are thread specific and not included.
|
||||
///
|
||||
/// \return Current state of the global system
|
||||
///
|
||||
/// \b Example:
|
||||
///
|
||||
@@ -544,6 +596,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \brief Sets the state of the system
|
||||
///
|
||||
/// The global system includes the reserved words, global objects, functions and types.
|
||||
/// local variables are thread specific and not included.
|
||||
///
|
||||
/// \param[in] t_state New state to set
|
||||
///
|
||||
/// \b Example:
|
||||
@@ -563,7 +619,23 @@ namespace chaiscript
|
||||
m_engine.set_state(t_state.engine_state);
|
||||
}
|
||||
|
||||
/// \brief Adds a type, function or object to ChaiScript
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
return m_engine.get_locals();
|
||||
}
|
||||
|
||||
/// \brief Sets all of the locals for the current thread state.
|
||||
///
|
||||
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||
///
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
m_engine.set_locals(t_locals);
|
||||
}
|
||||
|
||||
/// \brief Adds a type, function or object to ChaiScript. Objects are added to the local thread state.
|
||||
/// \param[in] t_t Item to add
|
||||
/// \param[in] t_name Name of item to add
|
||||
/// \returns Reference to current ChaiScript object
|
||||
@@ -577,7 +649,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)
|
||||
{
|
||||
@@ -621,12 +693,19 @@ 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("cyg");
|
||||
prefixes.push_back("");
|
||||
|
||||
std::vector<std::string> postfixes;
|
||||
@@ -634,17 +713,19 @@ namespace chaiscript
|
||||
postfixes.push_back(".so");
|
||||
postfixes.push_back("");
|
||||
|
||||
for (size_t i = 0; i < m_modulepaths.size(); ++i)
|
||||
for (auto & elem : m_modulepaths)
|
||||
{
|
||||
for (size_t j = 0; j < prefixes.size(); ++j)
|
||||
for (auto & prefix : prefixes)
|
||||
{
|
||||
for (size_t k = 0; k < postfixes.size(); ++k)
|
||||
for (auto & postfix : postfixes)
|
||||
{
|
||||
try {
|
||||
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
|
||||
load_module(t_module_name, name);
|
||||
return;
|
||||
std::string name = elem + prefix + t_module_name + postfix;
|
||||
// std::cerr << "trying location: " << name << std::endl;
|
||||
load_module(version_stripped_name, name);
|
||||
return name;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
// std::cerr << "error: " << e.what() << std::endl;
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
@@ -707,9 +788,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,6 +799,8 @@ namespace chaiscript
|
||||
/// \tparam T Type to extract from the result value of the script execution
|
||||
/// \param[in] t_input Script to execute
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
|
||||
/// in special cases where you are loading a file internally instead of using eval_file
|
||||
///
|
||||
/// \return result of the script execution
|
||||
///
|
||||
@@ -725,35 +808,45 @@ namespace chaiscript
|
||||
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||
/// to the requested type.
|
||||
template<typename T>
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
try {
|
||||
return boxed_cast<T>(do_eval(t_input));
|
||||
return 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
|
||||
/// in special cases where you are loading a file internally instead of using eval_file
|
||||
///
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
try {
|
||||
return do_eval(t_input);
|
||||
return do_eval(t_input, t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw bv;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,9 +860,9 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,12 +877,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
@@ -1,18 +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_PARSER_HPP_
|
||||
#define CHAISCRIPT_PARSER_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "chaiscript_prelude.hpp"
|
||||
#include "../dispatchkit/boxed_value.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -34,6 +39,8 @@ namespace chaiscript
|
||||
, bin_alphabet
|
||||
, id_alphabet
|
||||
, white_alphabet
|
||||
, int_suffix_alphabet
|
||||
, float_suffix_alphabet
|
||||
, max_alphabet
|
||||
, lengthof_alphabet = 256
|
||||
};
|
||||
@@ -55,7 +62,8 @@ namespace chaiscript
|
||||
|
||||
public:
|
||||
ChaiScript_Parser()
|
||||
: m_multiline_comment_begin("/*"),
|
||||
: m_line(-1), m_col(-1),
|
||||
m_multiline_comment_begin("/*"),
|
||||
m_multiline_comment_end("*/"),
|
||||
m_singleline_comment("//")
|
||||
{
|
||||
@@ -133,8 +141,8 @@ namespace chaiscript
|
||||
m_operator_matches.push_back(multiplication);
|
||||
|
||||
for ( int c = 0 ; c < detail::lengthof_alphabet ; ++c ) {
|
||||
for ( int a = 0 ; a < detail::max_alphabet ; a ++ ) {
|
||||
m_alphabet[a][c]=false;
|
||||
for (auto & elem : m_alphabet) {
|
||||
elem[c]=false;
|
||||
}
|
||||
}
|
||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('?')]=true;
|
||||
@@ -176,12 +184,23 @@ namespace chaiscript
|
||||
|
||||
m_alphabet[detail::white_alphabet][static_cast<int>(' ')]=true;
|
||||
m_alphabet[detail::white_alphabet][static_cast<int>('\t')]=true;
|
||||
|
||||
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('l')] = true;
|
||||
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('L')] = true;
|
||||
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('u')] = true;
|
||||
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('U')] = true;
|
||||
|
||||
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('l')] = true;
|
||||
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('L')] = true;
|
||||
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('f')] = true;
|
||||
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('F')] = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* test a char in an m_alphabet
|
||||
*/
|
||||
bool char_in_alphabet(unsigned char c, detail::Alphabet a) { return m_alphabet[a][c]; }
|
||||
bool char_in_alphabet(char c, detail::Alphabet a) { return m_alphabet[a][static_cast<int>(c)]; }
|
||||
|
||||
/**
|
||||
* Prints the parsed ast_nodes as a tree
|
||||
@@ -198,10 +217,10 @@ namespace chaiscript
|
||||
/**
|
||||
* Shows the current stack of matched ast_nodes
|
||||
*/
|
||||
void show_match_stack() {
|
||||
for (unsigned int i = 0; i < m_match_stack.size(); ++i) {
|
||||
void show_match_stack() const {
|
||||
for (auto & elem : m_match_stack) {
|
||||
//debug_print(match_stack[i]);
|
||||
std::cout << m_match_stack[i]->to_string();
|
||||
std::cout << elem->to_string();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +280,7 @@ namespace chaiscript
|
||||
/**
|
||||
* Check to see if there is more text parse
|
||||
*/
|
||||
inline bool has_more_input() {
|
||||
inline bool has_more_input() const {
|
||||
return (m_input_pos != m_input_end);
|
||||
}
|
||||
|
||||
@@ -305,13 +324,21 @@ namespace chaiscript
|
||||
|
||||
/**
|
||||
* Skips ChaiScript whitespace, which means space and tab, but not cr/lf
|
||||
* jespada: Modified SkipWS to skip optionally CR ('\n')
|
||||
*/
|
||||
bool SkipWS() {
|
||||
bool SkipWS(bool skip_cr=false) {
|
||||
bool retval = false;
|
||||
while (has_more_input()) {
|
||||
if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) ) {
|
||||
++m_input_pos;
|
||||
if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) || (skip_cr && (*m_input_pos == '\n'))) {
|
||||
if(*m_input_pos == '\n') {
|
||||
m_col = 1;
|
||||
++m_line;
|
||||
}
|
||||
else {
|
||||
++m_col;
|
||||
}
|
||||
++m_input_pos;
|
||||
|
||||
retval = true;
|
||||
}
|
||||
else if (SkipComment()) {
|
||||
@@ -344,6 +371,12 @@ namespace chaiscript
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_suffix_alphabet))
|
||||
{
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
--m_input_pos;
|
||||
@@ -372,6 +405,11 @@ namespace chaiscript
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet))
|
||||
{
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
--m_input_pos;
|
||||
@@ -387,6 +425,14 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
void IntSuffix_() {
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet))
|
||||
{
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a binary value from input, without skipping initial whitespace
|
||||
*/
|
||||
@@ -420,6 +466,164 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
static Boxed_Value buildFloat(const std::string &t_val)
|
||||
{
|
||||
bool float_ = false;
|
||||
bool long_ = false;
|
||||
|
||||
size_t i = t_val.size();
|
||||
|
||||
for (; i > 0; --i)
|
||||
{
|
||||
char val = t_val[i-1];
|
||||
|
||||
if (val == 'f' || val == 'F')
|
||||
{
|
||||
float_ = true;
|
||||
} else if (val == 'l' || val == 'L') {
|
||||
long_ = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss(t_val.substr(0, i));
|
||||
|
||||
if (float_)
|
||||
{
|
||||
float f;
|
||||
ss >> f;
|
||||
return Boxed_Value(const_var(f));
|
||||
} else if (long_) {
|
||||
long double f;
|
||||
ss >> f;
|
||||
return Boxed_Value(const_var(f));
|
||||
} else {
|
||||
double f;
|
||||
ss >> f;
|
||||
return Boxed_Value(const_var(f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename IntType>
|
||||
static Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
|
||||
{
|
||||
bool unsigned_ = false;
|
||||
bool long_ = false;
|
||||
bool longlong_ = false;
|
||||
|
||||
size_t i = t_val.size();
|
||||
|
||||
for (; i > 0; --i)
|
||||
{
|
||||
char val = t_val[i-1];
|
||||
|
||||
if (val == 'u' || val == 'U')
|
||||
{
|
||||
unsigned_ = true;
|
||||
} else if (val == 'l' || val == 'L') {
|
||||
if (long_)
|
||||
{
|
||||
longlong_ = true;
|
||||
}
|
||||
|
||||
long_ = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss(t_val.substr(0, i));
|
||||
ss >> t_type;
|
||||
|
||||
std::stringstream testu(t_val.substr(0, i));
|
||||
uint64_t u;
|
||||
testu >> t_type >> u;
|
||||
|
||||
bool unsignedrequired = false;
|
||||
size_t size = sizeof(int) * 8;
|
||||
|
||||
if ((u >> (sizeof(int) * 8)) > 0)
|
||||
{
|
||||
//requires something bigger than int
|
||||
long_ = true;
|
||||
}
|
||||
|
||||
static_assert(sizeof(long) == sizeof(uint64_t) || sizeof(long) * 2 == sizeof(uint64_t), "Unexpected sizing of integer types");
|
||||
|
||||
if ((sizeof(long) < sizeof(uint64_t))
|
||||
&& (u >> ((sizeof(uint64_t) - sizeof(long)) * 8)) > 0)
|
||||
{
|
||||
//requires something bigger than long
|
||||
longlong_ = true;
|
||||
}
|
||||
|
||||
|
||||
if (longlong_)
|
||||
{
|
||||
size = sizeof(int64_t) * 8;
|
||||
} else if (long_) {
|
||||
size = sizeof(long) * 8;
|
||||
}
|
||||
|
||||
if ( (u >> (size - 1)) > 0)
|
||||
{
|
||||
unsignedrequired = true;
|
||||
}
|
||||
|
||||
if (unsignedrequired && !unsigned_)
|
||||
{
|
||||
if (t_type == &std::hex || t_type == &std::oct)
|
||||
{
|
||||
// with hex and octal we are happy to just make it unsigned
|
||||
unsigned_ = true;
|
||||
} else {
|
||||
// with decimal we must bump it up to the next size
|
||||
if (long_)
|
||||
{
|
||||
longlong_ = true;
|
||||
} else if (!long_ && !longlong_) {
|
||||
long_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unsigned_)
|
||||
{
|
||||
if (longlong_)
|
||||
{
|
||||
uint64_t val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else if (long_) {
|
||||
unsigned long val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else {
|
||||
unsigned int val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
}
|
||||
} else {
|
||||
if (longlong_)
|
||||
{
|
||||
int64_t val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else if (long_) {
|
||||
long val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else {
|
||||
int val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a number from the input, detecting if it's an integer or floating point
|
||||
*/
|
||||
@@ -436,19 +640,14 @@ namespace chaiscript
|
||||
if (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_alphabet) ) {
|
||||
if (Hex_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
std::stringstream ss(match);
|
||||
unsigned int temp_int;
|
||||
ss >> std::hex >> temp_int;
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << static_cast<int>(temp_int);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i = buildInt(std::hex, match);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
if (Binary_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
int temp_int = 0;
|
||||
int64_t temp_int = 0;
|
||||
size_t pos = 0, end = match.length();
|
||||
|
||||
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
|
||||
@@ -459,32 +658,36 @@ namespace chaiscript
|
||||
++pos;
|
||||
}
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << temp_int;
|
||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i;
|
||||
if (match.length() <= sizeof(int) * 8)
|
||||
{
|
||||
i = Boxed_Value(const_var(int(temp_int)));
|
||||
} else {
|
||||
i = Boxed_Value(const_var(temp_int));
|
||||
}
|
||||
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
if (Float_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Float_AST_Node(match, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value f = buildFloat(match);
|
||||
AST_NodePtr t(new eval::Float_AST_Node(match, f, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
IntSuffix_();
|
||||
std::string match(start, m_input_pos);
|
||||
if ((match.size() > 0) && (match[0] == '0')) {
|
||||
std::stringstream ss(match);
|
||||
unsigned int temp_int;
|
||||
ss >> std::oct >> temp_int;
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << int(temp_int);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i = buildInt(std::oct, match);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
else {
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i = buildInt(std::dec, match);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
return true;
|
||||
@@ -554,13 +757,13 @@ namespace chaiscript
|
||||
if (*start == '`') {
|
||||
//Id Literal
|
||||
std::string match(start+1, m_input_pos-1);
|
||||
AST_NodePtr t(new eval::Id_AST_Node(match, AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Id_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Id_AST_Node(match, AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Id_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
@@ -593,7 +796,7 @@ namespace chaiscript
|
||||
} while (Symbol("#"));
|
||||
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Annotation_AST_Node(match, AST_Node_Type::Annotation, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Annotation_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
@@ -607,10 +810,9 @@ namespace chaiscript
|
||||
*/
|
||||
bool Quoted_String_() {
|
||||
bool retval = false;
|
||||
char prev_char = 0;
|
||||
if (has_more_input() && (*m_input_pos == '\"')) {
|
||||
retval = true;
|
||||
prev_char = *m_input_pos;
|
||||
char prev_char = *m_input_pos;
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
|
||||
@@ -668,13 +870,13 @@ namespace chaiscript
|
||||
if (is_interpolated) {
|
||||
//If we've seen previous interpolation, add on instead of making a new one
|
||||
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
|
||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else {
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
|
||||
@@ -694,17 +896,17 @@ namespace chaiscript
|
||||
|
||||
size_t tostr_stack_top = m_match_stack.size();
|
||||
|
||||
AST_NodePtr tostr(new eval::Id_AST_Node("to_string", AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr tostr(new eval::Id_AST_Node("to_string", m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(tostr);
|
||||
|
||||
size_t ev_stack_top = m_match_stack.size();
|
||||
|
||||
AST_NodePtr ev(new eval::Id_AST_Node("eval", AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr ev(new eval::Id_AST_Node("eval", m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(ev);
|
||||
|
||||
size_t arg_stack_top = m_match_stack.size();
|
||||
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
|
||||
build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), arg_stack_top);
|
||||
@@ -762,13 +964,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
if (is_interpolated) {
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
|
||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else {
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
return true;
|
||||
@@ -784,10 +986,9 @@ namespace chaiscript
|
||||
*/
|
||||
bool Single_Quoted_String_() {
|
||||
bool retval = false;
|
||||
char prev_char = 0;
|
||||
if (has_more_input() && (*m_input_pos == '\'')) {
|
||||
retval = true;
|
||||
prev_char = *m_input_pos;
|
||||
char prev_char = *m_input_pos;
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
|
||||
@@ -860,7 +1061,7 @@ namespace chaiscript
|
||||
is_escaped = false;
|
||||
}
|
||||
}
|
||||
AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, AST_Node_Type::Single_Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
@@ -899,7 +1100,7 @@ namespace chaiscript
|
||||
int prev_line = m_line;
|
||||
if (Char_(t_c)) {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Char_AST_Node(match, AST_Node_Type::Char, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Char_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
@@ -914,11 +1115,11 @@ namespace chaiscript
|
||||
*/
|
||||
bool Keyword_(const char *t_s) {
|
||||
bool retval = false;
|
||||
int len = static_cast<int>(strlen(t_s));
|
||||
size_t len = strlen(t_s);
|
||||
|
||||
if ((m_input_end - m_input_pos) >= len) {
|
||||
if ((m_input_end - m_input_pos) >= static_cast<std::make_signed<size_t>::type>(len)) {
|
||||
std::string::const_iterator tmp = m_input_pos;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (*tmp != t_s[i]) {
|
||||
return false;
|
||||
}
|
||||
@@ -951,7 +1152,7 @@ namespace chaiscript
|
||||
|
||||
if ( t_capture && retval ) {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Str_AST_Node(match, AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
return retval;
|
||||
@@ -962,11 +1163,11 @@ namespace chaiscript
|
||||
*/
|
||||
bool Symbol_(const char *t_s) {
|
||||
bool retval = false;
|
||||
int len = static_cast<int>(strlen(t_s));
|
||||
size_t len = strlen(t_s);
|
||||
|
||||
if ((m_input_end - m_input_pos) >= len) {
|
||||
if ((m_input_end - m_input_pos) >= static_cast<std::make_signed<size_t>::type>(len)) {
|
||||
std::string::const_iterator tmp = m_input_pos;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (*tmp != t_s[i]) {
|
||||
return false;
|
||||
}
|
||||
@@ -999,7 +1200,7 @@ namespace chaiscript
|
||||
|
||||
if ( t_capture && retval ) {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Str_AST_Node(match, AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
|
||||
@@ -1039,7 +1240,7 @@ namespace chaiscript
|
||||
int prev_line = m_line;
|
||||
if (Eol_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Eol_AST_Node(match, AST_Node_Type::Eol, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
AST_NodePtr t(new eval::Eol_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
@@ -1053,6 +1254,8 @@ namespace chaiscript
|
||||
* Reads a comma-separated list of values from input
|
||||
*/
|
||||
bool Arg_List() {
|
||||
|
||||
SkipWS(true);
|
||||
bool retval = false;
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
@@ -1071,6 +1274,8 @@ namespace chaiscript
|
||||
build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), prev_stack_top);
|
||||
}
|
||||
|
||||
SkipWS(true);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1079,6 +1284,7 @@ namespace chaiscript
|
||||
*/
|
||||
bool Container_Arg_List() {
|
||||
bool retval = false;
|
||||
SkipWS(true);
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
@@ -1113,6 +1319,8 @@ namespace chaiscript
|
||||
build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), prev_stack_top);
|
||||
}
|
||||
|
||||
SkipWS(true);
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
@@ -1153,7 +1361,6 @@ namespace chaiscript
|
||||
bool Def() {
|
||||
bool retval = false;
|
||||
bool is_annotated = false;
|
||||
bool is_method = false;
|
||||
AST_NodePtr annotation;
|
||||
|
||||
if (Annotation()) {
|
||||
@@ -1172,6 +1379,8 @@ namespace chaiscript
|
||||
throw exception::eval_error("Missing function name in definition", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
bool is_method = false;
|
||||
|
||||
if (Symbol("::", false)) {
|
||||
//We're now a method
|
||||
is_method = true;
|
||||
@@ -1278,7 +1487,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an if/elseif/else block from input
|
||||
* Reads an if/else if/else block from input
|
||||
*/
|
||||
bool If() {
|
||||
bool retval = false;
|
||||
@@ -1309,7 +1518,7 @@ namespace chaiscript
|
||||
if (Keyword("else", true)) {
|
||||
if (Keyword("if")) {
|
||||
AST_NodePtr back(m_match_stack.back());
|
||||
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if", back->identifier));
|
||||
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if"));
|
||||
m_match_stack.back()->start = back->start;
|
||||
m_match_stack.back()->end = back->end;
|
||||
m_match_stack.back()->children = back->children;
|
||||
@@ -1377,19 +1586,41 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the C-style for conditions from input
|
||||
*/
|
||||
bool For_Guards() {
|
||||
Equation();
|
||||
if (!(Equation() && Eol()))
|
||||
{
|
||||
if (!Eol())
|
||||
{
|
||||
throw exception::eval_error("'for' loop initial statment missing", File_Position(m_line, m_col), *m_filename);
|
||||
} else {
|
||||
AST_NodePtr t(new eval::Noop_AST_Node());
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(Equation() && Eol()))
|
||||
{
|
||||
if (!Eol())
|
||||
{
|
||||
throw exception::eval_error("'for' loop condition missing", File_Position(m_line, m_col), *m_filename);
|
||||
} else {
|
||||
AST_NodePtr t(new eval::Noop_AST_Node());
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Equation())
|
||||
{
|
||||
AST_NodePtr t(new eval::Noop_AST_Node());
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
|
||||
if (Char(';') && Operator() && Char(';') && Equation()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
throw exception::eval_error("Incomplete conditions in 'for' loop", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a for block from input
|
||||
@@ -1563,6 +1794,23 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a continue statement from input
|
||||
*/
|
||||
bool Continue() {
|
||||
bool retval = false;
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Keyword("continue")) {
|
||||
retval = true;
|
||||
|
||||
build_match(AST_NodePtr(new eval::Continue_AST_Node()), prev_stack_top);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a dot expression(member access), then proceeds to check if it's a function or array call
|
||||
*/
|
||||
@@ -1690,8 +1938,9 @@ namespace chaiscript
|
||||
if (Char('[')) {
|
||||
retval = true;
|
||||
Container_Arg_List();
|
||||
|
||||
if (!Char(']')) {
|
||||
throw exception::eval_error("Missing closing brace '}' in container initializer", File_Position(m_line, m_col), *m_filename);
|
||||
throw exception::eval_error("Missing closing square bracket ']' in container initializer", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) {
|
||||
if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) {
|
||||
@@ -1819,8 +2068,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool Operator_Helper(size_t t_precedence) {
|
||||
for (size_t i = 0; i < m_operator_matches[t_precedence].size(); ++i) {
|
||||
if (Symbol(m_operator_matches[t_precedence][i].c_str(), true)) {
|
||||
for (auto & elem : m_operator_matches[t_precedence]) {
|
||||
if (Symbol(elem.c_str(), true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2001,6 +2250,7 @@ namespace chaiscript
|
||||
Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true) ||
|
||||
Symbol("%=", true, true) || Symbol("<<=", true, true) || Symbol(">>=", true, true) ||
|
||||
Symbol("&=", true, true) || Symbol("^=", true, true) || Symbol("|=", true, true)) {
|
||||
SkipWS(true);
|
||||
if (!Equation()) {
|
||||
throw exception::eval_error("Incomplete equation", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
@@ -2088,6 +2338,14 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Continue()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Block()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
|
531
include/chaiscript/language/chaiscript_prelude.chai
Normal file
531
include/chaiscript/language/chaiscript_prelude.chai
Normal file
@@ -0,0 +1,531 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||
#define CHAISCRIPT_PRELUDE_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
struct ChaiScript_Prelude {
|
||||
static std::string chaiscript_prelude() { return R""(
|
||||
|
||||
def lt(l, r) {
|
||||
if (call_exists(`<`, l, r)) {
|
||||
l < r
|
||||
} else {
|
||||
type_name(l) < type_name(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def gt(l, r) {
|
||||
if (call_exists(`>`, l, r)) {
|
||||
l > r
|
||||
} else {
|
||||
type_name(l) > type_name(r)
|
||||
}
|
||||
}
|
||||
|
||||
def eq(l, r) {
|
||||
if (call_exists(`==`, l, r)) {
|
||||
l == r
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def new(x) {
|
||||
eval(type_name(x))();
|
||||
}
|
||||
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
|
||||
{
|
||||
eval(type_name(x))(x);
|
||||
}
|
||||
|
||||
|
||||
# to_string for Pair()
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) {
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">";
|
||||
}
|
||||
|
||||
# to_string for containers
|
||||
def to_string(x) : call_exists(range, x) && !x.is_type("string"){
|
||||
"[" + x.join(", ") + "]";
|
||||
}
|
||||
|
||||
# Basic to_string function
|
||||
def to_string(x) {
|
||||
internal_to_string(x);
|
||||
}
|
||||
|
||||
# Prints to console with no carriage return
|
||||
def puts(x) {
|
||||
print_string(x.to_string());
|
||||
}
|
||||
|
||||
# Prints to console with carriage return
|
||||
def print(x) {
|
||||
println_string(x.to_string());
|
||||
}
|
||||
|
||||
# Returns the maximum value of two numbers
|
||||
def max(a, b) {
|
||||
if (a>b) {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the minimum value of two numbers
|
||||
def min(a, b)
|
||||
{
|
||||
if (a<b)
|
||||
{
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns true if the value is odd
|
||||
def odd(x) {
|
||||
if (x % 2 == 1)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns true if the value is even
|
||||
def even(x)
|
||||
{
|
||||
if (x % 2 == 0)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Pushes the second value onto the container first value while making a clone of the value
|
||||
def push_back(container, x) : call_exists(push_back_ref, container, x)
|
||||
{
|
||||
container.push_back_ref(clone(x))
|
||||
}
|
||||
|
||||
# Pushes the second value onto the front of the container first value while making a clone of the value
|
||||
def push_front(container, x) : call_exists(push_front_ref, container, x)
|
||||
{
|
||||
container.push_front_ref(clone(x))
|
||||
}
|
||||
|
||||
# Inserts the third value at the position of the second value into the container of the first
|
||||
# while making a clone.
|
||||
def insert_at(container, pos, x)
|
||||
{
|
||||
container.insert_ref_at(pos, clone(x));
|
||||
}
|
||||
|
||||
# Returns the reverse of the given container
|
||||
def reverse(container) {
|
||||
auto retval = new(container);
|
||||
auto r = range(container);
|
||||
while (!r.empty()) {
|
||||
retval.push_back(r.back());
|
||||
r.pop_back();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
# Return a range from a range
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
|
||||
{
|
||||
return clone(r);
|
||||
}
|
||||
|
||||
|
||||
# The retro attribute that contains the underlying range
|
||||
attr retro::m_range;
|
||||
|
||||
# Creates a retro from a retro by returning the original range
|
||||
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro"
|
||||
{
|
||||
clone(r.m_range)
|
||||
}
|
||||
|
||||
|
||||
# Creates a retro range from a range
|
||||
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
|
||||
{
|
||||
this.m_range = r;
|
||||
}
|
||||
|
||||
# Returns the first value of a retro
|
||||
def retro::front()
|
||||
{
|
||||
back(this.m_range)
|
||||
}
|
||||
|
||||
# Returns the last value of a retro
|
||||
def retro::back()
|
||||
{
|
||||
front(this.m_range)
|
||||
}
|
||||
|
||||
# Moves the back iterator of a retro towards the front by one
|
||||
def retro::pop_back()
|
||||
{
|
||||
pop_front(this.m_range)
|
||||
}
|
||||
|
||||
# Moves the front iterator of a retro towards the back by one
|
||||
def retro::pop_front()
|
||||
{
|
||||
pop_back(this.m_range)
|
||||
}
|
||||
|
||||
# returns true if the retro is out of elements
|
||||
def retro::empty()
|
||||
{
|
||||
empty(this.m_range);
|
||||
}
|
||||
|
||||
# Performs the second value function over the container first value
|
||||
def for_each(container, func) : call_exists(range, container) {
|
||||
var t_range = range(container);
|
||||
while (!t_range.empty()) {
|
||||
func(t_range.front());
|
||||
t_range.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
def back_inserter(container) {
|
||||
bind(push_back, container, _);
|
||||
}
|
||||
|
||||
def contains(container, item, compare_func) : call_exists(range, container) {
|
||||
auto t_range = range(container);
|
||||
while (!t_range.empty()) {
|
||||
if ( compare_func(t_range.front(), item) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
t_range.pop_front();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
def contains(container, item) {
|
||||
return contains(container, item, eq)
|
||||
}
|
||||
|
||||
def map(container, func, inserter) : call_exists(range, container) {
|
||||
auto range = range(container);
|
||||
while (!range.empty()) {
|
||||
inserter(func(range.front()));
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
# Performs the second value function over the container first value. Creates a new container with the results
|
||||
def map(container, func) {
|
||||
auto retval = new(container);
|
||||
map(container, func, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
# Performs the second value function over the container first value. Starts with initial and continues with each element.
|
||||
def foldl(container, func, initial) : call_exists(range, container){
|
||||
auto retval = initial;
|
||||
auto range = range(container);
|
||||
while (!range.empty()) {
|
||||
retval = (func(range.front(), retval));
|
||||
range.pop_front();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
# Returns the sum of the elements of the given value
|
||||
def sum(container) {
|
||||
foldl(container, `+`, 0.0)
|
||||
}
|
||||
|
||||
# Returns the product of the elements of the given value
|
||||
def product(container) {
|
||||
foldl(container, `*`, 1.0)
|
||||
}
|
||||
|
||||
# Returns a new container with the elements of the first value concatenated with the elements of the second value
|
||||
def concat(x, y) : call_exists(clone, x) {
|
||||
auto retval = x;
|
||||
auto inserter = back_inserter(retval);
|
||||
auto range = range(y);
|
||||
while (!range.empty()) {
|
||||
inserter(range.front());
|
||||
range.pop_front();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def take(container, num, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto i = num;
|
||||
while ((i > 0) && (!r.empty())) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given number of elements taken from the container
|
||||
def take(container, num) {
|
||||
auto retval = new(container);
|
||||
take(container, num, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def take_while(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
while ((!r.empty()) && f(r.front())) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given elements match the second value function
|
||||
def take_while(container, f) {
|
||||
auto retval = new(container);
|
||||
take_while(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def drop(container, num, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto i = num;
|
||||
while ((i > 0) && (!r.empty())) {
|
||||
r.pop_front();
|
||||
--i;
|
||||
}
|
||||
while (!r.empty()) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given number of elements dropped from the given container
|
||||
def drop(container, num) {
|
||||
auto retval = new(container);
|
||||
drop(container, num, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def drop_while(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
while ((!r.empty())&& f(r.front())) {
|
||||
r.pop_front();
|
||||
}
|
||||
while (!r.empty()) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given elements dropped that match the second value function
|
||||
def drop_while(container, f) {
|
||||
auto retval = new(container);
|
||||
drop_while(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.
|
||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto retval = r.front();
|
||||
r.pop_front();
|
||||
retval = func(retval, r.front());
|
||||
r.pop_front();
|
||||
while (!r.empty()) {
|
||||
retval = func(retval, r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Returns a string of the elements in container delimited by the second value string
|
||||
def join(container, delim) {
|
||||
auto retval = "";
|
||||
auto range = range(container);
|
||||
if (!range.empty()) {
|
||||
retval += to_string(range.front());
|
||||
range.pop_front();
|
||||
while (!range.empty()) {
|
||||
retval += delim;
|
||||
retval += to_string(range.front());
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def filter(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
while (!r.empty()) {
|
||||
if (f(r.front())) {
|
||||
inserter(r.front());
|
||||
}
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which match the second value function
|
||||
def filter(container, f) {
|
||||
auto retval = new(container);
|
||||
filter(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def generate_range(x, y, inserter) {
|
||||
auto i = x;
|
||||
while (i <= y) {
|
||||
inserter(i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which represents the range from the first value to the second value
|
||||
def generate_range(x, y) {
|
||||
auto retval = Vector();
|
||||
generate_range(x,y,back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector with the first value to the second value as its elements
|
||||
def collate(x, y) {
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) {
|
||||
auto r_x = range(x);
|
||||
auto r_y = range(y);
|
||||
while (!r_x.empty() && !r_y.empty()) {
|
||||
inserter(f(r_x.front(), r_y.front()));
|
||||
r_x.pop_front();
|
||||
r_y.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which joins matching elements of the second and third value with the first value function
|
||||
def zip_with(f, x, y) {
|
||||
auto retval = Vector();
|
||||
zip_with(f,x,y,back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which joins matching elements of the first and second
|
||||
def zip(x, y) {
|
||||
zip_with(collate, x, y);
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the second value string in the first value string
|
||||
def string::find(substr) : is_type(substr, "string") {
|
||||
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") {
|
||||
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") {
|
||||
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") {
|
||||
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") {
|
||||
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") {
|
||||
find_last_not_of(this, list, size_t(-1));
|
||||
}
|
||||
|
||||
|
||||
def string::ltrim() {
|
||||
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'});
|
||||
}
|
||||
|
||||
|
||||
def string::rtrim() {
|
||||
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}));
|
||||
}
|
||||
|
||||
|
||||
def string::trim() {
|
||||
ltrim(rtrim(this));
|
||||
}
|
||||
|
||||
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
|
||||
auto range = range(container);
|
||||
while (!range.empty()) {
|
||||
if (compare_func(range.front(), value)) {
|
||||
return range;
|
||||
} else {
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
|
||||
def find(container, value) {
|
||||
return find(container, value, eq)
|
||||
}
|
||||
|
||||
|
||||
)"";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
@@ -1,329 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||
#define CHAISCRIPT_PRELUDE_HPP_
|
||||
|
||||
//Note, the expression "[x,y]" in "collate" is parsed as two separate expressions
|
||||
//by C++, so CODE_STRING, takes two expressions and adds in the missing comma
|
||||
#define CODE_STRING(x, y) #x ", " #y
|
||||
|
||||
#define chaiscript_prelude CODE_STRING(\
|
||||
def lt(l, r) { if (call_exists(`<`, l, r)) { l < r } else { type_name(l) < type_name(r) } } \n\
|
||||
def gt(l, r) { if (call_exists(`>`, l, r)) { l > r } else { type_name(l) > type_name(r) } } \n\
|
||||
def eq(l, r) { if (call_exists(`==`, l, r)) { l == r } else { false } } \n\
|
||||
def new(x) { eval(type_name(x))(); } \n\
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) { eval(type_name(x))(x); } \n\
|
||||
# to_string for Pair()\n\
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \n\
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \n\
|
||||
}\n\
|
||||
# to_string for containers\n\
|
||||
def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \n\
|
||||
"[" + x.join(", ") + "]"; \n\
|
||||
}\n\
|
||||
# Basic to_string function\n\
|
||||
def to_string(x) { \n\
|
||||
internal_to_string(x); \n\
|
||||
}\n\
|
||||
# Prints to console with no carriage return\n\
|
||||
def puts(x) { \n\
|
||||
print_string(x.to_string()); \n\
|
||||
} \n\
|
||||
# Prints to console with carriage return\n\
|
||||
def print(x) { \n\
|
||||
println_string(x.to_string()); \n\
|
||||
} \n\
|
||||
# Returns the maximum value of two numbers\n\
|
||||
def max(a, b) { if (a>b) { a } else { b } } \n\
|
||||
# Returns the minimum value of two numbers\n\
|
||||
def min(a, b) { if (a<b) { a } else { b } } \n\
|
||||
# Returns true if the value is odd\n\
|
||||
def odd(x) { if (x % 2 == 1) { true } else { false } } \n\
|
||||
# Returns true if the value is even\n\
|
||||
def even(x) { if (x % 2 == 0) { true } else { false } } \n\
|
||||
# Pushes the second value onto the container first value while making a clone of the value\n\
|
||||
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_ref(clone(x)) } \n\
|
||||
# Pushes the second value onto the front of the container first value while making a clone of the value\n\
|
||||
def push_front(container, x) : call_exists(push_front_ref, container, x) { container.push_front_ref(clone(x)) } \n\
|
||||
# Inserts the third value at the position of the second value into the container of the first\n\
|
||||
# while making a clone. \n\
|
||||
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
|
||||
# Returns the reverse of the given container\n\
|
||||
def reverse(container) {\n\
|
||||
auto retval = new(container); \n\
|
||||
auto r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval.push_back(r.back()); \n\
|
||||
r.pop_back(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Return a range from a range \n\
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { return clone(r); }\n\
|
||||
# The retro attribute that contains the underlying range \n\
|
||||
attr retro::m_range; \n\
|
||||
# Creates a retro from a retro by returning the original range\n\
|
||||
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro" { clone(r.m_range) }\n\
|
||||
# Creates a retro range from a range\n\
|
||||
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { this.m_range = r; }\n\
|
||||
# Returns the first value of a retro\n\
|
||||
def retro::front() { back(this.m_range) }\n\
|
||||
# Returns the last value of a retro\n\
|
||||
def retro::back() { front(this.m_range) }\n\
|
||||
# Moves the back iterator of a retro towards the front by one \n\
|
||||
def retro::pop_back() { pop_front(this.m_range) }\n\
|
||||
# Moves the front iterator of a retro towards the back by one \n\
|
||||
def retro::pop_front() { pop_back(this.m_range) } \n\
|
||||
# returns true if the retro is out of elements \n\
|
||||
def retro::empty() { empty(this.m_range); } \n\
|
||||
# Performs the second value function over the container first value\n\
|
||||
def for_each(container, func) : call_exists(range, container) { \n\
|
||||
auto t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
func(t_range.front()); \n\
|
||||
t_range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
def back_inserter(container) { \n\
|
||||
bind(push_back, container, _); \n\
|
||||
}\n\
|
||||
\n\
|
||||
def contains(container, item, compare_func) : call_exists(range, container) { \n\
|
||||
auto t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
if ( compare_func(t_range.front(), item) ) { return true; } \n\
|
||||
t_range.pop_front(); \n\
|
||||
} \n\
|
||||
return false; \n\
|
||||
} \n\
|
||||
def contains(container, item) { return contains(container, item, eq) } \n\
|
||||
def map(container, func, inserter) : call_exists(range, container) { \n\
|
||||
auto range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
inserter(func(range.front())); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Performs the second value function over the container first value. Creates a new container with the results\n\
|
||||
def map(container, func) { \n\
|
||||
auto retval = new(container); \n\
|
||||
map(container, func, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
|
||||
def foldl(container, func, initial) : call_exists(range, container){ \n\
|
||||
auto retval = initial; \n\
|
||||
auto range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval = (func(range.front(), retval)); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Returns the sum of the elements of the given value\n\
|
||||
def sum(container) { foldl(container, `+`, 0.0) } \n\
|
||||
# Returns the product of the elements of the given value\n\
|
||||
def product(container) { foldl(container, `*`, 1.0) } \n\
|
||||
# Returns a new container with the elements of the first value concatenated with the elements of the second value\n\
|
||||
def concat(x, y) : call_exists(clone, x) { \n\
|
||||
auto retval = x; \n\
|
||||
auto inserter = back_inserter(retval); \n\
|
||||
auto range = range(y); \n\
|
||||
while (!range.empty()) { \n\
|
||||
inserter(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def take(container, num, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
auto i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements taken from the container\n\
|
||||
def take(container, num) {\n\
|
||||
auto retval = new(container); \n\
|
||||
take(container, num, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
def take_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
while ((!r.empty()) && f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements match the second value function\n\
|
||||
def take_while(container, f) {\n\
|
||||
auto retval = new(container); \n\
|
||||
take_while(container, f, back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def drop(container, num, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
auto i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
} \n\
|
||||
while (!r.empty()) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements dropped from the given container \n\
|
||||
def drop(container, num) {\n\
|
||||
auto retval = new(container); \n\
|
||||
drop(container, num, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
def drop_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
while ((!r.empty())&& f(r.front())) { \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
while (!r.empty()) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements dropped that match the second value function\n\
|
||||
def drop_while(container, f) {\n\
|
||||
auto retval = new(container); \n\
|
||||
drop_while(container, f, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
|
||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
auto retval = r.front(); \n\
|
||||
r.pop_front(); \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Returns a string of the elements in container delimited by the second value string\n\
|
||||
def join(container, delim) { \n\
|
||||
auto retval = ""; \n\
|
||||
auto range = range(container); \n\
|
||||
if (!range.empty()) { \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval += delim; \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def filter(container, f, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
if (f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
} \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which match the second value function\n\
|
||||
def filter(container, f) { \n\
|
||||
auto retval = new(container); \n\
|
||||
filter(container, f, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def generate_range(x, y, inserter) { \n\
|
||||
auto i = x; \n\
|
||||
while (i <= y) { \n\
|
||||
inserter(i); \n\
|
||||
++i; \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which represents the range from the first value to the second value\n\
|
||||
def generate_range(x, y) { \n\
|
||||
auto retval = Vector(); \n\
|
||||
generate_range(x,y,back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
# Returns a new Vector with the first value to the second value as its elements\n\
|
||||
def collate(x, y) { \n\
|
||||
return [x, y]; \n\
|
||||
} \n\
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \n\
|
||||
auto r_x = range(x); \n\
|
||||
auto r_y = range(y); \n\
|
||||
while (!r_x.empty() && !r_y.empty()) { \n\
|
||||
inserter(f(r_x.front(), r_y.front())); \n\
|
||||
r_x.pop_front(); \n\
|
||||
r_y.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which joins matching elements of the second and third value with the first value function\n\
|
||||
def zip_with(f, x, y) { \n\
|
||||
auto retval = Vector(); \n\
|
||||
zip_with(f,x,y,back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
# Returns a new Vector which joins matching elements of the first and second\n\
|
||||
def zip(x, y) { \n\
|
||||
zip_with(collate, x, y); \n\
|
||||
}\n\
|
||||
# Returns the position of the second value string in the first value string\n\
|
||||
def string::find(substr) : is_type(substr, "string") { \n\
|
||||
int(find(this, substr, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of last match of the second value string in the first value string\n\
|
||||
def string::rfind(substr) : is_type(substr, "string") { \n\
|
||||
int(rfind(this, substr, -1)); \n\
|
||||
} \n\
|
||||
# Returns the position of the first match of elements in the second value string in the first value string\n\
|
||||
def string::find_first_of(list) : is_type(list, "string") { \n\
|
||||
int(find_first_of(this, list, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of the last match of elements in the second value string in the first value string\n\
|
||||
def string::find_last_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
# Returns the position of the first non-matching element in the second value string in the first value string\n\
|
||||
def string::find_first_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_first_not_of(this, list, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of the last non-matching element in the second value string in the first value string\n\
|
||||
def string::find_last_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_not_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
def string::ltrim() { \n\
|
||||
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}); \n\
|
||||
} \n\
|
||||
def string::rtrim() { \n\
|
||||
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'})); \n\
|
||||
} \n\
|
||||
def string::trim() { \n\
|
||||
ltrim(rtrim(this)); \n\
|
||||
} \n\
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { \n\
|
||||
auto range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
if (compare_func(range.front(), value)) { \n\
|
||||
return range; \n\
|
||||
} else { \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
return range; \n\
|
||||
} \n\
|
||||
def find(container, value) { return find(container, value, eq) } \
|
||||
)
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
@@ -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
|
||||
|
@@ -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,17 +21,19 @@ namespace chaiscript
|
||||
namespace utility
|
||||
{
|
||||
|
||||
/// \todo Use of this utility, and uniform initializer lists, is causing memory errors in MSVC
|
||||
|
||||
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)
|
||||
@@ -35,6 +42,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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:
|
||||
|
119
readme.md
Normal file
119
readme.md
Normal file
@@ -0,0 +1,119 @@
|
||||
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 Jonathan Turner
|
||||
(c) 2009-2014 Jason Turner
|
||||
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
ChaiScript is one of the only embedded scripting language designed from the
|
||||
ground up to directly target C++ and take advantage of modern C++ development
|
||||
techniques, working with the developer like he expects it to work. Being a
|
||||
native C++ application, it has some advantages over existing embedded scripting
|
||||
languages:
|
||||
|
||||
1. It uses a header-only approach, which makes it easy to integrate with
|
||||
existing projects.
|
||||
2. It maintains type safety between your C++ application and the user scripts.
|
||||
3. It supports a variety of C++ techniques including callbacks, overloaded
|
||||
functions, class methods, and stl containers.
|
||||
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
ChaiScript requires a C++11 compiler to build with support for variadic
|
||||
templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx). MacOS
|
||||
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
|
||||
clang 4.0.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
* Add the ChaiScript include directory to your project's header search path
|
||||
* Add `#include <chaiscript/chaiscript.hpp>` to your source file
|
||||
* Instantiate the ChaiScript engine in your application. For example, create a
|
||||
new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
|
||||
* The default behavior is to load the ChaiScript standard library from a
|
||||
loadable module. A second option is to compile the library into your code,
|
||||
see below for an example.
|
||||
|
||||
Once instantiated, the engine is ready to start running ChaiScript source. You
|
||||
have two main options for processing ChaiScript source: a line at a time using
|
||||
`chai.eval(string)` and a file at a time using `chai.eval_file(fname)`
|
||||
|
||||
To make functions in your C++ code visible to scripts, they must be registered
|
||||
with the scripting engine. To do so, call add:
|
||||
|
||||
chai.add(chaiscript::fun(&my_function), "my_function_name");
|
||||
|
||||
Once registered the function will be visible to scripts as "my_function_name"
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some
|
||||
modifications to make it easier to use. For usage examples see the "samples"
|
||||
directory, and for more in-depth look at the language, the unit tests in the
|
||||
"unittests" directory cover the most ground.
|
||||
|
||||
For examples of how to register parts of your C++ application, see
|
||||
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
|
||||
possible way of working with the library. For further documentation generate
|
||||
the doxygen documentation in the build folder or see the website
|
||||
http://www.chaiscript.com.
|
||||
|
||||
|
||||
The shortest complete example possible follows:
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Or, if you want to compile the std lib into your code, which reduces
|
||||
runtime requirements.
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
||||
|
||||
|
55
readme.txt
55
readme.txt
@@ -1,55 +0,0 @@
|
||||
ChaiScript
|
||||
http://www.chaiscript.com
|
||||
(c) 2009-2012 Jason Turner and Jonathan Turner
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
[Introduction]
|
||||
|
||||
ChaiScript is one of the only embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques, working with the developer like he expects it to work. Being a native C++ application, it has some advantages over existing embedded scripting languages:
|
||||
|
||||
1) It uses a header-only approach, which makes it easy to integrate with existing projects.
|
||||
2) It maintains type safety between your C++ application and the user scripts.
|
||||
3) It supports a variety of C++ techniques including callbacks, overloaded functions, class methods, and stl containers.
|
||||
|
||||
[Requirements]
|
||||
|
||||
ChaiScript requires a C++11 compiler to build with support for variadic templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx).
|
||||
|
||||
[Usage]
|
||||
|
||||
* Add the ChaiScript include directory to your project's header search path
|
||||
* Add "#include <chaiscript/chaiscript.hpp> to your source file
|
||||
* Instantiate the ChaiScript engine in your application. For example, create a new engine with the name 'chai' like so: "chaiscript::ChaiScript chai"
|
||||
|
||||
Once instantiated, the engine is ready to start running ChaiScript source. You have two main options for processing ChaiScript source: a line at a time using "chai.evaluate_string(string)" and a file at a time using "chai.evaluate_file(fname)"
|
||||
|
||||
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call add:
|
||||
|
||||
chai.add(chaiscript::fun(&my_function), "my_function_name");
|
||||
|
||||
Once registered the function will be visible to scripts as "my_function_name"
|
||||
|
||||
[Examples]
|
||||
|
||||
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some modifications to make it easier to use. For usage examples see the "samples" directory, and for more in-depth look at the language, the unit tests in the "unittests" directory cover the most ground.
|
||||
|
||||
For examples of how to register parts of your C++ application, see "example.cpp" in the "src" directory. Example.cpp is verbose and shows every possible way of working with the library. For further documentation generate the doxygen documentation in the build folder or see the website http://www.chaiscript.com.
|
||||
|
||||
The shortest complete example possible follows:
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
@@ -1,8 +1,58 @@
|
||||
Changes since 4.0.0
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.3.1
|
||||
|
||||
### 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
|
||||
### Changes since 3.1.0
|
||||
* svenstaro: Unused variables and CMake consistency fixes
|
||||
* Added support for returning pointers from functions (#13)
|
||||
* Compile with -pedantic (#9)
|
||||
@@ -21,7 +71,7 @@ Changes since 3.1.0
|
||||
* Increased unit tests to 161
|
||||
* Performance enhancements
|
||||
|
||||
Changes since 3.0.0
|
||||
### Changes since 3.0.0
|
||||
* Numeric operations performance increased approximately 10x
|
||||
* Looping operations performance increased up to 2x
|
||||
* Engine start up time decreased
|
||||
@@ -30,8 +80,7 @@ Changes since 3.0.0
|
||||
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
|
||||
|
||||
### Changes since 2.3.3
|
||||
* Code simplifications
|
||||
* Fully integrate documentation with source code in doxygen style comments
|
||||
* Unit tests increased from 114 to 137
|
@@ -5,6 +5,7 @@
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +137,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
|
||||
//To do: Add examples of handling Boxed_Values directly when needed
|
||||
|
||||
//Creating a functor on the stack and using it immediatly
|
||||
//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;
|
||||
|
@@ -24,7 +24,7 @@ std::string get_next_command() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void fuction(void)
|
||||
void function(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class test
|
||||
void ResetState()
|
||||
{
|
||||
chai.set_state(backupState);
|
||||
chai.add(chaiscript::fun(&fuction),"Whatever()");
|
||||
chai.add(chaiscript::fun(&function),"Whatever()");
|
||||
}
|
||||
|
||||
void RunFile(std::string sFile)
|
||||
@@ -70,7 +70,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
std::string command = "";
|
||||
|
||||
//
|
||||
// this loop increases memoryusage, if RunFile is not called (just hittin enter)
|
||||
// this loop increases memoryusage, 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
|
||||
|
@@ -5,7 +5,7 @@ def for_each(container, function)
|
||||
while (!range.empty())
|
||||
{
|
||||
function(range.front());
|
||||
range.popFront();
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
137
src/main.cpp
137
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,21 +15,125 @@
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
|
||||
char *mystrdup (const char *s) {
|
||||
size_t len = strlen(s) + 1; // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len));
|
||||
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
|
||||
d[len] = '\0';
|
||||
#endif
|
||||
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;
|
||||
@@ -148,8 +252,6 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -233,18 +339,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
||||
for (size_t j = 1; j < ee.call_stack.size(); ++j) {
|
||||
if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
|
||||
&& ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@@ -1,41 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <thread>
|
||||
|
||||
void do_work(chaiscript::ChaiScript &c)
|
||||
{
|
||||
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
|
||||
std::stringstream ss;
|
||||
ss << "MyVar" << rand();
|
||||
c.add(chaiscript::var(5), ss.str());
|
||||
c("use(\"work.chai\"); do_chai_work(10000);");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string input;
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
//chai.add_shared_object(chaiscript::Boxed_Value(10000), "num_iterations");
|
||||
|
||||
std::vector<std::shared_ptr<std::thread> > threads;
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads.push_back(std::shared_ptr<std::thread>(new std::thread(std::bind(do_work, std::ref(chai)))));
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,9 @@
|
||||
// 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.hpp>
|
||||
@@ -20,7 +26,12 @@ bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return bool(pf->get_parse_tree());
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -44,6 +55,12 @@ chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t
|
||||
}
|
||||
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#endif
|
||||
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
|
||||
{
|
||||
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||
@@ -64,6 +81,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
||||
{fun(&chaiscript::exception::eval_error::call_stack), "call_stack"} }
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
|
||||
"File_Position",
|
||||
{ constructor<File_Position()>(),
|
||||
@@ -72,6 +90,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
||||
{fun(&File_Position::column), "column"} }
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<AST_Node>(*m,
|
||||
"AST_Node",
|
||||
{ },
|
||||
@@ -86,6 +105,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
|
||||
"ChaiScript_Parser",
|
||||
{ constructor<parser::ChaiScript_Parser ()>() },
|
||||
@@ -98,6 +118,11 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
||||
return m;
|
||||
}
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
|
@@ -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)
|
||||
|
@@ -5,12 +5,21 @@
|
||||
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 &);
|
||||
};
|
||||
|
||||
enum TestEnum
|
||||
@@ -27,9 +36,29 @@ 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::shared_ptr<TestBaseType>(new TestDerivedType());
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> more_derived_type_factory()
|
||||
{
|
||||
return std::shared_ptr<TestBaseType>(new TestMoreDerivedType());
|
||||
}
|
||||
|
||||
std::string hello_world()
|
||||
{
|
||||
return "Hello World";
|
||||
@@ -47,6 +76,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 +89,7 @@ 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::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
@@ -65,23 +99,45 @@ 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(&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");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@@ -1,10 +0,0 @@
|
||||
def do_chai_work(num_iters)
|
||||
{
|
||||
var i = 0;
|
||||
for (var k = 0; k<num_iters * 10; ++k)
|
||||
{
|
||||
i += k;
|
||||
}
|
||||
|
||||
print(i);
|
||||
}
|
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;
|
||||
}
|
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);
|
20
unittests/c_linkage_test.cpp
Normal file
20
unittests/c_linkage_test.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int do_something(int i)
|
||||
{
|
||||
return i % 2;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&do_something), "do_something");
|
||||
|
||||
return chai.eval<int>("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
|
||||
|
||||
}
|
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);
|
@@ -9,7 +9,7 @@ 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;
|
||||
|
111
unittests/expected_eval_errors_test.cpp
Normal file
111
unittests/expected_eval_errors_test.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Tests to make sure no arity, dispatch or guard errors leak up past eval
|
||||
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
int test_one(const int &)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&test_one), "test_fun");
|
||||
|
||||
chai.eval("def guard_fun(i) : i.get_type_info().is_type_arithmetic() {} ");
|
||||
|
||||
bool eval_error = true;
|
||||
|
||||
// Dot notation
|
||||
|
||||
try {
|
||||
// non-existent function
|
||||
chai.eval("\"test\".test_one()");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong parameter type
|
||||
chai.eval("\"test\".test_fun()");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong number of parameters
|
||||
chai.eval("\"test\".test_fun(1)");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// guard failure
|
||||
chai.eval("\"test\".guard_fun(1)");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// regular notation
|
||||
|
||||
try {
|
||||
// non-existent function
|
||||
chai.eval("test_one(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong parameter type
|
||||
chai.eval("test_fun(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong number of parameters
|
||||
chai.eval("test_fun(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// guard failure
|
||||
chai.eval("guard_fun(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
|
||||
// index operator
|
||||
try {
|
||||
chai.eval("var a = [1,2,3]; a[\"bob\"];");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
// unary operator
|
||||
try {
|
||||
chai.eval("++\"bob\"");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
// binary operator
|
||||
try {
|
||||
chai.eval("\"bob\" + 1");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
|
||||
if (eval_error)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
|
||||
|
88
unittests/integer_literal_test.cpp
Normal file
88
unittests/integer_literal_test.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#define TEST_LITERAL(v) test_literal(v, #v)
|
||||
|
||||
template<typename T>
|
||||
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;
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if( TEST_LITERAL(0xF)
|
||||
&& TEST_LITERAL(0xFF)
|
||||
&& TEST_LITERAL(0xFFF)
|
||||
&& TEST_LITERAL(0xFFFF)
|
||||
&& TEST_LITERAL(0xFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
|
||||
&& TEST_LITERAL(01)
|
||||
&& TEST_LITERAL(017)
|
||||
&& TEST_LITERAL(0177)
|
||||
&& TEST_LITERAL(01777)
|
||||
&& TEST_LITERAL(017777)
|
||||
&& TEST_LITERAL(0177777)
|
||||
&& TEST_LITERAL(01777777)
|
||||
&& TEST_LITERAL(017777777)
|
||||
&& TEST_LITERAL(0177777777)
|
||||
&& TEST_LITERAL(01777777777)
|
||||
&& TEST_LITERAL(017777777777)
|
||||
&& TEST_LITERAL(0177777777777)
|
||||
&& TEST_LITERAL(01777777777777)
|
||||
&& TEST_LITERAL(017777777777777)
|
||||
&& TEST_LITERAL(0177777777777777)
|
||||
&& TEST_LITERAL(01777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777777)
|
||||
|
||||
&& TEST_LITERAL(1)
|
||||
&& TEST_LITERAL(17)
|
||||
&& TEST_LITERAL(177)
|
||||
&& TEST_LITERAL(1777)
|
||||
&& TEST_LITERAL(17777)
|
||||
&& TEST_LITERAL(177777)
|
||||
&& TEST_LITERAL(1777777)
|
||||
&& TEST_LITERAL(17777777)
|
||||
&& TEST_LITERAL(177777777)
|
||||
&& TEST_LITERAL(1777777777)
|
||||
&& TEST_LITERAL(17777777777)
|
||||
&& TEST_LITERAL(177777777777)
|
||||
&& TEST_LITERAL(1777777777777)
|
||||
&& TEST_LITERAL(17777777777777)
|
||||
&& TEST_LITERAL(177777777777777)
|
||||
&& TEST_LITERAL(1777777777777777)
|
||||
&& TEST_LITERAL(17777777777777777)
|
||||
&& TEST_LITERAL(177777777777777777)
|
||||
&& TEST_LITERAL(1777777777777777777)
|
||||
|
||||
)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -1,2 +1,4 @@
|
||||
load_module("test_module")
|
||||
assert_equal("Hello World", hello_world());
|
||||
|
||||
|
||||
|
@@ -1 +1,29 @@
|
||||
assert_equal([true, false, true], map([1,2,3], odd))
|
||||
|
||||
|
||||
|
||||
var m = ["a":1, "b":2];
|
||||
|
||||
assert_equal(1, m.count("a"))
|
||||
assert_equal(0, m.count("c"))
|
||||
assert_equal(1, m.erase("a"))
|
||||
assert_equal(1, m.size())
|
||||
assert_equal(0, m.erase("a"))
|
||||
|
||||
assert_equal(1, m.size());
|
||||
|
||||
var m2 = ["c":3, "b":4]
|
||||
m.insert(m2);
|
||||
|
||||
assert_equal(3, m["c"])
|
||||
// The inserted values do not overwrite the existing ones
|
||||
assert_equal(2, m["b"])
|
||||
assert_equal(2, m.size())
|
||||
|
||||
var v = "bob";
|
||||
|
||||
m.insert_ref(Map_Pair("d", v))
|
||||
|
||||
assert_equal("bob", m["d"])
|
||||
v = "bob2"
|
||||
assert_equal("bob2", m["d"])
|
||||
|
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)
|
||||
|
||||
|
102
unittests/multithreaded_test.cpp
Normal file
102
unittests/multithreaded_test.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
int expected_value(int num_iters)
|
||||
{
|
||||
int i = 0;
|
||||
for (int k = 0; k<num_iters * 10; ++k)
|
||||
{
|
||||
i += k;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void do_work(chaiscript::ChaiScript &c, int id)
|
||||
{
|
||||
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 CHAISCRIPT_MSVC
|
||||
#ifdef max // Why Microsoft? why?
|
||||
#undef max
|
||||
#endif
|
||||
#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;
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
|
||||
chaiscript::ChaiScript chai(modulepaths,usepaths);
|
||||
|
||||
std::vector<std::shared_ptr<std::thread> > threads;
|
||||
|
||||
// Ensure at least two, but say only 7 on an 8 core processor
|
||||
int num_threads = std::max(std::thread::hardware_concurrency() - 1, 2u);
|
||||
|
||||
for (int i = 0; i < num_threads; ++i)
|
||||
{
|
||||
threads.push_back(std::shared_ptr<std::thread>(new std::thread(do_work, std::ref(chai), i)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_threads; ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < num_threads; ++i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
if (chai.eval<int>("getvalue(" + ss.str() + ")") != expected_value(4000))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (chai.eval<int>("getid(" + ss.str() + ")") != i)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
15
unittests/multithreaded_work.inc
Normal file
15
unittests/multithreaded_work.inc
Normal file
@@ -0,0 +1,15 @@
|
||||
def do_chai_work(num_iters, id)
|
||||
{
|
||||
var i = 0;
|
||||
for (var k = 0; k<num_iters * 10; ++k)
|
||||
{
|
||||
if (k == 1000)
|
||||
{
|
||||
eval("def getid(id) : id == " + to_string(id) + " { return " + to_string(id) + "}");
|
||||
}
|
||||
i += k;
|
||||
}
|
||||
|
||||
eval("def getvalue(id) : id == " + to_string(id) + " { return " + to_string(i) + "}");
|
||||
|
||||
}
|
11
unittests/number_suffixes.chai
Normal file
11
unittests/number_suffixes.chai
Normal file
@@ -0,0 +1,11 @@
|
||||
assert_equal(true, int_type.bare_equal(1.get_type_info()))
|
||||
assert_equal(true, unsigned_int_type.bare_equal(1u.get_type_info()))
|
||||
assert_equal(true, unsigned_long_type.bare_equal(1lu.get_type_info()))
|
||||
assert_equal(true, long_type.bare_equal(1l.get_type_info()))
|
||||
assert_equal(true, int64_t_type.bare_equal(1ll.get_type_info()))
|
||||
assert_equal(true, uint64_t_type.bare_equal(1ull.get_type_info()))
|
||||
|
||||
assert_equal(true, double_type.bare_equal(1.6.get_type_info()))
|
||||
assert_equal(true, float_type.bare_equal(1.6f.get_type_info()))
|
||||
assert_equal(true, long_double_type.bare_equal(1.6l.get_type_info()))
|
||||
|
@@ -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);
|
||||
|
61
unittests/set_state_test.cpp
Normal file
61
unittests/set_state_test.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
|
||||
int myfun()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
// save the initial state of globals and locals
|
||||
chaiscript::ChaiScript::State firststate = chai.get_state();
|
||||
std::map<std::string, chaiscript::Boxed_Value> locals = chai.get_locals();
|
||||
|
||||
// add some new globals and locals
|
||||
chai.add(chaiscript::var(1), "i");
|
||||
|
||||
chai.add(chaiscript::fun(&myfun), "myfun");
|
||||
|
||||
|
||||
bool didcall = chai.eval<int>("myfun()") == 2;
|
||||
|
||||
bool hadi = chai.eval<int>("i") == 1;
|
||||
|
||||
chai.set_state(firststate);
|
||||
|
||||
// set state should have reverted the state of the functions and dropped
|
||||
// the 'myfun'
|
||||
bool didnotcall = false;
|
||||
|
||||
try {
|
||||
chai.eval<int>("myfun()");
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
didnotcall = true;
|
||||
}
|
||||
|
||||
// set state should not affect the local variables
|
||||
bool stillhasid = chai.eval<int>("i") == 1;
|
||||
|
||||
// After resetting the locals we expect the 'i' to be gone
|
||||
chai.set_locals(locals);
|
||||
|
||||
|
||||
bool nolongerhasid = false;
|
||||
|
||||
try {
|
||||
chai.eval<int>("i");
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
nolongerhasid = true;
|
||||
}
|
||||
|
||||
if (didcall && hadi && didnotcall && stillhasid && nolongerhasid)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
60
unittests/simultaneous_chaiscript_test.cpp
Normal file
60
unittests/simultaneous_chaiscript_test.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
int do_something(int i)
|
||||
{
|
||||
return i + 2;
|
||||
}
|
||||
|
||||
int do_something_else(int i)
|
||||
{
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&do_something), "do_something");
|
||||
chai.add(chaiscript::var(1), "i");
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
chaiscript::ChaiScript chai2;
|
||||
chai2.add(chaiscript::fun(&do_something_else), "do_something_else");
|
||||
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
|
||||
if (chai.eval<int>("do_something(" + ss.str() + ")") != i + 2)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (chai2.eval<int>("do_something_else(" + ss.str() + ")") != i * 2)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
try {
|
||||
chai2.eval("do_something(1)");
|
||||
return EXIT_FAILURE; // should not get here
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
// nothing to do, expected case
|
||||
}
|
||||
|
||||
try {
|
||||
chai2.eval("i");
|
||||
return EXIT_FAILURE; // should not get here
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
// nothing to do, expected case
|
||||
}
|
||||
|
||||
try {
|
||||
chai.eval("do_something_else(1)");
|
||||
return EXIT_FAILURE; // should not get here
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
// nothing to do, expected case
|
||||
}
|
||||
}
|
||||
}
|
2
unittests/string_size.chai
Normal file
2
unittests/string_size.chai
Normal file
@@ -0,0 +1,2 @@
|
||||
assert_equal(true, "".empty())
|
||||
assert_equal(3, "123".size())
|
1
unittests/string_substr.chai
Normal file
1
unittests/string_substr.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal("3ab", "123abab".substr(2,3))
|
@@ -1,6 +1,8 @@
|
||||
// Tests to make sure that the order in which function dispatches occur is correct
|
||||
|
||||
#include <chaiscript/chaiscript_defines.hpp>
|
||||
#include <chaiscript/dispatchkit/type_info.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
void test_type(const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void,
|
||||
bool t_is_undef)
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
#include <functional>
|
||||
|
||||
class Test
|
||||
{
|
||||
@@ -18,6 +20,7 @@ int main()
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
/// \todo fix overload resolution for fun<>
|
||||
chaiscript::utility::add_class<Test>(*m,
|
||||
"Test",
|
||||
{ constructor<Test ()>(),
|
||||
@@ -25,9 +28,9 @@ int main()
|
||||
{ {fun(&Test::function), "function"},
|
||||
{fun(&Test::function2), "function2"},
|
||||
{fun(&Test::function3), "function3"},
|
||||
{fun<std::string (Test::*)(double)>(&Test::functionOverload), "functionOverload"},
|
||||
{fun<std::string (Test::*)(int)>(&Test::functionOverload), "functionOverload"},
|
||||
{fun<Test & (Test::*)(const Test &)>(&Test::operator=), "="}
|
||||
{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=)), "=" }
|
||||
|
||||
}
|
||||
);
|
||||
|
@@ -3,6 +3,7 @@ assert_equal(3, x.size())
|
||||
|
||||
|
||||
|
||||
|
||||
// Make sure vector elements are copied into place for consistency with
|
||||
// map inplace construction
|
||||
var i = 1;
|
||||
@@ -12,3 +13,9 @@ assert_equal(1, y[0]);
|
||||
i = 3;
|
||||
assert_equal(3, i);
|
||||
assert_equal(1, y[0]);
|
||||
|
||||
|
||||
// make sure initialization with a break in the middle works as expected
|
||||
var a = [0.0,0.0,
|
||||
1.0,1.0]
|
||||
|
||||
|
3
unittests/vector_of_suffixed_numbers.chai
Normal file
3
unittests/vector_of_suffixed_numbers.chai
Normal file
@@ -0,0 +1,3 @@
|
||||
var x = [1, 2u, 3.0l]
|
||||
assert_equal(3.0l, x[2])
|
||||
assert_equal(2u, x[1])
|
Reference in New Issue
Block a user