Compare commits

..

77 Commits

Author SHA1 Message Date
Jason Turner
f78fb77128 Merge pull request #135 from ChaiScript/develop
Develop
2014-08-31 20:03:18 -06:00
Jason Turner
bb08cc3699 Add documenation for "class" keyword 2014-08-31 19:54:43 -06:00
Jason Turner
6692607507 Update version number to 5.4.0, update releasenotes 2014-08-31 19:45:07 -06:00
Jason Turner
6bea42c1c0 Speed up to_string performance by relying on C++ versions
Addresses #134, fixing issues introduced by #132
2014-08-31 16:03:42 -06:00
Jason Turner
251790f144 Fix some MSVC warnings 2014-08-31 12:04:02 -06:00
Jason Turner
4ee9ba9c96 Make up some of the performance losses #132 2014-08-30 14:49:31 -06:00
Jason Turner
a71903f185 Add strong reference to range objects #132 2014-08-30 13:36:36 -06:00
Jason Turner
3fe80d70c6 Roll back name of range class, it's half baked from the range fix 2014-08-27 12:24:46 -06:00
Jason Turner
9c05779fac Add failing range test
Crash occurs if the user attempts to use a range and the source
of the range has gone out of scope. #132
2014-08-27 12:15:47 -06:00
Jason Turner
a6e3fd5b42 Make reflection API part of stdlib
removes the reflection module completely. Reflection and the
ability to catch eval errors is too useful.
2014-08-27 12:05:03 -06:00
Jason Turner
6a3f19d575 Add copy constructor for Type_Info 2014-08-26 09:28:51 -06:00
Jason Turner
9b7e4d2e78 Let a subscript out of range be catchable from chaiscript 2014-08-26 08:51:02 -06:00
Jason Turner
f546e46582 Update to cppcheck 1.66 2014-08-22 21:29:14 -06:00
Jason Turner
fa1f4b795b Add class keyword for easier user defined types.
Issue #118
2014-08-22 21:11:49 -06:00
Jason Turner
cb1c7730cf Add the ability to look up user defined typenames
Closes #124
2014-08-17 09:05:29 -06:00
Jason Turner
3a775097dd Reduce size of Any template wrapper. 2014-08-17 06:52:11 -06:00
Jason Turner
5692dfc58a Move to unique_ptr for Any implemenation
Speed and size improvements
2014-08-15 20:38:35 -06:00
Jason Turner
c5f6c549ec Reduce compiled size with template reductions 2014-08-15 20:14:15 -06:00
Jason Turner
14a280713f Update version to 5.3.2 2014-06-11 15:15:51 -06:00
Jason Turner
e7b6ee6cf9 Update release notes for 5.3.1 2014-06-11 15:11:21 -06:00
Jason Turner
32a9aa9c3c Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-05-29 20:44:35 -06:00
Jason Turner
f57a14e3de Allow user to add globals from within script. 2014-05-29 20:44:05 -06:00
Jason Turner
4018c873dc Spelling fixes, phase 1. 2014-05-29 20:16:47 -06:00
Jason Turner
b4ea27d28a Add unsupported build support for Haiku 2014-05-27 06:51:38 +00:00
Jason Turner
e5d723621f Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-05-23 09:57:29 -06:00
Jason Turner
46e7d0ab99 Clean up tab vs space issues
discovered by @axelstudios
2014-05-23 09:56:55 -06:00
Jason Turner
d5378f50af Fix cygwin builds #121
Cygwin claims to be POSIX but only implementes part of
the dl_open interface.

For this usage, we revert to win32 interface when building on
Cygwin.
2014-05-13 14:55:27 -06:00
Jason Turner
be9632d0ad Balance signed/unsigned issues between msvc and gcc 2014-05-11 12:30:21 -06:00
Jason Turner
61cd633084 Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop
Conflicts:
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_parser.hpp
2014-05-11 12:02:33 -06:00
Jason Turner
c35b35e4f8 Fix issues discovered while evaluating pvs-studio 2014-05-11 11:53:03 -06:00
Jason Turner
bcb7172037 Enable MSVC warning for thread safety with statics
Clean up a couple of additional issues found while playing with /Wall in MSVC.
2014-05-11 10:52:07 -06:00
Jason Turner
3c552db548 Upgrade cppcheck and disable inconclusive checks 2014-05-10 20:14:40 -06:00
Jason Turner
37982cbdaa Fix issues found by cppcheck 1.65 2014-05-10 20:12:49 -06:00
Jason Turner
28a016b51d Fix potential memory issue discovered by clang's analyzer 2014-05-10 19:20:03 -06:00
Jason Turner
c0bf6ee99d Apply corrections from the "include what you use" tool
Generally cleanups of the includes. Making sure each file
can properly stand on its own and forward declares when possible.
2014-05-10 18:41:11 -06:00
Jason Turner
f29af4618a Make override a #define for gcc 4.6 support 2014-05-10 09:04:41 -06:00
Jason Turner
ee17a184c2 Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-05-10 08:39:59 -06:00
Jason Turner
6eab8ddfe1 Apply changes applied from clang-modernize
Needed 1-2 cleanups by hand. 99% was automatic.

* The version that ships with ubuntu 14.04 seems to not work.
  I had to build from scratch

* Use cmake to generate the build commands that clang-modernize wants

```sh
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS:bool=true ../ChaiScript/
```

* Use the clang-modernize tool. Note that you have to be pretty explicit
  about the include paths if you want it to also update your include
  files

```sh
../llvm-build/bin/clang-modernize ../ChaiScript/src/*.cpp -for-compilers=gcc-4.8 -include /home/jason/ChaiScript/include,/hjason/ChaiScript/include/chaiscript,/home/jason/ChaiScript/include/chaiscript/dispatchkit,/home/jason/ChaiScript/include/chaiscript/language -p compile_commands.json
```

* In my case, it left some unused `typedef`s behind, which I cleaned up.
2014-05-10 08:25:38 -06:00
Jason Turner
a7e8c6fe1f Merge pull request #120 from axelstudios/develop
Formatted CMakeLists.txt
2014-05-09 20:04:31 -06:00
Jason Turner
5f2796868b Fix threading warning discovered with MSVC -Wall
MSVC in -Wall mode creates approximately 6,500 warnings. 5,000+ of which are
from the std library. The one gem was the potential for threading issues with
the initilization of a function scoped static.

This fixes that.
2014-05-09 17:46:06 -06:00
Jason Turner
c2d08457ad Fix thread-unsafe builds 2014-05-09 15:55:29 -06:00
Alex Swindler
d3084ed136 Formatted CMakeLists.txt 2014-05-07 15:02:21 -06:00
Jason Turner
62b8977abe Correct linking of modules for coverage testing 2014-05-04 21:52:27 -06:00
Jason Turner
b87c37032b Add version numbers that can be queried at runtime 2014-05-04 10:14:42 -06:00
Jason Turner
7932cb18f3 Clean up linker flags and add sanitizer options
Sanitizers are features now built into gcc and clang to check for
runtime problems such as data races, memory errors or undefined
behavior.
2014-05-04 07:55:36 -06:00
Jason Turner
706b5aaa45 Merge remote-tracking branch 'origin/release-4.x' into develop
Conflicts:
	releasenotes.md
2014-05-04 07:16:27 -06:00
Jason Turner
41bf96c42e Update release notes for release 4.3.1 2014-05-03 17:44:54 -06:00
Jason Turner
67b5d989cb Merge remote-tracking branch 'origin/release-4.x' into develop 2014-04-22 19:52:01 -06:00
Jason Turner
fcc9bd9bbb Start porting of documentatation to markdown style 2014-04-13 19:16:51 -06:00
Jason Turner
825c28521e Update doxyfile to latest template 2014-04-13 19:16:23 -06:00
Jason Turner
5da1475082 Port is_prime.chai to run on pre-cpp11 versions 2014-04-13 19:15:39 -06:00
Jason Turner
c9a244019e Enhance the inheritance unit tests #117 2014-04-13 08:05:46 -06:00
Jason Turner
2bd1910c70 ~30% performance improvement with threading enabled 2014-04-05 22:49:50 -06:00
Jason Turner
4ace508339 Update travis token 2014-04-02 14:13:19 -06:00
Jason Turner
926e962fc0 Merge remote-tracking branch 'origin/release-4.x'
Conflicts:
	.travis.yml
	CMakeLists.txt
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/language/chaiscript_common.hpp
2014-03-29 07:30:14 -06:00
Jason Turner
caf4495cff Add unit tests for inheritance with multiple layers 2014-03-29 06:16:21 -06:00
Jason Turner
6b0e0dc7ae Removed erroneously kept debug output 2014-03-28 07:04:51 -06:00
Jason Turner
65b0846e41 Address some of the issues found by cppcheck 2014-03-26 16:59:41 -06:00
Jason Turner
296769ee24 Version number bump, cppcheck fix 2014-03-26 15:20:06 -06:00
Jason Turner
d9bdad714f Fix syntax problem with .travis.yml 2014-03-26 14:45:01 -06:00
Jason Turner
12de955a47 Post cppcheck results to pull request 2014-03-26 13:56:02 -06:00
Jason Turner
a652a7e564 Only post comment if this is a pull request 2014-03-26 13:37:51 -06:00
Jason Turner
611692646f Add travis support for testing with cppcheck 2014-03-26 13:32:25 -06:00
Jason Turner
96acf5e833 Update travis in 4.x branch for coveralls support 2014-03-26 11:37:37 -06:00
Jason Turner
656b438002 First cast up chain, if that fails, cast down 2014-03-26 10:52:56 -06:00
Jason Turner
56b036052f Add test for automatic casting down in inheritance 2014-03-26 09:14:06 -06:00
Jason Turner
7fade8e841 Allow for automatic conversion of arithmetic types
for returns from chaiscript function wrappers
2014-03-26 08:11:37 -06:00
Jason Turner
db8be03cee Add tests for returning of arithmetic types with conversions 2014-03-26 07:26:23 -06:00
Jason Turner
372cf73548 Correct typo in travis logic 2014-03-25 08:24:25 -06:00
Jason Turner
0213039ee7 Install gcc-4.8 in travis matrix and test both 4.6 & 4.8 2014-03-25 08:12:07 -06:00
Jason Turner
e8fcb3f68b Revert back to cpp and use ubuntu for builds with travis 2014-03-24 21:29:11 -06:00
Jason Turner
8d8df1f5bd Attempt objective-c for building on macos travis 2014-03-24 21:17:40 -06:00
Jason Turner
f40f9d8441 Fix call to gcov for older gcov ver / travis 2014-03-24 19:41:41 -06:00
Jason Turner
8879a89490 Utilize 2 cores on travis during build 2014-03-24 18:55:01 -06:00
Jason Turner
e4a3b3f620 Update coveralls execution to merge all data and ignore cpp 2014-03-24 18:51:25 -06:00
Jason Turner
d6c8b36eeb Update readme.md 2014-03-24 14:23:44 -06:00
Jason Turner
de86e79df2 Merge pull request #106 from ChaiScript/ChaiScript_5_0_CPP_11
Chai script 5 0 cpp 11
2014-03-24 14:16:38 -06:00
77 changed files with 3070 additions and 2026 deletions

View File

@@ -1,17 +1,31 @@
language: cpp
compiler:
- gcc
env:
- GCC_VER=4.6
- GCC_VER=4.8
before_install:
- sudo pip install cpp-coveralls --use-mirrors
- 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 -D USE_LIBCXX:BOOL=FALSE .
- make
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug .
- make -j2
- make test
- coveralls -x hpp
- 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:
recipients:
- jason@emptycrate.com
email:
recipients:
- jason@emptycrate.com
on_success: always
on_failure: always
env:
global:
secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=

View File

