Compare commits

..

125 Commits

Author SHA1 Message Date
Jason Turner
455324bf13 Merge branch 'master' into ChaiScript_5_0_CPP_11 / update version numbers
Conflicts:
	CMakeLists.txt
	releasenotes.txt
2012-11-17 18:33:13 -07:00
Jason Turner
85ba42849b Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
	include/chaiscript/language/chaiscript_parser.hpp
	unittests/multithreaded_test.cpp
2012-11-16 16:32:39 -07:00
Jason Turner
6bb90f9d6d Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
2012-11-10 16:59:32 -07:00
Jason Turner
57c6d72a79 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bind_first.hpp
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2012-11-07 17:04:54 -07:00
Jason Turner
c5a86401aa Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
2012-11-07 13:47:09 -07:00
Jason Turner
87c9006174 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	CMakeLists.txt
	readme.md
2012-08-14 12:07:45 -06:00
Jason Turner
d47cd63fec One more round of updates to readme.md 2012-08-14 11:45:00 -06:00
Jason Turner
193151f52e Minor syntax updates for C++11 readme.md 2012-08-14 11:43:11 -06:00
Jason Turner
6642e02496 Update readme for C++11 2012-08-14 11:37:58 -06:00
Jason Turner
d84b4c0b37 Merge branch 'master' into ChaiScript_5_0_CPP_11 2012-07-18 07:30:34 -06:00
Jason Turner
84e17b8d06 Port Boxed_Number enhancements from mgee to C++11 branch. #53 2012-07-16 22:24:25 -06:00
Jason Turner
32fab64882 Merge branch 'master' into 2011-09-09-CxScript 2012-07-16 22:17:37 -06:00
Jason Turner
8cb49e9494 Merge branch 'master' into 2011-09-09-CxScript 2012-07-16 22:12:29 -06:00
Jason Turner
7052234650 Revert "Use unique_ptr instead of shared_ptr in our any implementation, >10% speed improvement"
This reverts commit f27739cf71.
2012-07-13 13:54:48 -06:00
Jason Turner
c2934caad6 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
	src/multithreaded.cpp
2012-07-13 13:32:29 -06:00
Jason Turner
199b1f5233 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/boxed_value.hpp
2012-07-13 12:36:08 -06:00
Jason Turner
f27739cf71 Use unique_ptr instead of shared_ptr in our any implementation, >10% speed improvement 2012-07-09 16:20:55 -06:00
Jason Turner
a6924bcc9e Use C++11 Raw Strings for chaiscript prelude 2012-06-28 21:24:51 -06:00
Jason Turner
a3b50d4151 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
2012-06-25 16:50:21 -06:00
Jason Turner
d3b8daeff0 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	CMakeLists.txt
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_engine.hpp
	include/chaiscript/language/chaiscript_eval.hpp
2012-06-25 15:40:19 -06:00
Jason Turner
6cda1140c4 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_eval.hpp
	include/chaiscript/language/chaiscript_parser.hpp
2012-06-22 18:12:51 -06:00
Jason Turner
949f54b9c4 Use constexpr where possible in user_type() functions
- Task #52
 - Gives some performance improvement
2012-06-22 14:19:52 -06:00
Jason Turner
f6e53dd42d Correct some threading issues
- prototype avoiding a lock with __thread in g++
 - pass -pthread and -lpthread when building to get threading actually working
2012-06-22 14:18:44 -06:00
Jason Turner
d55439a7ac Fix multithreaded.cpp to compile / run with C++11 2012-06-19 09:40:51 -06:00
Jason Turner
953c4e4847 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	CMakeLists.txt
2012-06-13 21:54:48 -06:00
Jason Turner
a67022e31e Prep for 5.0.0 release 2012-06-07 20:04:14 -06:00
Jason Turner
a951d2b0af Fix crash discovered by the move to using stdlib for all tests. 2012-06-04 07:32:05 -06:00
Jason Turner
b7e1cf41e5 Move to using the new constructor that searched for the stdlib
to improve compile time.
2012-06-04 07:31:20 -06:00
Jason Turner
30104cc3ed Add missing file 2012-06-03 18:50:51 -06:00
Jason Turner
5a380abc68 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/dispatchkit.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
	src/multithreaded.cpp
2012-06-03 09:27:05 -06:00
Jason Turner
4ebfe264e9 Make stdlib
* Build the standard library as a module .so
 * Locate and load lib at runtime as a module
   if it is not provided to the ChaiScript
   constructor.

Decreases compile time by 1/2 for common use cases
where the user can use the dynamic library module.
2012-06-03 08:11:37 -06:00
Jason Turner
a3e299fe1b Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_common.hpp
	src/main.cpp
2012-06-03 06:04:24 -06:00
Jason Turner
b1a27020f7 Get Cx branch ready for release 2012-06-01 14:22:57 -06:00
Jason Turner
4767aeb544 Merge branch 'master' into 2011-09-09-CxScript 2012-06-01 14:20:58 -06:00
Jason Turner
66deef52c8 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
2012-06-01 13:46:58 -06:00
Jason Turner
8f7793a795 Merge branch 'master' into 2010-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bad_boxed_cast.hpp
2012-06-01 08:50:15 -06:00
Jason Turner
2969f61fe4 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/boxed_number.hpp
	include/chaiscript/dispatchkit/dispatchkit.hpp
2012-05-28 11:42:55 -06:00
Jason Turner
13a049cf54 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
2012-05-24 19:33:48 -06:00
Jason Turner
f2c6745b8a Merge branch 'master' into 2011-09-09-CxScript 2012-05-21 12:10:15 -06:00
Jason Turner
13ffc92bc3 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	CMakeLists.txt
	include/chaiscript/dispatchkit/boxed_value.hpp
	include/chaiscript/language/chaiscript_eval.hpp
2012-05-21 10:47:12 -06:00
Jonathan Turner
e853e2e4ac Merge branch 'master' into 2011-09-09-CxScript 2012-05-20 10:48:45 -07:00
Jonathan Turner
1bdedd3b45 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_common.hpp
2012-05-20 10:36:49 -07:00
Jason Turner
9162b02ce9 Merge branch 'master' into 2011-09-09-CxScript 2012-05-19 21:42:30 -06:00
Jason Turner
ba9d13bf7b Merge branch 'master' into 2011-09-09-CxScript 2012-05-19 18:05:58 -06:00
Jason Turner
16bdfe4571 Merge branch 'master' into 2011-09-09-CxScript 2012-05-19 09:51:19 -06:00
Jason Turner
62891b8537 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
2012-05-19 07:33:16 -06:00
Jason Turner
4c5df91d51 Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript 2012-05-18 16:58:13 -06:00
Jason Turner
a0f7c46cc9 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
	include/chaiscript/language/chaiscript_eval.hpp
2012-05-18 16:57:05 -06:00
Jonathan Turner
7f5fce001b Merge branch 'master' into 2011-09-09-CxScript 2012-05-18 08:45:14 -07:00
Jason Turner
90125d0f9a Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	contrib/geshi/chaiscript.php
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_eval.hpp
	include/chaiscript/language/chaiscript_parser.hpp
2012-05-18 09:05:46 -06:00
Jonathan Turner
919b6430c4 Adding tested compilers to readme. 2012-05-18 07:36:52 -07:00
Jonathan Turner
7027f6b834 Add syntax highlighting for switch/case/default 2012-05-17 13:59:43 -07:00
Jonathan Turner
cebd2c9763 Adding support for switch/case/default to 4.x 2012-05-17 13:56:10 -07:00
Jonathan Turner
b82895c489 Add the 'auto' keyword. 2012-05-17 10:31:55 -07:00
Jonathan Turner
cf97a73485 Syntax updates to a few unit tests. 2012-05-17 10:27:26 -07:00
Jonathan Turner
37b8e6c3f9 Merge branch '2011-09-09-CxScript' of github.com:ChaiScript/ChaiScript into 2011-09-09-CxScript 2012-05-17 10:16:35 -07:00
Jonathan Turner
c73f16fdfe Fixing 4.x grammar to be backward compatible.
Added 3.x unit tests back to show this.
2012-05-17 10:14:50 -07:00
Jason Turner
68df78a2a6 Add examples for using C++ lambdas with chaiscript. #32 2012-05-16 15:55:03 -06:00
Jason Turner
bca86c87e1 Update copyrights to 2012 #23 2012-05-16 11:54:46 -06:00
Jason Turner
a04dbf2c2d Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
	unittests/object_lifetime_test.cpp
	unittests/utility_test.cpp
2012-05-16 11:50:44 -06:00
Jason Turner
4674594ee7 Make libcxx a default option when using clang 2012-05-15 19:30:17 -06:00
Jonathan Turner
1f4900c363 Add support for building with clang/libcxx. 2012-05-15 14:50:56 -07:00
Jason Turner
8e24eef265 Tweaks to clang support and fix for clang/module support 2012-05-15 13:56:59 -06:00
Jason Turner
974c903d1c Get compiling with broken clang++ / libc++ implementation
libc++ will not let you get a pointer to a string member
2012-05-15 13:25:13 -06:00
Jason Turner
9ec78752a0 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/boxed_number.hpp
	samples/example.cpp
2012-05-14 18:20:36 -06:00
Jason Turner
48ecb3e2b4 Some performance improvements by using perfect argument forwarding 2012-05-14 17:45:30 -06:00
Jason Turner
98d2eadde2 Explicitly default the copy assignment operator for clang's benefit 2012-05-14 10:15:38 -06:00
Jason Turner
286b130f47 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	CMakeLists.txt
	include/chaiscript/dispatchkit/boxed_number.hpp
	include/chaiscript/language/chaiscript_engine.hpp
2012-05-14 10:08:04 -06:00
Jason Turner
927619bf47 Switch to using make_sharec 2012-05-14 08:56:33 -06:00
Jason Turner
179a674b00 Fix fix for duplication attribute name errors 2012-01-30 09:16:20 -07:00
Jason Turner
ee4c9575ae Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript 2012-01-30 09:10:55 -07:00
Jason Turner
b615d2a423 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
2012-01-30 09:10:43 -07:00
Jason Turner
dc6998259e Add missing chaiscript_stdlib.hpp file 2012-01-30 09:05:21 -07:00
Jason Turner
136b877afa Reduce cost of including chaiscript.hpp
- ChaiScript no longer includes or automatically instantiates std lib
 - ChaiScript constructor now requires an std lib instance in the form
   of a ModulePtr object
 - This new layout facilitates better usage of compilation firewalls and
   factories for reducing the overall impact of ChaiScript on a project
2011-12-27 21:37:00 -07:00
Jason Turner
9a9d4e1ae0 Remove map_literal_access test, it's invalid as there is no const [] on maps 2011-10-01 11:15:56 -06:00
Jason Turner
27ae40b813 Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript 2011-10-01 11:04:21 -06:00
Jason Turner
5dc0931ca2 Update is_prime analysis for new syntax 2011-10-01 11:03:03 -06:00
Jonathan Turner
5a3975b7a4 Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_parser.hpp
2011-10-01 10:24:48 -06:00
Jonathan Turner
bc75df4d58 Fixed parsing of block statements vs initializer expressions. 2011-10-01 10:19:45 -06:00
Jason Turner
b27aa50d6a Minor cleanups in cv qualification removal 2011-09-26 07:51:32 -06:00
Jason Turner
488f2ea393 C++11 cleanups 2011-09-26 07:14:24 -06:00
Jason Turner
db0e342a96 Remove little used Param_List_Builder 2011-09-25 18:34:02 -06:00
Jason Turner
702b5fdba1 Enhance and correct error messages 2011-09-25 16:46:05 -06:00
Jason Turner
3329732ceb Add scoping test 2011-09-24 15:21:15 -06:00
Jason Turner
e1e0561c7e Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
2011-09-24 15:10:18 -06:00
Jason Turner
52d9e1e871 Remove := operator and fix & usage. 2011-09-24 15:06:31 -06:00
Jason Turner
a28dfd8695 Get & variable declarations working 2011-09-24 14:21:21 -06:00
Jonathan Turner
1eb402e474 Adding an access to a map literal which doesn't seem to be working (though it's vector counterpart does) 2011-09-24 14:14:37 -06:00
Jonathan Turner
3765c23598 Switch lambda syntax over to [](){} format, to line up with C++11. 2011-09-24 13:31:24 -06:00
Jonathan Turner
784ca41270 Switch vectors and maps over to curly braces from square braces to line up with C++11. 2011-09-24 13:15:12 -06:00
Jason Turner
425ca59a34 Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript 2011-09-24 12:32:13 -06:00
Jason Turner
abfd37644e Fix "any" for unknown types 2011-09-24 12:30:43 -06:00
Jonathan Turner
4bf3783d0b Adding new test that is just a var decl. 2011-09-24 12:26:45 -06:00
Jonathan Turner
4a99471304 Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript 2011-09-24 12:26:17 -06:00
Jonathan Turner
e0d7977f8a Adding reference parsing at a var decl. 2011-09-24 12:25:55 -06:00
Jason Turner
92de42e42b Modify "var" to "auto" for unit tests. 2011-09-24 12:05:08 -06:00
Jason Turner
e3350fe55f Merge branch '2011-09-09-CxScript' of https://github.com/ChaiScript/ChaiScript into 2011-09-09-CxScript 2011-09-24 11:55:36 -06:00
Jason Turner
2ca7a7d7da Some C++11 cleaner usage updates 2011-09-24 11:54:40 -06:00
Jonathan Turner
ac4bb95dfb Rename var->auto. 2011-09-24 11:50:17 -06:00
Jason Turner
535adce298 Remove exception specifications in favor of noexcept keyword 2011-09-21 12:22:52 -06:00
Jason Turner
d04960bc4a Update for C++11 features 2011-09-21 10:01:21 -06:00
Jason Turner
12bd5b0af5 Boost eradicated from ChaiScript 2011-09-21 08:36:46 -06:00
Jason Turner
d6b475239a Remove boost from utility and associated module tests 2011-09-21 00:04:15 -06:00
Jason Turner
6f1bffda3a Remove boost from bind_first utility. 2011-09-15 17:38:46 -06:00
Jason Turner
64382a2399 One more file with boost_pp removed 2011-09-13 12:26:20 -06:00
Jason Turner
f996c0df37 One more file no longer using boost_pp 2011-09-13 09:40:10 -06:00
Jason Turner
d5e1650167 First file to eliminate need for boost_pp. 2 more to go 2011-09-12 23:08:27 -06:00
Jason Turner
cc927fc6bc Remove remaining non-boost_pp libraries as requirements. 2011-09-12 11:09:57 -06:00
Jason Turner
6f282b6a56 Remove need for boost::function_types library 2011-09-12 08:18:51 -06:00
Jason Turner
194001f9a1 Remove boost::any requirement by providing our own implementation 2011-09-11 19:51:37 -06:00
Jason Turner
a3c3b8683b Rename variables to reflect removal of boost 2011-09-11 09:22:44 -06:00
Jason Turner
5efdcdff99 Remove need for boost::thread_local_ptr 2011-09-11 09:19:06 -06:00
Jason Turner
cd97880d70 Drop boost::optional requirement 2011-09-11 06:56:15 -06:00
Jason Turner
0a9cb0cbe9 Move to std::threading from boost::thread. Still need to sort out thread local storage 2011-09-10 14:58:59 -06:00
Jason Turner
99aaa079a4 Add missing include for stringstream 2011-09-10 14:58:19 -06:00
Jason Turner
f4080c4c75 Move from boost::mem_fn to std::mem_fn 2011-09-10 14:01:05 -06:00
Jason Turner
4522ff0732 Remove various other boost libraries 2011-09-10 13:49:29 -06:00
Jason Turner
b297162d13 Move from boost::type_traits to std::type_traits 2011-09-10 13:18:29 -06:00
Jason Turner
62cf6293e8 Move from boost::uint* to std::uint* 2011-09-10 12:26:31 -06:00
Jason Turner
6bb2678d18 GO from boost::int64_t to std::int64_t, etc. 2011-09-10 11:10:14 -06:00
Jason Turner
aa402fdfde swap boost::reference_wrapper for std::reference_wrapper 2011-09-10 10:52:59 -06:00
Jason Turner
53108463df Move from boost::bind to std::bind 2011-09-10 10:19:55 -06:00
Jason Turner
c842bf14c1 Move from boost::function to std::function 2011-09-10 09:37:40 -06:00
Jason Turner
e2da56f199 Eliminate use of boost::shared_ptr 2011-09-10 07:24:46 -06:00
Jason Turner
afa96ecbf9 Begin port to C++11 2011-09-10 06:55:27 -06:00
305 changed files with 4183 additions and 3155 deletions

View File

@@ -16,21 +16,19 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 4)
set(CPACK_PACKAGE_VERSION_MINOR 3)
set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 1)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An embedded scripting language for C++")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-dev (>=1.36.0)")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_RPM_PACKAGE_LICENSE "BSD")
set(CPACK_RPM_PACKAGE_GROUP "Programming")
set(CPACK_RPM_PACKAGE_REQUIRES "boost-devel >= 1.36.0, boost-thread >= 1.36.0")
set(CHAI_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
@@ -39,8 +37,16 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest)
include(CPack)
include(cmake/CheckCXX11Features.cmake)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
if(HAS_CXX11_VARIADIC_TEMPLATES)
message(STATUS "Variadic Template support detected")
else()
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
endif()
enable_testing()
@@ -61,79 +67,81 @@ if(MSVC)
add_definitions(/bigobj)
endif()
else()
add_definitions(-Wall -Wextra -Wshadow -pedantic)
add_definitions(-Wall -Wextra -Wshadow -pedantic -std=c++0x)
if (APPLE)
# -Wno-missing-field-initializers is for boost on macos
add_definitions(-Wno-missing-field-initializers -Wno-sign-compare)
add_definitions(-Wno-sign-compare)
endif()
endif()
if (CMAKE_CXX_COMPILER MATCHES ".*clang")
option(USE_LIBCXX "Use clang's libcxx" TRUE)
if (USE_LIBCXX)
add_definitions(-stdlib=libc++)
set (EXTRA_LINKER_FLAGS -std=c++0x -stdlib=libc++)
else ()
set (EXTRA_LINKER_FLAGS -std=c++0x )
endif()
else()
set (EXTRA_LINKER_FLAGS )
endif()
include_directories(include)
set(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
set(Boost_USE_MULTITHREADED ON)
set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
if (MULTITHREAD_SUPPORT_ENABLED)
find_package(Boost 1.36.0 COMPONENTS thread system)
if (Boost_FOUND)
link_directories( ${Boost_LIBRARY_DIRS} )
else()
message(FATAL_ERROR "Can not find Boost")
endif(Boost_FOUND)
if (CMAKE_HOST_UNIX)
add_definitions(-pthread)
list(APPEND LIBS "pthread")
endif()
else()
add_definitions(-DCHAISCRIPT_NO_THREADS)
endif()
if (CMAKE_HOST_UNIX AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
if (CMAKE_HOST_UNIX)
list(APPEND LIBS "dl")
endif()
if (MULTITHREAD_SUPPORT_ENABLED)
list(APPEND LIBS "pthread")
add_definitions(-pthread)
endif()
endif(CMAKE_HOST_UNIX)
list(APPEND LIBS ${READLINE_LIB})
if (NOT MSVC)
# Boost on MSVC does automatic linking
list(APPEND LIBS ${Boost_LIBRARIES})
endif()
if (CMAKE_COMPILER_2005)
# vs2005 is a bit too loud about possible loss of data warnings
# ADD_DEFINITIONS(/wd4244)
endif()
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIR})
add_library(chaiscript_stdlib MODULE src/chaiscript_stdlib.cpp)
target_link_libraries(chaiscript_stdlib ${LIBS} ${EXTRA_LINKER_FLAGS})
add_executable(chai src/main.cpp ${Chai_INCLUDES})
target_link_libraries(chai ${LIBS})
target_link_libraries(chai ${LIBS} ${EXTRA_LINKER_FLAGS})
add_dependencies(chai chaiscript_stdlib)
if (BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
target_link_libraries(example ${LIBS} ${EXTRA_LINKER_FLAGS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS})
target_link_libraries(memory_leak_test ${LIBS} ${EXTRA_LINKER_FLAGS})
endif()
if (BUILD_MODULES)
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS})
target_link_libraries(stl_extra ${LIBS} ${EXTRA_LINKER_FLAGS})
add_library(reflection MODULE src/reflection.cpp)
target_link_libraries(reflection ${LIBS})
target_link_libraries(reflection ${LIBS} ${EXTRA_LINKER_FLAGS})
set(MODULES stl_extra reflection)
endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai)
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
list(SORT UNIT_TESTS)
@@ -143,7 +151,7 @@ if(BUILD_TESTING)
foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach(filename)
endforeach(filename)
set_property(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT
@@ -153,45 +161,49 @@ if(BUILD_TESTING)
if (NOT UNIT_TEST_LIGHT)
add_executable(utility_test unittests/utility_test.cpp)
target_link_libraries(utility_test ${LIBS})
target_link_libraries(utility_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Utility_Test COMMAND utility_test)
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
target_link_libraries(dynamic_object_test ${LIBS})
target_link_libraries(dynamic_object_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
target_link_libraries(functor_creation_test ${LIBS})
target_link_libraries(functor_creation_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
target_link_libraries(functor_cast_test ${LIBS})
target_link_libraries(functor_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
target_link_libraries(boxed_cast_test ${LIBS})
target_link_libraries(boxed_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
target_link_libraries(object_lifetime_test ${LIBS})
target_link_libraries(object_lifetime_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
target_link_libraries(function_ordering_test ${LIBS})
target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
add_executable(type_info_test unittests/type_info_test.cpp)
target_link_libraries(type_info_test ${LIBS})
target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
target_link_libraries(eval_catch_exception_test ${LIBS})
target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
target_link_libraries(short_comparison_test ${LIBS})
target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp)
target_link_libraries(cpp_lambda_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME cpp_lambda_test COMMAND cpp_lambda_test)
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
target_link_libraries(expected_eval_errors_test ${LIBS})
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
@@ -212,10 +224,6 @@ if(BUILD_TESTING)
target_link_libraries(integer_literal_test ${LIBS})
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp)
target_link_libraries(arithmetic_conversions_test ${LIBS})
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test)
if (MULTITHREAD_SUPPORT_ENABLED)
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
target_link_libraries(multithreaded_test ${LIBS})
@@ -231,18 +239,17 @@ if(BUILD_TESTING)
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
unittests/multifile_test_module.cpp)
target_link_libraries(multifile_test ${LIBS})
target_link_libraries(multifile_test ${LIBS} ${EXTRA_LINKER_FLAGS})
add_test(NAME MultiFile_Test COMMAND multifile_test)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
target_link_libraries(test_module ${LIBS} ${EXTRA_LINKER_FLAGS})
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
endif()
endif(BUILD_TESTING)
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
install(DIRECTORY include/chaiscript DESTINATION include
PATTERN "*.hpp"
PATTERN "*/.svn*" EXCLUDE

View File

@@ -0,0 +1,103 @@
# Checks for C++11 features
# CXX11_FEATURE_LIST - a list containing all supported features
# HAS_CXX11_AUTO - auto keyword
# HAS_CXX11_NULLPTR - nullptr
# HAS_CXX11_LAMBDA - lambdas
# HAS_CXX11_STATIC_ASSERT - static_assert()
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
# HAS_CXX11_DECLTYPE - decltype keyword
# HAS_CXX11_CSTDINT_H - cstdint header
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
# HAS_CXX11_CONSTEXPR - constexpr keyword
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
# HAS_CXX11_FUNC - __func__ preprocessor constant
#
# Original script by Rolf Eike Beer
# Modifications by Andreas Weis
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
SET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_CXX_FLAGS "-std=c++0x")
endif()
MACRO(CXX11_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
IF (NOT DEFINED ${RESULT_VAR})
SET(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11/cxx11_${FEATURE_NAME}")
IF (${FEATURE_NUMBER})
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
ELSE (${FEATURE_NUMBER})
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME})
SET(_LOG_NAME "\"${FEATURE_NAME}\"")
ENDIF (${FEATURE_NUMBER})
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME}")
SET(_SRCFILE "${_SRCFILE_BASE}.cpp")
SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
IF (CROSS_COMPILING)
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
ELSE (CROSS_COMPILING)
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
"${_bindir}" "${_SRCFILE}")
IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
SET(${RESULT_VAR} TRUE)
ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
SET(${RESULT_VAR} FALSE)
ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
"${_bindir}_fail" "${_SRCFILE_FAIL}")
IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
SET(${RESULT_VAR} TRUE)
ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
SET(${RESULT_VAR} FALSE)
ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
ENDIF (CROSS_COMPILING)
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
IF (_TMP_RESULT)
SET(${RESULT_VAR} FALSE)
ELSE (_TMP_RESULT)
SET(${RESULT_VAR} TRUE)
ENDIF (_TMP_RESULT)
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
IF (${RESULT_VAR})
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- works")
LIST(APPEND CXX11_FEATURE_LIST ${RESULT_VAR})
ELSE (${RESULT_VAR})
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- not supported")
ENDIF (${RESULT_VAR})
SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
ENDIF (NOT DEFINED ${RESULT_VAR})
ENDMACRO(CXX11_CHECK_FEATURE)
CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)
CXX11_CHECK_FEATURE("nullptr" 2431 HAS_CXX11_NULLPTR)
CXX11_CHECK_FEATURE("lambda" 2927 HAS_CXX11_LAMBDA)
CXX11_CHECK_FEATURE("static_assert" 1720 HAS_CXX11_STATIC_ASSERT)
CXX11_CHECK_FEATURE("rvalue_references" 2118 HAS_CXX11_RVALUE_REFERENCES)
CXX11_CHECK_FEATURE("decltype" 2343 HAS_CXX11_DECLTYPE)
CXX11_CHECK_FEATURE("cstdint" "" HAS_CXX11_CSTDINT_H)
CXX11_CHECK_FEATURE("long_long" 1811 HAS_CXX11_LONG_LONG)
CXX11_CHECK_FEATURE("variadic_templates" 2555 HAS_CXX11_VARIADIC_TEMPLATES)
CXX11_CHECK_FEATURE("constexpr" 2235 HAS_CXX11_CONSTEXPR)
CXX11_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX11_SIZEOF_MEMBER)
CXX11_CHECK_FEATURE("__func__" 2340 HAS_CXX11_FUNC)
SET(CXX11_FEATURE_LIST ${CXX11_FEATURE_LIST} CACHE STRING "C++11 feature support list")
MARK_AS_ADVANCED(FORCE CXX11_FEATURE_LIST)
SET(CMAKE_CXX_FLAGS ${CHECK_CXX11_OLD_CMAKE_CXX_FLAGS})
UNSET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS)