@@ -3,20 +3,45 @@ cmake_minimum_required(VERSION 2.8)
project(chaiscript)
# MINGW does not yet support C++11's concurrency features
if (MINGW)
if(MINGW)
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" FALSE)
else()
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
endif()
if (CMAKE_COMPILER_IS_GNUCC)
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
if(CMAKE_COMPILER_IS_GNUCC)
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
if(ENABLE_COVERAGE)
add_definitions(--coverage -O0)
set(LINKER_FLAGS "${LINKER_FLAGS} --coverage")
endif()
endif()
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
option(ENABLE_THREAD_SANITIZER "Enable thread sanitizer testing in gcc/clang" FALSE)
if(ENABLE_THREAD_SANITIZER)
add_definitions(-fsanitize=thread -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=thread")
endif()
option(ENABLE_ADDRESS_SANITIZER "Enable address sanitizer testing in gcc/clang" FALSE)
if(ENABLE_ADDRESS_SANITIZER)
add_definitions(-fsanitize=address -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
endif()
option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
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")
@@ -29,7 +54,7 @@ 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 3)
set(CPACK_PACKAGE_VERSION_MINOR 4)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
@@ -66,40 +91,30 @@ enable_testing()
message(STATUS "Detecting readline support")
if (READLINE_LIBRARY)
message(STATUS "Found: ${READLINE_LIBRARY}")
set (READLINE_LIB readline)
add_definitions(/DREADLINE_AVAILABLE)
else(READLINE_LIBRARY)
message(STATUS "Not Found")
set (READLINE_LIB )
set (READLINE_FLAG )
endif(READLINE_LIBRARY)
if(READLINE_LIBRARY)
message(STATUS "Found: ${READLINE_LIBRARY}")
set(READLINE_LIB readline)
add_definitions(/DREADLINE_AVAILABLE)
else()
message(STATUS "Not Found")
set(READLINE_LIB)
set(READLINE_FLAG)
endif()
SET(EXTRA_LINKER_FLAGS "")
if (CMAKE_COMPILER_IS_GNUCC)
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")
if(GCC_VERSION VERSION_LESS 4.8)
set(CPP11_FLAG "-std=c++0x")
else()
SET(CPP11_FLAG "-std=c++11")
set(CPP11_FLAG "-std=c++11")
endif()
if (ENABLE_COVERAGE)
add_definitions(-fprofile-arcs -ftest-coverage)
SET(EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} "-fprofile-arcs -ftest-coverage")
# SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-fprofile-arcs -ftest-coverage")
endif()
else()
SET(CPP11_FLAG "-std=c++11")
set(CPP11_FLAG "-std=c++11")
endif()
if(MSVC)
add_definitions(/W4)
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
@@ -108,94 +123,94 @@ if(MSVC)
# 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)
add_definitions(/wd4503)
else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic ${CPP11_FLAG})
if (APPLE)
if(APPLE)
add_definitions(-Wno-sign-compare)
endif()
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "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 ${EXTRA_LINKER_FLAGS} ${CPP11_FLAG} -stdlib=libc++)
else ()
set (EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} ${CPP11_FLAG})
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG} -stdlib=libc++")
else()
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC)
set (EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} ${CPP11_FLAG})
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)
if(MINGW OR CYGWIN)
add_definitions(-O3)
endif()
include_directories(include)
set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/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)
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
if(CMAKE_HOST_UNIX)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
list(APPEND LIBS "dl")
endif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
endif()
if (MULTITHREAD_SUPPORT_ENABLED)
if (CMAKE_COMPILER_IS_GNUCC)
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 (EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} -Wl,--no-as-needed -pthread )
if(GCC_FULL_VERSION MATCHES "4.8.1.*ubuntu")
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--no-as-needed -pthread")
else()
set (EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} -pthread )
set(LINKER_FLAGS "${LINKER_FLAGS} -pthread")
endif()
else()
set (EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} -pthread )
set(LINKER_FLAGS "${LINKER_FLAGS} -pthread")
endif()
add_definitions(-pthread)
endif()
endif(CMAKE_HOST_UNIX)
endif()
list(APPEND LIBS ${READLINE_LIB})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
add_library(chaiscript_stdlib MODULE src/chaiscript_stdlib.cpp)
target_link_libraries(chaiscript_stdlib ${LIBS} ${EXTRA_LINKER_FLAGS} ${CMAKE_THREAD_LIBS_INIT})
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})
set(MODULES stl_extra reflection)
set(MODULES stl_extra)
endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
@@ -205,134 +220,149 @@ list(SORT UNIT_TESTS)
if(BUILD_TESTING)
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach(filename)
set_property(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT
add_test(version_check chai -c "if(\"\\\${ version() };\\\${version_major()};\\\${version_minor()};\\\${version_patch()}\" != \"${CHAI_VERSION};${CPACK_PACKAGE_VERSION_MAJOR};${CPACK_PACKAGE_VERSION_MINOR};${CPACK_PACKAGE_VERSION_PATCH}\") { exit(-1) }")
set_property(TEST version_check
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
if (NOT UNIT_TEST_LIGHT)
foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach()
set_property(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
if(NOT UNIT_TEST_LIGHT)
# commented out because uniform initializer syntax is not working properly in MSVC 2013
add_executable(utility_test unittests/utility_test.cpp)
target_link_libraries(utility_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(utility_test ${LIBS})
add_test(NAME Utility_Test COMMAND utility_test)
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
target_link_libraries(dynamic_object_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(dynamic_object_test ${LIBS})
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
target_link_libraries(functor_creation_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(functor_creation_test ${LIBS})
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
target_link_libraries(functor_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(functor_cast_test ${LIBS})
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
target_link_libraries(boxed_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(boxed_cast_test ${LIBS})
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
target_link_libraries(object_lifetime_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(object_lifetime_test ${LIBS})
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(function_ordering_test ${LIBS})
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
add_executable(type_info_test unittests/type_info_test.cpp)
target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(type_info_test ${LIBS})
add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(type_name_test unittests/type_name_test.cpp)
target_link_libraries(type_name_test ${LIBS})
add_test(NAME Type_Name_Test COMMAND type_name_test)
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(eval_catch_exception_test ${LIBS})
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(short_comparison_test ${LIBS})
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp)
target_link_libraries(cpp_lambda_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(cpp_lambda_test ${LIBS})
add_test(NAME cpp_lambda_test COMMAND cpp_lambda_test)
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
target_link_libraries(expected_eval_errors_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(expected_eval_errors_test ${LIBS})
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
add_executable(set_state_test unittests/set_state_test.cpp)
target_link_libraries(set_state_test ${LIBS} ${EXTRA_LINKER_FLAGS})
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} ${EXTRA_LINKER_FLAGS})
add_test(NAME Simultaneous_Chaiscript_Test COMMAND simultaneous_chaiscript_test)
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} ${EXTRA_LINKER_FLAGS})
add_test(NAME Heap_Allocated_Chaiscript_Test COMMAND heap_allocated_chaiscript_test)
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} ${EXTRA_LINKER_FLAGS})
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} ${EXTRA_LINKER_FLAGS})
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} ${EXTRA_LINKER_FLAGS})
target_link_libraries(arithmetic_conversions_test ${LIBS})
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test)
if (MULTITHREAD_SUPPORT_ENABLED)
if(MULTITHREAD_SUPPORT_ENABLED)
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
target_link_libraries(multithreaded_test ${LIBS} ${EXTRA_LINKER_FLAGS})
target_link_libraries(multithreaded_test ${LIBS})
add_test(NAME Multithreaded_Test COMMAND multithreaded_test)
set_property(TEST Multithreaded_Test
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
)
endif()
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
unittests/multifile_test_module.cpp)
target_link_libraries(multifile_test ${LIBS} ${EXTRA_LINKER_FLAGS})
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 ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
install(TARGETS chai chaiscript_stdlib-${CHAI_VERSION} ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
install(DIRECTORY include/chaiscript DESTINATION include
PATTERN "*.hpp"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
PATTERN "*.hpp"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
install(DIRECTORY unittests DESTINATION share/chaiscript
PATTERN "*.chai"
PATTERN "*.inc"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
PATTERN "*.chai"
PATTERN "*.inc"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
install(DIRECTORY samples DESTINATION share/chaiscript
PATTERN "*.chai"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
PATTERN "*.chai"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"

File diff suppressed because it is too large Load Diff

View File

@@ -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())

View File

@@ -0,0 +1,16 @@
#!/bin/bash
pushd ..
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
tar -xvf cppcheck-1.66.tar.bz2
cd cppcheck-1.66
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

View File

@@ -38,7 +38,7 @@
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'Chaiscript',
'LANG_NAME' => 'ChaiScript',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
//Regular Expressions

View File

@@ -9,8 +9,8 @@
/// \mainpage
/// <a href="http://www.chaiscript.com">ChaiScript</a> is a scripting language designed specifically for integration with C++. It provides
/// @mainpage
/// [ChaiScript](http://www.chaiscript.com") is a scripting language designed specifically for integration with C++. It provides
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
///
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
@@ -18,42 +18,42 @@
///
/// The end user parts of the API are extremely simple both in size and ease of use.
///
/// Currently, all source control and project management aspects of ChaiScript occur on <a href="http://www.github.com/ChaiScript/ChaiScript">github</a>.
/// Currently, all source control and project management aspects of ChaiScript occur on [github](http://www.github.com/ChaiScript/ChaiScript").
///
/// <hr>
/// ------------------------------------------------------------
///
/// \sa chaiscript
/// \sa chaiscript::ChaiScript
/// \sa ChaiScript_Language for Built in Functions
/// \sa \ref LangGettingStarted
/// \sa \ref LangKeywordRef
/// \sa \ref LangInPlaceRef
/// \sa \ref LangObjectSystemRef
/// \sa http://www.chaiscript.com
/// \sa http://www.github.com/ChaiScript/ChaiScript
/// @sa chaiscript
/// @sa chaiscript::ChaiScript
/// @sa ChaiScript_Language for Built in Functions
/// @sa @ref LangGettingStarted
/// @sa @ref LangKeywordRef
/// @sa @ref LangInPlaceRef
/// @sa @ref LangObjectSystemRef
/// @sa http://www.chaiscript.com
/// @sa http://www.github.com/ChaiScript/ChaiScript
///
/// <hr>
/// -----------------------------------------------------------
///
/// \section gettingstarted API Getting Started
/// @section gettingstarted API Getting Started
///
/// \li \ref basics
/// \li \ref compiling
/// \li \ref eval
/// \li \ref addingitems
/// \li \ref operatoroverloading
/// \li \ref helpermacro
/// \li \ref pointerconversions
/// \li \ref baseclasses
/// \li \ref functionobjects
/// \li \ref threading
/// \li \ref exceptions
/// - @ref basics
/// - @ref compiling
/// - @ref eval
/// - @ref adding_items
/// - @ref operatoroverloading
/// - @ref add_class
/// - @ref pointer_conversions
/// - @ref baseclasses
/// - @ref functionobjects
/// - @ref threading
/// - @ref exceptions
///
///
/// \subsection basics Basics
/// @subsection basics Basics
///
/// Basic simple example:
///
/// \code
/// ~~~~~~~{.cpp}
/// //main.cpp
/// #include <chaiscript/chaiscript.hpp>
///
@@ -69,111 +69,115 @@
///
/// double d = chai.eval<double>("function(3, 4.75);");
/// }
/// \endcode
/// ~~~~~~~
///
/// <hr>
/// \subsection compiling Compiling ChaiScript Applications
/// ------------------------------------------------------
///
/// @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
/// chaiscript::ChaiScript chai;
/// chai("print(\"hello world\")");
/// \endcode
///
/// \sa chaiscript::ChaiScript::operator()(const std::string &)
///
/// \subsubsection evalmethod Method 'eval'
/// ~~~~~~~~{.cpp}
/// chaiscript::ChaiScript chai;
/// chai("print(@"hello world@")");
/// ~~~~~~~~
///
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
///
/// @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. Note: adding a object
/// adds it to the current thread scope, not to a global scope. If you have multiple
/// threads that need to access the same variables you will need to add them
/// separately for each thread, from the thread itself.
///
/// \code
/// ~~~~~~~~~{.cpp}
/// using namespace chaiscript;
/// ChaiScript chai;
/// int i = 5;
/// chai.add(var(i), "i");
/// chai("print(i)");
/// \endcode
/// ~~~~~~~~~
///
/// Immutable objects can be created with the chaiscript::const_var function.
///
/// \code
/// ~~~~~~~~~{.cpp}
/// chai.add(const_var(i), "i");
/// chai("i = 5"); // exception throw, cannot assign const var
/// \endcode
/// ~~~~~~~~~
///
/// Named variables can only be accessed from the context they are created in.
/// If you want a global variable, it must be const, and created with the
/// chaiscript::ChaiScript::add_global_const function.
///
/// \code
/// ~~~~~~~~~{.cpp}
/// chai.add_global_const(const_var(i), "i");
/// chai("def somefun() { print(i); }; sumfun();");
/// \endcode
/// ~~~~~~~~~
///
/// \subsubsection addingfunctions Adding Functions
/// @subsubsection adding_functions Adding Functions
///
/// Functions, methods and members are all added using the same function: chaiscript::fun.
///
/// \code
/// ~~~~~~~~~{.cpp}
/// using namespace chaiscript;
///
/// class MyClass {
@@ -190,26 +194,26 @@
/// chai.add(fun(&MyClass::memberdata), "memberdata");
/// chai.add(fun(&MyClass::method), "method");
/// chai.add(fun(&MyClass::staticmethod), "staticmethod");
/// \endcode
/// ~~~~~~~~~
///
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
///
/// \code
/// ~~~~~~~~~{.cpp}
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod");
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod), "overloadedmethod");
/// \endcode
/// ~~~~~~~~~
///
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
///
/// \code
/// ~~~~~~~~~{.cpp}
/// MyClass obj;
/// chai.add(fun(&MyClass::method, &obj), "method");
/// chai("method()"); // equiv to obj.method()
/// chai.add(fun(&MyClass::method2, &obj, 3), "method2");
/// chai("method2()"); // equiv to obj.method2(3)
/// \endcode
/// ~~~~~~~~~
///
/// \subsubsection addingtypeinfo Adding Type Info
/// @subsubsection addingtypeinfo Adding Type Info
///
/// ChaiScript will automatically support any type implicitly provided to it in the form
/// of objects and function parameters / return types. However, it can be nice to let ChaiScript
@@ -219,27 +223,28 @@
///
/// Continuing with the example "MyClass" from above:
///
/// \code
/// ~~~~~~~~{.cpp}
/// chai.add(user_type<MyClass>(), "MyClass");
/// \endcode
/// ~~~~~~~~
///
/// \subsubsection addingmodules Adding Modules
/// @subsubsection adding_modules Adding Modules
///
/// Modules are holders for collections of ChaiScript registrations.
///
/// \code
/// ~~~~~~~~{.cpp}
/// ModulePtr module = get_sum_module();
/// chai.add(module);
/// \endcode
/// ~~~~~~~~
///
/// \sa chaiscript::Module
/// @sa chaiscript::Module
///
/// <hr>
/// \subsection operatoroverloading Operator Overloading
/// -----------------------------------------------------------------------
///
/// @subsection operatoroverloading Operator Overloading
///
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
///
/// \code
/// ~~~~~~~~{.cpp}
/// class MyClass {
/// MyClass operator+(const MyClass &) const;
/// };
@@ -254,17 +259,18 @@
/// }
///
/// chai.add(fun(append_string_int), "+");
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref addingfunctions
/// @sa @ref adding_functions
///
/// <hr>
/// \subsection helpermacro Class Helper Macro
/// -----------------------------------------------------------------------
///
/// @subsection add_class Class Helper Utility
///
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
/// of the CHAISCRIPT_CLASS helper macro.
/// of the add_class helper utility.
///
/// \code
/// ~~~~~~~~{.cpp}
/// class Test
/// {
/// public:
@@ -277,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.
@@ -310,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);
@@ -350,18 +356,19 @@
/// chai("fun9(i)");
/// chai("fun10(i)");
/// }
/// \endcode
/// ~~~~~~~~
///
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
/// available and tested.
///
/// <hr>
/// \subsection baseclasses Base Classes
/// -----------------------------------------------------------------------
///
/// @subsection baseclasses Base Classes
///
/// ChaiScript supports handling of passing a derived class object to a function expecting a base class object.
/// For the process to work, the base/derived relationship must be registered with the engine.
///
/// \code
/// ~~~~~~~~{.cpp}
/// class Base {};
/// class Derived : public Base {};
/// void myfunction(Base *b);
@@ -375,16 +382,17 @@
/// chai.add(chaiscript::fun(&myfunction), "myfunction");
/// chai("myfunction(d)");
/// }
/// \endcode
/// ~~~~~~~~
///
/// <hr>
/// -----------------------------------------------------------------------
///
/// \subsection functionobjects Function Objects
///
/// Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion
/// @subsection functionobjects Function Objects
///
/// Functions are first class objects in ChaiScript and ChaiScript supports automatic conversion
/// between ChaiScript functions and std::function objects.
///
/// \code
/// ~~~~~~~~{.cpp}
/// void callafunc(const std::function<void (const std::string &)> &t_func)
/// {
/// t_func("bob");
@@ -400,11 +408,12 @@
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
/// f(); // call the ChaiScript function dump_system, from C++
/// }
/// \endcode
/// ~~~~~~~~
///
/// <hr>
/// -----------------------------------------------------------------------
///
/// \subsection threading Threading
///
/// @subsection threading Threading
///
/// Thread safety is automatically handled within the ChaiScript system. Objects can be added
/// and scripts executed from multiple threads. For each thread that executes scripts, a new
@@ -414,16 +423,17 @@
///
/// Disabling thread safety increases performance in many cases.
///
/// <hr>
/// -----------------------------------------------------------------------
///
/// \subsection exceptions Exception Handling
///
/// @subsection exceptions Exception Handling
///
/// \subsubsection exceptionsbasics Exception Handling Basics
/// @subsubsection exceptionsbasics Exception Handling Basics
///
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
/// ChaiScript.
///
/// \code
/// ~~~~~~~~{.cpp}
/// void throwexception()
/// {
/// throw std::runtime_error("err");
@@ -444,19 +454,19 @@
/// // i == 1
/// }
/// }
/// \endcode
/// ~~~~~~~~
///
/// \subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
/// @subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
///
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
/// ChaiScript what possible exceptions are expected from the script being executed.
///
/// Example:
/// \code
/// ~~~~~~~~{.cpp}
/// chaiscript::ChaiScript chai;
///
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
/// chai.eval("throw(runtime_error(@"error@"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
/// } catch (const double e) {
/// } catch (int) {
/// } catch (float) {
@@ -464,19 +474,19 @@
/// } catch (const std::exception &e) {
/// // This is the one what will be called in the specific throw() above
/// }
/// \endcode
/// ~~~~~~~~
///
/// \sa chaiscript::Exception_Handler for details on automatic exception unboxing
/// \sa chaiscript::exception_specification
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
/// @sa chaiscript::exception_specification
/// \page LangObjectSystemRef ChaiScript Language Object Model Reference
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
///
///
/// ChaiScript has an object system built in, for types defined within the ChaiScript system.
///
/// \code
/// ~~~~~~~~~
/// attr Rectangle::height
/// attr Rectangle::width
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
@@ -485,67 +495,84 @@
/// var rect = Rectangle()
/// rect.height = 30
/// print(rect.area())
/// \endcode
/// ~~~~~~~~~
///
/// \sa \ref keywordattr
/// \sa \ref keyworddef
/// Since ChaiScript 5.4.0 it has been possible to use the "class" keyword to simplify this code.
///
/// ~~~~~~~~~
/// class Rectangle {
/// attr height
/// attr width
/// def Rectangle() { this.height = 10; this.width = 20 }
/// def area() { this.height * this.width }
/// }
///
/// var rect = Rectangle()
/// rect.height = 30
/// print(rect.area())
/// ~~~~~~~~~
///
/// @sa @ref keywordattr
/// @sa @ref keyworddef
/// \page LangInPlaceRef ChaiScript Language In-Place Creation Reference
/// \section inplacevector Vector
/// @page LangInPlaceRef ChaiScript Language In-Place Creation Reference
/// @section inplacevector Vector
///
/// \code
/// ~~~~~~~~~
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
/// \endcode
/// ~~~~~~~~~
///
/// \section inplacerangedvector Ranged Vector
/// @section inplacerangedvector Ranged Vector
///
/// \code
/// ~~~~~~~~~
/// In-place Ranged Vector ::= "[" value ".." value "]"
/// \endcode
/// ~~~~~~~~~
///
/// Creates a vector over a range (eg. 1..10)
///
/// \section inplacemap Map
/// @section inplacemap Map
///
/// \code
/// ~~~~~~~~
/// In-place Map ::= "[" (string ":" expression)+ "]"
/// \endcode
/// ~~~~~~~~
/// \page LangGettingStarted ChaiScript Language Getting Started
/// @page LangGettingStarted ChaiScript Language Getting Started
///
/// ChaiScript is a simple language that should feel familiar to anyone who knows
/// C++ or ECMAScript (JavaScript).
///
/// <hr>
/// \section chaiscriptloops Loops
/// -----------------------------------------------------------------------
///
/// @section chaiscriptloops Loops
///
/// Common looping constructs exist in ChaiScript
///
/// \code
/// ~~~~~~~~
/// var i = 0;
/// while (i < 10)
/// {
/// // do something
/// ++i;
/// }
/// \endcode
/// ~~~~~~~~
///
/// \code
/// ~~~~~~~~
/// for (var i = 0; i < 10; ++i)
/// {
/// // do something
/// }
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref keywordfor
/// \sa \ref keywordwhile
/// @sa @ref keywordfor
/// @sa @ref keywordwhile
///
/// <hr>
/// \section chaiscriptifs Conditionals
/// -----------------------------------------------------------------------
///
/// @section chaiscriptifs Conditionals
///
/// If statements work as expected
///
/// \code
/// ~~~~~~~~
/// var b = true;
///
/// if (b) {
@@ -555,103 +582,109 @@
/// } else {
/// // or do this
/// }
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref keywordif
/// @sa @ref keywordif
///
/// <hr>
/// \section chaiscriptfunctions Functions
/// -----------------------------------------------------------------------
///
/// @section chaiscriptfunctions Functions
///
/// Functions are defined with the def keyword
///
/// \code
/// ~~~~~~~~
/// def myfun(x) { print(x); }
///
/// myfun(10);
/// \endcode
/// ~~~~~~~~
///
/// Functions may have "guards" which determine if which is called.
///
/// \code
/// ~~~~~~~~
/// eval> def myfun2(x) : x < 10 { print("less than 10"); }
/// eval> def myfun2(x) : x >= 10 { print("10 or greater"); }
/// eval> myfun2(5)
/// less than 10
/// eval> myfun2(12)
/// 10 or greater
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref keyworddef
/// \sa \ref keywordattr
/// \sa \ref LangObjectSystemRef
/// @sa @ref keyworddef
/// @sa @ref keywordattr
/// @sa @ref LangObjectSystemRef
///
/// <hr>
/// \section chaiscriptfunctionobjects Function Objects
/// -----------------------------------------------------------------------
///
/// @section chaiscriptfunctionobjects Function Objects
///
/// Functions are first class types in ChaiScript and can be used as variables.
///
/// \code
/// ~~~~~~~~
/// eval> var p = print;
/// eval> p(1);
/// 1
/// \endcode
/// ~~~~~~~~
///
/// They can also be passed to functions.
///
/// \code
/// ~~~~~~~~
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
/// eval> def dosomething(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
/// eval> callfunc(dosomething, 1, 2);
/// eval> def do_something(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
/// eval> callfunc(do_something, 1, 2);
/// lhs: 1, rhs: 2
/// \endcode
/// ~~~~~~~~
///
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
///
/// \code
/// ~~~~~~~~
/// eval> callfunc(`+`, 1, 4);
/// 5
/// eval> callfunc(`*`, 3, 2);
/// 6
/// \endcode
/// ~~~~~~~~
///
/// <hr>
/// \sa \ref LangKeywordRef
/// \sa ChaiScript_Language for Built in Functions
/// -----------------------------------------------------------------------
///
/// @sa @ref LangKeywordRef
/// @sa ChaiScript_Language for Built in Functions
/// \page LangKeywordRef ChaiScript Language Keyword Reference
/// @page LangKeywordRef ChaiScript Language Keyword Reference
///
///
/// <hr>
/// \section keywordattr attr
/// -----------------------------------------------------------------------
///
/// @section keywordattr attr
/// Defines a ChaiScript object attribute
///
/// \code
/// ~~~~~~~~
/// Attribute Definition ::= "attr" class_name "::" attribute_name
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref LangObjectSystemRef
/// @sa @ref LangObjectSystemRef
///
/// <hr>
/// \section keywordbreak break
/// -----------------------------------------------------------------------
///
/// @section keywordbreak break
/// Stops execution of a looping block.
///
/// \code
/// ~~~~~~~~
/// Break Statement ::= "break"
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref keywordfor
/// \sa \ref keywordwhile
/// @sa @ref keywordfor
/// @sa @ref keywordwhile
///
///
/// <hr>
/// \section keyworddef def
/// -----------------------------------------------------------------------
///
/// @section keyworddef def
/// Begins a function or method definition
///
/// \code
/// ~~~~~~~~
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [arg ("," arg)*] ")" [":" guard] block
/// \endcode
/// ~~~~~~~~
///
/// annotation: meta-annotation on function, currently used as documentation. Optional.
/// identifier: name of function. Required.
@@ -667,50 +700,56 @@
/// Method definitions for known types extend those types with new methods. This includes C++ and ChaiScript defined types.
/// Method definitions for unknown types implicitly define the named type.
///
/// \sa \ref LangObjectSystemRef
/// @sa @ref LangObjectSystemRef
///
///
/// <hr>
/// \section keywordelse else
/// \sa \ref keywordif
/// -----------------------------------------------------------------------
///
/// @section keywordelse else
/// @sa @ref keywordif
///
///
/// <hr>
/// \section keywordfor for
/// \code
/// -----------------------------------------------------------------------
///
/// @section keywordfor for
/// ~~~~~~~~
/// For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block
/// \endcode
/// This loop can be broken using the \ref keywordbreak command.
/// ~~~~~~~~
/// This loop can be broken using the @ref keywordbreak command.
///
///
/// <hr>
/// \section keywordfun fun
/// -----------------------------------------------------------------------
///
/// @section keywordfun fun
/// Begins an anonymous function declaration (sometimes called a lambda).
///
/// \code
/// ~~~~~~~~
/// Lambda ::= "fun" "(" [variable] ("," variable)* ")" block
/// \endcode
/// ~~~~~~~~
///
/// \b Examples:
/// _Example_
///
/// \code
/// ~~~~~~~~
/// // Generate an anonymous function object that adds 2 to its parameter
/// var f = fun(x) { x + 2; }
/// \endcode
/// ~~~~~~~~
///
/// \sa \ref keyworddef for more details on ChaiScript functions
/// @sa @ref keyworddef for more details on ChaiScript functions
///
///
/// <hr>
/// \section keywordif if
/// -----------------------------------------------------------------------
///
/// @section keywordif if
/// Begins a conditional block of code that only executes if the condition evaluates as true.
/// \code
/// ~~~~~~~~
/// If Block ::= "if" "(" condition ")" block
/// Else If Block ::= "else if" "(" condition ")" block
/// Else Block ::= "else" block
/// \endcode
/// \b Example:
/// \code
/// ~~~~~~~~
///
/// _Example_
///
/// ~~~~~~~~
/// if (true) {
/// // do something
/// } else if (false) {
@@ -718,35 +757,38 @@
/// } else {
/// // otherwise do this
/// }
/// \endcode
/// ~~~~~~~~
///
///
/// <hr>
/// \section keywordtry try
/// \code
/// -----------------------------------------------------------------------
///
/// @section keywordtry try
/// ~~~~~~~~
/// Try Block ::= "try" block
/// ("catch" ["(" variable ")"] [":" guards] block)+
/// ["finally" block]
/// \endcode
/// ~~~~~~~~
///
/// \sa ChaiScript_Language::throw
/// @sa ChaiScript_Language::throw
///
/// <hr>
/// \section keywordwhile while
/// -----------------------------------------------------------------------
///
/// @section keywordwhile while
///
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
///
/// \code
/// ~~~~~~~~
/// While Block ::= "while" "(" condition ")" block
/// \endcode
/// This loop can be broken using the \ref keywordbreak command.
/// ~~~~~~~~
///
/// This loop can be broken using the @ref keywordbreak command.
/// \namespace chaiscript
/// \brief Namespace chaiscript contains every API call that the average user will be concerned with.
/// @namespace chaiscript
/// @brief Namespace chaiscript contains every API call that the average user will be concerned with.
/// \namespace chaiscript::detail
/// \brief Classes and functions reserved for internal use. Items in this namespace are not supported.
/// @namespace chaiscript::detail
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
#include "chaiscript_defines.hpp"

View File

@@ -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_
@@ -12,10 +12,22 @@
#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)
@@ -31,7 +43,11 @@
#define CHAISCRIPT_CONSTEXPR constexpr
#endif
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 4;
static const int version_patch = 0;
}
#endif

View File

@@ -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.

View File

@@ -64,16 +64,59 @@ namespace chaiscript
using std::recursive_mutex;
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// \todo move to thread_local when it exists
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *t_key)
: m_key(t_key)
{
}
~Thread_Storage()
{
t().erase(m_key);
}
inline T *operator->() const
{
return &(t()[m_key]);
}
inline T &operator*() const
{
return t()[m_key];
}
void *m_key;
private:
static std::unordered_map<void*, T> &t()
{
thread_local static std::unordered_map<void *, T> my_t;
return my_t;
}
};
#else
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// This version is used if the compiler does not support thread_local
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *)
{
}
inline T *operator->() const
{
return get_tls().get();
@@ -88,35 +131,26 @@ namespace chaiscript
private:
std::shared_ptr<T> get_tls() const
{
unique_lock<mutex> lock(m_mutex);
auto itr = m_instances.find(std::this_thread::get_id());
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(new T());
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
return new_instance;
/*
static __thread std::shared_ptr<T> *m_data = 0;
if (!m_data) { m_data = new std::shared_ptr<T>(new T()); }
return *m_data;
*/
}
mutable mutex m_mutex;
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
};
#endif // threading enabled but no tls
#else
#else // threading disabled
template<typename T>
class unique_lock
{
@@ -151,6 +185,10 @@ namespace chaiscript
class Thread_Storage
{
public:
Thread_Storage(void *)
{
}
inline T *operator->() const
{
return &obj;

View File

@@ -7,6 +7,8 @@
#ifndef CHAISCRIPT_ANY_HPP_
#define CHAISCRIPT_ANY_HPP_
#include <utility>
namespace chaiscript {
namespace detail {
namespace exception
@@ -27,7 +29,7 @@ namespace chaiscript {
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occured
virtual const char * what() const CHAISCRIPT_NOEXCEPT
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();
}
@@ -42,45 +44,51 @@ namespace chaiscript {
private:
struct Data
{
Data(const std::type_info &t_type)
: m_type(t_type)
{
}
Data &operator=(const Data &) = delete;
virtual ~Data() {}
virtual void *data() = 0;
virtual const std::type_info &type() const = 0;
virtual std::shared_ptr<Data> clone() const = 0;
const std::type_info &type() const
{
return m_type;
}
virtual std::unique_ptr<Data> clone() const = 0;
const std::type_info &m_type;
};
template<typename T>
struct Data_Impl : Data
{
Data_Impl(const T &t_type)
: m_type(typeid(T)),
m_data(t_type)
Data_Impl(T t_type)
: Data(typeid(T)),
m_data(std::move(t_type))
{
}
virtual ~Data_Impl() {}
virtual void *data()
virtual void *data() CHAISCRIPT_OVERRIDE
{
return &m_data;
}
const std::type_info &type() const
std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
{
return m_type;
}
std::shared_ptr<Data> clone() const
{
return std::shared_ptr<Data>(new Data_Impl<T>(m_data));
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
}
Data_Impl &operator=(const Data_Impl&) = delete;
const std::type_info &m_type;
T m_data;
};
std::shared_ptr<Data> m_data;
std::unique_ptr<Data> m_data;
public:
// construct/copy/destruct
@@ -98,7 +106,7 @@ 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::unique_ptr<Data>(new Data_Impl<ValueType>(t_value)))
{
}
@@ -112,7 +120,7 @@ namespace chaiscript {
template<typename ValueType>
Any & operator=(const ValueType &t_value)
{
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
m_data = std::unique_ptr<Data>(new Data_Impl<ValueType>(t_value));
return *this;
}
@@ -125,7 +133,6 @@ namespace chaiscript {
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -136,9 +143,7 @@ namespace chaiscript {
// modifiers
Any & swap(Any &t_other)
{
std::shared_ptr<Data> data = t_other.m_data;
t_other.m_data = m_data;
m_data = data;
std::swap(t_other.m_data, m_data);
return *this;
}

View File

@@ -7,8 +7,15 @@
#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,8 +29,8 @@ namespace chaiscript
{
public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_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))
{
}
@@ -32,15 +39,15 @@ namespace chaiscript
{
}
bad_boxed_cast(const std::string &t_what) CHAISCRIPT_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() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occured
virtual const char * what() const CHAISCRIPT_NOEXCEPT
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();
}

View File

@@ -7,13 +7,33 @@
#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"
#include "../utility/utility.hpp"
#include "../language/chaiscript_common.hpp"
namespace chaiscript
{
@@ -304,14 +324,6 @@ namespace chaiscript
static void throw_exception(const Boxed_Value &bv) {
throw bv;
}
static std::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(
std::shared_ptr<chaiscript::detail::Dispatch_Engine> e
= std::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
{
e->add(user_type<void>(), "void");
return e;
}
static std::string what(const std::exception &e)
{
@@ -347,12 +359,48 @@ namespace chaiscript
return vbv;
}
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return true;
} else {
return false;
}
} else {
return false;
}
}
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return pf->get_parse_tree();
} else {
throw std::runtime_error("Function does not have a parse tree");
}
} else {
throw std::runtime_error("Function does not have a parse tree");
}
}
template<typename Function>
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
{
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
}
public:
/// \brief perform all common bootstrap functions for std::string, void and POD types
/// \param[in,out] m Module to add bootstrapped functions to
@@ -370,7 +418,7 @@ namespace chaiscript
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
@@ -399,9 +447,12 @@ namespace chaiscript
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
operators::equal<Type_Info>(m);
@@ -421,8 +472,8 @@ namespace chaiscript
operators::assign<bool>(m);
operators::equal<bool>(m);
m->add(fun(&to_string<const std::string &>), "internal_to_string");
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
m->add(fun(&to_string<const std::string &>), "to_string");
m->add(fun(&Bootstrap::bool_to_string), "to_string");
m->add(fun(&unknown_assign), "=");
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
@@ -462,6 +513,68 @@ namespace chaiscript
m->add(fun(&Boxed_Value::type_match), "type_match");
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
return retval;
})), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
{ {fun(&File_Position::line), "line"},
{fun(&File_Position::column), "column"} }
);
chaiscript::utility::add_class<AST_Node>(*m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
{fun(&AST_Node::identifier), "identifier"},
{fun(&AST_Node::filename), "filename"},
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::to_string), "to_string"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) {
std::vector<Boxed_Value> retval;
std::transform(t_node.children.begin(), t_node.children.end(),
std::back_inserter(retval),
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
return retval;
})), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
return m;
}
};