View File

@@ -0,0 +1,8 @@
#include <cstring>
int main()
{
if (!__func__) { return 1; }
if(std::strlen(__func__) <= 0) { return 1; }
return 0;
}

View File

@@ -0,0 +1,12 @@
int main()
{
auto i = 5;
auto f = 3.14159f;
auto d = 3.14159;
bool ret = (
(sizeof(f) < sizeof(d)) &&
(sizeof(i) == sizeof(int))
);
return ret ? 0 : 1;
}

View File

@@ -0,0 +1,19 @@
constexpr int square(int x)
{
return x*x;
}
constexpr int the_answer()
{
return 42;
}
int main()
{
int test_arr[square(3)];
bool ret = (
(square(the_answer()) == 1764) &&
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
);
return ret ? 0 : 1;
}

View File

@@ -0,0 +1,10 @@
#include <cstdint>
int main()
{
bool test =
(sizeof(int8_t) == 1) &&
(sizeof(int16_t) == 2) &&
(sizeof(int32_t) == 4) &&
(sizeof(int64_t) == 8);
return test ? 0 : 1;
}

View File

@@ -0,0 +1,11 @@
bool check_size(int i)
{
return sizeof(int) == sizeof(decltype(i));
}
int main()
{
bool ret = check_size(42);
return ret ? 0 : 1;
}

View File

@@ -0,0 +1,5 @@
int main()
{
int ret = 0;
return ([&ret]() -> int { return ret; })();
}

View File

@@ -0,0 +1,7 @@
int main(void)
{
long long l;
unsigned long long ul;
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
}

View File

@@ -0,0 +1,5 @@
int main()
{
int* test = nullptr;
return test ? 1 : 0;
}

View File

@@ -0,0 +1,5 @@
int main()
{
int i = nullptr;
return 1;
}

View File

@@ -0,0 +1,15 @@
int foo(int& lvalue)
{
return 123;
}
int foo(int&& rvalue)
{
return 321;
}
int main()
{
int i = 42;
return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1;
}

View File

@@ -0,0 +1,14 @@
struct foo {
char bar;
int baz;
};
int main(void)
{
bool ret = (
(sizeof(foo::bar) == 1) &&
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
(sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz))
);
return ret ? 0 : 1;
}

View File

@@ -0,0 +1,5 @@
int main()
{
static_assert(0 < 1, "your ordering of integers is screwed");
return 0;
}

View File

@@ -0,0 +1,5 @@
int main()
{
static_assert(1 < 0, "this should fail");
return 0;
}

View File

@@ -0,0 +1,23 @@
int Accumulate()
{
return 0;
}
template<typename T, typename... Ts>
int Accumulate(T v, Ts... vs)
{
return v + Accumulate(vs...);
}
template<int... Is>
int CountElements()
{
return sizeof...(Is);
}
int main()
{
int acc = Accumulate(1, 2, 3, 4, -5);
int count = CountElements<1,2,3,4,5>();
return ((acc == 5) && (count == 5)) ? 0 : 1;
}

View File

@@ -50,7 +50,7 @@ function run_test
# Run multithreaded tests
echo "****Building multithreaded test"
pushd src
g++ multithreaded.cpp -lboost_thread-mt -ldl -omultithreaded -I../include -O3
g++ multithreaded.cpp -ldl -omultithreaded -I../include -O3
echo "****Testing 1 thread runtime"
/usr/bin/time -p ./multithreaded 1 2> ../../r$1-1threadruntime.out
echo "****Testing 2 thread runtime"

View File

@@ -1,10 +0,0 @@
var my_array=["1", 4, 6.6l, 10ul, "1000", 100, 10.9f ];
for (var j = 0; j < 10000; ++j)
{
for (var i = 0; i < 6; ++i)
{
to_string(my_array[i]);
}
}

View File

@@ -1,6 +1,6 @@
def isprime(n)
{
for (var i = 2; i < n; ++i)
for (auto i = 2; i < n; ++i)
{
if (n % i == 0) {return false}
}
@@ -11,8 +11,8 @@ def isprime(n)
def primes(n)
{
var count = 0
for (var i = 2; i <= n; ++i)
auto count = 0
for (auto i = 2; i <= n; ++i)
{
if (isprime(i)) {++count}
}
@@ -21,5 +21,6 @@ def primes(n)
}
var N = 5000
auto N = 5000
print("primes: " + primes(N).to_string())

View File

@@ -51,7 +51,7 @@ $language_data = array (
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally', 'case', 'switch', 'default',
),
2 => array(
'def', 'false', 'fun', 'true', 'var', 'attr',
'def', 'false', 'fun', 'true', 'var', 'auto', 'attr',
),
3 => array(
// built in functions

View File

@@ -52,7 +52,7 @@ syn keyword chaiscriptExceptions try catch throw
syn keyword chaiscriptKeyword def true false attr
"Built in types
syn keyword chaiscriptType fun var
syn keyword chaiscriptType fun var auto
"Built in funcs, keep it simple
syn keyword chaiscriptFunc eval throw

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_
@@ -74,16 +74,16 @@
/// <hr>
/// \subsection compiling Compiling ChaiScript Applications
///
/// ChaiScript is a header only library with only two dependecies. boost::threads (optional) and the
/// ChaiScript is a header only library with only one dependecy: The
/// operating system provided dynamic library loader, which has to be specified on some platforms.
///
/// \subsubsection compilinggcc Compiling with GCC
///
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
/// both boost::threads and the dynamic loader. For example:
/// the dynamic loader. For example:
///
/// \code
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -lboost_threads
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
/// \endcode
///
/// Alternatively, you may compile without threading support.
@@ -248,7 +248,9 @@
///
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
/// {
/// return t_lhs + boost::lexical_cast<std::string>(t_rhs);
/// std::stringstream ss;
/// ss << t_lhs << t_rhs;
/// return ss.str();
/// }
///
/// chai.add(fun(append_string_int), "+");
@@ -300,8 +302,8 @@
/// <hr>
/// \subsection pointerconversions Pointer / Object Conversions
///
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, boost::shared_ptr<T>,
/// boost::shared_ptr<const T>, boost::reference_wrapper<T>, boost::reference_wrapper<const T> and value types automatically.
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
///
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
/// Const may be added, but never removed.
@@ -314,12 +316,12 @@
/// void fun3(int);
/// void fun4(int &);
/// void fun5(const int &);
/// void fun5(boost::shared_ptr<int>);
/// void fun6(boost::shared_ptr<const int>);
/// void fun7(const boost::shared_ptr<int> &);
/// void fun8(const boost::shared_ptr<const int> &);
/// void fun9(boost::reference_wrapper<int>);
/// void fun10(boost::reference_wrapper<const int>);
/// void fun5(std::shared_ptr<int>);
/// void fun6(std::shared_ptr<const int>);
/// void fun7(const std::shared_ptr<int> &);
/// void fun8(const std::shared_ptr<const int> &);
/// void fun9(std::reference_wrapper<int>);
/// void fun10(std::reference_wrapper<const int>);
///
/// int main()
/// {
@@ -380,10 +382,10 @@
/// \subsection functionobjects Function Objects
///
/// Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion
/// between ChaiScript functions and boost::function objects.
/// between ChaiScript functions and std::function objects.
///
/// \code
/// void callafunc(const boost::function<void (const std::string &)> &t_func)
/// void callafunc(const std::function<void (const std::string &)> &t_func)
/// {
/// t_func("bob");
/// }
@@ -393,9 +395,9 @@
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::fun(&callafunc), "callafunc");
/// chai("callafunc(fun(x) { print(x); })"); // pass a lambda function to the registered function
/// // which expects a typed boost::function
/// // which expects a typed std::function
///
/// boost::function<void ()> f = chai.eval<boost::function<void ()> >("dump_system");
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
/// f(); // call the ChaiScript function dump_system, from C++
/// }
/// \endcode
@@ -410,7 +412,7 @@
///
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
///
/// Disabling thread safety increases performance and removes the requirement for boost_threads.
/// Disabling thread safety increases performance in many cases.
///
/// <hr>
///
@@ -746,20 +748,16 @@
/// \namespace chaiscript::detail
/// \brief Classes and functions reserved for internal use. Items in this namespace are not supported.
#include "chaiscript_defines.hpp"
#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/function_call.hpp"
#include "dispatchkit/dynamic_object.hpp"
#include "dispatchkit/boxed_number.hpp"
#ifdef BOOST_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
#else
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#include "language/chaiscript_eval.hpp"
#include "language/chaiscript_engine.hpp"
#endif /* CHAISCRIPT_HPP_ */

View File

@@ -0,0 +1,28 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DEFINES_HPP_
#define CHAISCRIPT_DEFINES_HPP_
#ifdef _MSC_VER
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEc
#endif
#ifdef _WIN32
#define CHAISCRIPT_WINDOWS
#endif
#ifdef CHAISCRIPT_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
#else
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#endif

View File

@@ -0,0 +1,44 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_STDLIB_HPP_
#define CHAISCRIPT_STDLIB_HPP_
#include "chaiscript_defines.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
/// \file
///
/// This file generates the standard library that normal ChaiScript usage requires.
namespace chaiscript
{
class Std_Lib
{
public:
static ModulePtr library()
{
using namespace bootstrap;
ModulePtr lib = Bootstrap::bootstrap();
lib->add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
lib->add(standard_library::string_type<std::string>("string"));
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
return lib;
}
};
}
#endif

View File

@@ -1,23 +1,17 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_
#define CHAISCRIPT_THREADING_HPP_
#ifndef CHAISCRIPT_NO_THREADS
#include <unordered_map>
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++11-long-long"
#pragma clang diagnostic ignored "-Wshadow"
#endif
#include <boost/thread.hpp>
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifndef CHAISCRIPT_NO_THREADS
#include <thread>
#include <mutex>
#else
#pragma message ("ChaiScript is compiling without thread safety.")
#endif
@@ -34,48 +28,92 @@ namespace chaiscript
{
namespace detail
{
/// If threading is enabled, then this namespace contains boost::thread classes.
/// If threading is enabled, then this namespace contains std thread classes.
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
/// This allows us to avoid \#ifdef code in the sections that need thread safety.
namespace threading
{
#ifndef CHAISCRIPT_NO_THREADS
using boost::unique_lock;
using boost::shared_lock;
using boost::lock_guard;
using boost::shared_mutex;
using boost::recursive_mutex;
template<typename T>
class unique_lock : public std::unique_lock<T>
{
public:
unique_lock(T &t) : std::unique_lock<T>(t) {}
};
template<typename T>
class shared_lock : public std::unique_lock<T>
{
public:
shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
template<typename T>
class lock_guard : public std::lock_guard<T>
{
public:
lock_guard(T &t) : std::lock_guard<T>(t) {}
};
class shared_mutex : public std::mutex { };
using std::mutex;
using std::recursive_mutex;
/// Typesafe thread specific storage. If threading is enabled, this class uses boost::thread_specific_ptr<T>. If
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// \todo move to thread_local when it exists
template<typename T>
class Thread_Storage
{
public:
~Thread_Storage()
{
m_thread_storage.reset();
}
inline T *operator->() const
{
if (!m_thread_storage.get())
{
m_thread_storage.reset(new T());
}
return m_thread_storage.get();
return get_tls().get();
}
inline T &operator*() const
{
return *(this->operator->());
return *get_tls();
}
private:
mutable boost::thread_specific_ptr<T> m_thread_storage;
std::shared_ptr<T> get_tls() const
{
unique_lock<mutex> lock(m_mutex);
auto itr = m_instances.find(std::this_thread::get_id());
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(new T());
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
return new_instance;
/*
static __thread std::shared_ptr<T> *m_data = 0;
if (!m_data) { m_data = new std::shared_ptr<T>(new T()); }
return *m_data;
*/
}
mutable mutex m_mutex;
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
};
#else
@@ -84,8 +122,6 @@ namespace chaiscript
{
public:
unique_lock(T &) {}
void lock() {}
void unlock() {}
};
template<typename T>
@@ -93,7 +129,6 @@ namespace chaiscript
{
public:
shared_lock(T &) {}
void lock() {}
void unlock() {}
};

View File

@@ -0,0 +1,162 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ANY_HPP_
#define CHAISCRIPT_ANY_HPP_
namespace chaiscript {
namespace detail {
namespace exception
{
/// \brief Thrown in the event that an Any cannot be cast to the desired type
///
/// It is used internally during function dispatch.
///
/// \sa chaiscript::detail::Any
class bad_any_cast : public std::bad_cast
{
public:
bad_any_cast() noexcept
: m_what("bad any cast")
{
}
virtual ~bad_any_cast() noexcept {}
/// \brief Description of what error occured
virtual const char * what() const noexcept
{
return m_what.c_str();
}
private:
std::string m_what;
};
}
class Any {
private:
struct Data
{
virtual void *data() = 0;
virtual const std::type_info &type() const = 0;
virtual std::shared_ptr<Data> clone() const = 0;
};
template<typename T>
struct Data_Impl : Data
{
Data_Impl(const T &t_type)
: m_type(typeid(T)),
m_data(t_type)
{
}
virtual void *data()
{
return &m_data;
}
const std::type_info &type() const
{
return m_type;
}
std::shared_ptr<Data> clone() const
{
return std::shared_ptr<Data>(new Data_Impl<T>(m_data));
}
const std::type_info &m_type;
T m_data;
};
std::shared_ptr<Data> m_data;
public:
// construct/copy/destruct
Any() = default;
Any(const Any &t_any)
{
if (!t_any.empty())
{
m_data = t_any.m_data->clone();
} else {
m_data.reset();
}
}
template<typename ValueType>
Any(const ValueType &t_value)
{
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
}
Any & operator=(const Any &t_any)
{
Any copy(t_any);
swap(copy);
return *this;
}
template<typename ValueType>
Any & operator=(const ValueType &t_value)
{
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
return *this;
}
template<typename ToType>
ToType &cast() const
{
if (m_data && typeid(ToType) == m_data->type())
{
return *static_cast<ToType *>(m_data->data());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
~Any()
{
}
// modifiers
Any & swap(Any &t_other)
{
std::shared_ptr<Data> data = t_other.m_data;
t_other.m_data = m_data;
m_data = data;
return *this;
}
// queries
bool empty() const
{
return !bool(m_data);
}
const std::type_info & type() const
{
if (m_data)
{
return m_data->type();
} else {
return typeid(void);
}
}
};
}
}
#endif

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
@@ -22,25 +22,25 @@ namespace chaiscript
{
public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) throw()
const std::string &t_what) noexcept
: from(t_from), to(&t_to), m_what(t_what)
{
}
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
{
}
bad_boxed_cast(const std::string &t_what) throw()
bad_boxed_cast(const std::string &t_what) noexcept
: to(0), m_what(t_what)
{
}
virtual ~bad_boxed_cast() throw() {}
virtual ~bad_boxed_cast() noexcept {}
/// \brief Description of what error occured
virtual const char * what() const throw()
virtual const char * what() const noexcept
{
return m_what.c_str();
}

View File

@@ -1,94 +1,133 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#define param(z,n,text) BOOST_PP_CAT(text, BOOST_PP_INC(n))
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
#define CHAISCRIPT_BIND_FIRST_HPP_
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#define BOOST_PP_ITERATION_LIMITS ( 0, 8 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/bind_first.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
# define m BOOST_PP_INC(n)
#include <functional>
namespace chaiscript
{
namespace detail
{
/// \brief Helper function for binding the first parameter of a class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
{
template<int>
struct Placeholder
{
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
};
template<>
struct Placeholder<1>
{
static decltype(std::placeholders::_1) value() { return std::placeholders::_1; }
};
template<>
struct Placeholder<2>
{
static decltype(std::placeholders::_2) value() { return std::placeholders::_2; }
};
template<>
struct Placeholder<3>
{
static decltype(std::placeholders::_3) value() { return std::placeholders::_3; }
};
template<>
struct Placeholder<4>
{
static decltype(std::placeholders::_4) value() { return std::placeholders::_4; }
};
template<>
struct Placeholder<5>
{
static decltype(std::placeholders::_5) value() { return std::placeholders::_5; }
};
template<>
struct Placeholder<6>
{
static decltype(std::placeholders::_6) value() { return std::placeholders::_6; }
};
template<>
struct Placeholder<7>
{
static decltype(std::placeholders::_7) value() { return std::placeholders::_7; }
};
template<>
struct Placeholder<8>
{
static decltype(std::placeholders::_8) value() { return std::placeholders::_8; }
};
template<>
struct Placeholder<9>
{
static decltype(std::placeholders::_9) value() { return std::placeholders::_9; }
};
template<>
struct Placeholder<10>
{
static decltype(std::placeholders::_10) value() { return std::placeholders::_10; }
};
template<int count, int maxcount, typename Sig>
struct Bind_First
{
template<typename F, typename ... InnerParams>
static std::function<Sig> bind(F f, InnerParams ... innerparams)
{
return Bind_First<count - 1, maxcount, Sig>::bind(f, innerparams..., Placeholder<maxcount - count + 1>::value());
}
};
template<int maxcount, typename Sig>
struct Bind_First<0, maxcount, Sig>
{
template<typename F, typename ... InnerParams>
static std::function<Sig> bind(F f, InnerParams ... innerparams)
{
return std::bind(f, innerparams...);
}
};
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
}
/// \brief Helper function for binding the first parameter of a const class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)) const, const O &o)
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
{
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
}
/// \brief Helper function for binding the first parameter of a function pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O o)
{
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
}
/// \brief Helper function for binding the first parameter of a boost::function object. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O o)
{
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
}
}
}
#undef n
#undef m
#undef param
#endif

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
@@ -12,8 +12,8 @@
#include "register_function.hpp"
#include "operators.hpp"
#include "boxed_number.hpp"
#include <boost/function_types/result_type.hpp>
#include <sstream>
#include <type_traits>
namespace chaiscript
{
@@ -26,9 +26,9 @@ namespace chaiscript
/// \param[in] v Boxed_Number to copy into the new object
/// \returns The newly created object.
template<typename P1>
boost::shared_ptr<P1> construct_pod(Boxed_Number v)
std::shared_ptr<P1> construct_pod(Boxed_Number v)
{
boost::shared_ptr<P1> p(new P1());
std::shared_ptr<P1> p(new P1());
Boxed_Value bv(p);
Boxed_Number nb(bv);
nb = v;
@@ -97,29 +97,25 @@ namespace chaiscript
* to_string function for internal use. Uses ostream operator<<
*/
template<typename Input>
std::string to_string(Input i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
std::string to_string(Input i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
/**
* Internal function for converting from a string to a value
* uses ostream operator >> to perform the conversion
*/
template<typename Input>
Input parse_string(const std::string &i)
{
std::stringstream ss(i);
Input t;
ss >> t;
return t;
}
Input parse_string(const std::string &i)
{
std::stringstream ss(i);
Input t;
ss >> t;
return t;
}
/**
@@ -147,7 +143,7 @@ namespace chaiscript
* function variables.
*/
template<typename Type>
boost::shared_ptr<Type> shared_ptr_clone(const boost::shared_ptr<Type> &p)
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
{
return p;
}
@@ -156,10 +152,10 @@ namespace chaiscript
* Specific version of shared_ptr_clone just for Proxy_Functions
*/
template<typename Type>
boost::shared_ptr<typename boost::remove_const<Type>::type>
shared_ptr_unconst_clone(const boost::shared_ptr<typename boost::add_const<Type>::type> &p)
std::shared_ptr<typename std::remove_const<Type>::type>
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
{
return boost::const_pointer_cast<typename boost::remove_const<Type>::type>(p);
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
}
@@ -170,7 +166,7 @@ namespace chaiscript
* Similar to shared_ptr_clone. Used for Proxy_Function.
*/
template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<Type> &rhs)
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
{
if (lhs.is_undef()
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
@@ -273,17 +269,28 @@ namespace chaiscript
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
}
/**
* Returns true if a call can be made that consists of the first parameter
* (the function) with the remaining parameters as its arguments.
*/
static Boxed_Value call_exists(const std::vector<Boxed_Value> &params)
{
if (params.size() < 1)
{
throw exception::arity_error(static_cast<int>(params.size()), 1);
}
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
}
static bool has_guard(const Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_guard()) {
return true;
} else {
return false;
}
return bool(pf->get_guard());
} else {
return false;
}
@@ -291,7 +298,7 @@ namespace chaiscript
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_guard())
@@ -309,7 +316,9 @@ namespace chaiscript
throw bv;
}
static boost::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(boost::shared_ptr<chaiscript::detail::Dispatch_Engine> e = boost::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
static std::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(
std::shared_ptr<chaiscript::detail::Dispatch_Engine> e
= std::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
{
e->add(user_type<void>(), "void");
return e;
@@ -337,24 +346,22 @@ namespace chaiscript
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
const dispatch::Proxy_Function_Base *b)
{
typedef typename boost::function_types::result_type<FunctionType>::type Vector;
Vector v = (b->*f)();
auto v = (b->*f)();
std::vector<Boxed_Value> vbv;
for (typename Vector::const_iterator itr = v.begin();
itr != v.end();
++itr)
for (const auto &o: v)
{
vbv.push_back(const_var(*itr));
vbv.push_back(const_var(o));
}
return vbv;
}
template<typename Function>
static boost::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
{
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1);
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
}
public:
@@ -372,6 +379,7 @@ namespace chaiscript
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
@@ -384,7 +392,7 @@ namespace chaiscript
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
@@ -392,7 +400,7 @@ namespace chaiscript
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::get_attr), "get_attr");
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
m->eval("def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard");
@@ -440,14 +448,14 @@ namespace chaiscript
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<boost::int8_t>("int8_t", m);
bootstrap_pod_type<boost::int16_t>("int16_t", m);
bootstrap_pod_type<boost::int32_t>("int32_t", m);
bootstrap_pod_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<boost::uint8_t>("uint8_t", m);
bootstrap_pod_type<boost::uint16_t>("uint16_t", m);
bootstrap_pod_type<boost::uint32_t>("uint32_t", m);
bootstrap_pod_type<boost::uint64_t>("uint64_t", m);
bootstrap_pod_type<std::int8_t>("int8_t", m);
bootstrap_pod_type<std::int16_t>("int16_t", m);
bootstrap_pod_type<std::int32_t>("int32_t", m);
bootstrap_pod_type<std::int64_t>("int64_t", m);
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m);
@@ -457,14 +465,17 @@ namespace chaiscript
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))),
"bind");
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&type_match), "type_match");
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&call_exists, std::placeholders::_1))),
"call_exists");
m->add(fun(&Boxed_Value::type_match), "type_match");
return m;
}

View File

@@ -1,19 +1,23 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
/// \file
/// This file contains utility functions for registration of STL container
/// classes. The methodology used is based on the SGI STL concepts.
/// http://www.sgi.com/tech/stl/table_of_contents.html
/**
* \file
* This file contains utility functions for registration of STL container
* classes. The methodology used is based on the SGI STL concepts.
* http://www.sgi.com/tech/stl/table_of_contents.html
*/
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
#include "dispatchkit.hpp"
#include "bootstrap.hpp"
#include "register_function.hpp"
namespace chaiscript
@@ -22,10 +26,11 @@ namespace chaiscript
{
namespace standard_library
{
/// Bidir_Range, based on the D concept of ranges.
/// \todo Update the Range code to base its capabilities on
/// the user_typetraits of the iterator passed in
/**
* Bidir_Range, based on the D concept of ranges.
* \todo Update the Range code to base its capabilities on
* the user_typetraits of the iterator passed in
*/
template<typename Container>
struct Bidir_Range
{
@@ -143,88 +148,6 @@ namespace chaiscript
};
namespace detail {
template<typename T>
int return_int_impl(const boost::function<typename T::size_type (const T *)> &t_func, const T *t_obj)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T>
boost::function<int (const T *)> return_int(size_t (T::*t_func)() const)
{
return boost::bind(&return_int_impl<T>, boost::function<size_t (const T *)>(boost::mem_fn(t_func)), _1);
}
template<typename T, typename P1>
int return_int_impl(const boost::function<typename T::size_type (const T *, P1)> &t_func, const T *t_obj, P1 p1)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T, typename P1>
int return_int_impl_non_const(const boost::function<typename T::size_type (T *, P1)> &t_func, T *t_obj, P1 p1)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T, typename P1>
boost::function<int (const T *, P1)> return_int(size_t (T::*t_func)(P1) const)
{
return boost::bind(&return_int_impl<T, P1>, boost::function<size_t (const T *, P1)>(boost::mem_fn(t_func)), _1, _2);
}
template<typename T, typename P1>
boost::function<int (T *, P1)> return_int(size_t (T::*t_func)(P1) )
{
return boost::bind(&return_int_impl_non_const<T, P1>, boost::function<size_t (T*, P1)>(boost::mem_fn(t_func)), _1, _2);
}
template<typename T, typename P1, typename P2>
int return_int_impl(const boost::function<typename T::size_type (const T *, P1, P2)> &t_func, const T *t_obj, P1 p1, P2 p2)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1, p2);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename StringType, StringType (StringType::*Func)(typename StringType::size_type, typename StringType::size_type) const >
StringType substr_helper(const StringType &str, int begin, int end)
{
return (str.*Func)(begin, end);
}
template<typename T, typename P1, typename P2>
boost::function<int (const T *, P1, P2)> return_int(size_t (T::*t_func)(P1, P2) const)
{
return boost::bind(&return_int_impl<T, P1, P2>, boost::function<size_t (const T *, P1, P2)>(boost::mem_fn(t_func)), _1, _2, _3);
}
template<typename T>
void insert(T &t_target, const T &t_other)
@@ -240,9 +163,9 @@ namespace chaiscript
/// Add Bidir_Range support for the given ContainerType
/**
* Add Bidir_Range support for the given ContainerType
*/
template<typename Bidir_Type>
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -261,8 +184,9 @@ namespace chaiscript
return m;
}
/// Algorithm for inserting at a specific position into a container
/**
* Algorithm for inserting at a specific position into a container
*/
template<typename Type>
void insert_at(Type &container, int pos, const typename Type::value_type &v)
{
@@ -278,8 +202,9 @@ namespace chaiscript
container.insert(itr, v);
}
/// Algorithm for erasing a specific position from a container
/**
* Algorithm for erasing a specific position from a container
*/
template<typename Type>
void erase_at(Type &container, int pos)
{
@@ -305,9 +230,10 @@ namespace chaiscript
return m;
}
/// Add random_access_container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
/**
* Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
@@ -317,18 +243,19 @@ namespace chaiscript
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
//to throw an exception in an out of bounds condition.
m->add(
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>
(boost::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
m->add(
fun(boost::function<typename ContainerType::const_reference (const ContainerType *, int)>
(boost::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
fun(std::function<typename ContainerType::const_reference (const ContainerType *, int)>
(std::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
return m;
}
/// Add assignable concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Assignable.html
/**
* Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -337,22 +264,23 @@ namespace chaiscript
return m;
}
/// Add container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Container.html
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
m->add(fun(f), "size");
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
m->add(fun( std::function<int (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
return m;
}
/// Add default constructable concept to the given Type
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -362,9 +290,10 @@ namespace chaiscript
/// Add sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Sequence.html
/**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
@@ -382,9 +311,10 @@ namespace chaiscript
return m;
}
/// Add back insertion sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
/**
* Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
@@ -407,9 +337,10 @@ namespace chaiscript
}
/// Front insertion sequence
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
/**
*Front insertion sequence
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
{
@@ -432,9 +363,10 @@ namespace chaiscript
return m;
}
/// bootstrap a given PairType
/// http://www.sgi.com/tech/stl/pair.html
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -454,10 +386,10 @@ namespace chaiscript
}
/// Add pair associative container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
/**
* Add pair associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -466,19 +398,18 @@ namespace chaiscript
return m;
}
/// Add unique associative container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
/**
* Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(&ContainerType::count))), "count");
m->add(fun<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count), "count");
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
typedef size_t (ContainerType::*erase)(const typename ContainerType::key_type &);
erase eraseptr(&ContainerType::erase);
m->add(fun(boost::function<int (ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(eraseptr))), "erase");
m->add(fun<int (ContainerType *, const typename ContainerType::key_type &)>(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
m->add(fun(&detail::insert<ContainerType>), "insert");
@@ -494,9 +425,10 @@ namespace chaiscript
return m;
}
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
/**
* Add a MapType container
* http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -515,9 +447,10 @@ namespace chaiscript
return m;
}
/// hopefully working List type
/// http://www.sgi.com/tech/stl/List.html
/**
* hopefully working List type
* http://www.sgi.com/tech/stl/List.html
*/
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -534,9 +467,10 @@ namespace chaiscript
return m;
}
/// Create a vector type with associated concepts
/// http://www.sgi.com/tech/stl/Vector.html
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -560,8 +494,8 @@ namespace chaiscript
if ( rhs.size() != this.size() ) { \
return false; \
} else { \
var r1 = range(this); \
var r2 = range(rhs); \
auto r1 = range(this); \
auto r2 = range(rhs); \
while (!r1.empty()) \
{ \
if (!eq(r1.front(), r2.front())) \
@@ -579,34 +513,10 @@ namespace chaiscript
return m;
}
namespace detail {
template<typename String>
struct apple_string_workarounds
{
/// The latest version of MacOS has a broken std::string implementation which will not allow
/// us to take pointers to the members. Code compiles, but does not link
/// \todo re-evaluate at some point
static size_t find(const String *s, const String &w, int pos) { return s->find(w, pos); }
static size_t rfind(const String *s, const String &w, size_t pos) { return s->rfind(w, pos); }
static size_t find_first_of(const String *s, const String &w, size_t pos) { return s->find_first_of(w, pos); }
static size_t find_last_of(const String *s, const String &w, size_t pos) { return s->find_last_of(w, pos); }
static size_t find_first_not_of(const String *s, const String &w, size_t pos) { return s->find_first_not_of(w, pos); }
static size_t find_last_not_of(const String *s, const String &w, size_t pos) { return s->find_last_not_of(w, pos); }
static void clear(String *s) { s->clear(); }
static bool empty(const String *s) { return s->empty(); }
static size_t size(const String *s) { return s->size(); }
static std::string substr(const String *s, size_t pos, size_t len) { return s->substr(pos,len); }
static const char *c_str(const String *s) { return s->c_str(); }
static const char *data(const String *s) { return s->data(); }
};
}
/// Add a String container
/// http://www.sgi.com/tech/stl/basic_string.html
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -617,7 +527,7 @@ namespace chaiscript
random_access_container_type<String>(type, m);
sequence_type<String>(type, m);
default_constructible_type<String>(type, m);
// container_type<String>(type, m);
container_type<String>(type, m);
assignable_type<String>(type, m);
input_range_type<String>(type, m);
@@ -631,21 +541,20 @@ namespace chaiscript
}
m->add(fun(&String::push_back), push_back_name);
m->add(fun(&detail::apple_string_workarounds<String>::find), "find");
m->add(fun(&detail::apple_string_workarounds<String>::rfind), "rfind");
m->add(fun(&detail::apple_string_workarounds<String>::find_first_of), "find_first_of");
m->add(fun(&detail::apple_string_workarounds<String>::find_last_of), "find_last_of");
m->add(fun(&detail::apple_string_workarounds<String>::find_first_not_of), "find_first_not_of");
m->add(fun(&detail::apple_string_workarounds<String>::find_last_not_of), "find_last_not_of");
m->add(fun(&detail::apple_string_workarounds<String>::clear), "clear");
m->add(fun(&detail::apple_string_workarounds<String>::size), "size");
m->add(fun(&detail::apple_string_workarounds<String>::empty), "empty");
m->add(fun(&detail::apple_string_workarounds<String>::substr), "substr");
m->add(fun(&detail::apple_string_workarounds<String>::c_str), "c_str");
m->add(fun(&detail::apple_string_workarounds<String>::data), "data");
typedef std::function<int (const String *, const String &, int)> find_func;
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find(f, pos); } )), "find");
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->rfind(f, pos); } ) ), "rfind");
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_first_of(f, pos); } ) ), "find_first_of");
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_last_of(f, pos); } ) ), "find_last_of");
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of");
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->c_str(); } ) ), "c_str");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->data(); } ) ), "data");
m->add(fun( std::function<String (const String *, int, int)>( [](const String *s, int pos, int len) { return s->substr(pos, len); } ) ), "substr");
return m;
}
}

View File