View File

@@ -13,9 +13,21 @@
#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
{
@@ -173,7 +185,7 @@ namespace chaiscript
copy_constructor<Bidir_Type>(type + "_Range", m);
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range");
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
m->add(fun(&Bidir_Type::empty), "empty");
m->add(fun(&Bidir_Type::pop_front), "pop_front");
@@ -189,8 +201,8 @@ namespace chaiscript
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)
{
@@ -206,8 +218,8 @@ namespace chaiscript
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))
{
@@ -217,7 +229,7 @@ namespace chaiscript
std::advance(itr, pos);
container.erase(itr);
}
}
template<typename ContainerType>
@@ -322,8 +334,8 @@ 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;
}
@@ -336,10 +348,12 @@ namespace chaiscript
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
{
typedef typename ContainerType::reference (ContainerType::*frontptr)();
typedef typename ContainerType::const_reference (ContainerType::*constfrontptr)() const;
typedef void (ContainerType::*pushptr)(typename ContainerType::const_reference);
typedef void (ContainerType::*popptr)();
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<constfrontptr>(&ContainerType::front)), "front");
std::string push_front_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
@@ -463,7 +477,10 @@ namespace chaiscript
m->add(user_type<VectorType>(), type);
typedef typename VectorType::reference (VectorType::*frontptr)();
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
back_insertion_sequence_type<VectorType>(type, m);
@@ -535,13 +552,13 @@ namespace chaiscript
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<void (String *)>( [](String *s) { return s->clear(); } ) ), "clear");
m->add(fun( std::function<bool (const String *)>( [](const String *s) { return s->empty(); } ) ), "empty");
m->add(fun( std::function<size_t (const String *)>( [](const String *s) { return s->size(); } ) ), "size");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->c_str(); } ) ), "c_str");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->data(); } ) ), "data");
m->add(fun( std::function<String (const String *, int, int)>( [](const String *s, int pos, int len) { return s->substr(pos, len); } ) ), "substr");
m->add(fun( std::function<String (const String *, size_t, size_t)>( [](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ) ), "substr");
return m;
}

View File

@@ -7,14 +7,24 @@
#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
{
@@ -79,11 +89,18 @@ namespace chaiscript
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(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
} 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

View File

@@ -7,8 +7,12 @@
#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
@@ -48,10 +52,10 @@ namespace chaiscript
}
};
template<typename Result>
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
{
};
template<typename Result>
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
{
};
/**
* Cast_Helper_Inner for casting to a const & type
@@ -201,10 +205,25 @@ namespace chaiscript
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
{
return ob;
return ob;
}
};
/**
* Cast_Helper_Inner for casting to a Boxed_Value & type
*/
template<>
struct Cast_Helper_Inner<Boxed_Value &>
{
typedef Boxed_Value& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
{
return const_cast<Boxed_Value &>(ob);
}
};
/**
* Cast_Helper_Inner for casting to a const Boxed_Value & type
*/
@@ -217,9 +236,9 @@ namespace chaiscript
struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
{
};
/**
/**
* Cast_Helper_Inner for casting to a std::reference_wrapper type
*/
template<typename Result>
@@ -259,7 +278,7 @@ namespace chaiscript
struct Cast_Helper
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
{
return Cast_Helper_Inner<T>::cast(ob, t_conversions);

View File

@@ -7,17 +7,30 @@
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
#include "boxed_value.hpp"
#include "../language/chaiscript_algebraic.hpp"
#include <sstream>
#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
{
// 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
@@ -307,7 +320,7 @@ namespace chaiscript
}
template<typename Source>
std::string to_string_aux(const Boxed_Value &v) const
static std::string to_string_aux(const Boxed_Value &v)
{
std::ostringstream oss;
oss << *static_cast<const Source *>(v.get_const_ptr());
@@ -520,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))

View File