@@ -1,26 +1,20 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
#define CHAISCRIPT_BOXED_CAST_HPP_
#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 <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/integer_traits.hpp>
namespace chaiscript
{
@@ -31,63 +25,64 @@ namespace chaiscript
/// \returns Type equivalent to the requested type
/// \throws exception::bad_boxed_cast If the requested conversion is not possible
///
/// boxed_cast will attempt to make conversions between value, &, *, boost::shared_ptr, boost::reference_wrapper,
/// and boost::function (const and non-const) where possible. boxed_cast is used internally during function
/// boxed_cast will attempt to make conversions between value, &, *, std::shared_ptr, std::reference_wrapper,
/// and std::function (const and non-const) where possible. boxed_cast is used internally during function
/// dispatch. This means that all of these conversions will be attempted automatically for you during
/// ChaiScript function calls.
///
/// \li non-const values can be extracted as const or non-const
/// \li const values can be extracted only as const
/// \li Boxed_Value constructed from pointer or boost::reference_wrapper can be extracted as reference,
/// \li Boxed_Value constructed from pointer or std::reference_wrapper can be extracted as reference,
/// pointer or value types
/// \li Boxed_Value constructed from boost::shared_ptr or value types can be extracted as reference,
/// pointer, value, or boost::shared_ptr types
/// \li Boxed_Value constructed from std::shared_ptr or value types can be extracted as reference,
/// pointer, value, or std::shared_ptr types
///
/// Conversions to boost::function objects are attempted as well
/// Conversions to std::function objects are attempted as well
///
/// Example:
/// \code
/// // All of the following should succeed
/// chaiscript::Boxed_Value bv(1);
/// boost::shared_ptr<int> spi = chaiscript::boxed_cast<boost::shared_ptr<int> >(bv);
/// std::shared_ptr<int> spi = chaiscript::boxed_cast<std::shared_ptr<int> >(bv);
/// int i = chaiscript::boxed_cast<int>(bv);
/// int *ip = chaiscript::boxed_cast<int *>(bv);
/// int &ir = chaiscript::boxed_cast<int &>(bv);
/// boost::shared_ptr<const int> cspi = chaiscript::boxed_cast<boost::shared_ptr<const int> >(bv);
/// std::shared_ptr<const int> cspi = chaiscript::boxed_cast<std::shared_ptr<const int> >(bv);
/// const int ci = chaiscript::boxed_cast<const int>(bv);
/// const int *cip = chaiscript::boxed_cast<const int *>(bv);
/// const int &cir = chaiscript::boxed_cast<const int &>(bv);
/// \endcode
///
/// boost::function conversion example
/// std::function conversion example
/// \code
/// chaiscript::ChaiScript chai;
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
/// boost::function<int (int, int)> f = chaiscript::boxed_cast<boost::function<int (int, int)> >(bv);
/// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
/// int i = f(2,3);
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions = 0)
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
{
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const boost::bad_any_cast &) {
return detail::Cast_Helper<Type>::cast(bv);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
//Thank you MSVC, yes we know that a constant value is being used in the if
// statment in THIS VERSION of the template instantiation
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
{
try {
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
} catch (const boost::bad_any_cast &) {
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv));
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
} else {
@@ -96,7 +91,7 @@ namespace chaiscript
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
@@ -10,15 +10,9 @@
#include "type_info.hpp"
#include "boxed_value.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/ref.hpp>
#include <boost/type_traits/add_const.hpp>
namespace chaiscript
{
class Dynamic_Cast_Conversions;
namespace detail
{
// Cast_Helper_Inner helper classes
@@ -29,24 +23,24 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner
{
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().is_const())
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
} else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
return ob.get().cast<std::reference_wrapper<const Result> >();
}
} else {
if (!ob.get_type_info().is_const())
{
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<const Result> >(ob.get())));
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
}
}
}
@@ -73,22 +67,22 @@ namespace chaiscript
{
typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().is_const())
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else {
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
}
} else {
if (!ob.get_type_info().is_const())
{
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
return (ob.get().cast<std::shared_ptr<Result> >()).get();
} else {
return (boost::any_cast<boost::shared_ptr<const Result> >(ob.get())).get();
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
}
}
}
@@ -102,13 +96,13 @@ namespace chaiscript
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else {
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
return (ob.get().cast<std::shared_ptr<Result> >()).get();
}
}
};
@@ -119,76 +113,77 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<Result &>
{
typedef typename boost::reference_wrapper<Result> Result_Type;
typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result &cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
return boost::any_cast<boost::reference_wrapper<Result> >(ob.get());
return ob.get().cast<std::reference_wrapper<Result> >();
} else {
return boost::ref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
return r;
}
}
};
/**
* Cast_Helper_Inner for casting to a boost::shared_ptr<> type
* Cast_Helper_Inner for casting to a std::shared_ptr<> type
*/
template<typename Result>
struct Cast_Helper_Inner<typename boost::shared_ptr<Result> >
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
{
typedef typename boost::shared_ptr<Result> Result_Type;
typedef typename std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
return ob.get().cast<std::shared_ptr<Result> >();
}
};
/**
* Cast_Helper_Inner for casting to a boost::shared_ptr<const> type
* Cast_Helper_Inner for casting to a std::shared_ptr<const> type
*/
template<typename Result>
struct Cast_Helper_Inner<typename boost::shared_ptr<const Result> >
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
{
typedef typename boost::shared_ptr<const Result> Result_Type;
typedef typename std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
if (!ob.get_type_info().is_const())
{
return boost::const_pointer_cast<const Result>(boost::any_cast<boost::shared_ptr<Result> >(ob.get()));
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
} else {
return boost::any_cast<boost::shared_ptr<const Result> >(ob.get());
return ob.get().cast<std::shared_ptr<const Result> >();
}
}
};
/**
* Cast_Helper_Inner for casting to a const boost::shared_ptr<> & type
* Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
*/
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<Result> > : Cast_Helper_Inner<boost::shared_ptr<Result> >
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<Result> &> : Cast_Helper_Inner<boost::shared_ptr<Result> >
struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
{
};
/**
* Cast_Helper_Inner for casting to a const boost::shared_ptr<const> & type
* Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
*/
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> > : Cast_Helper_Inner<boost::shared_ptr<const Result> >
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> &> : Cast_Helper_Inner<boost::shared_ptr<const Result> >
struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
{
};
@@ -202,7 +197,7 @@ namespace chaiscript
{
typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
return ob;
}
@@ -223,35 +218,35 @@ namespace chaiscript
/**
* Cast_Helper_Inner for casting to a boost::reference_wrapper type
* Cast_Helper_Inner for casting to a std::reference_wrapper type
*/
template<typename Result>
struct Cast_Helper_Inner<boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
{
};
@@ -263,9 +258,9 @@ namespace chaiscript
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob)
{
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
return Cast_Helper_Inner<T>::cast(ob);
}
};
}

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
@@ -9,7 +9,6 @@
#include "boxed_value.hpp"
#include "../language/chaiscript_algebraic.hpp"
#include <boost/cstdint.hpp>
#include <sstream>
namespace chaiscript
@@ -48,8 +47,9 @@ namespace chaiscript
case Operators::not_equal:
return const_var(t != u);
default:
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
throw chaiscript::detail::exception::bad_any_cast();
}
};
@@ -82,7 +82,7 @@ namespace chaiscript
t -= u;
break;
default:
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
return t_lhs;
@@ -115,7 +115,7 @@ namespace chaiscript
t ^= u;
break;
default:
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
return t_lhs;
}
@@ -143,8 +143,9 @@ namespace chaiscript
case Operators::bitwise_complement:
return const_var(~t);
default:
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
throw chaiscript::detail::exception::bad_any_cast();
}
};
@@ -168,8 +169,9 @@ namespace chaiscript
case Operators::unary_plus:
return const_var(+t);
default:
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
throw chaiscript::detail::exception::bad_any_cast();
}
};
@@ -190,7 +192,7 @@ namespace chaiscript
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
@@ -206,13 +208,13 @@ namespace chaiscript
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
@@ -238,24 +240,24 @@ namespace chaiscript
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) {
return Go<LHS, boost::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) {
return Go<LHS, boost::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) {
return Go<LHS, boost::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) {
return Go<LHS, boost::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) {
return Go<LHS, boost::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) {
return Go<LHS, boost::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) {
return Go<LHS, boost::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) {
return Go<LHS, boost::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int8_t)) {
return Go<LHS, std::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int16_t)) {
return Go<LHS, std::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int32_t)) {
return Go<LHS, std::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int64_t)) {
return Go<LHS, std::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint8_t)) {
return Go<LHS, std::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint16_t)) {
return Go<LHS, std::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint32_t)) {
return Go<LHS, std::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint64_t)) {
return Go<LHS, std::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -279,24 +281,24 @@ namespace chaiscript
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) {
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) {
return oper_rhs<boost::int16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) {
return oper_rhs<boost::int64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) {
return oper_rhs<boost::uint8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) {
return oper_rhs<boost::uint16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) {
return oper_rhs<boost::uint32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) {
return oper_rhs<boost::uint64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int8_t)) {
return oper_rhs<std::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int16_t)) {
return oper_rhs<std::int16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int32_t)) {
return oper_rhs<std::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int64_t)) {
return oper_rhs<std::int64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint8_t)) {
return oper_rhs<std::uint8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint16_t)) {
return oper_rhs<std::uint16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint32_t)) {
return oper_rhs<std::uint32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint64_t)) {
return oper_rhs<std::uint64_t, false>(t_oper, t_lhs, t_rhs);
} else {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -333,46 +335,6 @@ namespace chaiscript
validate_boxed_number(bv);
}
Boxed_Number get_as(const Type_Info &inp_) const
{
if (inp_.bare_equal_type_info(typeid(int))) {
return Boxed_Number(get_as<int>());
} else if (inp_.bare_equal_type_info(typeid(double))) {
return Boxed_Number(get_as<double>());
} else if (inp_.bare_equal_type_info(typeid(float))) {
return Boxed_Number(get_as<float>());
} else if (inp_.bare_equal_type_info(typeid(long double))) {
return Boxed_Number(get_as<long double>());
} else if (inp_.bare_equal_type_info(typeid(char))) {
return Boxed_Number(get_as<char>());
} else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
return Boxed_Number(get_as<unsigned int>());
} else if (inp_.bare_equal_type_info(typeid(long))) {
return Boxed_Number(get_as<long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
return Boxed_Number(get_as<unsigned long>());
} else if (inp_.bare_equal_type_info(typeid(boost::int8_t))) {
return Boxed_Number(get_as<boost::int8_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::int16_t))) {
return Boxed_Number(get_as<boost::int16_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::int32_t))) {
return Boxed_Number(get_as<boost::int32_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::int64_t))) {
return Boxed_Number(get_as<boost::int64_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::uint8_t))) {
return Boxed_Number(get_as<boost::uint8_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::uint16_t))) {
return Boxed_Number(get_as<boost::uint16_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::uint32_t))) {
return Boxed_Number(get_as<boost::uint32_t>());
} else if (inp_.bare_equal_type_info(typeid(boost::uint64_t))) {
return Boxed_Number(get_as<boost::uint64_t>());
} else {
throw boost::bad_any_cast();
}
}
template<typename Target> Target get_as() const
{
const Type_Info &inp_ = bv.get_type_info();
@@ -393,24 +355,24 @@ namespace chaiscript
return get_as_aux<Target, long>();
} else if (inp_ == typeid(unsigned long)) {
return get_as_aux<Target, unsigned long>();
} else if (inp_ == typeid(boost::int8_t)) {
return get_as_aux<Target, boost::int8_t>();
} else if (inp_ == typeid(boost::int16_t)) {
return get_as_aux<Target, boost::int16_t>();
} else if (inp_ == typeid(boost::int32_t)) {
return get_as_aux<Target, boost::int32_t>();
} else if (inp_ == typeid(boost::int64_t)) {
return get_as_aux<Target, boost::int64_t>();
} else if (inp_ == typeid(boost::uint8_t)) {
return get_as_aux<Target, boost::uint8_t>();
} else if (inp_ == typeid(boost::uint16_t)) {
return get_as_aux<Target, boost::uint16_t>();
} else if (inp_ == typeid(boost::uint32_t)) {
return get_as_aux<Target, boost::uint32_t>();
} else if (inp_ == typeid(boost::uint64_t)) {
return get_as_aux<Target, boost::uint64_t>();
} else if (inp_ == typeid(std::int8_t)) {
return get_as_aux<Target, std::int8_t>();
} else if (inp_ == typeid(std::int16_t)) {
return get_as_aux<Target, std::int16_t>();
} else if (inp_ == typeid(std::int32_t)) {
return get_as_aux<Target, std::int32_t>();
} else if (inp_ == typeid(std::int64_t)) {
return get_as_aux<Target, std::int64_t>();
} else if (inp_ == typeid(std::uint8_t)) {
return get_as_aux<Target, std::uint8_t>();
} else if (inp_ == typeid(std::uint16_t)) {
return get_as_aux<Target, std::uint16_t>();
} else if (inp_ == typeid(std::uint32_t)) {
return get_as_aux<Target, std::uint32_t>();
} else if (inp_ == typeid(std::uint64_t)) {
return get_as_aux<Target, std::uint64_t>();
} else {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -434,24 +396,24 @@ namespace chaiscript
return to_string_aux<long>(bv);
} else if (inp_ == typeid(unsigned long)) {
return to_string_aux<unsigned long>(bv);
} else if (inp_ == typeid(boost::int8_t)) {
return to_string_aux<int>(Boxed_Value(get_as_aux<int, boost::int8_t>()));
} else if (inp_ == typeid(boost::int16_t)) {
return to_string_aux<boost::int16_t>(bv);
} else if (inp_ == typeid(boost::int32_t)) {
return to_string_aux<boost::int32_t>(bv);
} else if (inp_ == typeid(boost::int64_t)) {
return to_string_aux<boost::int64_t>(bv);
} else if (inp_ == typeid(boost::uint8_t)) {
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, boost::uint8_t>()));
} else if (inp_ == typeid(boost::uint16_t)) {
return to_string_aux<boost::uint16_t>(bv);
} else if (inp_ == typeid(boost::uint32_t)) {
return to_string_aux<boost::uint32_t>(bv);
} else if (inp_ == typeid(boost::uint64_t)) {
return to_string_aux<boost::uint64_t>(bv);
} else if (inp_ == typeid(std::int8_t)) {
return to_string_aux<int>(Boxed_Value(get_as_aux<int, std::int8_t>()));
} else if (inp_ == typeid(std::int16_t)) {
return to_string_aux<std::int16_t>(bv);
} else if (inp_ == typeid(std::int32_t)) {
return to_string_aux<std::int32_t>(bv);
} else if (inp_ == typeid(std::int64_t)) {
return to_string_aux<std::int64_t>(bv);
} else if (inp_ == typeid(std::uint8_t)) {
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, std::uint8_t>()));
} else if (inp_ == typeid(std::uint16_t)) {
return to_string_aux<std::uint16_t>(bv);
} else if (inp_ == typeid(std::uint32_t)) {
return to_string_aux<std::uint32_t>(bv);
} else if (inp_ == typeid(std::uint64_t)) {
return to_string_aux<std::uint64_t>(bv);
} else {
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -525,12 +487,12 @@ namespace chaiscript
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool))
{
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
if (!inp_.is_arithmetic())
{
throw boost::bad_any_cast();
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -821,7 +783,7 @@ namespace chaiscript
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_Number(ob);
}

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
@@ -12,27 +12,7 @@
#include "../chaiscript_threading.hpp"
#include <map>
#include <boost/shared_ptr.hpp>
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
#include <boost/make_shared.hpp>
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/integer_traits.hpp>
#include "any.hpp"
namespace chaiscript
{
@@ -56,7 +36,7 @@ namespace chaiscript
struct Data
{
Data(const Type_Info &ti,
const boost::any &to,
const chaiscript::detail::Any &to,
bool tr,
const void *t_void_ptr)
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?0:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
@@ -80,7 +60,7 @@ namespace chaiscript
}
Type_Info m_type_info;
boost::any m_obj;
chaiscript::detail::Any m_obj;
void *m_data_ptr;
const void *m_const_data_ptr;
bool m_is_ref;
@@ -88,65 +68,70 @@ namespace chaiscript
struct Object_Data
{
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
{
return boost::make_shared<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
boost::any(),
chaiscript::detail::Any(),
false,
static_cast<void *>(0));
nullptr)
;
}
template<typename T>
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
{
return get(*obj);
}
template<typename T>
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
{
return boost::make_shared<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
chaiscript::detail::Any(obj),
false,
obj.get());
obj.get()
);
}
template<typename T>
static boost::shared_ptr<Data> get(T *t)
static std::shared_ptr<Data> get(T *t)
{
return get(boost::ref(*t));
return get(std::ref(*t));
}
template<typename T>
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
{
return boost::make_shared<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
chaiscript::detail::Any(obj),
true,
obj.get_pointer());
&obj.get()
);
}
template<typename T>
static boost::shared_ptr<Data> get(const T& t)
static std::shared_ptr<Data> get(const T& t)
{
boost::shared_ptr<T> p(new T(t));
return boost::make_shared<Data>(
auto p = std::make_shared<T>(t);
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
boost::any(p),
chaiscript::detail::Any(p),
false,
p.get());
p.get()
);
}
static boost::shared_ptr<Data> get()
static std::shared_ptr<Data> get()
{
return boost::make_shared<Data>(
return std::make_shared<Data>(
Type_Info(),
boost::any(),
chaiscript::detail::Any(),
false,
static_cast<void *>(0));
nullptr
);
}
};
@@ -234,7 +219,7 @@ namespace chaiscript
return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0);
}
const boost::any & get() const
const chaiscript::detail::Any & get() const
{
return m_data->m_obj;
}
@@ -259,11 +244,17 @@ namespace chaiscript
return m_data->m_const_data_ptr;
}
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(Boxed_Value l, Boxed_Value r)
{
return l.get_type_info() == r.get_type_info();
}
private:
boost::shared_ptr<Data> m_data;
std::shared_ptr<Data> m_data;
};
/// \brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, boost::shared_ptr, or boost::reference_type
/// \brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
/// a copy is not made.
/// \param t The value to box
///
@@ -290,7 +281,7 @@ namespace chaiscript
template<typename T>
Boxed_Value const_var_impl(const T &t)
{
return Boxed_Value(boost::shared_ptr<typename boost::add_const<T>::type >(new T(t)));
return Boxed_Value(std::shared_ptr<typename std::add_const<T>::type >(new T(t)));
}
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
@@ -301,33 +292,33 @@ namespace chaiscript
template<typename T>
Boxed_Value const_var_impl(T *t)
{
return Boxed_Value( const_cast<typename boost::add_const<T>::type *>(t) );
return Boxed_Value( const_cast<typename std::add_const<T>::type *>(t) );
}
/// \brief Takes a boost::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
/// \brief Takes a std::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
/// Does not copy the pointed to value.
/// \param[in] t Pointer to make immutable
/// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const
template<typename T>
Boxed_Value const_var_impl(const boost::shared_ptr<T> &t)
Boxed_Value const_var_impl(const std::shared_ptr<T> &t)
{
return Boxed_Value( boost::const_pointer_cast<typename boost::add_const<T>::type>(t) );
return Boxed_Value( std::const_pointer_cast<typename std::add_const<T>::type>(t) );
}
/// \brief Takes a boost::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
/// \brief Takes a std::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
/// Does not copy the referenced value.
/// \param[in] t Reference object to make immutable
/// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const
template<typename T>
Boxed_Value const_var_impl(const boost::reference_wrapper<T> &t)
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
{
return Boxed_Value( boost::cref(t.get()) );
return Boxed_Value( std::cref(t.get()) );
}
}
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a boost::reference or pointer type
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer type
/// the value is not copied. If it is an object type, it is copied.
/// \param[in] t Object to make immutable
/// \returns Immutable Boxed_Value
@@ -357,11 +348,6 @@ namespace chaiscript
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(Boxed_Value l, Boxed_Value r)
{
return l.get_type_info() == r.get_type_info();
}
}
#endif

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
@@ -11,12 +11,12 @@
#include <string>
#include <map>
#include <set>
#include <boost/shared_ptr.hpp>
#include <stdexcept>
#include <vector>
#include <iostream>
#include <deque>
#include <list>
#include <algorithm>
#include "boxed_value.hpp"
#include "type_info.hpp"
@@ -39,12 +39,12 @@ namespace chaiscript
class reserved_word_error : public std::runtime_error
{
public:
reserved_word_error(const std::string &t_word) throw()
reserved_word_error(const std::string &t_word) noexcept
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
{
}
virtual ~reserved_word_error() throw() {}
virtual ~reserved_word_error() noexcept {}
std::string word() const
{
@@ -53,31 +53,9 @@ namespace chaiscript
private:
std::string m_word;
};
/**
* Exception thrown in the case that an object name is invalid because it contains illegal characters
*/
class illegal_name_error : public std::runtime_error
{
public:
illegal_name_error(const std::string &t_name) throw()
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
{
}
virtual ~illegal_name_error() throw() {}
std::string name() const
{
return m_name;
}
private:
std::string m_name;
};
/**
* Exception thrown in the case that an object name is invalid because it already exists in current context
*/
@@ -108,12 +86,12 @@ namespace chaiscript
class global_non_const : public std::runtime_error
{
public:
global_non_const() throw()
global_non_const() noexcept
: std::runtime_error("a global object must be const")
{
}
virtual ~global_non_const() throw() {}
virtual ~global_non_const() noexcept {}
};
}
@@ -145,7 +123,7 @@ namespace chaiscript
{
if (!t_bv.is_const())
{
throw exception::global_non_const();
throw chaiscript::exception::global_non_const();
}
m_globals.push_back(std::make_pair(t_bv, t_name));
@@ -160,7 +138,7 @@ namespace chaiscript
return *this;
}
Module &add(const boost::shared_ptr<Module> &m)
Module &add(const std::shared_ptr<Module> &m)
{
m->apply(*this, *this);
return *m;
@@ -176,6 +154,11 @@ namespace chaiscript
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
}
~Module()
{
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
}
private:
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
@@ -190,7 +173,7 @@ namespace chaiscript
{
try {
t.add(begin->first, begin->second);
} catch (const exception::name_conflict_error &) {
} catch (const chaiscript::exception::name_conflict_error &) {
/// \todo Should we throw an error if there's a name conflict
/// while applying a module?
}
@@ -230,7 +213,7 @@ namespace chaiscript
};
/// Convenience typedef for Module objects to be added to the ChaiScript runtime
typedef boost::shared_ptr<Module> ModulePtr;
typedef std::shared_ptr<Module> ModulePtr;
namespace detail
{
@@ -244,9 +227,9 @@ namespace chaiscript
public:
Dispatch_Function(const std::vector<Proxy_Function> &t_funcs)
: Proxy_Function_Base(build_type_infos(t_funcs)),
m_funcs(t_funcs)
{
}
m_funcs(t_funcs)
{
}
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const
{
@@ -296,7 +279,7 @@ 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
{
typedef std::vector<Proxy_Function> function_vec;
@@ -305,7 +288,7 @@ namespace chaiscript
while (begin != end)
{
if ((*begin)->call_match(vals, t_conversions))
if ((*begin)->call_match(vals))
{
return true;
} else {
@@ -322,9 +305,9 @@ namespace chaiscript
}
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
{
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params);
}
private:
@@ -393,7 +376,7 @@ namespace chaiscript
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
typedef std::map<std::string, Boxed_Value> Scope;
typedef std::deque<Scope> StackData;
typedef boost::shared_ptr<StackData> Stack;
typedef std::shared_ptr<StackData> Stack;
struct State
{
@@ -402,30 +385,27 @@ namespace chaiscript
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
State &operator=(const State &) = default;
};
Dispatch_Engine()
: m_place_holder(boost::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
: m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
{
}
~Dispatch_Engine()
{
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
}
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
{
return chaiscript::boxed_cast<Type>(bv, &m_conversions);
}
/**
* Add a new conversion for upcasting to a base class
*/
void add(const Dynamic_Cast_Conversion &d)
{
m_conversions.add_conversion(d);
m_conversions.push_back(d);
return detail::Dynamic_Conversions::get().add_conversion(d);
}
/**
@@ -472,7 +452,7 @@ namespace chaiscript
Scope::iterator itr = scope.find(name);
if (itr != stack.back().end())
{
throw exception::name_conflict_error(name);
throw chaiscript::exception::name_conflict_error(name);
} else {
stack.back().insert(std::make_pair(name, obj));
}
@@ -486,38 +466,19 @@ namespace chaiscript
validate_object_name(name);
if (!obj.is_const())
{
throw exception::global_non_const();
throw chaiscript::exception::global_non_const();
}
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
{
throw exception::name_conflict_error(name);
throw chaiscript::exception::name_conflict_error(name);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
}
}
/**
* Adds a new global (non-const) shared object, between all the threads
*/
void add_global(const Boxed_Value &obj, const std::string &name)
{
validate_object_name(name);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
{
throw exception::name_conflict_error(name);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
}
}
/**
* Adds a new scope to the stack
*/
@@ -817,16 +778,11 @@ namespace chaiscript
m_state.m_reserved_words.insert(name);
}
const Dynamic_Cast_Conversions &conversions() const
{
return m_conversions;
}
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const
{
std::vector<Proxy_Function> functions = get_function(t_name);
return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
return dispatch::dispatch(functions.begin(), functions.end(), params);
}
Boxed_Value call_function(const std::string &t_name) const
@@ -895,22 +851,6 @@ namespace chaiscript
std::cout << ") " << std::endl;
}
/**
* Returns true if a call can be made that consists of the first parameter
* (the function) with the remaining parameters as its arguments.
*/
Boxed_Value call_exists(const std::vector<Boxed_Value> &params)
{
if (params.size() < 1)
{
throw exception::arity_error(static_cast<int>(params.size()), 1);
}
Const_Proxy_Function f = this->boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
}
/**
* Dump all system info to stdout
*/
@@ -1048,8 +988,8 @@ namespace chaiscript
const Type_Info boxed_type = user_type<Boxed_Value>();
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
if (dynamic_lhs && dynamic_rhs)
{
@@ -1137,15 +1077,11 @@ namespace chaiscript
*/
void validate_object_name(const std::string &name) const
{
if (name.find("::") != std::string::npos) {
throw exception::illegal_name_error(name);
}
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
{
throw exception::reserved_word_error(name);
throw chaiscript::exception::reserved_word_error(name);
}
}
@@ -1173,21 +1109,13 @@ namespace chaiscript
{
if ((*t_f) == *(*itr2))
{
throw exception::name_conflict_error(t_name);
throw chaiscript::exception::name_conflict_error(t_name);
}
}
vec.push_back(t_f);
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
} else if (t_f->has_arithmetic_param()) {
// if the function is the only function but it also contains
// arithmetic operators, we must wrap it in a dispatch function
// to allow for automatic arithmetic type conversions
std::vector<Proxy_Function> vec;
vec.push_back(t_f);
funcs.insert(std::make_pair(t_name, vec));
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
} else {
std::vector<Proxy_Function> vec;
vec.push_back(t_f);
@@ -1217,7 +1145,7 @@ namespace chaiscript
int call_depth;
};
Dynamic_Cast_Conversions m_conversions;
std::vector<Dynamic_Cast_Conversion> m_conversions;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
@@ -11,9 +11,6 @@
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include "bad_boxed_cast.hpp"
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace chaiscript
{
@@ -23,22 +20,22 @@ namespace chaiscript
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) throw()
const std::string &t_what) noexcept
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) throw()
bad_boxed_dynamic_cast(const std::string &w) noexcept
: bad_boxed_cast(w)
{
}
virtual ~bad_boxed_dynamic_cast() throw() {}
virtual ~bad_boxed_dynamic_cast() noexcept {}
};
}
@@ -47,7 +44,7 @@ namespace chaiscript
class Dynamic_Conversion
{
public:
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
const Type_Info &base()
{
@@ -73,7 +70,7 @@ namespace chaiscript
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Dynamic_Conversion
class Dynamic_Conversion_Impl : public Dynamic_Conversion
{
public:
Dynamic_Conversion_Impl()
@@ -81,7 +78,7 @@ namespace chaiscript
{
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const
virtual Boxed_Value convert(const Boxed_Value &t_derived)
{
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
{
@@ -90,8 +87,8 @@ namespace chaiscript
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
boost::shared_ptr<const Base> data
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived, 0));
std::shared_ptr<const Base> data
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived));
if (!data)
{
throw std::bad_cast();
@@ -99,8 +96,8 @@ namespace chaiscript
return Boxed_Value(data);
} else {
boost::shared_ptr<Base> data
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived, 0));
std::shared_ptr<Base> data
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived));
if (!data)
{
@@ -113,113 +110,116 @@ namespace chaiscript
// 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 Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
const Base &data = dynamic_cast<const Base &>(d);
return Boxed_Value(boost::cref(data));
return Boxed_Value(std::cref(data));
} else {
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived, 0);
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
Base &data = dynamic_cast<Base &>(d);
return Boxed_Value(boost::ref(data));
return Boxed_Value(std::ref(data));
}
}
} else {
throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
}
}
};
class Dynamic_Conversions
{
public:
static inline Dynamic_Conversions &get()
{
static Dynamic_Conversions obj;
return obj;
}
template<typename Base, typename Derived>
static std::shared_ptr<Dynamic_Conversion> create()
{
std::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
/// \todo this is a hack and a kludge. The idea is to make sure that
/// the conversion is registered both in the module's notion of the static conversion object
/// and in the global notion of the static conversion object
/// someday this will almost certainly have to change. Maybe it is time for ChaiScript
/// to become a library?
Dynamic_Conversions::get().add_conversion(conversion);
return conversion;
}
template<typename InItr>
void cleanup(InItr begin, const InItr &end)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
while (begin != end)
{
if (begin->unique())
{
m_conversions.erase(begin->get());
}
++begin;
}
}
void add_conversion(const std::shared_ptr<Dynamic_Conversion> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion.get());
}
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end();
}
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<Dynamic_Conversion *>::const_iterator itr =
find(base, derived);
if (itr != m_conversions.end())
{
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
}
}
private:
Dynamic_Conversions() {}
std::set<Dynamic_Conversion *>::const_iterator find(
const Type_Info &base, const Type_Info &derived) const
{
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
itr != m_conversions.end();
++itr)
{
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
{
return itr;
}
}
return m_conversions.end();
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<Dynamic_Conversion *> m_conversions;
};
}
class Dynamic_Cast_Conversions
{
public:
Dynamic_Cast_Conversions()
{
}
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
: m_conversions(t_other.get_conversions())
{
}
void add_conversion(const boost::shared_ptr<detail::Dynamic_Conversion> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion);
}
template<typename Base, typename Derived>
bool dynamic_cast_converts() const
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
{
return has_conversion(base, derived);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
{
try {
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end();
}
boost::shared_ptr<detail::Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<boost::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr =
find(base, derived);
if (itr != m_conversions.end())
{
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
}
}
private:
std::set<boost::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
const Type_Info &base, const Type_Info &derived) const
{
for (std::set<boost::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr = m_conversions.begin();
itr != m_conversions.end();
++itr)
{
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
{
return itr;
}
}
return m_conversions.end();
}
std::set<boost::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return m_conversions;
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<boost::shared_ptr<detail::Dynamic_Conversion> > m_conversions;
};
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
/// want automatic conversions up your inheritance hierarchy.
@@ -245,17 +245,42 @@ namespace chaiscript
/// \todo Move share static type registration code into a mechanism that allows it to be properly
/// shared by all modules
template<typename Base, typename Derived>
Dynamic_Cast_Conversion base_class()
{
//Can only be used with related polymorphic types
//may be expanded some day to support conversions other than child -> parent
BOOST_STATIC_ASSERT((boost::is_base_of<Base,Derived>::value));
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
Dynamic_Cast_Conversion base_class()
{
//Can only be used with related polymorphic types
//may be expanded some day to support conversions other than child -> parent
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
return boost::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<Base, Derived>());
return detail::Dynamic_Conversions::create<Base, Derived>();
}
namespace detail
{
template<typename Base, typename Derived>
bool dynamic_cast_converts()
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
{
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
{
try {
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
}
}

View File

@@ -1,13 +1,12 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#include <boost/optional.hpp>
namespace chaiscript
{
@@ -52,12 +51,22 @@ namespace chaiscript
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(t_func->get_param_types()),
m_type_name(t_type_name), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func,
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
const Type_Info &t_ti)
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
m_type_name(t_type_name), m_func(t_func), m_ti(new Type_Info(t_ti))
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
@@ -76,11 +85,11 @@ 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
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
{
return m_func->call_match(vals, t_conversions);
return m_func->call_match(vals);
} else {
return false;
}
@@ -88,9 +97,7 @@ namespace chaiscript
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
{
std::vector<Const_Proxy_Function> fs;
fs.push_back(m_func);
return fs;
return {m_func};
}
@@ -106,46 +113,41 @@ namespace chaiscript
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
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
if (dynamic_object_typename_match(params, m_type_name, m_ti))
{
return (*m_func)(params, t_conversions);
return (*m_func)(params);
} else {
throw exception::guard_error();
}
}
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
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
return dynamic_object_typename_match(bv, m_type_name, m_ti);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
{
if (t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = *t_objectti;
return types;
} else {
return t_inner_types;
}
assert(types.size() > 1);
assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = t_objectti;
return types;
}
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const boost::optional<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions)
const std::shared_ptr<Type_Info> &ti)
{
static Type_Info doti = user_type<Dynamic_Object>();
if (bv.get_type_info().bare_equal(doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
@@ -162,11 +164,11 @@ namespace chaiscript
}
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const boost::optional<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions)
const std::shared_ptr<Type_Info> &ti)
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
return dynamic_object_typename_match(bvs[0], name, ti);
} else {
return false;
}
@@ -174,7 +176,7 @@ namespace chaiscript
std::string m_type_name;
Proxy_Function m_func;
boost::optional<Type_Info> m_ti;
std::shared_ptr<Type_Info> m_ti;
};
@@ -192,7 +194,7 @@ namespace chaiscript
const 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(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)");
@@ -224,13 +226,13 @@ 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
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
return m_func->call_match(new_vals);
}
@@ -246,14 +248,14 @@ namespace chaiscript
}
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
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
(*m_func)(new_params);
return bv;
}

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
@@ -15,77 +15,65 @@ namespace chaiscript
{
struct Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
virtual ~Exception_Handler_Base() {}
virtual void handle(const Boxed_Value &bv) = 0;
protected:
template<typename T>
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
void throw_type(const Boxed_Value &bv)
{
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
}
};
template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl1() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv, t_engine);
throw_type<T1>(bv);
}
};
template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl2() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T1>(bv);
throw_type<T2>(bv);
}
};
template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl3() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
}
};
template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl4() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
throw_type<T4>(bv);
}
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl5() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
throw_type<T5>(bv, t_engine);
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
throw_type<T4>(bv);
throw_type<T5>(bv);
}
};
}
@@ -140,7 +128,7 @@ namespace chaiscript
///
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
/// \sa \ref exceptions
typedef boost::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
typedef std::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions

View File