@@ -7,12 +7,14 @@
#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)
{
}
@@ -52,9 +51,16 @@ namespace chaiscript
m_data_ptr = rhs.m_data_ptr;
m_const_data_ptr = rhs.m_const_data_ptr;
if (rhs.m_attrs)
{
m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*rhs.m_attrs));
}
return *this;
}
Data(const Data &) = delete;
~Data()
{
}
@@ -64,6 +70,7 @@ namespace chaiscript
void *m_data_ptr;
const void *m_const_data_ptr;
bool m_is_ref;
std::unique_ptr<std::map<std::string, Boxed_Value>> m_attrs;
};
struct Object_Data
@@ -137,28 +144,22 @@ 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())
: m_data(Object_Data::get())
{
}
@@ -171,19 +172,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 +193,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 +211,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
@@ -244,6 +239,26 @@ namespace chaiscript
return m_data->m_const_data_ptr;
}
Boxed_Value get_attr(const std::string &t_name)
{
if (!m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>());
}
return (*m_data->m_attrs)[t_name];
}
Boxed_Value &copy_attrs(const Boxed_Value &t_obj)
{
if (t_obj.m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*t_obj.m_data->m_attrs));
}
return *this;
}
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(Boxed_Value l, Boxed_Value r)
{
@@ -254,19 +269,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 +355,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)
{

View File

@@ -7,23 +7,43 @@
#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
@@ -188,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)
{
@@ -203,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)
{
@@ -213,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)
{
@@ -223,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)
{
@@ -252,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);
@@ -264,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)
@@ -300,12 +320,10 @@ namespace chaiscript
return -1; // unknown arity
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) 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)
{
@@ -320,13 +338,13 @@ 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> &params, const Dynamic_Cast_Conversions &t_conversions) const
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
}
@@ -338,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)
@@ -347,7 +365,7 @@ namespace chaiscript
++begin;
bool sizemismatch = false;
bool size_mismatch = false;
while (begin != end)
{
@@ -355,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)
@@ -371,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);
}
@@ -411,7 +429,9 @@ 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()))
{
}
@@ -464,18 +484,18 @@ namespace chaiscript
add_object(name, obj);
}
/**
* 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);
@@ -596,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;
@@ -626,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())
{
@@ -645,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;
}
}
@@ -678,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())
@@ -697,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())
{
@@ -718,6 +736,19 @@ namespace chaiscript
return functions.find(name) != functions.end();
}
/// \returns All values in the local thread state in the parent scope, or if it doesn't exist,
/// the current scope.
std::map<std::string, Boxed_Value> get_parent_locals() const
{
StackData &stack = get_stack_data();
if (stack.size() > 1)
{
return stack[1];
} else {
return stack[0];
}
}
/// \returns All values in the local thread state, added through the add() function
std::map<std::string, Boxed_Value> get_locals() const
{
@@ -745,14 +776,16 @@ namespace chaiscript
///
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());
}
@@ -779,11 +812,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;
@@ -801,15 +832,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));
}
}
@@ -973,7 +1000,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);
@@ -991,7 +1018,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()
@@ -1001,15 +1029,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();
}
}
@@ -1165,7 +1194,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();

View File

@@ -9,11 +9,16 @@
#include <memory>
#include <set>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <typeinfo>
#include "type_info.hpp"
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include "../chaiscript_threading.hpp"
#include "bad_boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript
{
@@ -48,12 +53,13 @@ namespace chaiscript
{
public:
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;
}
@@ -72,6 +78,57 @@ namespace chaiscript
};
template<typename From, typename To>
class Dynamic_Caster
{
public:
static Boxed_Value cast(const Boxed_Value &t_from)
{
if (t_from.get_type_info().bare_equal(user_type<From>()))
{
if (t_from.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
std::shared_ptr<const To> data
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
} else {
std::shared_ptr<To> data
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
const To &data = dynamic_cast<const To &>(d);
return Boxed_Value(std::cref(data));
} else {
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
To &data = dynamic_cast<To &>(d);
return Boxed_Value(std::ref(data));
}
}
} else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
}
}
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Dynamic_Conversion
{
@@ -81,50 +138,14 @@ namespace chaiscript
{
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
{
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
{
if (t_derived.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
std::shared_ptr<const Base> data
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Dynamic_Caster<Base, Derived>::cast(t_base);
}
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, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived, 0);
const Base &data = dynamic_cast<const Base &>(d);
return Boxed_Value(std::cref(data));
} else {
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived, 0);
Base &data = dynamic_cast<Base &>(d);
return Boxed_Value(std::ref(data));
}
}
} else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
{
return Dynamic_Caster<Derived, Base>::cast(t_derived);
}
};
}
@@ -155,7 +176,7 @@ namespace chaiscript
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
{
return has_conversion(base, derived);
return has_conversion(base, derived) || has_conversion(derived, base);
}
template<typename Base>
@@ -170,6 +191,19 @@ namespace chaiscript
}
}
template<typename Derived>
Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const
{
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);
@@ -180,7 +214,7 @@ namespace chaiscript
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr =
auto itr =
find(base, derived);
if (itr != m_conversions.end())
@@ -195,7 +229,7 @@ namespace chaiscript
std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
const Type_Info &base, const Type_Info &derived) const
{
for (std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr = m_conversions.begin();
for (auto itr = m_conversions.begin();
itr != m_conversions.end();
++itr)
{
@@ -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()
{

View File

@@ -7,6 +7,27 @@
#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,7 +108,7 @@ namespace chaiscript
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) 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, t_conversions))
{
@@ -95,25 +118,25 @@ namespace chaiscript
}
}
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> &params, const Dynamic_Cast_Conversions &t_conversions) const
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
@@ -123,7 +146,7 @@ namespace chaiscript
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) 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, t_conversions);
}
@@ -140,11 +163,10 @@ 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, const Dynamic_Cast_Conversions &t_conversions)
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, &t_conversions);
@@ -163,8 +185,8 @@ namespace chaiscript
}
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions)
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)
{
@@ -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,7 +250,7 @@ namespace chaiscript
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) 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)));
@@ -236,19 +260,19 @@ namespace chaiscript
}
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> &params, const Dynamic_Cast_Conversions &t_conversions) const
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, 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));

View File

@@ -7,8 +7,18 @@
#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
@@ -32,7 +42,7 @@ namespace chaiscript
{
virtual ~Exception_Handler_Impl1() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
}
@@ -42,7 +52,7 @@ namespace chaiscript
{
virtual ~Exception_Handler_Impl2() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
@@ -54,7 +64,7 @@ namespace chaiscript
{
virtual ~Exception_Handler_Impl3() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
@@ -66,7 +76,7 @@ namespace chaiscript
{
virtual ~Exception_Handler_Impl4() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
@@ -79,7 +89,7 @@ namespace chaiscript
{
virtual ~Exception_Handler_Impl5() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);

View File

@@ -7,13 +7,22 @@
#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
{
@@ -31,7 +40,7 @@ namespace chaiscript
std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
{
FunctionType *p=0;
FunctionType *p=nullptr;
return detail::build_function_caller_helper(p, funcs, t_conversions);
}

View File

@@ -7,8 +7,17 @@
#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,12 +26,11 @@ 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,
@@ -32,11 +40,25 @@ namespace chaiscript
}
};
/**
* 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> &params, 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> &params, const Dynamic_Cast_Conversions &t_conversions)
@@ -51,19 +73,19 @@ namespace chaiscript
template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper
{
Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs, const Dynamic_Cast_Conversions &t_conversions)
: 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)...
}, m_conversions
);
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
);
}

View File

@@ -7,14 +7,20 @@
#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

View File

@@ -48,7 +48,7 @@ namespace chaiscript
template<typename T>
Proxy_Function constructor()
{
T *f = 0;
T *f = nullptr;
return (dispatch::detail::build_constructor_(f));
}

View File

@@ -9,21 +9,36 @@
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
#include "boxed_value.hpp"
#include "type_info.hpp"
#include <algorithm>
#include <cassert>
#include <functional>
#include <memory>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <stdexcept>
#include <vector>
#include <cassert>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "proxy_functions_detail.hpp"
#include "type_info.hpp"
namespace chaiscript {
class 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
{
@@ -112,8 +127,8 @@ namespace chaiscript
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const = 0;
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
: m_types(t_types), m_has_arithmetic_param(false)
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)
{
@@ -196,19 +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 ~Dynamic_Proxy_Function() {}
virtual bool operator==(const Proxy_Function_Base &rhs) const
virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
@@ -218,13 +233,13 @@ namespace chaiscript
&& !this->m_guard && !prhs->m_guard);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) 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, t_conversions);
}
virtual int get_arity() const
virtual int get_arity() const CHAISCRIPT_OVERRIDE
{
return m_arity;
}
@@ -239,13 +254,13 @@ 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> &params, const Dynamic_Cast_Conversions &t_conversions) const
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (m_arity < 0 || params.size() == size_t(m_arity))
{
@@ -329,19 +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 Dynamic_Cast_Conversions &t_conversions) 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), t_conversions);
}
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);
@@ -351,10 +366,8 @@ namespace chaiscript
std::vector<Boxed_Value> build_param_list(const std::vector<Boxed_Value> &params) 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;
@@ -382,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();
}
@@ -416,7 +429,7 @@ namespace chaiscript
return retval;
}
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
return (*m_f)(build_param_list(params), t_conversions);
}
@@ -427,47 +440,64 @@ namespace chaiscript
int m_arity;
};
/**
* The standard typesafe function call implementation of Proxy_Function
* It takes a std::function<> object and performs runtime
* type checking of Boxed_Value parameters, in a type safe manner
*/
template<typename Func>
class Proxy_Function_Impl : public Proxy_Function_Base
class Proxy_Function_Impl_Base : 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_Base(std::vector<Type_Info> t_types)
: Proxy_Function_Base(std::move(t_types))
{
}
virtual ~Proxy_Function_Impl() {}
virtual ~Proxy_Function_Impl_Base() {}
virtual bool operator==(const Proxy_Function_Base &t_func) const
{
const Proxy_Function_Impl *pimpl = dynamic_cast<const Proxy_Function_Impl<Func> *>(&t_func);
return pimpl != 0;
}
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 Dynamic_Cast_Conversions &t_conversions) const
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "";
}
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, t_conversions);
return compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions);
}
virtual std::string annotation() const
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
};
/**
* The standard typesafe function call implementation of Proxy_Function
* It takes a std::function<> object and performs runtime
* type checking of Boxed_Value parameters, in a type safe manner
*/
template<typename Func>
class Proxy_Function_Impl : public Proxy_Function_Impl_Base
{
public:
Proxy_Function_Impl(std::function<Func> f)
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
m_f(std::move(f)), m_dummy_func(nullptr)
{
return "";
}
virtual ~Proxy_Function_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
}
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
{
return dynamic_cast<const Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
}
std::function<Func> internal_function() const
@@ -501,7 +531,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);
@@ -514,12 +544,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 Dynamic_Cast_Conversions &) const
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &) const CHAISCRIPT_OVERRIDE
{
if (vals.size() != 1)
{
@@ -529,13 +559,13 @@ 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> &params, const Dynamic_Cast_Conversions &t_conversions) const
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (params.size() == 1)
{
@@ -573,9 +603,9 @@ namespace chaiscript
class dispatch_error : public std::runtime_error
{
public:
dispatch_error(const std::vector<Boxed_Value> &t_parameters,
const std::vector<Const_Proxy_Function> &t_functions)
: std::runtime_error("Error with function dispatch"), parameters(t_parameters), functions(t_functions)
dispatch_error(std::vector<Boxed_Value> t_parameters,
std::vector<Const_Proxy_Function> t_functions)
: std::runtime_error("Error with function dispatch"), parameters(std::move(t_parameters)), functions(std::move(t_functions))
{
}

View File

@@ -7,15 +7,25 @@
#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
@@ -104,7 +114,7 @@ namespace chaiscript
{
}
};
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
@@ -145,7 +155,7 @@ namespace chaiscript
#endif
template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
const std::vector<Boxed_Value> &, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
}
@@ -171,7 +181,7 @@ namespace chaiscript
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
}
}
}

View File

@@ -7,8 +7,12 @@
#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
{
@@ -92,7 +96,7 @@ namespace chaiscript
/// chai.add(fun(&MyClass::memberdata), "memberdata");
/// \endcode
///
/// \sa \ref addingfunctions
/// \sa \ref adding_functions
template<typename T>
Proxy_Function fun(T t)
{
@@ -110,7 +114,7 @@ namespace chaiscript
/// chai.add(fun(f), "some_function");
/// \endcode
///
/// \sa \ref addingfunctions
/// \sa \ref adding_functions
template<typename T>
Proxy_Function fun(const std::function<T> &f)
{
@@ -135,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)
{
@@ -161,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)
{

View File

@@ -7,10 +7,11 @@
#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
{
@@ -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
@@ -92,7 +93,7 @@ namespace chaiscript
bool bare_equal_type_info(const std::type_info &ti) const
{
return m_bare_type_info != 0
return m_bare_type_info != nullptr
&& (*m_bare_type_info) == ti;
}
@@ -100,7 +101,7 @@ namespace chaiscript
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

View File

@@ -5,7 +5,9 @@
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#include <string>
#include "../dispatchkit/dispatchkit.hpp"
@@ -126,5 +128,5 @@ namespace chaiscript
};
}
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */

View File

@@ -5,10 +5,24 @@
// http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_
#include <algorithm>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
namespace chaiscript {
struct AST_Node;
} // namespace chaiscript
namespace chaiscript
{
@@ -23,7 +37,7 @@ namespace chaiscript
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, 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, Noop
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class
};
};
@@ -54,7 +68,7 @@ namespace chaiscript
};
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
typedef std::shared_ptr<AST_Node> AST_NodePtr;
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
@@ -253,11 +267,9 @@ namespace chaiscript
} else {
ss << " " << t_functions.size() << " overloads available:" << std::endl;
for (std::vector<chaiscript::Const_Proxy_Function>::const_iterator itr = t_functions.begin();
itr != t_functions.end();
++itr)
for (const auto & t_function : t_functions)
{
ss << " " << format_types((*itr), t_dot_notation, t_ss) << std::endl;
ss << " " << format_types((t_function), t_dot_notation, t_ss) << std::endl;
}
}
@@ -277,7 +289,7 @@ namespace chaiscript
{
std::string paramstr;
for (std::vector<Boxed_Value>::const_iterator itr = t_parameters.begin();
for (auto itr = t_parameters.begin();
itr != t_parameters.end();
++itr)
{
@@ -404,8 +416,8 @@ namespace chaiscript
oss << text;
for (unsigned int j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->pretty_print();
for (auto & elem : this->children) {
oss << elem->pretty_print();
}
return oss.str();
@@ -413,29 +425,25 @@ namespace chaiscript
/// Prints the contents of an AST node, including its children, recursively
std::string to_string(std::string t_prepend = "") {
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();
}
std::string internal_to_string() {
return to_string();
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
{
try {
return eval_internal(t_e);
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this());
throw ee;
throw;
}
}
@@ -446,15 +454,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() {}
@@ -498,6 +506,9 @@ namespace chaiscript
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
@@ -511,16 +522,16 @@ namespace chaiscript
private:
// explicitly unimplemented copy and assignment
Scope_Push_Pop(const Scope_Push_Pop &);
Scope_Push_Pop& operator=(const Scope_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
};
/// Creates a new functon call and pops it on destruction
/// Creates a new function call and pops it on destruction
struct Function_Push_Pop
{
Function_Push_Pop(const Function_Push_Pop &) = delete;
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
@@ -539,9 +550,6 @@ namespace chaiscript
private:
// explicitly unimplemented copy and assignment
Function_Push_Pop(const Function_Push_Pop &);
Function_Push_Pop& operator=(const Function_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
};
@@ -549,6 +557,9 @@ namespace chaiscript
/// Creates a new scope then pops it on destruction
struct Stack_Push_Pop
{
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
@@ -562,9 +573,6 @@ namespace chaiscript
private:
// explicitly unimplemented copy and assignment
Stack_Push_Pop(const Stack_Push_Pop &);
Stack_Push_Pop& operator=(const Stack_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
};
@@ -572,5 +580,5 @@ namespace chaiscript
}
}
#endif /* _CHAISCRIPT_COMMON_HPP */
#endif /* _CHAISCRIPT_COMMON_HPP */

View File

@@ -7,17 +7,34 @@
#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.chai"
#include "chaiscript_parser.hpp"
#include "../dispatchkit/exception_specification.hpp"
#include "chaiscript_parser.hpp"
#include "chaiscript_prelude.chai"
namespace chaiscript
{
@@ -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;
@@ -173,17 +190,17 @@ namespace chaiscript
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()));
}
}
@@ -203,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()));
}
}
@@ -253,8 +270,6 @@ namespace chaiscript
chaiscript::detail::Dispatch_Engine m_engine;
/// 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)
{
@@ -315,6 +330,7 @@ namespace chaiscript
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("class");
m_engine.add_reserved_word("_");
if (t_lib)
@@ -329,7 +345,6 @@ 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");
@@ -347,12 +362,20 @@ namespace chaiscript
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
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) {
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()) {
@@ -380,9 +403,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())
{
@@ -404,9 +427,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())
{
@@ -418,8 +441,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
@@ -455,11 +477,43 @@ namespace chaiscript
// attempt to load the stdlib
load_module("chaiscript_stdlib");
load_module("chaiscript_stdlib-" + version());
build_eval_system(ModulePtr());
}
int version_major() const
{
return chaiscript::version_major;
}
int version_minor() const
{
return chaiscript::version_minor;
}
int version_patch() const
{
return chaiscript::version_patch;
}
std::string version() const
{
std::stringstream ss;
ss << version_major() << "." << version_minor() << "." << version_patch();
return ss.str();
}
std::string get_type_name(const Type_Info &ti) const
{
return m_engine.get_type_name(ti);
}
template<typename T>
std::string get_type_name() const
{
return get_type_name(user_type<T>());
}
/// \brief Loads and parses a file. If the file is already, it is not reloaded
@@ -608,7 +662,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)
{
@@ -655,9 +709,16 @@ namespace chaiscript
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;
@@ -665,16 +726,16 @@ 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];
std::string name = elem + prefix + t_module_name + postfix;
// std::cerr << "trying location: " << name << std::endl;
load_module(t_module_name, name);
load_module(version_stripped_name, name);
return name;
} catch (const chaiscript::exception::load_module_error &e) {
// std::cerr << "error: " << e.what() << std::endl;
@@ -742,7 +803,7 @@ namespace chaiscript
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw bv;
throw;
}
}
@@ -768,7 +829,7 @@ namespace chaiscript
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw bv;
throw;
}
}
@@ -798,7 +859,7 @@ namespace chaiscript
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw bv;
throw;
}
}
@@ -814,7 +875,7 @@ namespace chaiscript
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw bv;
throw;
}
}
@@ -834,7 +895,7 @@ namespace chaiscript
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw bv;
throw;
}
}
};

View File

@@ -7,10 +7,36 @@
#ifndef CHAISCRIPT_EVAL_HPP_
#define CHAISCRIPT_EVAL_HPP_
#include <assert.h>
#include <cstdlib>
#include <exception>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <ostream>
#include <stdexcept>
#include <string>
#include <vector>
#include "chaiscript_common.hpp"
#include "../chaiscript_defines.hpp"
#include "../dispatchkit/boxed_cast.hpp"
#include "../dispatchkit/boxed_cast_helper.hpp"
#include "../dispatchkit/boxed_number.hpp"
#include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/proxy_functions_detail.hpp"
#include "../dispatchkit/register_function.hpp"
#include "../dispatchkit/type_info.hpp"
#include "chaiscript_algebraic.hpp"
#include "chaiscript_common.hpp"
namespace chaiscript {
namespace exception {
class bad_boxed_cast;
} // namespace exception
} // namespace chaiscript
namespace chaiscript
{
@@ -44,13 +70,13 @@ namespace chaiscript
{ }
virtual ~Binary_Operator_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, Operators::to_operator(children[1]->text), children[1]->text,
this->children[0]->eval(t_ss),
this->children[2]->eval(t_ss));
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
if (children.size() == 3)
{
@@ -108,7 +134,7 @@ namespace chaiscript
AST_Node(t_ast_node_text, AST_Node_Type::Int, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
m_value(t_bv) { }
virtual ~Int_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{
return m_value;
}
@@ -126,7 +152,7 @@ namespace chaiscript
AST_Node(t_ast_node_text, AST_Node_Type::Float, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
m_value(t_bv) { }
virtual ~Float_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{
return m_value;
}
@@ -143,7 +169,7 @@ namespace chaiscript
{ }
virtual ~Id_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
if (!m_value.is_undef())
{
return m_value;
@@ -199,7 +225,7 @@ namespace chaiscript
AST_Node(t_ast_node_text, AST_Node_Type::Eol, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Eol_AST_Node() {}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "\n";
}
@@ -210,7 +236,7 @@ namespace chaiscript
Fun_Call_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Fun_Call, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Fun_Call_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
std::vector<Boxed_Value> params;
@@ -254,11 +280,11 @@ namespace chaiscript
}
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
for (unsigned int j = 0; j < this->children.size(); ++j) {
for (size_t j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->pretty_print();
if (j == 0)
@@ -279,7 +305,7 @@ namespace chaiscript
Inplace_Fun_Call_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Inplace_Fun_Call, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inplace_Fun_Call_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
std::vector<Boxed_Value> params;
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
@@ -320,10 +346,10 @@ namespace chaiscript
}
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
for (unsigned int j = 0; j < this->children.size(); ++j) {
for (size_t j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->pretty_print();
if (j == 0)
@@ -345,7 +371,7 @@ namespace chaiscript
AST_Node(t_ast_node_text, AST_Node_Type::Arg_List, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Arg_List_AST_Node() {}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
for (unsigned int j = 0; j < this->children.size(); ++j) {
@@ -375,7 +401,7 @@ namespace chaiscript
{}
virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
Boxed_Value retval = this->children.back()->eval(t_ss);
@@ -443,7 +469,7 @@ namespace chaiscript
Var_Decl_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Var_Decl, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Var_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
if (this->children[0]->identifier == AST_Node_Type::Reference)
{
return this->children[0]->eval(t_ss);
@@ -463,7 +489,7 @@ namespace chaiscript
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "var " + this->children[0]->text;
}
@@ -484,7 +510,7 @@ namespace chaiscript
int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Addition, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Addition_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, Operators::sum, "+", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
@@ -496,7 +522,7 @@ namespace chaiscript
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Subtraction, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Subtraction_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, Operators::difference, "-", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
@@ -508,7 +534,7 @@ namespace chaiscript
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Multiplication, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Multiplication_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, Operators::product, "*", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
@@ -520,7 +546,7 @@ namespace chaiscript
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Division, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Division_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, Operators::quotient, "/", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
@@ -532,7 +558,7 @@ namespace chaiscript
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Modulus, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Modulus_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, Operators::remainder, "%", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
@@ -542,7 +568,7 @@ namespace chaiscript
Array_Call_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Array_Call, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Array_Call_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value retval = this->children[0]->eval(t_ss);
std::vector<Boxed_Value> params;
@@ -558,9 +584,6 @@ namespace chaiscript
params.clear();
retval = t_ss.call_function("[]", retval, p1);
}
catch(std::out_of_range &) {
throw exception::eval_error("Out of bounds exception");
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, t_ss );
}
@@ -569,7 +592,7 @@ namespace chaiscript
return retval;
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
oss << this->children[0]->pretty_print();
@@ -590,7 +613,7 @@ namespace chaiscript
Dot_Access_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Dot_Access, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Dot_Access_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
Boxed_Value retval = this->children[0]->eval(t_ss);
if (this->children.size() > 1) {
@@ -636,9 +659,6 @@ namespace chaiscript
try {
retval = t_ss.call_function("[]", retval, this->children[i]->children[j]->eval(t_ss));
}
catch(std::out_of_range &) {
throw exception::eval_error("Out of bounds exception");
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, t_ss);
}
@@ -658,11 +678,11 @@ namespace chaiscript
AST_Node(t_ast_node_text, AST_Node_Type::Quoted_String, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
m_value(const_var(t_ast_node_text)) { }
virtual ~Quoted_String_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE {
return m_value;
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "\"" + text + "\"";
}
@@ -678,11 +698,11 @@ namespace chaiscript
AST_Node(t_ast_node_text, AST_Node_Type::Single_Quoted_String, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
m_value(const_var(char(t_ast_node_text.at(0)))) { }
virtual ~Single_Quoted_String_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{
return m_value;
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "'" + text + "'";
}
@@ -696,7 +716,7 @@ namespace chaiscript
Lambda_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Lambda, const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Lambda_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
std::vector<std::string> t_param_names;
size_t numparams = 0;
@@ -724,7 +744,7 @@ namespace chaiscript
Block_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Block, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Block_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
const size_t num_children = this->children.size();
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
@@ -753,7 +773,7 @@ namespace chaiscript
Def_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Def, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Def_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
std::vector<std::string> t_param_names;
size_t numparams = 0;
AST_NodePtr guardnode;
@@ -809,7 +829,7 @@ namespace chaiscript
While_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::While, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~While_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
try {
@@ -830,7 +850,23 @@ namespace chaiscript
return Boxed_Value();
}
};
struct Class_AST_Node : public AST_Node {
public:
Class_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Class, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Class_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
// put class name in current scope so it can be looked up by the attrs and methods
t_ss.add_object("_current_class_name", const_var(this->children[0]->text));
this->children[1]->eval(t_ss);
return Boxed_Value();
}
};
struct Ternary_Cond_AST_Node : public AST_Node {
@@ -838,7 +874,7 @@ namespace chaiscript
Ternary_Cond_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::If, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Ternary_Cond_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
bool cond;
try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
@@ -861,7 +897,7 @@ namespace chaiscript
If_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::If, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~If_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
bool cond;
try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
@@ -906,7 +942,7 @@ namespace chaiscript
For_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::For, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~For_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
// initial expression
@@ -945,7 +981,7 @@ namespace chaiscript
Switch_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Switch, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Switch_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
Boxed_Value match_value;
bool breaking = false;
size_t currentCase = 1;
@@ -988,7 +1024,7 @@ namespace chaiscript
Case_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Case, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Case_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
this->children[1]->eval(t_ss);
@@ -1002,7 +1038,7 @@ namespace chaiscript
Default_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Default, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Default_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
this->children[0]->eval(t_ss);
@@ -1017,7 +1053,7 @@ namespace chaiscript
Inline_Array_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Inline_Array, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Array_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
try {
std::vector<Boxed_Value> vec;
if (this->children.size() > 0) {
@@ -1034,7 +1070,7 @@ namespace chaiscript
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "[" + AST_Node::pretty_print() + "]";
}
@@ -1045,7 +1081,7 @@ namespace chaiscript
Inline_Map_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Inline_Map, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Map_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
try {
std::map<std::string, Boxed_Value> retval;
for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
@@ -1067,7 +1103,7 @@ namespace chaiscript
Return_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Return, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Return_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
if (this->children.size() > 0) {
throw detail::Return_Value(this->children[0]->eval(t_ss));
}
@@ -1083,7 +1119,7 @@ namespace chaiscript
File_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::File, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~File_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE {
const size_t size = this->children.size();
for (size_t i = 0; i < size; ++i) {
const Boxed_Value &retval = this->children[i]->eval(t_ss);
@@ -1101,7 +1137,7 @@ namespace chaiscript
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col)
{ }
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
try {
t_ss.add_object(this->children[0]->text, Boxed_Value());
}
@@ -1121,7 +1157,7 @@ namespace chaiscript
{ }
virtual ~Prefix_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value bv(this->children[1]->eval(t_ss));
@@ -1150,7 +1186,7 @@ namespace chaiscript
Break_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Break, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Break_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{
throw detail::Break_Loop();
}
};
@@ -1160,7 +1196,7 @@ namespace chaiscript
Continue_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Continue, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Continue_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{
throw detail::Continue_Loop();
}
};
@@ -1173,7 +1209,7 @@ namespace chaiscript
{ }
virtual ~Noop_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{
// It's a no-op, that evaluates to "true"
return m_value;
}
@@ -1201,7 +1237,7 @@ namespace chaiscript
Inline_Range_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Inline_Range, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Range_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
try {
return t_ss.call_function("generate_range",
this->children[0]->children[0]->children[0]->eval(t_ss),
@@ -1226,7 +1262,7 @@ namespace chaiscript
Try_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Try, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Try_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
Boxed_Value retval;
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
@@ -1248,7 +1284,7 @@ namespace chaiscript
assert(end_point > 0);
end_point = this->children.size() - 1;
}
for (unsigned int i = 1; i < end_point; ++i) {
for (size_t i = 1; i < end_point; ++i) {
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
AST_NodePtr catch_block = this->children[i];
@@ -1369,28 +1405,34 @@ namespace chaiscript
Method_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Method, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Method_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
std::vector<std::string> t_param_names;
AST_NodePtr guardnode;
auto d = t_ss.get_parent_locals();
auto itr = d.find("_current_class_name");
int class_offset = 0;
if (itr != d.end()) class_offset = -1;
const std::string & class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
//The first param of a method is always the implied this ptr.
t_param_names.push_back("this");
if ((this->children.size() > 3) && (this->children[2]->identifier == AST_Node_Type::Arg_List)) {
for (size_t i = 0; i < this->children[2]->children.size(); ++i) {
t_param_names.push_back(this->children[2]->children[i]->text);
if ((this->children.size() > (3 + class_offset)) && (this->children[(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) {
for (size_t i = 0; i < this->children[(2 + class_offset)]->children.size(); ++i) {
t_param_names.push_back(this->children[(2 + class_offset)]->children[i]->text);
}
if (this->children.size() > 4) {
guardnode = this->children[3];
if (this->children.size() > (4 + class_offset)) {
guardnode = this->children[(3 + class_offset)];
}
}
else {
//no parameters
if (this->children.size() > 3) {
guardnode = this->children[2];
if (this->children.size() > (3 + class_offset)) {
guardnode = this->children[(2 + class_offset)];
}
}
@@ -1406,8 +1448,9 @@ namespace chaiscript
try {
const std::string & l_annotation = this->annotation?this->annotation->text:"";
const std::string & class_name = this->children[0]->text;
const std::string & function_name = this->children[1]->text;
const std::string & function_name = this->children[(1 + class_offset)]->text;
if (function_name == class_name) {
t_ss.add(Proxy_Function
(new dispatch::detail::Dynamic_Object_Constructor(class_name, Proxy_Function
@@ -1452,22 +1495,28 @@ namespace chaiscript
Attr_Decl_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Attr_Decl, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Attr_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try {
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE
{
const auto &d = t_ss.get_parent_locals();
const auto itr = d.find("_current_class_name");
int class_offset = 0;
if (itr != d.end()) class_offset = -1;
std::string class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
try {
t_ss.add(Proxy_Function
(new dispatch::detail::Dynamic_Object_Function(
this->children[0]->text,
class_name,
fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::Dynamic_Object::get_attr,
std::placeholders::_1,
this->children[1]->text
this->children[(1 + class_offset)]->text
)))
)
), this->children[1]->text);
), this->children[(1 + class_offset)]->text);
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as attribute '" + this->children[1]->text + "'");
throw exception::eval_error("Reserved word used as attribute '" + this->children[(1 + class_offset)]->text + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
}
@@ -1516,7 +1565,7 @@ namespace chaiscript
Logical_And_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Logical_And, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Logical_And_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
Boxed_Value retval = this->children[0]->eval(t_ss);
if (this->children.size() > 1) {
@@ -1539,7 +1588,7 @@ namespace chaiscript
return retval;
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "(" + AST_Node::pretty_print() + ")";
}
@@ -1550,7 +1599,7 @@ namespace chaiscript
Logical_Or_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, AST_Node_Type::Logical_Or, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Logical_Or_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{
Boxed_Value retval;
retval = this->children[0]->eval(t_ss);
@@ -1570,7 +1619,7 @@ namespace chaiscript
return retval;
}
virtual std::string pretty_print() const
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "(" + AST_Node::pretty_print() + ")";
}

View File

@@ -7,11 +7,17 @@
#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 "../dispatchkit/boxed_value.hpp"
#include "chaiscript_common.hpp"
namespace chaiscript
@@ -56,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("//")
{
@@ -134,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;
@@ -193,7 +200,7 @@ namespace chaiscript
/**
* 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
@@ -210,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();
}
}
@@ -273,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);
}
@@ -459,7 +466,7 @@ namespace chaiscript
return retval;
}
Boxed_Value buildFloat(const std::string &t_val)
static Boxed_Value buildFloat(const std::string &t_val)
{
bool float_ = false;
bool long_ = false;
@@ -501,7 +508,7 @@ namespace chaiscript
template<typename IntType>
Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
static Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
{
bool unsigned_ = false;
bool long_ = false;
@@ -803,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;
@@ -980,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;
@@ -1110,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;
}
@@ -1122,7 +1127,7 @@ namespace chaiscript
}
retval = true;
m_input_pos = tmp;
m_col += len;
m_col += static_cast<int>(len);
}
return retval;
@@ -1158,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;
}
@@ -1170,7 +1175,7 @@ namespace chaiscript
}
retval = true;
m_input_pos = tmp;
m_col += len;
m_col += static_cast<int>(len);
}
return retval;
@@ -1353,10 +1358,9 @@ namespace chaiscript
/**
* Reads a function definition from input
*/
bool Def() {
bool Def(bool t_class_context = false) {
bool retval = false;
bool is_annotated = false;
bool is_method = false;
AST_NodePtr annotation;
if (Annotation()) {
@@ -1375,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;
@@ -1404,7 +1410,7 @@ namespace chaiscript
throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename);
}
if (is_method) {
if (is_method || t_class_context) {
build_match(AST_NodePtr(new eval::Method_AST_Node()), prev_stack_top);
}
else {
@@ -1481,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;
@@ -1549,6 +1555,35 @@ namespace chaiscript
return retval;
}
/**
* Reads a class block from input
*/
bool Class() {
bool retval = false;
size_t prev_stack_top = m_match_stack.size();
if (Keyword("class")) {
retval = true;
if (!Id(true)) {
throw exception::eval_error("Missing class name in definition", File_Position(m_line, m_col), *m_filename);
}
while (Eol()) {}
if (!Class_Block()) {
throw exception::eval_error("Incomplete 'class' block", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Class_AST_Node()), prev_stack_top);
}
return retval;
}
/**
* Reads a while block from input
*/
@@ -1731,6 +1766,28 @@ namespace chaiscript
}
/**
* Reads a curly-brace C-style class block from input
*/
bool Class_Block() {
bool retval = false;
size_t prev_stack_top = m_match_stack.size();
if (Char('{')) {
retval = true;
Class_Statements();
if (!Char('}')) {
throw exception::eval_error("Incomplete class block", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Block_AST_Node()), prev_stack_top);
}
return retval;
}
/**
* Reads a curly-brace C-style block from input
*/
@@ -1869,12 +1926,20 @@ namespace chaiscript
/**
* Reads a variable declaration from input
*/
bool Var_Decl() {
bool Var_Decl(bool t_class_context = false) {
bool retval = false;
size_t prev_stack_top = m_match_stack.size();
if (Keyword("auto") || Keyword("var")) {
if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) {
retval = true;
if (!Id(true)) {
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Attr_Decl_AST_Node()), prev_stack_top);
} else if (Keyword("auto") || Keyword("var")) {
retval = true;
if (!(Reference() || Id(true))) {
@@ -1882,8 +1947,7 @@ namespace chaiscript
}
build_match(AST_NodePtr(new eval::Var_Decl_AST_Node()), prev_stack_top);
}
else if (Keyword("attr")) {
} else if (Keyword("attr")) {
retval = true;
if (!Id(true)) {
@@ -2062,8 +2126,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;
}
}
@@ -2256,6 +2320,44 @@ namespace chaiscript
return retval;
}
/**
* Parses statements allowed inside of a class block
*/
bool Class_Statements() {
bool retval = false;
bool has_more = true;
bool saw_eol = true;
while (has_more) {
int prev_line = m_line;
int prev_col = m_col;
if (Def(true)) {
if (!saw_eol) {
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
}
has_more = true;
retval = true;
saw_eol = true;
} else if (Var_Decl(true)) {
if (!saw_eol) {
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
}
has_more = true;
retval = true;
saw_eol = true;
} else if (Eol()) {
has_more = true;
retval = true;
saw_eol = true;
} else {
has_more = false;
}
}
return retval;
}
/**
* Top level parser, starts parsing of all known parses
*/
@@ -2300,6 +2402,14 @@ namespace chaiscript
retval = true;
saw_eol = true;
}
else if (Class()) {
if (!saw_eol) {
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
}
has_more = true;
retval = true;
saw_eol = true;
}
else if (For()) {
if (!saw_eol) {
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);

View File

@@ -40,9 +40,9 @@ def new(x) {
eval(type_name(x))();
}
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x);
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x).copy_var_attrs(x);
}
@@ -56,11 +56,6 @@ def to_string(x) : call_exists(range, x) && !x.is_type("string"){
"[" + x.join(", ") + "]";
}
# Basic to_string function
def to_string(x) {
internal_to_string(x);
}
# Prints to console with no carriage return
def puts(x) {
print_string(x.to_string());
@@ -136,8 +131,8 @@ def insert_at(container, pos, x)
# Returns the reverse of the given container
def reverse(container) {
auto retval = new(container);
auto r = range(container);
auto retval := new(container);
auto r := range(container);
while (!r.empty()) {
retval.push_back(r.back());
r.pop_back();
@@ -147,10 +142,16 @@ def reverse(container) {
# Return a range from a range
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
{
return clone(r);
{
clone(r);
}
def range(r) : call_exists(range_internal, r)
{
var ri := range_internal(r);
ri.get_var_attr("internal_obj") := r;
ri;
}
# The retro attribute that contains the underlying range
attr retro::m_range;
@@ -200,19 +201,19 @@ def retro::empty()
# Performs the second value function over the container first value
def for_each(container, func) : call_exists(range, container) {
var t_range = range(container);
var t_range := range(container);
while (!t_range.empty()) {
func(t_range.front());
t_range.pop_front();
}
}
def back_inserter(container) {
bind(push_back, container, _);
def back_inserter(container) {
bind(push_back, container, _);
}
def contains(container, item, compare_func) : call_exists(range, container) {
auto t_range = range(container);
auto t_range := range(container);
while (!t_range.empty()) {
if ( compare_func(t_range.front(), item) ) {
return true;
@@ -220,15 +221,15 @@ def contains(container, item, compare_func) : call_exists(range, container) {
t_range.pop_front();
}
return false;
false;
}
def contains(container, item) {
return contains(container, item, eq)
contains(container, item, eq)
}
def map(container, func, inserter) : call_exists(range, container) {
auto range = range(container);
auto range := range(container);
while (!range.empty()) {
inserter(func(range.front()));
range.pop_front();
@@ -237,7 +238,7 @@ def map(container, func, inserter) : call_exists(range, container) {
# Performs the second value function over the container first value. Creates a new container with the results
def map(container, func) {
auto retval = new(container);
auto retval := new(container);
map(container, func, back_inserter(retval));
retval;
}
@@ -245,7 +246,7 @@ def map(container, func) {
# Performs the second value function over the container first value. Starts with initial and continues with each element.
def foldl(container, func, initial) : call_exists(range, container){
auto retval = initial;
auto range = range(container);
auto range := range(container);
while (!range.empty()) {
retval = (func(range.front(), retval));
range.pop_front();
@@ -266,8 +267,8 @@ def product(container) {
# Returns a new container with the elements of the first value concatenated with the elements of the second value
def concat(x, y) : call_exists(clone, x) {
auto retval = x;
auto inserter = back_inserter(retval);
auto range = range(y);
auto inserter := back_inserter(retval);
auto range := range(y);
while (!range.empty()) {
inserter(range.front());
range.pop_front();
@@ -277,7 +278,7 @@ def concat(x, y) : call_exists(clone, x) {
def take(container, num, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
auto i = num;
while ((i > 0) && (!r.empty())) {
inserter(r.front());
@@ -289,14 +290,14 @@ def take(container, num, inserter) : call_exists(range, container) {
# Returns a new container with the given number of elements taken from the container
def take(container, num) {
auto retval = new(container);
auto retval := new(container);
take(container, num, back_inserter(retval));
retval;
}
def take_while(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
while ((!r.empty()) && f(r.front())) {
inserter(r.front());
r.pop_front();
@@ -306,14 +307,14 @@ def take_while(container, f, inserter) : call_exists(range, container) {
# Returns a new container with the given elements match the second value function
def take_while(container, f) {
auto retval = new(container);
auto retval := new(container);
take_while(container, f, back_inserter(retval));
retval;
}
def drop(container, num, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
auto i = num;
while ((i > 0) && (!r.empty())) {
r.pop_front();
@@ -328,14 +329,14 @@ def drop(container, num, inserter) : call_exists(range, container) {
# Returns a new container with the given number of elements dropped from the given container
def drop(container, num) {
auto retval = new(container);
auto retval := new(container);
drop(container, num, back_inserter(retval));
retval;
}
def drop_while(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
while ((!r.empty())&& f(r.front())) {
r.pop_front();
}
@@ -348,7 +349,7 @@ def drop_while(container, f, inserter) : call_exists(range, container) {
# Returns a new container with the given elements dropped that match the second value function
def drop_while(container, f) {
auto retval = new(container);
auto retval := new(container);
drop_while(container, f, back_inserter(retval));
retval;
}
@@ -356,7 +357,7 @@ def drop_while(container, f) {
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) {
auto r = range(container);
auto r := range(container);
auto retval = r.front();
r.pop_front();
retval = func(retval, r.front());
@@ -372,7 +373,7 @@ def reduce(container, func) : container.size() >= 2 && call_exists(range, contai
# Returns a string of the elements in container delimited by the second value string
def join(container, delim) {
auto retval = "";
auto range = range(container);
auto range := range(container);
if (!range.empty()) {
retval += to_string(range.front());
range.pop_front();
@@ -387,7 +388,7 @@ def join(container, delim) {
def filter(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
while (!r.empty()) {
if (f(r.front())) {
inserter(r.front());
@@ -399,7 +400,7 @@ def filter(container, f, inserter) : call_exists(range, container) {
# Returns a new Vector which match the second value function
def filter(container, f) {
auto retval = new(container);
auto retval := new(container);
filter(container, f, back_inserter(retval));
retval;
}
@@ -416,7 +417,7 @@ def generate_range(x, y, inserter) {
# Returns a new Vector which represents the range from the first value to the second value
def generate_range(x, y) {
auto retval = Vector();
auto retval := Vector();
generate_range(x,y,back_inserter(retval));
retval;
}
@@ -429,8 +430,8 @@ def collate(x, y) {
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) {
auto r_x = range(x);
auto r_y = range(y);
auto r_x := range(x);
auto r_y := range(y);
while (!r_x.empty() && !r_y.empty()) {
inserter(f(r_x.front(), r_y.front()));
r_x.pop_front();
@@ -441,7 +442,7 @@ def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y)
# Returns a new Vector which joins matching elements of the second and third value with the first value function
def zip_with(f, x, y) {
auto retval = Vector();
auto retval := Vector();
zip_with(f,x,y,back_inserter(retval));
retval;
}
@@ -505,7 +506,7 @@ def string::trim() {
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
auto range = range(container);
auto range := range(container);
while (!range.empty()) {
if (compare_func(range.front(), value)) {
return range;
@@ -513,12 +514,12 @@ def find(container, value, compare_func) : call_exists(range, container) && is_t
range.pop_front();
}
}
return range;
range;
}
def find(container, value) {
return find(container, value, eq)
find(container, value, eq)
}

View File

@@ -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

View File

@@ -7,8 +7,13 @@
#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
@@ -20,15 +25,15 @@ namespace chaiscript
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)

View File

@@ -1,5 +1,7 @@
[![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=ChaiScript_5_0_CPP_11)](https://travis-ci.org/ChaiScript/ChaiScript)
[![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=ChaiScript_5_0_CPP_11)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=ChaiScript_5_0_CPP_11)
Master Status: [![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=master)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=master)
Develop Status: [![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=develop)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop)
ChaiScript

View File

@@ -1,11 +1,37 @@
Notes:
=======
Current Version: 5.4.0
* There was overlap during the 5.x and 4.x development cycle, so some of the notes appear twice as the new features were developed for 4.x (which required boost) then ported to 5.x (which requires C++11).
* This is the last release of 5.x, all future development will be on the final merged 6.x line.
### Changes since 5.3.1
* Decreased compile time and build size
* Make "reflection" module built in (losing some of the time / build size gains)
* Add new "class" syntax for ChaiScript defined methods and attributes see: [unittests/class.chai](unittests/class.chai) for examples
* Minor performance enhancements
* major to_string performance enhancements
* Provide API for retrieving registered type name #124
* Added strong reference to container to range object #132
### Changes since 5.3.0
* Add automatic conversion of arithmetic return types, following the same
rules as conversion of arithmetic types when passing parameters
* Add automatic casting up the inheritence hierarchy when possible.
* Enable travis.ci testing
* Allow users to add globals from within script
* Various static analysis fixes
* Code modernization to C++11
* Unofficial support for Haiku added
* Fix #121 - Inability to compile on cygwin
* Formatting fixes and spelling corrections
* Apply "include what you use" https://code.google.com/p/include-what-you-use/
* Apply clang-modernize
* Various threading fixes
* Performance improvements
### Changes since 5.2.0
* Official support for MSVC with C++11. All major platforms and compilers are now support for C++11 release
### Changes since 4.2.0
* Enhanced unit tests
* Add `continue` statement, fix various use cases for `for` loops
* Fix use of suffixed numbers in vector initialization

View File

@@ -137,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;

View File

@@ -1,13 +1,13 @@
for (var i = 0; i < 10; ++i) {
print(i)
print(i)
}
for (var i = 10; i >= 0; i -= 2) {
print(i)
print(i)
}
var i = 0
for (; i < 5; ++i) {
print(i)
print(i)
}

View File

@@ -1,10 +1,10 @@
//functions of zero params don't need them:
def meet {
print("Hello")
print("Hello")
}
def greet(x) {
print("Hello, " + x.to_string())
print("Hello, " + x.to_string())
}
//but you need parens for invocation:

View File

@@ -1,10 +1,10 @@
var i = 0
if (i == 0) {
print("i is 0")
print("i is 0")
}
else if (i == 1) {
print("i is 1")
print("i is 1")
}
else {
print("i is not 0 or 1")
print("i is not 0 or 1")
}

View File

@@ -1,20 +1,20 @@
for (var i = 0; i < 10; ++i) {
print("i: " + i.to_string())
if (i == 5) {
break
}
print("i: " + i.to_string())
if (i == 5) {
break
}
}
var j = 0
while (true) {
while (true) {
++j;
if (j == 5) {
break
}
}
break
while (true) {
++j;
if (j == 5) {
break
}
}
break
}
print("j: " + j.to_string())

View File

@@ -24,7 +24,7 @@ std::string get_next_command() {
#endif
}
void fuction(void)
void function(void)
{
// do nothing
}
@@ -35,28 +35,28 @@ class test
chaiscript::ChaiScript::State backupState;
public:
test()
: chai(chaiscript::Std_Lib::library())
{
backupState = chai.get_state();
}
~test(){}
test()
: chai(chaiscript::Std_Lib::library())
{
backupState = chai.get_state();
}
~test(){}
void ResetState()
{
chai.set_state(backupState);
chai.add(chaiscript::fun(&fuction),"Whatever()");
}
void ResetState()
{
chai.set_state(backupState);
chai.add(chaiscript::fun(&function),"Whatever()");
}
void RunFile(std::string sFile)
{
try {
chaiscript::Boxed_Value val = chai.eval_file(sFile);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
void RunFile(std::string sFile)
{
try {
chaiscript::Boxed_Value val = chai.eval_file(sFile);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
};
@@ -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

View File

@@ -2,7 +2,7 @@ var x = -(1 + 2 - 3 * 4 / 2)
print("Answer: " + x.to_string())
if (x >= 2 && x <= 4) {
print("x is between 2 and 4")
print("x is between 2 and 4")
}

View File

@@ -6,10 +6,10 @@
*/
var x = 4
def do_it() {
var x = 1
print(x)
var y = fun(x) { x + 1 }
print(y(9))
var x = 1
print(x)
var y = fun(x) { x + 1 }
print(y(9))
}
do_it()
print(x)

View File

@@ -11,6 +11,6 @@ var size = vec.size()
print("Vector Size: " + size.to_string());
while (i < size) {
print(i.to_string() + ": " + to_string(vec[i]))
i = i + 1
print(i.to_string() + ": " + to_string(vec[i]))
i = i + 1
}

View File

@@ -1,5 +1,5 @@
var i = 0
while (i < 10) {
print("i: " + i.to_string())
i = i + 1
print("i: " + i.to_string())
i = i + 1
}

View File

@@ -17,14 +17,15 @@
#else
char *mystrdup (const char *s) {
size_t len = strlen(s) + 1; // Space for length plus nul
char *d = static_cast<char*>(malloc (len));
size_t len = strlen(s); // Space for length plus nul
char *d = static_cast<char*>(malloc (len+1));
if (d == nullptr) return nullptr; // No memory
#ifdef CHAISCRIPT_MSVC
strcpy_s(d, len, s); // Copy the characters
#else
strcpy(d,s); // Copy the characters
strncpy(d,s,len); // Copy the characters
#endif
d[len] = '\0';
return d; // Return the new string
}
@@ -33,7 +34,7 @@ char* readline(const char* p)
std::string retval;
std::cout << p ;
std::getline(std::cin, retval);
return std::cin.eof() ? NULL : mystrdup(retval.c_str());
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
}

View File

@@ -1,129 +0,0 @@
// 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>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/utility/utility.hpp>
#include <string>
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return true;
} else {
return false;
}
} else {
return false;
}
}
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return pf->get_parse_tree();
} else {
throw std::runtime_error("Function does not have a parse tree");
}
} else {
throw std::runtime_error("Function does not have a parse tree");
}
}
#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());
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
using namespace chaiscript;
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(&chaiscript::exception::eval_error::call_stack), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
{ {fun(&File_Position::line), "line"},
{fun(&File_Position::column), "column"} }
);
chaiscript::utility::add_class<AST_Node>(*m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
{fun(&AST_Node::identifier), "identifier"},
{fun(&AST_Node::filename), "filename"},
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::internal_to_string), "internal_to_string"},
{fun(&AST_Node::children), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
return m;
}
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@@ -11,6 +11,8 @@ class TestBaseType
virtual ~TestBaseType() {}
virtual int func() { return 0; }
int base_only_func() { return -9; }
const TestBaseType &constMe() const { return *this; }
int val;
@@ -34,12 +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";
@@ -70,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");
@@ -79,14 +99,29 @@ 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");

View File

@@ -1,7 +1,7 @@
var i = 0
while (i < 10) {
if (++i == 5) {
break
}
if (++i == 5) {
break
}
}
assert_equal(5, i);

View File

@@ -1,4 +1,3 @@
load_module("reflection")
def deep()
{

View File

@@ -1,17 +1,17 @@
def bob(x, y, z) {
x + y + z
x + y + z
}
def bob(x, y) {
x - y
x - y
}
def bob(x) {
-x
-x
}
def bob() {
10
10
}
assert_equal(10, bob())

View File

@@ -1,4 +1,3 @@
load_module("reflection")
var parser := ChaiScript_Parser()
var parse_success = parser.parse("3 + 4", "INPUT")
var a := parser.ast()

View File

@@ -1,5 +1,5 @@
def sam() {
return 5
return 5
}
assert_equal(5, sam())

View File

@@ -1,4 +1,4 @@
def greet {
return("hello")
return("hello")
}

View File

@@ -18,6 +18,11 @@ 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()
{
@@ -29,6 +34,8 @@ int main()
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)");
@@ -46,7 +53,12 @@ int main()
// 1 non-arithmetic overload
chai.eval("f2(1.0)");
// this is the one call we expect to fail
// 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 &) {

View File

@@ -44,9 +44,9 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
if (!ret)
{
std::cerr << "Error with type conversion test. From: "
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
<< " To: "
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
<< " To: "
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not" << std::endl;
}

View File

@@ -1,7 +1,7 @@
auto i = 0
while (i < 10) {
if (++i == 5) {
break
}
if (++i == 5) {
break
}
}
assert_equal(5, i);

View File

@@ -3,7 +3,7 @@
extern "C"
{
int dosomething(int i)
int do_something(int i)
{
return i % 2;
}
@@ -13,8 +13,8 @@ int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&dosomething), "dosomething");
chai.add(chaiscript::fun(&do_something), "do_something");
return chai.eval<int>("dosomething(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
return chai.eval<int>("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
}

27
unittests/class.chai Normal file
View File

@@ -0,0 +1,27 @@
class Vector3
{
// you can use attr, auto or var in this context
attr x
auto y
var z
def Vector3(x,y,z)
{
this.x = x
this.y = y
this.z = z
}
def doSomething(mult)
{
return this.x * this.y * this.z * mult
}
}
auto v = Vector3(1,2,3)
assert_equal(1, v.x)
assert_equal(v.doSomething(2), 12)

View File

@@ -1,4 +1,3 @@
load_module("reflection")
def deep()
{

View File

@@ -19,7 +19,7 @@ int main()
// Dot notation
try {
// non-existant function
// non-existent function
chai.eval("\"test\".test_one()");
eval_error = false;
} catch (const chaiscript::exception::eval_error &) {
@@ -51,7 +51,7 @@ int main()
// regular notation
try {
// non-existant function
// non-existent function
chai.eval("test_one(\"test\")");
eval_error = false;
} catch (const chaiscript::exception::eval_error &) {

View File

@@ -0,0 +1,10 @@
var i = 5
add_global(i, "j")
def myFun()
{
assert_equal(j, 5)
}
myFun();

View File

@@ -15,3 +15,26 @@ 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);

View File

@@ -1,17 +1,17 @@
def bob(x, y, z) {
x + y + z
x + y + z
}
def bob(x, y) {
x - y
x - y
}
def bob(x) {
-x
-x
}
def bob() {
10
10
}
assert_equal(10, bob())

View File

@@ -35,7 +35,7 @@ int main()
{
// Disable deprecation warning for getenv call.
#ifdef CHAISCRIPT_MSVC
#ifdef max // Why microsoft? why?
#ifdef max // Why Microsoft? why?
#undef max
#endif
#pragma warning(push)

View File

@@ -1,4 +1,3 @@
load_module("reflection")
try {
eval("def `+`(x, y) \n { \n print(i); \n } \n \n var i = 10; \n \"1\" + 1;\n")

View File

@@ -2,3 +2,9 @@ auto x = [1, 2, 3, 4]
auto r = range(x)
r.pop_front()
assert_equal(2, r.front());
// test with temporary vector for range
auto q = range([1, 2, 3, 4])
q.pop_front()
assert_equal(2, q.front());

View File

@@ -1,4 +1,3 @@
load_module("reflection")
auto& parser = ChaiScript_Parser()
auto parse_success = parser.parse("3 + 4", "INPUT")
auto& a = parser.ast()

View File

@@ -1,5 +1,5 @@
def sam() {
return 5
return 5
}
assert_equal(5, sam())

View File

@@ -1,11 +1,11 @@
#include <chaiscript/chaiscript.hpp>
int dosomething(int i)
int do_something(int i)
{
return i + 2;
}
int dosomethingelse(int i)
int do_something_else(int i)
{
return i * 2;
}
@@ -15,29 +15,29 @@ int dosomethingelse(int i)
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&dosomething), "dosomething");
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(&dosomethingelse), "dosomethingelse");
chai2.add(chaiscript::fun(&do_something_else), "do_something_else");
std::stringstream ss;
ss << i;
if (chai.eval<int>("dosomething(" + ss.str() + ")") != i + 2)
if (chai.eval<int>("do_something(" + ss.str() + ")") != i + 2)
{
return EXIT_FAILURE;
}
if (chai2.eval<int>("dosomethingelse(" + ss.str() + ")") != i * 2)
if (chai2.eval<int>("do_something_else(" + ss.str() + ")") != i * 2)
{
return EXIT_FAILURE;
}
try {
chai2.eval("dosomething(1)");
chai2.eval("do_something(1)");
return EXIT_FAILURE; // should not get here
} catch (const chaiscript::exception::eval_error &) {
// nothing to do, expected case
@@ -51,7 +51,7 @@ int main()
}
try {
chai.eval("dosomethingelse(1)");
chai.eval("do_something_else(1)");
return EXIT_FAILURE; // should not get here
} catch (const chaiscript::exception::eval_error &) {
// nothing to do, expected case

View File

@@ -0,0 +1,22 @@
// Tests to make sure that the order in which function dispatches occur is correct
#include <chaiscript/chaiscript.hpp>
#include <cstdlib>
class MyClass
{
};
int main()
{
chaiscript::ChaiScript chai;
auto type = chaiscript::user_type<MyClass>();
chai.add(type, "MyClass");
if (chai.get_type_name(type) == "MyClass" && chai.get_type_name<MyClass>() == "MyClass")
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}

View File

@@ -1,4 +1,4 @@
def greet {
return("hello")
return("hello")
}