@@ -1,15 +1,12 @@
// 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)
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <string>
#include <vector>
#include "proxy_functions.hpp"
@@ -25,17 +22,17 @@ namespace chaiscript
/**
* Build a function caller that knows how to dispatch on a set of functions
* example:
* boost::function<void (int)> f =
* std::function<void (int)> f =
* build_function_caller(dispatchkit.get_function("print"));
* \returns A boost::function object for dispatching
* \returns A std::function object for dispatching
* \param[in] funcs the set of functions to dispatch on.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs)
{
FunctionType *p=0;
return detail::build_function_caller_helper(p, funcs, t_conversions);
return detail::build_function_caller_helper(p, funcs);
}
/**
@@ -45,19 +42,19 @@ namespace chaiscript
* example:
* void my_function(Proxy_Function f)
* {
* boost::function<void (int)> local_f =
* std::function<void (int)> local_f =
* build_function_caller(f);
* }
* \returns A boost::function object for dispatching
* \returns A std::function object for dispatching
* \param[in] func A function to execute.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions)
std::function<FunctionType>
functor(Const_Proxy_Function func)
{
std::vector<Const_Proxy_Function> funcs;
funcs.push_back(func);
return functor<FunctionType>(funcs, t_conversions);
return functor<FunctionType>(funcs);
}
/**
@@ -65,67 +62,67 @@ namespace chaiscript
* and creating a typesafe C++ function caller from it.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions)
std::function<FunctionType>
functor(const Boxed_Value &bv)
{
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
}
}
namespace detail{
/**
* Cast helper to handle automatic casting to const boost::function &
* Cast helper to handle automatic casting to const std::function &
*/
template<typename Signature>
struct Cast_Helper<const boost::function<Signature> &>
struct Cast_Helper<const std::function<Signature> &>
{
typedef boost::function<Signature> Result_Type;
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return dispatch::functor<Signature>(ob, t_conversions);
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob, t_conversions);
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob);
}
}
};
/**
* Cast helper to handle automatic casting to boost::function
* Cast helper to handle automatic casting to std::function
*/
template<typename Signature>
struct Cast_Helper<boost::function<Signature> >
struct Cast_Helper<std::function<Signature> >
{
typedef boost::function<Signature> Result_Type;
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return dispatch::functor<Signature>(ob, t_conversions);
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob, t_conversions);
return Cast_Helper_Inner<std::function<Signature> >::cast(ob);
}
}
};
/**
* Cast helper to handle automatic casting to const boost::function
* Cast helper to handle automatic casting to const std::function
*/
template<typename Signature>
struct Cast_Helper<const boost::function<Signature> >
struct Cast_Helper<const std::function<Signature> >
{
typedef boost::function<Signature> Result_Type;
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return dispatch::functor<Signature>(ob, t_conversions);
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob, t_conversions);
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob);
}
}
};

View File

@@ -1,22 +1,12 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define addparam(z,n,text) params.push_back((boost::is_reference<Param ## n>::value&&!(boost::is_same<chaiscript::Boxed_Value, typename boost::remove_const<typename boost::remove_reference<Param ## n>::type>::type>::value))?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <string>
#include <vector>
#include "proxy_functions.hpp"
@@ -36,9 +26,9 @@ namespace chaiscript
struct Function_Caller_Ret
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &params)
{
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params));
}
};
@@ -49,56 +39,46 @@ namespace chaiscript
struct Function_Caller_Ret<void>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &params)
{
dispatch::dispatch(t_funcs, params, t_conversions);
dispatch::dispatch(t_funcs, params);
}
};
}
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 9 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/function_call_detail.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions &t_conversions
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper
{
std::vector<Boxed_Value> params;
Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs)
: m_funcs(t_funcs)
{
}
BOOST_PP_REPEAT(n, addparam, ~);
Ret operator()(Param...param)
{
return Function_Caller_Ret<Ret>::call(m_funcs, {
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
}
);
return Function_Caller_Ret<Ret>::call(funcs, params, t_conversions);
}
}
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs,
const Dynamic_Cast_Conversions *t_conversions)
std::vector<Const_Proxy_Function> m_funcs;
};
template<typename Ret, typename ... Params>
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs)
{
if (funcs.size() == 1)
{
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
(funcs[0]);
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
(funcs[0]);
if (pfi)
{
@@ -108,15 +88,11 @@ namespace chaiscript
// we cannot make any other guesses or assumptions really, so continuing
}
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs, (t_conversions?*t_conversions:Dynamic_Cast_Conversions())
BOOST_PP_ENUM_TRAILING(n, curry, ~));
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs));
}
}
}
}
#undef n
#undef addparam
#undef curry
#endif

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
@@ -11,7 +11,6 @@
#include "boxed_number.hpp"
#include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
#include <stdexcept>
#include <vector>
@@ -44,27 +43,27 @@ namespace chaiscript
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &>
struct Handle_Return<std::shared_ptr<Ret> &>
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> >
struct Handle_Return<std::shared_ptr<Ret> >
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &>
struct Handle_Return<const std::shared_ptr<Ret> &>
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
@@ -75,7 +74,7 @@ namespace chaiscript
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(boost::cref(r));
return Boxed_Value(std::cref(r));
}
};
@@ -88,12 +87,12 @@ namespace chaiscript
{
static Boxed_Value handle(Ret &r)
{
return Boxed_Value(boost::ref(r));
return Boxed_Value(std::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(boost::cref(r));
return Boxed_Value(std::cref(r));
}
};

View File

@@ -1,12 +1,14 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_OPERATORS_HPP_
#define CHAISCRIPT_OPERATORS_HPP_
#include "../chaiscript_defines.hpp"
namespace chaiscript
{
namespace bootstrap
@@ -154,7 +156,7 @@ namespace chaiscript
template<typename Ret, typename L>
Ret unary_minus(L l)
{
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4146)
return (-l);

View File

@@ -1,27 +1,39 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_constructors.hpp>
#include BOOST_PP_ITERATE()
# endif
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class, typename ... Params>
std::shared_ptr<Class> constructor_(Params ... params)
{
return std::shared_ptr<Class>(new Class(params...));
}
template<typename Class, typename ... Params >
Proxy_Function build_constructor_(Class (*)(Params...))
{
typedef std::shared_ptr<Class> (sig)(Params...);
return Proxy_Function(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>))));
}
}
}
/// \brief Generates a constructor function for use with ChaiScript
///
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
@@ -39,43 +51,8 @@ namespace chaiscript
T *f = 0;
return (dispatch::detail::build_constructor_(f));
}
}
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
}
/**
* Helper function for build a constructor function
* example:
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
* \todo See if it is possible to make this not be a variadic function
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
}
}
}
#undef n
#endif

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -12,10 +12,10 @@
#include "boxed_value.hpp"
#include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <type_traits>
#include <stdexcept>
#include <vector>
#include <cassert>
#include "proxy_functions_detail.hpp"
namespace chaiscript
@@ -23,41 +23,10 @@ namespace chaiscript
class Boxed_Number;
struct AST_Node;
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
namespace dispatch
{
/**
* Helper for building a list of parameters for calling a Proxy_Function
* it does automatic conversion to Boxed_Value types via operator<<
*
* example usage:
* Boxed_Value retval = dispatch(dispatchengine.get_function("+"),
* chaiscript::Param_List_Builder() << 5 << 6);
*/
struct Param_List_Builder
{
Param_List_Builder &operator<<(const Boxed_Value &so)
{
objects.push_back(so);
return *this;
}
template<typename T>
Param_List_Builder &operator<<(T t)
{
objects.push_back(Boxed_Value(t));
return *this;
}
operator const std::vector<Boxed_Value> &() const
{
return objects;
}
std::vector<Boxed_Value> objects;
};
/**
* Pure virtual base class for all Proxy_Function implementations
* Proxy_Functions are a type erasure of type safe C++
@@ -70,9 +39,9 @@ namespace chaiscript
{
public:
virtual ~Proxy_Function_Base() {}
Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Dynamic_Cast_Conversions &t_conversions) const
Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
Boxed_Value bv = do_call(params, t_conversions);
Boxed_Value bv = do_call(params);
return bv;
}
@@ -80,25 +49,20 @@ namespace chaiscript
/// if the function is variadic or takes no arguments (arity of 0 or -1), the returned
/// value containes exactly 1 Type_Info object: the return type
/// \returns the types of all parameters.
std::vector<Type_Info> get_param_types() const { return m_types; }
const std::vector<Type_Info> &get_param_types() const { return m_types; }
virtual bool operator==(const Proxy_Function_Base &) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
bool has_arithmetic_param() const
virtual std::vector<std::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
{
return m_has_arithmetic_param;
}
virtual std::vector<boost::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
{
return std::vector<boost::shared_ptr<const Proxy_Function_Base> >();
return std::vector<std::shared_ptr<const Proxy_Function_Base> >();
}
//! Return true if the function is a possible match
//! to the passed in values
bool filter(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
bool filter(const std::vector<Boxed_Value> &vals) const
{
int arity = get_arity();
@@ -110,7 +74,7 @@ namespace chaiscript
{
return true;
} else {
return compare_first_type(vals[0], t_conversions);
return compare_first_type(vals[0]);
}
} else {
return false;
@@ -122,15 +86,30 @@ namespace chaiscript
virtual std::string annotation() const = 0;
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const = 0;
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
: m_types(t_types)
{
}
virtual bool compare_first_type(const Boxed_Value &bv) const
{
const std::vector<Type_Info> &types = get_param_types();
if (types.size() < 2)
{
return true;
}
const Type_Info &ti = types[1];
if (ti.is_undef()
|| ti.bare_equal(user_type<Boxed_Value>())
|| (!bv.get_type_info().is_undef()
&& (ti.bare_equal(user_type<Boxed_Number>())
|| ti.bare_equal(bv.get_type_info())
|| bv.get_type_info().bare_equal(user_type<boost::shared_ptr<const Proxy_Function_Base> >())
|| t_conversions.dynamic_cast_converts(ti, bv.get_type_info())
|| chaiscript::detail::dynamic_cast_converts(ti, bv.get_type_info())
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
)
)
)
@@ -140,38 +119,8 @@ namespace chaiscript
return false;
}
}
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)
{
for (size_t i = 1; i < m_types.size(); ++i)
{
if (m_types[i].is_arithmetic())
{
m_has_arithmetic_param = true;
return;
}
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
{
const std::vector<Type_Info> &types = get_param_types();
if (types.size() < 2)
{
return true;
}
const Type_Info &ti = types[1];
return compare_type_to_param(ti, bv, t_conversions);
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
{
if (tis.size() - 1 != bvs.size())
{
@@ -190,17 +139,15 @@ namespace chaiscript
}
std::vector<Type_Info> m_types;
bool m_has_arithmetic_param;
};
}
/// \brief Common typedef used for passing of any registered function in ChaiScript
typedef boost::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
typedef std::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
/// \brief Const version of Proxy_Function chaiscript. Points to a const Proxy_Function. This is how most registered functions
/// are handled internally.
typedef boost::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
typedef std::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
namespace exception
{
@@ -208,11 +155,11 @@ namespace chaiscript
class guard_error : public std::runtime_error
{
public:
guard_error() throw()
guard_error() noexcept
: std::runtime_error("Guard evaluation failed")
{ }
virtual ~guard_error() throw()
virtual ~guard_error() noexcept
{ }
};
}
@@ -227,7 +174,7 @@ namespace chaiscript
{
public:
Dynamic_Proxy_Function(
const boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
const std::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
int t_arity=-1,
const AST_NodePtr &t_parsenode = AST_NodePtr(),
const std::string &t_description = "",
@@ -247,10 +194,10 @@ 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
{
return (m_arity < 0 || vals.size() == size_t(m_arity))
&& test_guard(vals, t_conversions);
&& test_guard(vals);
}
virtual ~Dynamic_Proxy_Function() {}
@@ -277,12 +224,12 @@ namespace chaiscript
}
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
{
if (m_arity < 0 || params.size() == size_t(m_arity))
{
if (test_guard(params, t_conversions))
if (test_guard(params))
{
return m_f(params);
} else {
@@ -295,12 +242,12 @@ namespace chaiscript
}
private:
bool test_guard(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
bool test_guard(const std::vector<Boxed_Value> &params) const
{
if (m_guard)
{
try {
return boxed_cast<bool>((*m_guard)(params, t_conversions));
return boxed_cast<bool>((*m_guard)(params));
} catch (const exception::arity_error &) {
return false;
} catch (const exception::bad_boxed_cast &) {
@@ -318,7 +265,7 @@ namespace chaiscript
// For the return type
types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get());
if (arity >= 0)
if (arity > 0)
{
for (int i = 0; i < arity; ++i)
{
@@ -329,7 +276,7 @@ namespace chaiscript
return types;
}
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
int m_arity;
std::string m_description;
Proxy_Function m_guard;
@@ -356,7 +303,7 @@ namespace chaiscript
Bound_Function(const Const_Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args)
: Proxy_Function_Base(build_param_type_info(t_f, t_args)),
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
{
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
}
@@ -368,9 +315,14 @@ namespace chaiscript
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
{
return m_f->call_match(build_param_list(vals), t_conversions);
return m_f->call_match(build_param_list(vals));
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
return (*m_f)(build_param_list(params));
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
@@ -429,6 +381,7 @@ namespace chaiscript
const std::vector<Boxed_Value> &t_args)
{
assert(t_f->get_arity() < 0 || t_f->get_arity() == static_cast<int>(t_args.size()));
if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }
std::vector<Type_Info> types = t_f->get_param_types();
@@ -447,9 +400,9 @@ 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
{
return (*m_f)(build_param_list(params), t_conversions);
return (*m_f)(build_param_list(params));
}
private:
@@ -460,14 +413,14 @@ namespace chaiscript
/**
* The standard typesafe function call implementation of Proxy_Function
* It takes a boost::function<> object and performs runtime
* It takes a std::function<> object and performs runtime
* type checking of Boxed_Value parameters, in a type safe manner
*/
template<typename Func>
class Proxy_Function_Impl : public Proxy_Function_Base
{
public:
Proxy_Function_Impl(const boost::function<Func> &f)
Proxy_Function_Impl(const std::function<Func> &f)
: Proxy_Function_Base(detail::build_param_type_list(static_cast<Func *>(0))),
m_f(f), m_dummy_func(0)
{
@@ -481,21 +434,19 @@ namespace chaiscript
return pimpl != 0;
}
virtual int get_arity() const
{
return static_cast<int>(m_types.size()) - 1;
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
if (int(vals.size()) != get_arity())
{
return false;
}
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals, t_conversions);
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals);
}
virtual std::string annotation() const
@@ -503,19 +454,19 @@ namespace chaiscript
return "";
}
boost::function<Func> internal_function() const
std::function<Func> internal_function() const
{
return m_f;
}
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
{
return detail::Do_Call<typename boost::function<Func>::result_type>::go(m_f, params, t_conversions);
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params);
}
private:
boost::function<Func> m_f;
std::function<Func> m_f;
Func *m_dummy_func;
};
@@ -538,6 +489,7 @@ namespace chaiscript
{
const Attribute_Access<T, Class> * aa
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
if (aa) {
return m_attr == aa->m_attr;
} else {
@@ -551,7 +503,7 @@ namespace chaiscript
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
{
if (vals.size() != 1)
{
@@ -567,18 +519,18 @@ namespace chaiscript
}
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
{
if (params.size() == 1)
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
const Class *o = boxed_cast<const Class *>(bv);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
} else {
Class *o = boxed_cast<Class *>(bv, &t_conversions);
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
Class *o = boxed_cast<Class *>(bv);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
}
} else {
throw exception::arity_error(static_cast<int>(params.size()), 1);
@@ -588,11 +540,9 @@ namespace chaiscript
private:
static std::vector<Type_Info> param_types()
{
std::vector<Type_Info> v;
v.push_back(user_type<T>());
v.push_back(user_type<Class>());
return v;
return {user_type<T>(), user_type<Class>()};
}
T Class::* m_attr;
};
}
@@ -613,7 +563,7 @@ namespace chaiscript
{
}
virtual ~dispatch_error() throw() {}
virtual ~dispatch_error() noexcept {}
std::vector<Boxed_Value> parameters;
std::vector<Const_Proxy_Function> functions;
@@ -622,94 +572,6 @@ namespace chaiscript
namespace dispatch
{
namespace detail
{
template<typename FuncType>
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
const Dynamic_Cast_Conversions &t_conversions)
{
if (t_func->get_arity() != static_cast<int>(plist.size()))
{
return false;
}
const std::vector<Type_Info> &types = t_func->get_param_types();
assert(plist.size() == types.size() - 1);
for (size_t i = 0; i < plist.size(); ++i)
{
if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i], t_conversions)
|| (types[i+1].is_arithmetic() && plist[i].get_type_info().is_arithmetic()))
{
// types continue to match
} else {
return false;
}
}
// all types match
return true;
}
template<typename InItr>
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
const Dynamic_Cast_Conversions &t_conversions)
{
InItr orig(begin);
InItr matching_func(end);
while (begin != end)
{
if (types_match_except_for_arithmetic(*begin, plist, t_conversions))
{
if (matching_func == end)
{
matching_func = begin;
} else {
// More than one function matches, not attempting
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
}
}
++begin;
}
if (matching_func == end)
{
// no appropriate function to attempt arithmetic type conversion on
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
}
std::vector<Boxed_Value> newplist;
const std::vector<Type_Info> &tis = (*matching_func)->get_param_types();
for (size_t i = 0; i < plist.size(); ++i)
{
if (tis[i+1].is_arithmetic()
&& plist[i].get_type_info().is_arithmetic()) {
newplist.push_back(Boxed_Number(plist[i]).get_as(tis[i+1]).bv);
} else {
newplist.push_back(plist[i]);
}
}
try {
return (*(*matching_func))(newplist, t_conversions);
} catch (const exception::bad_boxed_cast &) {
//parameter failed to cast
} catch (const exception::arity_error &) {
//invalid num params
} catch (const exception::guard_error &) {
//guard failed to allow the function to execute
}
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
}
}
/**
* Take a vector of functions and a vector of parameters. Attempt to execute
@@ -718,15 +580,15 @@ namespace chaiscript
*/
template<typename InItr>
Boxed_Value dispatch(InItr begin, const InItr &end,
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &plist)
{
InItr orig(begin);
while (begin != end)
{
try {
if ((*begin)->filter(plist, t_conversions))
if ((*begin)->filter(plist))
{
return (*(*begin))(plist, t_conversions);
return (*(*begin))(plist);
}
} catch (const exception::bad_boxed_cast &) {
//parameter failed to cast, try again
@@ -739,7 +601,7 @@ namespace chaiscript
++begin;
}
return detail::dispatch_with_conversions(orig, end, plist, t_conversions);
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
}
/**
@@ -749,9 +611,9 @@ namespace chaiscript
*/
template<typename Funcs>
Boxed_Value dispatch(const Funcs &funcs,
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &plist)
{
return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions);
return dispatch::dispatch(funcs.begin(), funcs.end(), plist);
}
}
}

View File

@@ -1,16 +1,9 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define gettypeinfo(z,n,text) ti.push_back(chaiscript::detail::Get_Type_Info<Param ## n>::get());
#define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n], &t_conversions)
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n], &t_conversions);
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
@@ -19,8 +12,6 @@
#include "type_info.hpp"
#include "handle_return.hpp"
#include <string>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <stdexcept>
#include <vector>
@@ -41,26 +32,13 @@ namespace chaiscript
{
}
virtual ~arity_error() throw() {}
virtual ~arity_error() noexcept {}
int got;
int expected;
};
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions_detail.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
namespace dispatch
{
namespace detail
@@ -69,81 +47,51 @@ namespace chaiscript
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
template<typename Ret, typename ... Params>
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
{
std::vector<Type_Info> ti;
ti.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
BOOST_PP_REPEAT(n, gettypeinfo, ~)
return ti;
return std::vector<Type_Info> { chaiscript::detail::Get_Type_Info<Ret>::get(),
chaiscript::detail::Get_Type_Info<Params>::get()... };
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each paramter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4100)
#endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
// Forward declaration
template<typename ... Rest>
struct Try_Cast;
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions & BOOST_PP_IF(n, t_conversions, BOOST_PP_EMPTY))
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
// implementation
template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...>
{
if (params.size() != n)
static void do_try(const std::vector<Boxed_Value> &params, int generation)
{
throw exception::arity_error(static_cast<int>(params.size()), n);
} else {
return f(BOOST_PP_REPEAT(n, casthelper, ~));
boxed_cast<Param>(params[generation]);
Try_Cast<Rest...>::do_try(params, generation+1);
}
}
};
// 0th case
template<>
struct Try_Cast<>
{
static void do_try(const std::vector<Boxed_Value> &, int)
{
}
};
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarly used to prevent
* registration of two functions with the exact same signatures
*/
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4100)
#endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, BOOST_PP_EMPTY), const Dynamic_Cast_Conversions &t_conversions)
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params)
{
try {
(void)t_conversions;
BOOST_PP_REPEAT(n, trycast, ~);
Try_Cast<Params...>::do_try(params, 0);
} catch (const exception::bad_boxed_cast &) {
return false;
}
@@ -151,24 +99,52 @@ namespace chaiscript
return true;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
template<typename Ret, int count, typename ... Params>
struct Call_Func
{
template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params, InnerParams &&... innerparams)
{
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
}
};
template<typename Ret, typename ... Params>
struct Call_Func<Ret, 0, Params...>
{
template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams))...);
}
};
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each paramter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
template<typename Ret, typename ... Params>
Ret call_func(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params)
{
if (params.size() == sizeof...(Params))
{
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params);
}
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
}
}
}
}
#undef n
#undef gettypeinfo
#undef casthelper
#undef trycast
#endif
#ifndef BOOST_PP_IS_ITERATING
namespace chaiscript
{
@@ -180,9 +156,9 @@ namespace chaiscript
struct Do_Call
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
return Handle_Return<Ret>::handle(call_func(fun, params));
}
};
@@ -190,9 +166,9 @@ namespace chaiscript
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
call_func(fun, params, t_conversions);
call_func(fun, params);
return Handle_Return<void>::handle();
}
};

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
@@ -9,12 +9,6 @@
#include "dispatchkit.hpp"
#include "bind_first.hpp"
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_object_pointer.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
namespace chaiscript
{
@@ -22,39 +16,48 @@ namespace chaiscript
{
namespace detail
{
template<bool Object, bool MemFn>
template<typename T>
struct FunctionSignature
{
};
template<typename Sig>
struct FunctionSignature<std::function<Sig> >
{
typedef Sig Signature;
};
template<typename Ret, typename ... Args>
std::function<Ret (Args...) > to_function(Ret (*func)(Args...))
{
return std::function<Ret (Args...)>(func);
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
{
return std::function<Ret (Class &, Args...)>(func);
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
{
return std::function<Ret (const Class &, Args...)>(func);
}
template<bool Object>
struct Fun_Helper
{
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
}
};
template<>
struct Fun_Helper<false, true>
{
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(boost::mem_fn(t))));
}
};
template<>
struct Fun_Helper<true, false>
struct Fun_Helper<true>
{
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
@@ -65,19 +68,19 @@ namespace chaiscript
}
}
/// \brief Creates a new Proxy_Function object from a boost::function object
/// \param[in] f boost::function to expose to ChaiScript
/// \brief Creates a new Proxy_Function object from a std::function object
/// \param[in] f std::function to expose to ChaiScript
///
/// \b Example:
/// \code
/// boost::function<int (char, float, std::string)> f = get_some_function();
/// std::function<int (char, float, std::string)> f = get_some_function();
/// chaiscript::ChaiScript chai;
/// chai.add(fun(f), "some_function");
/// \endcode
///
/// \sa \ref addingfunctions
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
Proxy_Function fun(const std::function<T> &f)
{
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
}
@@ -105,7 +108,7 @@ namespace chaiscript
template<typename T>
Proxy_Function fun(T t)
{
return dispatch::detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t);
return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
}
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
@@ -122,7 +125,7 @@ namespace chaiscript
/// MyClass obj;
/// chaiscript::ChaiScript chai;
/// // Add function taking only one argument, an int, and permanently bound to "obj"
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj)), "memberfunction");
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
/// \endcode
///
/// \sa \ref addingfunctions
@@ -148,7 +151,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai;
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
/// // memberfunction() will be equivalent to obj.memberfunction(1)
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj), 1), "memberfunction");
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
/// \endcode
///
/// \sa \ref addingfunctions

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
@@ -9,17 +9,8 @@
#include <string>
#include <typeinfo>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/ref.hpp>
#include <memory>
#include <type_traits>
namespace chaiscript
{
@@ -29,7 +20,7 @@ namespace chaiscript
template<typename T>
struct Bare_Type
{
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
};
}
@@ -99,12 +90,6 @@ namespace chaiscript
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
}
bool bare_equal_type_info(const std::type_info &ti) const
{
return m_bare_type_info != 0
&& (*m_bare_type_info) == ti;
}
bool is_const() const { return m_is_const; }
bool is_reference() const { return m_is_reference; }
bool is_void() const { return m_is_void; }
@@ -153,72 +138,72 @@ namespace chaiscript
{
typedef T type;
static Type_Info get()
constexpr static Type_Info get()
{
return Type_Info(boost::is_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(T),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<boost::shared_ptr<T> >
struct Get_Type_Info<std::shared_ptr<T> >
{
typedef T type;
static Type_Info get()
constexpr static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(boost::shared_ptr<T> ),
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(std::shared_ptr<T> ),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<const boost::shared_ptr<T> &>
struct Get_Type_Info<const std::shared_ptr<T> &>
{
typedef T type;
static Type_Info get()
constexpr static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(const boost::shared_ptr<T> &),
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(const std::shared_ptr<T> &),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<boost::reference_wrapper<T> >
struct Get_Type_Info<std::reference_wrapper<T> >
{
typedef T type;
static Type_Info get()
constexpr static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(boost::reference_wrapper<T> ),
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(std::reference_wrapper<T> ),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<const boost::reference_wrapper<T> &>
struct Get_Type_Info<const std::reference_wrapper<T> &>
{
typedef T type;
static Type_Info get()
constexpr static Type_Info get()
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(const boost::reference_wrapper<T> &),
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(const std::reference_wrapper<T> &),
&typeid(typename Bare_Type<T>::type));
}
};
@@ -240,7 +225,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode
template<typename T>
Type_Info user_type(const T &/*t*/)
constexpr Type_Info user_type(const T &/*t*/)
{
return detail::Get_Type_Info<T>::get();
}
@@ -255,7 +240,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \endcode
template<typename T>
Type_Info user_type()
constexpr Type_Info user_type()
{
return detail::Get_Type_Info<T>::get();
}

View File

@@ -1,14 +1,13 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "../dispatchkit/dispatchkit.hpp"
namespace chaiscript
{

View File

@@ -1,14 +1,14 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <sstream>
#include "../dispatchkit/dispatchkit.hpp"
namespace chaiscript
{
@@ -21,22 +21,23 @@ namespace chaiscript
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Switch, Case, Default, Ternary_Cond, Noop
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond
};
};
namespace
{
/// Helper lookup to get the name of each node type
/**
* Helper lookup to get the name of each node type
*/
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or", "Switch", "Case", "Default", "Ternary Condition", "Noop"};
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition"};
return ast_node_types[ast_node_type];
}
@@ -54,14 +55,15 @@ namespace chaiscript
};
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
namespace exception
{
/// Errors generated during parsing or evaluation
/**
* Errors generated during parsing or evaluation
*/
struct eval_error : public std::runtime_error {
std::string reason;
File_Position start_position;
@@ -73,26 +75,26 @@ namespace chaiscript
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) :
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) :
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) :
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
std::runtime_error(format(t_why, t_where, t_fname)),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
{}
eval_error(const std::string &t_why) throw()
eval_error(const std::string &t_why) noexcept
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
@@ -119,7 +121,7 @@ namespace chaiscript
return ss.str();
}
virtual ~eval_error() throw() {}
virtual ~eval_error() noexcept {}
private:
@@ -203,8 +205,8 @@ namespace chaiscript
}
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
if (dynfun)
{
@@ -212,8 +214,8 @@ namespace chaiscript
if (f)
{
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
if (dynfunguard)
{
retval += " : " + format_guard(dynfunguard->get_parse_tree());
@@ -375,25 +377,26 @@ namespace chaiscript
}
};
/// Errors generated when loading a file
/**
* Errors generated when loading a file
*/
struct file_not_found_error : public std::runtime_error {
file_not_found_error(const std::string &t_filename) throw()
file_not_found_error(const std::string &t_filename) noexcept
: std::runtime_error("File Not Found: " + t_filename)
{ }
virtual ~file_not_found_error() throw() {}
virtual ~file_not_found_error() noexcept {}
};
}
/// \brief Struct that doubles as both a parser ast_node and an AST node.
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
struct AST_Node : std::enable_shared_from_this<AST_Node> {
public:
const std::string text;
const int identifier;
boost::shared_ptr<const std::string> filename;
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
std::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
@@ -411,8 +414,9 @@ namespace chaiscript
return oss.str();
}
/// Prints the contents of an AST node, including its children, recursively
/**
* Prints the contents of an AST node, including its children, recursively
*/
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss;
@@ -446,14 +450,14 @@ namespace chaiscript
}
protected:
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(t_ast_node_text), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
@@ -474,27 +478,22 @@ namespace chaiscript
{
namespace detail
{
/// Special type for returned values
/**
* Special type for returned values
*/
struct Return_Value {
Boxed_Value retval;
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
};
/// Special type indicating a call to 'break'
/**
* Special type indicating a call to 'break'
*/
struct Break_Loop {
Break_Loop() { }
};
/// Special type indicating a call to 'continue'
struct Continue_Loop {
Continue_Loop() { }
};
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ENGINE_HPP_
@@ -10,12 +10,17 @@
#include <exception>
#include <fstream>
#include "../chaiscript_defines.hpp"
#include "chaiscript_common.hpp"
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
#include <unistd.h>
#endif
#ifdef _POSIX_VERSION
#include <dlfcn.h>
#else
#ifdef BOOST_WINDOWS
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
@@ -23,7 +28,7 @@
#endif
#include "chaiscript_prelude.hpp"
#include "chaiscript_prelude.chai"
#include "chaiscript_parser.hpp"
#include "../dispatchkit/exception_specification.hpp"
@@ -34,12 +39,12 @@ namespace chaiscript
/// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error
{
load_module_error(const std::string &t_reason) throw()
load_module_error(const std::string &t_reason) noexcept
: std::runtime_error(t_reason)
{
}
virtual ~load_module_error() throw()
virtual ~load_module_error() noexcept
{
}
};
@@ -57,7 +62,7 @@ namespace chaiscript
{
if (!m_data)
{
throw exception::load_module_error(dlerror());
throw chaiscript::exception::load_module_error(dlerror());
}
}
@@ -80,7 +85,7 @@ namespace chaiscript
{
if (!m_symbol)
{
throw exception::load_module_error(dlerror());
throw chaiscript::exception::load_module_error(dlerror());
}
}
@@ -180,7 +185,7 @@ namespace chaiscript
{
if (!m_data)
{
throw exception::load_module_error(GetErrorMessage(GetLastError()));
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
}
}
@@ -200,7 +205,7 @@ namespace chaiscript
{
if (!m_symbol)
{
throw exception::load_module_error(GetErrorMessage(GetLastError()));
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
}
}
@@ -223,7 +228,7 @@ namespace chaiscript
{
Loadable_Module(const std::string &, const std::string &)
{
throw exception::load_module_error("Loadable module support not available for your platform");
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
}
ModulePtr m_moduleptr;
@@ -231,7 +236,7 @@ namespace chaiscript
#endif
#endif
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
}
@@ -251,8 +256,9 @@ namespace chaiscript
chaiscript::detail::Dispatch_Engine m_engine;
/// Evaluates the given string in by parsing it and running the results through the evaluator
/**
* Evaluates the given string in by parsing it and running the results through the evaluator
*/
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
{
try {
@@ -281,8 +287,9 @@ namespace chaiscript
}
/// Evaluates the given string, used during eval() inside of a script
/**
* Evaluates the given string, used during eval() inside of a script
*/
const Boxed_Value internal_eval(const std::string &t_e) {
try {
return do_eval(t_e, "__EVAL__", true);
@@ -291,18 +298,17 @@ namespace chaiscript
}
}
/// Returns the current evaluation m_engine
/**
* Returns the current evaluation m_engine
*/
chaiscript::detail::Dispatch_Engine &get_eval_engine() {
return m_engine;
}
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
void build_eval_system() {
using namespace bootstrap;
m_engine.add_reserved_word("auto");
/**
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
*/
void build_eval_system(const ModulePtr &t_lib) {
m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while");
@@ -312,32 +318,27 @@ namespace chaiscript
m_engine.add_reserved_word("&&");
m_engine.add_reserved_word("||");
m_engine.add_reserved_word(",");
m_engine.add_reserved_word(":=");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("auto");
m_engine.add_reserved_word("return");
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("_");
add(Bootstrap::bootstrap());
if (t_lib)
{
add(t_lib);
}
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, boost::ref(m_engine)), "dump_system");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, boost::ref(m_engine)), "dump_object");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, boost::ref(m_engine)), "get_functions");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, boost::ref(m_engine)), "get_objects");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, std::ref(m_engine)), "dump_system");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, std::ref(m_engine)), "dump_object");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&chaiscript::detail::Dispatch_Engine::call_exists, boost::ref(m_engine), _1))),
"call_exists");
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(boost::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), _1, _2, boost::ref(m_engine.conversions()))), "call");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
typedef void (ChaiScript::*load_mod_1)(const std::string&);
@@ -346,25 +347,21 @@ namespace chaiscript
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
add(standard_library::string_type<std::string>("string"));
add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
m_engine.add(fun(&ChaiScript::use, this), "use");
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
do_eval(chaiscript_prelude, "standard prelude");
do_eval(ChaiScript_Prelude::chaiscript_prelude, "standard prelude");
}
/// Helper function for loading a file
/**
* Helper function for loading a file
*/
std::string load_file(const std::string &t_filename) {
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
if (!infile.is_open()) {
throw exception::file_not_found_error(t_filename);
throw chaiscript::exception::file_not_found_error(t_filename);
}
std::streampos size = infile.tellg();
@@ -384,9 +381,11 @@ namespace chaiscript
public:
/// \brief Constructor for ChaiScript
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
ChaiScript(const ModulePtr &t_lib,
const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
const std::vector<std::string> &t_usepaths = std::vector<std::string>())
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths)
{
@@ -400,9 +399,74 @@ namespace chaiscript
m_usepaths.push_back("");
}
build_eval_system();
build_eval_system(t_lib);
}
/// \brief Constructor for ChaiScript.
///
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
/// at runtime generates an error if it cannot be found.
///
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript( const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
const std::vector<std::string> &t_usepaths = std::vector<std::string>())
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths)
{
if (m_modulepaths.empty())
{
m_modulepaths.push_back("");
}
if (m_usepaths.empty())
{
m_usepaths.push_back("");
}
#ifdef _POSIX_VERSION
// If on Unix, add the path of the current executable to the module search path
// as windows would do
union cast_union
{
void (ChaiScript::*in_ptr)(const std::string&);
void *out_ptr;
};
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
cast_union u;
u.in_ptr = &ChaiScript::use;
if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
std::string dllpath(rInfo.dli_fname);
size_t lastslash = dllpath.rfind('/');
if (lastslash != std::string::npos)
{
dllpath.erase(lastslash);
}
// Let's see if this is a link that we should expand
std::vector<char> buf(2048);
size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && pathlen < buf.size())
{
dllpath = std::string(&buf.front(), pathlen);
}
m_modulepaths.push_back(dllpath+"/");
}
#endif
// attempt to load the stdlib
load_module("chaiscript_stdlib");
build_eval_system(ModulePtr());
}
/// \brief Loads and parses a file. If the file is already, it is not reloaded
/// The use paths specified at ChaiScript construction time are searched for the
/// requested file.
@@ -415,20 +479,19 @@ namespace chaiscript
try {
const std::string appendedpath = m_usepaths[i] + t_filename;
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
if (m_used_files.count(appendedpath) == 0)
{
m_used_files.insert(appendedpath);
l2.unlock();
eval_file(appendedpath);
l2.lock();
m_used_files.insert(appendedpath);
}
}
return; // return, we loaded it, or it was already loaded
} catch (const exception::file_not_found_error &) {
if (i == m_usepaths.size() - 1)
if (i == m_usepaths.size() - 1)
{
throw exception::file_not_found_error(t_filename);
}
@@ -441,7 +504,7 @@ namespace chaiscript
/// \brief Adds a constant object that is available in all contexts and to all threads
/// \param[in] t_bv Boxed_Value to add as a global
/// \param[in] t_name Name of the value to add
/// \throw exception::global_non_const If t_bv is not a constant object
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
/// \sa Boxed_Value::is_const
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
{
@@ -449,17 +512,6 @@ namespace chaiscript
return *this;
}
/// \brief Adds a mutable object that is available in all contexts and to all threads
/// \param[in] t_bv Boxed_Value to add as a global
/// \param[in] t_name Name of the value to add
/// \warning The user is responsible for making sure the object is thread-safe if necessary
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
{
m_engine.add_global(t_bv, t_name);
return *this;
}
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
/// \sa ChaiScript::get_state
/// \sa ChaiScript::set_state
@@ -592,7 +644,7 @@ namespace chaiscript
/// If no file can be found matching the search criteria and containing the appropriate entry point
/// (the symbol mentioned above), an exception is thrown.
///
/// \throw exception::load_module_error In the event that no matching module can be found.
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
void load_module(const std::string &t_module_name)
{
std::vector<exception::load_module_error> errors;
@@ -616,7 +668,7 @@ namespace chaiscript
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
load_module(t_module_name, name);
return;
} catch (const exception::load_module_error &e) {
} catch (const chaiscript::exception::load_module_error &e) {
errors.push_back(e);
// Try next set
}
@@ -638,7 +690,7 @@ namespace chaiscript
errstring += itr->what();
}
throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
}
/// \brief Load a binary module from a dynamic library. Works on platforms that support
@@ -672,14 +724,14 @@ namespace chaiscript
///
/// \return result of the script execution
///
/// \throw exception::eval_error In the case that evaluation fails.
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
{
try {
return do_eval(t_script);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
t_handler->handle(bv);
}
throw bv;
}
@@ -695,30 +747,22 @@ namespace chaiscript
///
/// \return result of the script execution
///
/// \throw exception::eval_error In the case that evaluation fails.
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// to the requested type.
template<typename T>
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
{
try {
return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
return boxed_cast<T>(do_eval(t_input, t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
t_handler->handle(bv);
}
throw bv;
}
}
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
{
return m_engine.boxed_cast<Type>(bv);
}
/// \brief Evaluates a string.
///
/// \param[in] t_input Script to execute
@@ -735,7 +779,7 @@ namespace chaiscript
return do_eval(t_input, t_filename);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
t_handler->handle(bv);
}
throw bv;
}
@@ -745,13 +789,13 @@ namespace chaiscript
/// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \return result of the script execution
/// \throw exception::eval_error In the case that evaluation fails.
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return do_eval(load_file(t_filename), t_filename);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
t_handler->handle(bv);
}
throw bv;
}
@@ -762,16 +806,16 @@ namespace chaiscript
/// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \return result of the script execution
/// \throw exception::eval_error In the case that evaluation fails.
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// to the requested type.
template<typename T>
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
t_handler->handle(bv);
}
throw bv;
}

File diff suppressed because it is too large Load Diff

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)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PARSER_HPP_
@@ -10,8 +10,8 @@
#include <exception>
#include <fstream>
#include <sstream>
#include <cstring>
#include "chaiscript_prelude.hpp"
#include "chaiscript_common.hpp"
namespace chaiscript
@@ -47,7 +47,7 @@ namespace chaiscript
std::string m_multiline_comment_begin;
std::string m_multiline_comment_end;
std::string m_singleline_comment;
boost::shared_ptr<std::string> m_filename;
std::shared_ptr<std::string> m_filename;
std::vector<AST_NodePtr> m_match_stack;
bool m_alphabet[detail::max_alphabet][detail::lengthof_alphabet];
@@ -524,7 +524,7 @@ namespace chaiscript
ss >> t_type;
std::stringstream testu(t_val.substr(0, i));
boost::uint64_t u;
uint64_t u;
testu >> t_type >> u;
bool unsignedrequired = false;
@@ -536,28 +536,19 @@ namespace chaiscript
long_ = true;
}
BOOST_ASSERT(sizeof(long) == sizeof(boost::uint64_t) || sizeof(long) * 2 == sizeof(boost::uint64_t));
static_assert(sizeof(long) == sizeof(uint64_t) || sizeof(long) * 2 == sizeof(uint64_t), "Unexpected sizing of integer types");
#ifdef BOOST_MSVC
//Thank you MSVC, yes we know that a constant value is being used in the if
// statment in this compiler / architecture
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
if ( sizeof(long) < sizeof(boost::uint64_t) && (u >> ((sizeof(boost::uint64_t) - sizeof(long)) * 8)) > 0)
if ((sizeof(long) < sizeof(uint64_t))
&& (u >> ((sizeof(uint64_t) - sizeof(long)) * 8)) > 0)
{
//requires something bigger than long
longlong_ = true;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
if (longlong_)
{
size = sizeof(boost::int64_t) * 8;
size = sizeof(int64_t) * 8;
} else if (long_) {
size = sizeof(long) * 8;
}
@@ -588,7 +579,7 @@ namespace chaiscript
{
if (longlong_)
{
boost::uint64_t val;
uint64_t val;
ss >> val;
return Boxed_Value(const_var(val));
} else if (long_) {
@@ -603,7 +594,7 @@ namespace chaiscript
} else {
if (longlong_)
{
boost::int64_t val;
int64_t val;
ss >> val;
return Boxed_Value(const_var(val));
} else if (long_) {
@@ -635,13 +626,13 @@ namespace chaiscript
if (Hex_()) {
std::string match(start, m_input_pos);
Boxed_Value i = buildInt(std::hex, match);
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
if (Binary_()) {
std::string match(start, m_input_pos);
boost::int64_t temp_int = 0;
int64_t temp_int = 0;
size_t pos = 0, end = match.length();
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
@@ -660,14 +651,14 @@ namespace chaiscript
i = Boxed_Value(const_var(temp_int));
}
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
if (Float_()) {
std::string match(start, m_input_pos);
Boxed_Value f = buildFloat(match);
AST_NodePtr t(new eval::Float_AST_Node(match, f, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Float_AST_Node(match, f, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
@@ -676,12 +667,12 @@ namespace chaiscript
std::string match(start, m_input_pos);
if ((match.size() > 0) && (match[0] == '0')) {
Boxed_Value i = buildInt(std::oct, match);
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
}
else {
Boxed_Value i = buildInt(std::dec, match);
AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
}
return true;
@@ -751,13 +742,13 @@ namespace chaiscript
if (*start == '`') {
//Id Literal
std::string match(start+1, m_input_pos-1);
AST_NodePtr t(new eval::Id_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Id_AST_Node(match, AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
else {
std::string match(start, m_input_pos);
AST_NodePtr t(new eval::Id_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Id_AST_Node(match, AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
@@ -790,7 +781,7 @@ namespace chaiscript
} while (Symbol("#"));
std::string match(start, m_input_pos);
AST_NodePtr t(new eval::Annotation_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Annotation_AST_Node(match, AST_Node_Type::Annotation, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
@@ -865,13 +856,13 @@ namespace chaiscript
if (is_interpolated) {
//If we've seen previous interpolation, add on instead of making a new one
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
}
else {
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
}
@@ -891,17 +882,17 @@ namespace chaiscript
size_t tostr_stack_top = m_match_stack.size();
AST_NodePtr tostr(new eval::Id_AST_Node("to_string", m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr tostr(new eval::Id_AST_Node("to_string", AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(tostr);
size_t ev_stack_top = m_match_stack.size();
AST_NodePtr ev(new eval::Id_AST_Node("eval", m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr ev(new eval::Id_AST_Node("eval", AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(ev);
size_t arg_stack_top = m_match_stack.size();
AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), arg_stack_top);
@@ -959,13 +950,13 @@ namespace chaiscript
}
}
if (is_interpolated) {
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
}
else {
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
}
return true;
@@ -1057,7 +1048,7 @@ namespace chaiscript
is_escaped = false;
}
}
AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, AST_Node_Type::Single_Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
@@ -1096,7 +1087,7 @@ namespace chaiscript
int prev_line = m_line;
if (Char_(t_c)) {
std::string match(start, m_input_pos);
AST_NodePtr t(new eval::Char_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Char_AST_Node(match, AST_Node_Type::Char, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
@@ -1148,7 +1139,7 @@ namespace chaiscript
if ( t_capture && retval ) {
std::string match(start, m_input_pos);
AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Str_AST_Node(match, AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
}
return retval;
@@ -1196,7 +1187,7 @@ namespace chaiscript
if ( t_capture && retval ) {
std::string match(start, m_input_pos);
AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Str_AST_Node(match, AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
}
@@ -1236,7 +1227,7 @@ namespace chaiscript
int prev_line = m_line;
if (Eol_()) {
std::string match(start, m_input_pos);
AST_NodePtr t(new eval::Eol_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
AST_NodePtr t(new eval::Eol_AST_Node(match, AST_Node_Type::Eol, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
return true;
}
@@ -1506,7 +1497,7 @@ namespace chaiscript
if (Keyword("else", true)) {
if (Keyword("if")) {
AST_NodePtr back(m_match_stack.back());
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if"));
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if", back->identifier));
m_match_stack.back()->start = back->start;
m_match_stack.back()->end = back->end;
m_match_stack.back()->children = back->children;
@@ -1574,40 +1565,18 @@ namespace chaiscript
return retval;
}
/**
* Reads the C-style for conditions from input
*/
bool For_Guards() {
if (!(Equation() && Eol()))
{
if (!Eol())
{
throw exception::eval_error("'for' loop initial statment missing", File_Position(m_line, m_col), *m_filename);
} else {
AST_NodePtr t(new eval::Noop_AST_Node());
m_match_stack.push_back(t);
}
}
Equation();
if (!(Equation() && Eol()))
{
if (!Eol())
{
throw exception::eval_error("'for' loop condition missing", File_Position(m_line, m_col), *m_filename);
} else {
AST_NodePtr t(new eval::Noop_AST_Node());
m_match_stack.push_back(t);
}
if (Char(';') && Operator() && Char(';') && Equation()) {
return true;
}
if (!Equation())
{
AST_NodePtr t(new eval::Noop_AST_Node());
m_match_stack.push_back(t);
else {
throw exception::eval_error("Incomplete conditions in 'for' loop", File_Position(m_line, m_col), *m_filename);
}
return true;
}
/**
@@ -1724,7 +1693,7 @@ namespace chaiscript
}
}
/**
* Reads a curly-brace C-style block from input
*/
@@ -1782,23 +1751,6 @@ namespace chaiscript
return retval;
}
/**
* Reads a continue statement from input
*/
bool Continue() {
bool retval = false;
size_t prev_stack_top = m_match_stack.size();
if (Keyword("continue")) {
retval = true;
build_match(AST_NodePtr(new eval::Continue_AST_Node()), prev_stack_top);
}
return retval;
}
/**
* Reads a dot expression(member access), then proceeds to check if it's a function or array call
*/
@@ -1868,10 +1820,10 @@ namespace chaiscript
size_t prev_stack_top = m_match_stack.size();
if (Keyword("var")) {
if (Keyword("auto") || Keyword("var")) {
retval = true;
if (!Id(true)) {
if (!(Reference() || Id(true))) {
throw exception::eval_error("Incomplete variable declaration", File_Position(m_line, m_col), *m_filename);
}
@@ -1948,6 +1900,25 @@ namespace chaiscript
return retval;
}
bool Reference() {
bool retval = false;
size_t prev_stack_top = m_match_stack.size();
if (Symbol("&", false)) {
retval = true;
if (!Id(true)) {
throw exception::eval_error("Incomplete '&' expression", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(
new eval::Reference_AST_Node()), prev_stack_top);
}
return retval;
}
/**
* Reads a unary prefixed expression from input
*/
@@ -2010,6 +1981,15 @@ namespace chaiscript
build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top);
}
else if (Char('&', true)) {
retval = true;
if (!Operator(m_operators.size()-1)) {
throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top);
}
return retval;
}
@@ -2296,13 +2276,10 @@ namespace chaiscript
retval = true;
saw_eol = false;
}
else if (Continue()) {
if (!saw_eol) {
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
}
else if (Block()) {
has_more = true;
retval = true;
saw_eol = false;
saw_eol = true;
}
else if (Equation()) {
if (!saw_eol) {
@@ -2317,11 +2294,6 @@ namespace chaiscript
retval = true;
saw_eol = true;
}
else if (Block()) {
has_more = true;
retval = true;
saw_eol = true;
}
else {
has_more = false;
}
@@ -2338,7 +2310,7 @@ namespace chaiscript
m_input_end = t_input.end();
m_line = 1;
m_col = 1;
m_filename = boost::shared_ptr<std::string>(new std::string(t_fname));
m_filename = std::shared_ptr<std::string>(new std::string(t_fname));
if ((t_input.size() > 1) && (t_input[0] == '#') && (t_input[1] == '!')) {
while ((m_input_pos != m_input_end) && (!Eol())) {

View File

@@ -0,0 +1,530 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_
#define CHAISCRIPT_PRELUDE_HPP_
namespace chaiscript {
struct ChaiScript_Prelude {
constexpr static const char *chaiscript_prelude=R""(
def lt(l, r) {
if (call_exists(`<`, l, r)) {
l < r
} else {
type_name(l) < type_name(r)
}
}
def gt(l, r) {
if (call_exists(`>`, l, r)) {
l > r
} else {
type_name(l) > type_name(r)
}
}
def eq(l, r) {
if (call_exists(`==`, l, r)) {
l == r
} else {
false
}
}
def new(x) {
eval(type_name(x))();
}
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x);
}
# to_string for Pair()
def to_string(x) : call_exists(first, x) && call_exists(second, x) {
"<" + x.first.to_string() + ", " + x.second.to_string() + ">";
}
# to_string for containers
def to_string(x) : call_exists(range, x) && !x.is_type("string"){
"[" + x.join(", ") + "]";
}
# Basic to_string function
def to_string(x) {
internal_to_string(x);
}
# Prints to console with no carriage return
def puts(x) {
print_string(x.to_string());
}
# Prints to console with carriage return
def print(x) {
println_string(x.to_string());
}
# Returns the maximum value of two numbers
def max(a, b) {
if (a>b) {
a
} else {
b
}
}
# Returns the minimum value of two numbers
def min(a, b)
{
if (a<b)
{
a
} else {
b
}
}
# Returns true if the value is odd
def odd(x) {
if (x % 2 == 1)
{
true
} else {
false
}
}
# Returns true if the value is even
def even(x)
{
if (x % 2 == 0)
{
true
} else {
false
}
}
# Pushes the second value onto the container first value while making a clone of the value
def push_back(container, x) : call_exists(push_back_ref, container, x)
{
container.push_back_ref(clone(x))
}
# Pushes the second value onto the front of the container first value while making a clone of the value
def push_front(container, x) : call_exists(push_front_ref, container, x)
{
container.push_front_ref(clone(x))
}
# Inserts the third value at the position of the second value into the container of the first
# while making a clone.
def insert_at(container, pos, x)
{
container.insert_ref_at(pos, clone(x));
}
# Returns the reverse of the given container
def reverse(container) {
auto retval = new(container);
auto r = range(container);
while (!r.empty()) {
retval.push_back(r.back());
r.pop_back();
}
retval;
}
# Return a range from a range
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
{
return clone(r);
}
# The retro attribute that contains the underlying range
attr retro::m_range;
# Creates a retro from a retro by returning the original range
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro"
{
clone(r.m_range)
}
# Creates a retro range from a range
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
{
this.m_range = r;
}
# Returns the first value of a retro
def retro::front()
{
back(this.m_range)
}
# Returns the last value of a retro
def retro::back()
{
front(this.m_range)
}
# Moves the back iterator of a retro towards the front by one
def retro::pop_back()
{
pop_front(this.m_range)
}
# Moves the front iterator of a retro towards the back by one
def retro::pop_front()
{
pop_back(this.m_range)
}
# returns true if the retro is out of elements
def retro::empty()
{
empty(this.m_range);
}
# Performs the second value function over the container first value
def for_each(container, func) : call_exists(range, container) {
var t_range = range(container);
while (!t_range.empty()) {
func(t_range.front());
t_range.pop_front();
}
}
def back_inserter(container) {
bind(push_back, container, _);
}
def contains(container, item, compare_func) : call_exists(range, container) {
auto t_range = range(container);
while (!t_range.empty()) {
if ( compare_func(t_range.front(), item) ) {
return true;
}
t_range.pop_front();
}
return false;
}
def contains(container, item) {
return contains(container, item, eq)
}
def map(container, func, inserter) : call_exists(range, container) {
auto range = range(container);
while (!range.empty()) {
inserter(func(range.front()));
range.pop_front();
}
}
# Performs the second value function over the container first value. Creates a new container with the results
def map(container, func) {
auto retval = new(container);
map(container, func, back_inserter(retval));
retval;
}
# Performs the second value function over the container first value. Starts with initial and continues with each element.
def foldl(container, func, initial) : call_exists(range, container){
auto retval = initial;
auto range = range(container);
while (!range.empty()) {
retval = (func(range.front(), retval));
range.pop_front();
}
retval;
}
# Returns the sum of the elements of the given value
def sum(container) {
foldl(container, `+`, 0.0)
}
# Returns the product of the elements of the given value
def product(container) {
foldl(container, `*`, 1.0)
}
# Returns a new container with the elements of the first value concatenated with the elements of the second value
def concat(x, y) : call_exists(clone, x) {
auto retval = x;
auto inserter = back_inserter(retval);
auto range = range(y);
while (!range.empty()) {
inserter(range.front());
range.pop_front();
}
retval;
}
def take(container, num, inserter) : call_exists(range, container) {
auto r = range(container);
auto i = num;
while ((i > 0) && (!r.empty())) {
inserter(r.front());
r.pop_front();
--i;
}
}
# Returns a new container with the given number of elements taken from the container
def take(container, num) {
auto retval = new(container);
take(container, num, back_inserter(retval));
retval;
}
def take_while(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
while ((!r.empty()) && f(r.front())) {
inserter(r.front());
r.pop_front();
}
}
# Returns a new container with the given elements match the second value function
def take_while(container, f) {
auto retval = new(container);
take_while(container, f, back_inserter(retval));
retval;
}
def drop(container, num, inserter) : call_exists(range, container) {
auto r = range(container);
auto i = num;
while ((i > 0) && (!r.empty())) {
r.pop_front();
--i;
}
while (!r.empty()) {
inserter(r.front());
r.pop_front();
}
}
# Returns a new container with the given number of elements dropped from the given container
def drop(container, num) {
auto retval = new(container);
drop(container, num, back_inserter(retval));
retval;
}
def drop_while(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
while ((!r.empty())&& f(r.front())) {
r.pop_front();
}
while (!r.empty()) {
inserter(r.front());
r.pop_front();
}
}
# Returns a new container with the given elements dropped that match the second value function
def drop_while(container, f) {
auto retval = new(container);
drop_while(container, f, back_inserter(retval));
retval;
}
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) {
auto r = range(container);
auto retval = r.front();
r.pop_front();
retval = func(retval, r.front());
r.pop_front();
while (!r.empty()) {
retval = func(retval, r.front());
r.pop_front();
}
retval;
}
# Returns a string of the elements in container delimited by the second value string
def join(container, delim) {
auto retval = "";
auto range = range(container);
if (!range.empty()) {
retval += to_string(range.front());
range.pop_front();
while (!range.empty()) {
retval += delim;
retval += to_string(range.front());
range.pop_front();
}
}
retval;
}
def filter(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
while (!r.empty()) {
if (f(r.front())) {
inserter(r.front());
}
r.pop_front();
}
}
# Returns a new Vector which match the second value function
def filter(container, f) {
auto retval = new(container);
filter(container, f, back_inserter(retval));
retval;
}
def generate_range(x, y, inserter) {
auto i = x;
while (i <= y) {
inserter(i);
++i;
}
}
# Returns a new Vector which represents the range from the first value to the second value
def generate_range(x, y) {
auto retval = Vector();
generate_range(x,y,back_inserter(retval));
retval;
}
# Returns a new Vector with the first value to the second value as its elements
def collate(x, y) {
return [x, y];
}
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) {
auto r_x = range(x);
auto r_y = range(y);
while (!r_x.empty() && !r_y.empty()) {
inserter(f(r_x.front(), r_y.front()));
r_x.pop_front();
r_y.pop_front();
}
}
# Returns a new Vector which joins matching elements of the second and third value with the first value function
def zip_with(f, x, y) {
auto retval = Vector();
zip_with(f,x,y,back_inserter(retval));
retval;
}
# Returns a new Vector which joins matching elements of the first and second
def zip(x, y) {
zip_with(collate, x, y);
}
# Returns the position of the second value string in the first value string
def string::find(substr) : is_type(substr, "string") {
int(find(this, substr, 0));
}
# Returns the position of last match of the second value string in the first value string
def string::rfind(substr) : is_type(substr, "string") {
int(rfind(this, substr, -1));
}
# Returns the position of the first match of elements in the second value string in the first value string
def string::find_first_of(list) : is_type(list, "string") {
int(find_first_of(this, list, 0));
}
# Returns the position of the last match of elements in the second value string in the first value string
def string::find_last_of(list) : is_type(list, "string") {
int(find_last_of(this, list, -1));
}
# Returns the position of the first non-matching element in the second value string in the first value string
def string::find_first_not_of(list) : is_type(list, "string") {
int(find_first_not_of(this, list, 0));
}
# Returns the position of the last non-matching element in the second value string in the first value string
def string::find_last_not_of(list) : is_type(list, "string") {
int(find_last_not_of(this, list, -1));
}
def string::ltrim() {
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'});
}
def string::rtrim() {
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}));
}
def string::trim() {
ltrim(rtrim(this));
}
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
auto range = range(container);
while (!range.empty()) {
if (compare_func(range.front(), value)) {
return range;
} else {
range.pop_front();
}
}
return range;
}
def find(container, value) {
return find(container, value, eq)
}
)"";
};
}
#endif /* CHAISCRIPT_PRELUDE_HPP_ */

View File

@@ -1,329 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_
#define CHAISCRIPT_PRELUDE_HPP_
//Note, the expression "[x,y]" in "collate" is parsed as two separate expressions
//by C++, so CODE_STRING, takes two expressions and adds in the missing comma
#define CODE_STRING(x, y) #x ", " #y
#define chaiscript_prelude CODE_STRING(\
def lt(l, r) { if (call_exists(`<`, l, r)) { l < r } else { type_name(l) < type_name(r) } } \n\
def gt(l, r) { if (call_exists(`>`, l, r)) { l > r } else { type_name(l) > type_name(r) } } \n\
def eq(l, r) { if (call_exists(`==`, l, r)) { l == r } else { false } } \n\
def new(x) { eval(type_name(x))(); } \n\
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) { eval(type_name(x))(x); } \n\
# to_string for Pair()\n\
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \n\
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \n\
}\n\
# to_string for containers\n\
def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \n\
"[" + x.join(", ") + "]"; \n\
}\n\
# Basic to_string function\n\
def to_string(x) { \n\
internal_to_string(x); \n\
}\n\
# Prints to console with no carriage return\n\
def puts(x) { \n\
print_string(x.to_string()); \n\
} \n\
# Prints to console with carriage return\n\
def print(x) { \n\
println_string(x.to_string()); \n\
} \n\
# Returns the maximum value of two numbers\n\
def max(a, b) { if (a>b) { a } else { b } } \n\
# Returns the minimum value of two numbers\n\
def min(a, b) { if (a<b) { a } else { b } } \n\
# Returns true if the value is odd\n\
def odd(x) { if (x % 2 == 1) { true } else { false } } \n\
# Returns true if the value is even\n\
def even(x) { if (x % 2 == 0) { true } else { false } } \n\
# Pushes the second value onto the container first value while making a clone of the value\n\
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_ref(clone(x)) } \n\
# Pushes the second value onto the front of the container first value while making a clone of the value\n\
def push_front(container, x) : call_exists(push_front_ref, container, x) { container.push_front_ref(clone(x)) } \n\
# Inserts the third value at the position of the second value into the container of the first\n\
# while making a clone. \n\
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
# Returns the reverse of the given container\n\
def reverse(container) {\n\
var retval = new(container); \n\
var r = range(container); \n\
while (!r.empty()) { \n\
retval.push_back(r.back()); \n\
r.pop_back(); \n\
} \n\
retval; \n\
} \n\
# Return a range from a range \n\
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { return clone(r); }\n\
# The retro attribute that contains the underlying range \n\
attr retro::m_range; \n\
# Creates a retro from a retro by returning the original range\n\
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro" { clone(r.m_range) }\n\
# Creates a retro range from a range\n\
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { this.m_range = r; }\n\
# Returns the first value of a retro\n\
def retro::front() { back(this.m_range) }\n\
# Returns the last value of a retro\n\
def retro::back() { front(this.m_range) }\n\
# Moves the back iterator of a retro towards the front by one \n\
def retro::pop_back() { pop_front(this.m_range) }\n\
# Moves the front iterator of a retro towards the back by one \n\
def retro::pop_front() { pop_back(this.m_range) } \n\
# returns true if the retro is out of elements \n\
def retro::empty() { empty(this.m_range); } \n\
# Performs the second value function over the container first value\n\
def for_each(container, func) : call_exists(range, container) { \n\
var t_range = range(container); \n\
while (!t_range.empty()) { \n\
func(t_range.front()); \n\
t_range.pop_front(); \n\
} \n\
} \n\
def back_inserter(container) { \n\
bind(push_back, container, _); \n\
}\n\
\n\
def contains(container, item, compare_func) : call_exists(range, container) { \n\
var t_range = range(container); \n\
while (!t_range.empty()) { \n\
if ( compare_func(t_range.front(), item) ) { return true; } \n\
t_range.pop_front(); \n\
} \n\
return false; \n\
} \n\
def contains(container, item) { return contains(container, item, eq) } \n\
def map(container, func, inserter) : call_exists(range, container) { \n\
var range = range(container); \n\
while (!range.empty()) { \n\
inserter(func(range.front())); \n\
range.pop_front(); \n\
} \n\
} \n\
# Performs the second value function over the container first value. Creates a new container with the results\n\
def map(container, func) { \n\
var retval = new(container); \n\
map(container, func, back_inserter(retval));\n\
retval;\n\
}\n\
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
def foldl(container, func, initial) : call_exists(range, container){ \n\
var retval = initial; \n\
var range = range(container); \n\
while (!range.empty()) { \n\
retval = (func(range.front(), retval)); \n\
range.pop_front(); \n\
} \n\
retval; \n\
} \n\
# Returns the sum of the elements of the given value\n\
def sum(container) { foldl(container, `+`, 0.0) } \n\
# Returns the product of the elements of the given value\n\
def product(container) { foldl(container, `*`, 1.0) } \n\
# Returns a new container with the elements of the first value concatenated with the elements of the second value\n\
def concat(x, y) : call_exists(clone, x) { \n\
var retval = x; \n\
var inserter = back_inserter(retval); \n\
var range = range(y); \n\
while (!range.empty()) { \n\
inserter(range.front()); \n\
range.pop_front(); \n\
} \n\
retval; \n\
} \n\
def take(container, num, inserter) : call_exists(range, container) { \n\
var r = range(container); \n\
var i = num; \n\
while ((i > 0) && (!r.empty())) { \n\
inserter(r.front()); \n\
r.pop_front(); \n\
--i; \n\
} \n\
} \n\
# Returns a new container with the given number of elements taken from the container\n\
def take(container, num) {\n\
var retval = new(container); \n\
take(container, num, back_inserter(retval)); \n\
retval; \n\
}\n\
def take_while(container, f, inserter) : call_exists(range, container) { \n\
var r = range(container); \n\
while ((!r.empty()) && f(r.front())) { \n\
inserter(r.front()); \n\
r.pop_front(); \n\
} \n\
} \n\
# Returns a new container with the given elements match the second value function\n\
def take_while(container, f) {\n\
var retval = new(container); \n\
take_while(container, f, back_inserter(retval)); \n\
retval;\n\
}\n\
def drop(container, num, inserter) : call_exists(range, container) { \n\
var r = range(container); \n\
var i = num; \n\
while ((i > 0) && (!r.empty())) { \n\
r.pop_front(); \n\
--i; \n\
} \n\
while (!r.empty()) { \n\
inserter(r.front()); \n\
r.pop_front(); \n\
} \n\
} \n\
# Returns a new container with the given number of elements dropped from the given container \n\
def drop(container, num) {\n\
var retval = new(container); \n\
drop(container, num, back_inserter(retval)); \n\
retval; \n\
}\n\
def drop_while(container, f, inserter) : call_exists(range, container) { \n\
var r = range(container); \n\
while ((!r.empty())&& f(r.front())) { \n\
r.pop_front(); \n\
} \n\
while (!r.empty()) { \n\
inserter(r.front()); \n\
r.pop_front(); \n\
} \n\
} \n\
# Returns a new container with the given elements dropped that match the second value function\n\
def drop_while(container, f) {\n\
var retval = new(container); \n\
drop_while(container, f, back_inserter(retval)); \n\
retval; \n\
}\n\
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \n\
var r = range(container); \n\
var retval = r.front(); \n\
r.pop_front(); \n\
retval = func(retval, r.front()); \n\
r.pop_front(); \n\
while (!r.empty()) { \n\
retval = func(retval, r.front()); \n\
r.pop_front(); \n\
} \n\
retval; \n\
} \n\
# Returns a string of the elements in container delimited by the second value string\n\
def join(container, delim) { \n\
var retval = ""; \n\
var range = range(container); \n\
if (!range.empty()) { \n\
retval += to_string(range.front()); \n\
range.pop_front(); \n\
while (!range.empty()) { \n\
retval += delim; \n\
retval += to_string(range.front()); \n\
range.pop_front(); \n\
} \n\
} \n\
retval; \n\
} \n\
def filter(container, f, inserter) : call_exists(range, container) { \n\
var r = range(container); \n\
while (!r.empty()) { \n\
if (f(r.front())) { \n\
inserter(r.front()); \n\
} \n\
r.pop_front(); \n\
} \n\
} \n\
# Returns a new Vector which match the second value function\n\
def filter(container, f) { \n\
var retval = new(container); \n\
filter(container, f, back_inserter(retval));\n\
retval;\n\
}\n\
def generate_range(x, y, inserter) { \n\
var i = x; \n\
while (i <= y) { \n\
inserter(i); \n\
++i; \n\
} \n\
} \n\
# Returns a new Vector which represents the range from the first value to the second value\n\
def generate_range(x, y) { \n\
var retval = Vector(); \n\
generate_range(x,y,back_inserter(retval)); \n\
retval; \n\
}\n\
# Returns a new Vector with the first value to the second value as its elements\n\
def collate(x, y) { \n\
[x, y]; \n\
} \n\
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \n\
var r_x = range(x); \n\
var r_y = range(y); \n\
while (!r_x.empty() && !r_y.empty()) { \n\
inserter(f(r_x.front(), r_y.front())); \n\
r_x.pop_front(); \n\
r_y.pop_front(); \n\
} \n\
} \n\
# Returns a new Vector which joins matching elements of the second and third value with the first value function\n\
def zip_with(f, x, y) { \n\
var retval = Vector(); \n\
zip_with(f,x,y,back_inserter(retval)); \n\
retval;\n\
}\n\
# Returns a new Vector which joins matching elements of the first and second\n\
def zip(x, y) { \n\
zip_with(collate, x, y); \n\
}\n\
# Returns the position of the second value string in the first value string\n\
def string::find(substr) : is_type(substr, "string") { \n\
int(find(this, substr, 0)); \n\
} \n\
# Returns the position of last match of the second value string in the first value string\n\
def string::rfind(substr) : is_type(substr, "string") { \n\
int(rfind(this, substr, -1)); \n\
} \n\
# Returns the position of the first match of elements in the second value string in the first value string\n\
def string::find_first_of(list) : is_type(list, "string") { \n\
int(find_first_of(this, list, 0)); \n\
} \n\
# Returns the position of the last match of elements in the second value string in the first value string\n\
def string::find_last_of(list) : is_type(list, "string") { \n\
int(find_last_of(this, list, -1)); \n\
} \n\
# Returns the position of the first non-matching element in the second value string in the first value string\n\
def string::find_first_not_of(list) : is_type(list, "string") { \n\
int(find_first_not_of(this, list, 0)); \n\
} \n\
# Returns the position of the last non-matching element in the second value string in the first value string\n\
def string::find_last_not_of(list) : is_type(list, "string") { \n\
int(find_last_not_of(this, list, -1)); \n\
} \n\
def string::ltrim() { \n\
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}); \n\
} \n\
def string::rtrim() { \n\
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'})); \n\
} \n\
def string::trim() { \n\
ltrim(rtrim(this)); \n\
} \n\
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { \n\
var range = range(container); \n\
while (!range.empty()) { \n\
if (compare_func(range.front(), value)) { \n\
return range; \n\
} else { \n\
range.pop_front(); \n\
} \n\
} \n\
return range; \n\
} \n\
def find(container, value) { return find(container, value, eq) } \
)
#endif /* CHAISCRIPT_PRELUDE_HPP_ */

View File

@@ -1,97 +1,40 @@
// 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)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include "../chaiscript.hpp"
#include <boost/preprocessor.hpp>
#include <string>
#define CHAISCRIPT_MODULE(_info) BOOST_PP_SEQ_ELEM(0, _info)
#define CHAISCRIPT_CLASS_ELEM(_info) BOOST_PP_SEQ_ELEM(1, _info)
#define CHAISCRIPT_METHOD(_info, _method) & CHAISCRIPT_CLASS_ELEM(_info) :: BOOST_PP_SEQ_ELEM(0, _method)
#define CHAISCRIPT_METHOD_NAME(_info, _method) \
BOOST_PP_SEQ_ELEM(3, _info) (BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0, _method ) ) )
#define CHAISCRIPT_CLASS_NAME(_info) \
BOOST_PP_SEQ_ELEM(2, _info) (BOOST_PP_STRINGIZE(CHAISCRIPT_CLASS_ELEM(_info) ) )
#define CHAISCRIPT_METHOD_SIGNATURE_PART(_r, _info, _i, _method_part) \
BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(_i, 1), < _method_part > )
#define CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
BOOST_PP_SEQ_FOR_EACH_I(CHAISCRIPT_METHOD_SIGNATURE_PART, _info, _method)
#define CHAISCRIPT_CLASS_CONSTRUCTOR(_r, _info, _constructor) \
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::constructor<_constructor>() BOOST_PP_COMMA() CHAISCRIPT_CLASS_NAME(_info) BOOST_PP_RPAREN() ;
#define CHAISCRIPT_CLASS_METHOD(_r, _info, _method) \
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::fun CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
BOOST_PP_LPAREN() CHAISCRIPT_METHOD(_info, _method) BOOST_PP_RPAREN() BOOST_PP_COMMA() CHAISCRIPT_METHOD_NAME(_info, _method)BOOST_PP_RPAREN() ;
#define CHAISCRIPT_CLASS_CONSTRUCTORS(_info, _constructors) \
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_CONSTRUCTOR, _info, _constructors)
#define CHAISCRIPT_CLASS_METHODS(_info, _methods) \
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_METHOD, _info, _methods)
#define CHAISCRIPT_CLASS_EX(_module, _class_name, _class_name_translator, _method_name_translator, _constructors, _methods) \
{ \
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
CHAISCRIPT_CLASS_CONSTRUCTORS((_module)(_class_name)(_class_name_translator), _constructors) \
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
}
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, _class_name_translator, _method_name_translator, _methods) \
{ \
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
}
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _constructors, _methods)
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR(_module, _class_name, _methods) \
CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _methods)
namespace chaiscript
{
/// \brief Classes and functions which provide general utility to the end user.
namespace utility
{
inline std::string class_name_translator(const std::string &t_name)
{
size_t colon = t_name.rfind("::");
if (colon != std::string::npos)
template<typename Class, typename ModuleType>
void add_class(ModuleType &t_module,
const std::string &t_classname,
const std::vector<chaiscript::Proxy_Function> &t_constructors,
const std::vector<std::pair<chaiscript::Proxy_Function, std::string>> &t_funcs)
{
return t_name.substr(colon+2, std::string::npos);
} else {
return t_name;
t_module.add(chaiscript::user_type<Class>(), t_classname);
for(const chaiscript::Proxy_Function &ctor: t_constructors)
{
t_module.add(ctor, t_classname);
}
for(auto fun: t_funcs)
{
t_module.add(fun.first, fun.second);
}
}
}
inline std::string method_name_translator(const std::string &t_name)
{
size_t namestart = t_name.rfind("operator");
namestart = (namestart == std::string::npos)?0:namestart+strlen("operator");
if (namestart == 0)
{
namestart = t_name.rfind("::");
namestart = (namestart == std::string::npos)?0:namestart+strlen("::");
}
return t_name.substr(namestart, std::string::npos);
}
}
}

View File

@@ -1,7 +1,4 @@
Copyright 2009-2014 Jason Turner
Copyright 2009-2012 Jonathan Turner.
All Rights Reserved.
Copyright 2009-2012 Jason Turner and Jonathan Turner. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

View File

@@ -2,11 +2,11 @@ ChaiScript
http://www.chaiscript.com
(c) 2009-2012 Jonathan Turner
(c) 2009-2014 Jason Turner
(c) 2009-2012 Jason Turner and Jonathan Turner
Release under the BSD license, see "license.txt" for details.
Introduction
============
@@ -16,26 +16,33 @@ techniques, working with the developer like he expects it to work. Being a
native C++ application, it has some advantages over existing embedded scripting
languages:
1) It uses a header-only approach, which makes it easy to integrate with
1. It uses a header-only approach, which makes it easy to integrate with
existing projects.
2) It maintains type safety between your C++ application and the user scripts.
3) It supports a variety of C++ techniques including callbacks, overloaded
2. It maintains type safety between your C++ application and the user scripts.
3. It supports a variety of C++ techniques including callbacks, overloaded
functions, class methods, and stl containers.
Requirements
============
ChaiScript requires a recent version of Boost (http://www.boost.org) to build.
ChaiScript requires a C++11 compiler to build with support for variadic
templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx). MacOS
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
clang 4.0.
Usage
=====
* Add the ChaiScript include directory to your project's header search path
* Add `#include <chaiscript/chaiscript.hpp>` to your source file
* Instantiate the ChaiScript engine in your application. For example, create
a new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
* Instantiate the ChaiScript engine in your application. For example, create a
new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
* The default behavior is to load the ChaiScript standard library from a
loadable module. A second option is to compile the library into your code,
see below for an example.
Once instantiated, the engine is ready to start running ChaiScript source. You
Once instantiated, the engine is ready to start running ChaiScript source. You
have two main options for processing ChaiScript source: a line at a time using
`chai.eval(string)` and a file at a time using `chai.eval_file(fname)`
@@ -81,3 +88,26 @@ The shortest complete example possible follows:
}
Or, if you want to compile the std lib into your code, which reduces
runtime requirements.
/// main.cpp
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}

View File

@@ -1,36 +1,12 @@
Current Version: 4.3.0
Note: this is scheduled to be the last release that requires boost, new releases after this will require a C++11 compiler.
### Changes since 4.2.0
* Enhanced unit tests
* Add `continue` statement, fix various use cases for `for` loops
* Fix use of suffixed numbers in vector initialization
* Code cleanups
* Eliminate global data, which makes code more portable and thread safe
* Fix issue #79
* Merge pretty_print fixes from @mgee #82
* Compiler warning fixes for latest compiler releases
* Fix threading problems
* Fix linking error on MacOS Mavericks #88
* Allow non-const globals
* Make sure user cannot name a variable with `::` in it #91
* Fix various string / map / vector `size` and `count` calls for compilers which have weird overloads for them. #90 #93 #95
* Make module search path relative to the currently running executable
* Build and work with wstring windows builds
### Changes since 4.1.1
* Add support for automatic conversion of arithmetic types when possible
and when no ambiguous method dispatch exists.
### Changes since 4.1.0
* Fix missed gcc build error in 4.1.0
Changes since 4.0.0
Changes since 5.0.0
* Fix sizing of numeric constants to match that of the C++ standard
* Add support for u,ll,l,f suffixes for numeric constants
* Siginificant improvement in error reporting
Changes since 4.0.0
* Dropped boost in favor of C++11
* Separated out stdlib to make more options for compile time improvements
Changes since 3.1.0
* svenstaro: Unused variables and CMake consistency fixes
* Added support for returning pointers from functions (#13)
@@ -50,7 +26,7 @@ Changes since 3.1.0
* Increased unit tests to 161
* Performance enhancements
### Changes since 3.0.0
Changes since 3.0.0
* Numeric operations performance increased approximately 10x
* Looping operations performance increased up to 2x
* Engine start up time decreased
@@ -59,7 +35,8 @@ Changes since 3.1.0
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
* Enhanced support for capturing of exceptions thrown from ChaiScript in C++
### Changes since 2.3.3
Changes since 2.3.3
* Code simplifications
* Fully integrate documentation with source code in doxygen style comments
* Unit tests increased from 114 to 137

View File

@@ -7,30 +7,17 @@
#include <iostream>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/dispatchkit/function_call.hpp>
#include <boost/function.hpp>
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
#include <boost/date_time/posix_time/posix_time.hpp>
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#include <boost/regex.hpp>
void log(const std::string &msg)
{
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] " << msg << std::endl;
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
}
void log(const std::string &module, const std::string &msg)
{
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl;
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
}
void bound_log(const std::string &msg)
@@ -51,19 +38,19 @@ void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
struct System
{
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
void add_callback(const std::string &t_name,
const boost::function<std::string (const std::string &)> &t_func)
const chaiscript::Proxy_Function &t_func)
{
m_callbacks[t_name] = t_func;
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func);
}
void do_callbacks(const std::string &inp)
{
log("Running Callbacks: " + inp);
for (std::map<std::string, boost::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
for (std::map<std::string, std::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
itr != m_callbacks.end();
++itr)
{
@@ -72,7 +59,7 @@ struct System
}
};
void take_shared_ptr(const boost::shared_ptr<const std::string> &p)
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
{
std::cout << *p << std::endl;
}
@@ -98,7 +85,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
// Let's use chaiscript to add a new lambda callback to our system.
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
// in the "add_callback" function of struct System the chaiscript function is converted into a
// boost::function, so it can be handled and called easily and type-safely
// std::function, so it can be handled and called easily and type-safely
chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");
// Because we are sharing the "system" object with the chaiscript engine we have equal
@@ -119,14 +106,14 @@ int main(int /*argc*/, char * /*argv*/[]) {
// A shortcut to using eval is just to use the chai operator()
chai("log(\"Test Module\", \"Test Message\");");
//Finally, it is possible to register any boost::function as a system function, in this
//Finally, it is possible to register any std::function as a system function, in this
//way, we can, for instance add a bound member function to the system
chai.add(fun(&System::do_callbacks, boost::ref(system), std::string("Bound Test")), "do_callbacks");
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
//Call bound version of do_callbacks
chai("do_callbacks()");
boost::function<void ()> caller = chai.eval<boost::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
std::function<void ()> caller = chai.eval<std::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
caller();
@@ -150,13 +137,13 @@ int main(int /*argc*/, char * /*argv*/[]) {
//To do: Add examples of handling Boxed_Values directly when needed
//Creating a functor on the stack and using it immediatly
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
std::stringstream ss;
ss << x;
log("Functor test output", ss.str());
chai.add(var(boost::shared_ptr<int>()), "nullvar");
chai.add(var(std::shared_ptr<int>()), "nullvar");
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
// test the global const action
@@ -178,7 +165,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//Dynamic objects test
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
// chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
// chai.add(fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", std::placeholders::_1))), "attr");
chai.eval("var x = TestType()");
// chai.eval("x.attr = \"hi\"");

View File

@@ -1,13 +1,14 @@
#include <iostream>
#include "chaiscript/chaiscript.hpp"
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
#include <readline/history.h>
#endif
using namespace chaiscript;
std::string get_next_command() {
#ifdef READLINE_AVAILABLE
@@ -30,30 +31,32 @@ void fuction(void)
class test
{
ChaiScript chai;
ChaiScript::State backupState;
chaiscript::ChaiScript chai;
chaiscript::ChaiScript::State backupState;
public:
test()
{
backupState = chai.get_state();
}
~test(){}
void ResetState()
{
chai.set_state(backupState);
chai.add(fun(&fuction),"Whatever()");
}
void RunFile(std::string sFile)
{
try {
chaiscript::Boxed_Value val = chai.eval_file(sFile);
test()
: chai(chaiscript::Std_Lib::library())
{
backupState = chai.get_state();
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
~test(){}
void ResetState()
{
chai.set_state(backupState);
chai.add(chaiscript::fun(&fuction),"Whatever()");
}
void RunFile(std::string sFile)
{
try {
chaiscript::Boxed_Value val = chai.eval_file(sFile);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
}
};

View File

@@ -5,7 +5,7 @@ def for_each(container, function)
while (!range.empty())
{
function(range.front());
range.pop_front();
range.popFront();
}
}

21
src/chaiscript_stdlib.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include <chaiscript/chaiscript_stdlib.hpp>
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_chaiscript_stdlib()
{
return chaiscript::Std_Lib::library();
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@@ -1,12 +1,12 @@
// 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)
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
#include <list>
#include <boost/algorithm/string/trim.hpp>
#include <regex>
#define _CRT_SECURE_NO_WARNINGS
#include <chaiscript/chaiscript.hpp>
@@ -20,7 +20,7 @@ char* readline(const char* p)
std::string retval;
std::cout << p ;
std::getline(std::cin, retval);
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
return std::cin.eof() ? NULL : _strdup(retval.c_str());
#else
return std::cin.eof() ? NULL : strdup(retval.c_str());
@@ -30,86 +30,6 @@ void add_history(const char*){}
void using_history(){}
#endif
void *cast_module_symbol(std::string (*t_path)())
{
union cast_union
{
std::string (*in_ptr)();
void *out_ptr;
};
cast_union c;
c.in_ptr = t_path;
return c.out_ptr;
}
std::string default_search_path()
{
#ifdef BOOST_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
std::string exepath(path, size);
size_t secondtolastslash = exepath.rfind('\\', exepath.rfind('\\') - 1);
if (secondtolastslash != std::string::npos)
{
return exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\";
} else {
return "";
}
#else
std::string exepath;
std::vector<char> buf(2048);
ssize_t size = -1;
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
if (exepath.empty())
{
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
}
if (exepath.empty())
{
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
}
if (exepath.empty())
{
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
if ( !dladdr(cast_module_symbol(&default_search_path), &rInfo) || !rInfo.dli_fname ) {
return "";
}
exepath = std::string(rInfo.dli_fname);
}
size_t secondtolastslash = exepath.rfind('/', exepath.rfind('/') - 1);
if (secondtolastslash != std::string::npos)
{
return exepath.substr(0, secondtolastslash) + "/lib/chaiscript/";
} else {
return "";
}
#endif
}
void help(int n) {
if ( n >= 0 ) {
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
@@ -132,7 +52,7 @@ void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
bool throws_exception(const boost::function<void ()> &f)
bool throws_exception(const std::function<void ()> &f)
{
try {
f();
@@ -143,7 +63,7 @@ bool throws_exception(const boost::function<void ()> &f)
return false;
}
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f)
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
{
try {
f();
@@ -160,18 +80,21 @@ std::string get_next_command() {
char *input_raw = readline("eval> ");
if ( input_raw ) {
add_history(input_raw);
std::string val(input_raw);
size_t pos = val.find_first_not_of("\t \n");
if (pos != std::string::npos)
{
val.erase(0, pos);
}
pos = val.find_last_not_of("\t \n");
if (pos != std::string::npos)
{
val.erase(pos+1, std::string::npos);
}
std::string val(input_raw);
size_t pos = val.find_first_not_of("\t \n");
if (pos != std::string::npos)
{
val.erase(0, pos);
}
pos = val.find_last_not_of("\t \n");
if (pos != std::string::npos)
{
val.erase(pos+1, std::string::npos);
}
retval = val;
::free(input_raw);
}
}
@@ -204,7 +127,7 @@ void interactive(chaiscript::ChaiScript& chai)
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
std::cout << chai.eval<boost::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
}
catch (...) {} //If we can't, do nothing
}
@@ -229,7 +152,7 @@ int main(int argc, char *argv[])
std::vector<std::string> modulepaths;
// Disable deprecation warning for getenv call.
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
@@ -237,7 +160,7 @@ int main(int argc, char *argv[])
const char *usepath = getenv("CHAI_USE_PATH");
const char *modulepath = getenv("CHAI_MODULE_PATH");
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
@@ -247,8 +170,6 @@ int main(int argc, char *argv[])
usepaths.push_back(usepath);
}
std::string searchpath = default_search_path();
modulepaths.push_back(searchpath);
modulepaths.push_back("");
if (modulepath)
{

View File

@@ -1,18 +1,14 @@
// 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 BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
@@ -20,16 +16,11 @@
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return true;
} else {
return false;
}
return bool(pf->get_parse_tree());
} else {
return false;
}
@@ -37,8 +28,8 @@ bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
@@ -53,12 +44,6 @@ chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t
}
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
{
chaiscript::ModulePtr m(new chaiscript::Module());
@@ -68,51 +53,52 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
chaiscript::exception::eval_error,
((reason))
((call_stack))
using namespace chaiscript;
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(&chaiscript::exception::eval_error::call_stack), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
{ {fun(&File_Position::line), "line"},
{fun(&File_Position::column), "column"} }
);
chaiscript::utility::add_class<AST_Node>(*m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
{fun(&AST_Node::identifier), "identifier"},
{fun(&AST_Node::filename), "filename"},
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::internal_to_string), "internal_to_string"},
{fun(&AST_Node::children), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}
);
CHAISCRIPT_CLASS( m,
chaiscript::File_Position,
(chaiscript::File_Position())
(chaiscript::File_Position(int,int)),
((line))
((column))
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
chaiscript::AST_Node,
((text))
((identifier))
((filename))
((start))
((end))
((internal_to_string))
((children))
((replace_child))
);
CHAISCRIPT_CLASS( m,
chaiscript::parser::ChaiScript_Parser,
(chaiscript::parser::ChaiScript_Parser ()),
((parse))
((ast))
);
return m;
}
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@@ -1,34 +1,22 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <list>
#include <string>
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
{
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
}
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@@ -5,19 +5,12 @@
class TestBaseType
{
public:
TestBaseType() : val(10), const_val(15) { }
TestBaseType(int) : val(10), const_val(15) {}
TestBaseType(int *) : val(10), const_val(15) {}
TestBaseType() {}
TestBaseType(int) {}
TestBaseType(int *) {}
virtual ~TestBaseType() {}
virtual int func() { return 0; }
const TestBaseType &constMe() const { return *this; }
int val;
const int const_val;
private:
TestBaseType &operator=(const TestBaseType &);
};
enum TestEnum
@@ -35,9 +28,6 @@ class TestDerivedType : public TestBaseType
public:
virtual ~TestDerivedType() {}
virtual int func() { return 1; }
private:
TestDerivedType &operator=(const TestDerivedType &);
};
std::string hello_world()
@@ -52,15 +42,11 @@ int *get_new_int()
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
{
@@ -82,8 +68,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
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(&get_new_int), "get_new_int");
@@ -92,17 +76,12 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
m->add(chaiscript::fun(&to_int), "to_int");
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
return m;
}
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@@ -0,0 +1,2 @@
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );

2
unittests/3.x/bind.chai Normal file
View File

@@ -0,0 +1,2 @@
var prod = bind(foldl, _, `*`, 1.0)
assert_equal(60, prod([3, 4, 5]))

34
unittests/3.x/bind2.chai Normal file
View File

@@ -0,0 +1,34 @@
def add(x, y)
{
return x + y;
}
assert_equal(2, add.get_arity());
var b = bind(add, 2, _);
assert_equal(1, b.get_arity());
var c = bind(b, 3);
assert_equal(0, c.get_arity());
assert_equal(6, b(4));
assert_equal(5, c());
def concat2(a,b,c,d)
{
return to_string(a) + to_string(b) + to_string(c) + to_string(d);
}
var d = bind(concat2, _, " Hello ", _, " World");
assert_equal(2, d.get_arity());
assert_equal("1 Hello 3 World", d(1,3));
var e = bind(`<`, _, 5);
var types = e.get_param_types();
assert_equal(2, types.size());
assert_equal(true, types[0].bare_equal(bool_type));

View File

@@ -0,0 +1 @@
{print("hello")}

View File

@@ -0,0 +1 @@
assert_equal(false, !true)

View File

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

View File

@@ -0,0 +1 @@
assert_equal("b", to_string('b'))

View File

@@ -0,0 +1,7 @@
assert_equal(true, 1.is_var_const());
assert_equal(false, 1.is_var_reference());
assert_equal(true, 1.is_var_pointer());
assert_equal(false, 1.is_var_null());
assert_equal(false, 1.is_var_undef());
var i;
assert_equal(true, i.is_var_undef());

View File

@@ -0,0 +1,3 @@
var v = collate(1, 2)
assert_equal(1, v[0])
assert_equal(2, v[1])

View File

@@ -0,0 +1 @@
assert_equal(false, 1 > 2);

View File

@@ -0,0 +1 @@
assert_equal(true, 1 < 2)

View File

@@ -0,0 +1,5 @@
var v = concat([1, 2], [3, 4]);
assert_equal(4, v.size());
assert_equal(1, v[0]);
assert_equal(4, v[3]);

View File

@@ -0,0 +1,4 @@
//If the following succeeds, the test passes
"Hello World".for_each(fun(x) { print(x) } )

View File

@@ -0,0 +1 @@
assert_equal("3.5bob", 3.5.to_string() + "bob");

View File

@@ -0,0 +1 @@
assert_equal("3bob", 3.to_string + "bob")

View File

@@ -0,0 +1 @@
assert_equal(6.8, "3.5".to_double() + 3.3)

View File

@@ -0,0 +1 @@
assert_equal(8, "4".to_int() + 4)

View File

@@ -0,0 +1,11 @@
var a = [1,2,3, [4,5,6] ]
assert_equal(a[3][0], 4)
def Test::Test() { this.a = [1,2,3]; }
attr Test::a;
var t = Test();
assert_equal(t.a[0], 1)

View File

@@ -0,0 +1,11 @@
assert_equal(`==`, `==`);
assert_not_equal(`==`, `<`);
assert_equal(`<`.get_arity(), 2);
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
assert_equal(get_arity.get_contained_functions().size(), 0);
assert_equal(get_arity.get_arity(), 1);
assert_equal(get_arity.get_param_types().size(), 2);
var paramtypes = get_arity.get_param_types();
assert_equal(true, paramtypes[1].bare_equal(Function_type));

1
unittests/3.x/drop.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal([3,4], drop([1, 2, 3, 4], 2))

View File

@@ -0,0 +1 @@
assert_equal([2, 3], drop_while([1, 2, 3], odd))

0
unittests/3.x/empty.chai Normal file
View File

View File

@@ -0,0 +1,4 @@
var x=.5
assert_equal(.5, x)
var y=-.5
assert_equal(-.5, y)

1
unittests/3.x/eval.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(7, eval("3 + 4"))

View File

@@ -0,0 +1,39 @@
load_module("reflection")
def deep()
{
try {
} catch {
} finally {
if (2)
{
}
}
}
def func()
{
deep();
}
def doing()
{
for (var i = 0; i < 10; ++i)
{
func();
}
}
def while_doing()
{
while (true)
{
doing();
}
}
var f = fun() { while_doing(); }
assert_equal(get_eval_error(f).call_stack.size(), 16)

1
unittests/3.x/even.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(true, even(4))

View File

@@ -0,0 +1,9 @@
var x = 1
try {
throw(x)
x = 2
}
catch(e) {
x = e + 3
}
assert_equal(4, x);

View File

@@ -0,0 +1,32 @@
var finallyone = false;
try {
throw(3)
}
catch(x) {
assert_equal(3, x)
}
finally {
finallyone = true;
}
assert_equal(true, finallyone);
var try2 = false;
var catch2 = false;
var finally2 = false;
try {
try2 = true;
}
catch {
catch2 = true;
}
finally {
finally2 = true;
}
assert_equal(true, try2);
assert_equal(false, catch2);
assert_equal(true, finally2);

View File

@@ -0,0 +1,34 @@
var results = [];
for (var i = 2; i < 6; ++i) {
try {
throw(i)
}
catch(e) : e < 2 {
results.push_back("c1: " + e.to_string());
}
catch(e) : e < 4 {
results.push_back("c2: " + e.to_string());
}
catch(e) {
results.push_back("c3: " + e.to_string());
}
catch {
// Should never get called
assert_equal(false, true)
}
}
try {
throw(3)
}
catch(e) : e < 3
{
// Should never get called
assert_equal(false, true);
}
catch {
results.push_back("defaultcatch");
}
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);

View File

@@ -0,0 +1 @@
assert_equal([1,3], filter([1, 2, 3, 4], odd))

7
unittests/3.x/float.chai Normal file
View File

@@ -0,0 +1,7 @@
assert_equal(true, 1.2 < 2)
assert_equal(true, 1.2 > 1)
assert_equal(1.2, 1.2)
assert_equal(true, .5 > 0)
assert_equal(true, .5 < 1)
assert_equal(0.5, .5)

1
unittests/3.x/foldl.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(10, foldl([1, 2, 3, 4], `+`, 0))

7
unittests/3.x/for.chai Normal file
View File

@@ -0,0 +1,7 @@
var ret = []
for (var i = 0; i < 5; ++i) {
ret.push_back(i);
}
assert_equal([0,1,2,3,4], ret);

View File

@@ -0,0 +1 @@
for_each([1, 2, 3], print)

Some files were not shown because too many files have changed in this diff Show More