Compare commits

..

162 Commits

Author SHA1 Message Date
Jason Turner
6c483bd6f6 Update release notes and prepare for 5.8.0 2016-02-16 15:00:13 -07:00
Jason Turner
7f8a6f24f9 Fix a few warnings from old gcc 2016-02-16 11:13:14 -07:00
Jason Turner
07fa8010e4 Ack! Rollback debug statement print out 2016-02-16 11:06:20 -07:00
Jason Turner
e024b99b36 Fixes for type_conversion handling 2016-02-16 08:29:01 -07:00
Jason Turner
ed65ad72d0 Update copyrights 2016-02-14 20:04:17 -07:00
Jason Turner
bc0eaa5d15 Fix some issues found by cppcheck 2016-02-14 20:01:49 -07:00
Jason Turner
e0827634bb Add some cpp<->chai performance tests 2016-02-05 16:18:54 -07:00
Jason Turner
08ba646200 Enable thread local in MSVC 2015 2016-02-02 09:18:08 -07:00
Jason Turner
caf0a8b5d1 Remove extra version of push_back async vector 2016-02-02 07:25:41 -07:00
Jason Turner
357df5c8ec Remove async test from list_push_back 2016-02-01 15:38:32 -07:00
Jason Turner
d0630d5edd Attempt to fix warning from MSVC 2016-02-01 15:24:08 -07:00
Jason Turner
c562d0d78b Fix MSVC build 2016-01-31 21:18:23 -07:00
Jason Turner
bff30278e1 Fix string parsing 2016-01-31 19:35:40 -07:00
Jason Turner
b104b26f11 Also allow lcase global keyword
Closes #221
2016-01-31 19:15:32 -07:00
Jason Turner
03ef44f415 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-01-31 19:12:37 -07:00
Jason Turner
1a06e53c58 Add some compiler identification info to build 2016-01-31 19:06:44 -07:00
Jason Turner
c438a388d7 Add workaround for msvc 2015 update 1 with 1 CPU. 2016-01-31 19:05:37 -07:00
Jason Turner
7923c3e0c7 Add docs on set_global 2016-01-31 14:05:44 -07:00
Jason Turner
872f16e45a Add some tests that were laying around 2016-01-30 06:56:01 -07:00
Jason Turner
7688c14d43 Parse strings in ${} closes #131 2016-01-29 21:34:04 -07:00
Jason Turner
bde2a45384 Add map conversions
closes #57
2016-01-29 20:41:12 -07:00
Jason Turner
7f4ef8d8fd Fix cppcheck warnings 2016-01-29 20:00:20 -07:00
Jason Turner
0dab950ebf Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-01-29 19:43:12 -07:00
Jason Turner
485482b2be Fix tabs in source code 2016-01-29 19:42:50 -07:00
Jason Turner
b2ae317877 Seperate out async moves into a separate test 2016-01-29 19:13:10 -07:00
Jason Turner
5b1b1dbcb4 Added appveyor.yml 2016-01-29 17:20:19 -07:00
Jason Turner
7222390c96 Fix build 2016-01-29 16:12:10 -07:00
Jason Turner
b33f0a08bc Remove initializer_list conversion due to the issues mentioned here:
http://stackoverflow.com/questions/18895583/convert-a-vectort-to-initializer-listt
2016-01-29 16:04:06 -07:00
Jason Turner
140a90f72a Fix g++4.6 build issues 2016-01-29 15:35:40 -07:00
Jason Turner
f697384028 Merge pull request #243 from vrennert/feature_initializer_list_conversion
Added initializer_list<T> conversion as possible function call argument or return type.
2016-01-29 15:20:38 -07:00
Jason Turner
dfd04c8291 Clean up formatting from last merge
Closes #238
2016-01-29 15:16:35 -07:00
Jason Turner
209d6ed2e4 Merge remote-tracking branch 'ktm/set-global' into develop 2016-01-29 15:14:32 -07:00
Jason Turner
d8fa6061a2 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-01-29 13:57:57 -07:00
Jason Turner
651eed8d7a Add no-threads build for testing
Closes #60
2016-01-29 13:57:14 -07:00
Viktor Rennert
af1eba1b0e Added type fix for gcc/clang and tiny formating fixes. 2016-01-26 18:36:45 +01:00
Jason Turner
f82f6c2068 Some fixes found by resharper c++ 2016-01-25 16:41:11 -07:00
Viktor Rennert
fcca453223 Added initializer_list<T> conversion as possible function call argument or return type. 2016-01-26 00:06:57 +01:00
Jason Turner
7ed5c18a86 Merge pull request #241 from ChaiScript/add_performance_tests
Add performance tests
2016-01-20 18:30:35 -07:00
Jason Turner
c067575ac4 Merge branch 'develop' into add_performance_tests 2016-01-20 18:24:50 -07:00
Jason Turner
52c96de6a8 Merge pull request #239 from ChaiScript/assign_to_result_of_map
Add test for assignment of map() return vector
2016-01-20 18:20:04 -07:00
Jason Turner
907e6d74e0 Merge pull request #240 from ChaiScript/add_custom_checks
Add a custom check-for-tabs test to CI
2016-01-20 18:19:31 -07:00
Jason Turner
12cbbd2097 Add test for assignment of map() return vector 2016-01-19 10:00:26 -07:00
ktm
4aa370fbfd restore newline to bottom of file 2016-01-18 13:33:38 -05:00
ktm
3587c3e165 fixed comment on set_global 2016-01-18 13:24:59 -05:00
Jason Turner
acc4345b65 Add a custom check-for-tabs test to CI 2016-01-18 10:36:21 -07:00
ktm
43def57852 add set_global, update unit test 2016-01-17 00:01:51 -05:00
Jason Turner
561b47e463 More explicit int/bool conversions 2016-01-16 09:27:16 -07:00
Jason Turner
9885534b5b Merge branch 'develop' into add_performance_tests 2016-01-16 09:02:52 -07:00
ktm
ad3f111e13 Merge remote-tracking branch 'upstream/master' 2016-01-14 07:52:38 -05:00
Jason Turner
452f71b51f Merge pull request #235 from mlamby/patch-1
Fix user_type example in cheatsheet.md
2016-01-11 20:39:36 -07:00
Michael Lamb
a97cb1530d Fix user_type example in cheatsheet.md
Fixed example code as chaiscript::user_type is a function.
2016-01-08 14:23:09 +11:00
Jason Turner
21048b9e65 Merge pull request #233 from vrennert/feature_enum_utility_helper
Added template specialization in chaiscript::utility::add_class<Enum> to register bulk constants.
2016-01-05 14:03:32 -07:00
Viktor Rennert
d73e715997 Merge branch 'ChaiScript-feature_enum_utility_helper' into feature_enum_utility_helper 2016-01-04 16:00:57 +01:00
Jason Turner
353a077c6b Merge branch 'feature_enum_utility_helper' of github.com:vrennert/ChaiScript into feature_enum_utility_helper 2016-01-03 18:40:34 -07:00
Jason Turner
373a3688c9 Merge branch 'feature_enum_utility_helper' into Fix_Crash_From_CppCon 2016-01-03 18:13:48 -07:00
Jason Turner
208107fd7e Add additional tests for vector conversion 2016-01-03 17:58:05 -07:00
Jason Turner
e19a8e31ea Merge pull request #234 from Bobhostern/patch-1
Fix formatting error in cheatsheet.md
2016-01-03 17:07:24 -07:00
Bobhostern
b55eff95cf Fix formatting error in cheatsheet.md 2016-01-03 13:34:27 -06:00
Viktor Rennert
b6287a194c Merge pull request #1 from ChaiScript/feature_enum_utility_helper
Feature enum utility helper
2016-01-03 10:09:05 +01:00
Jason Turner
888d897a3e Simplify use of enum helper 2016-01-02 19:59:54 -07:00
Jason Turner
e32714c456 Add some operators for Enums made with helper class 2016-01-02 19:45:10 -07:00
Jason Turner
e1c40f3e8f Automatically add copy constuctor for enums added with utility 2016-01-02 19:26:53 -07:00
Jason Turner
d7489358f3 Add failing test for vector of enum values 2016-01-02 19:24:14 -07:00
Viktor Rennert
316ba45e3c Added unittest to cover utility::add_class<Enum> registration. 2016-01-02 20:54:55 +01:00
Viktor Rennert
f0796b51c8 Added template specialization in chaiscript::utility::add_class<Enum> to register bulk constants. 2016-01-02 14:25:44 +01:00
Jason Turner
e638d450ed Merge pull request #232 from RaptorFactor/develop
Fix multiply defined symbols.
2015-12-30 13:09:57 -07:00
Joshua Boyce
e60eabbeb2 Fix another multiply defined symbol. 2015-12-26 03:04:05 -08:00
Joshua Boyce
c249bef27d Fix multiply defined symbols. 2015-12-26 03:03:24 -08:00
Jason Turner
4e69e5a3d2 Merge branch 'Fix_Crash_From_CppCon' of github.com:ChaiScript/ChaiScript into Fix_Crash_From_CppCon 2015-11-25 07:51:12 -07:00
Jason Turner
49c89a3b88 un-break ** cast operation 2015-11-25 09:49:26 -05:00
Jason Turner
7507223c8b Merge pull request #228 from ChristianKaeser/ckfix
String escape sequence bug fix
2015-11-23 12:12:58 -05:00
Jason Turner
681b7db727 Merge branch 'Fix_Crash_From_CppCon' of github.com:ChaiScript/ChaiScript into Fix_Crash_From_CppCon 2015-11-20 06:49:35 -07:00
Jason Turner
4826bddb5b Add overloads for cosnt *& casts 2015-11-20 07:46:52 -06:00
Jason Turner
49436e5740 Merge branch 'develop' into Fix_Crash_From_CppCon 2015-11-20 05:53:44 -07:00
Christian Kaeser
202204a82a Limit hexadecimal escape sequence length
Helps with cases like "\xFFecho" by limiting the number of hex digits
that will be parsed to maximum suitable for the char type.
This rule differs from the C/C++ standard, but ChaiScript does not offer
the same workaround options.
Furthermore, without it having hexadecimal sequences longer than can fit
into the char type is undefined behavior anyway.
2015-11-08 18:36:16 +01:00
Christian Kaeser
34c6b17215 Fix broken escape sequence parsing after octal/hex escape
The parser code just added the first character after an octal/hex sequence
as raw text, resulting in erroneous data whenever another escape
sequence follows directly after.
2015-11-08 18:07:04 +01:00
Jason Turner
6fe7f5ce98 Don't return reference to copied values 2015-11-03 16:02:25 -07:00
Jason Turner
d9f86a96f0 Add initial failing test 2015-11-03 15:59:43 -07:00
Jason Turner
da1511a092 Enable collection of performance results where possible 2015-10-23 20:38:51 -06:00
Jason Turner
8bd7ccfa9f Only run performance tests on linux 2015-10-23 16:38:04 -06:00
Jason Turner
0806df11d2 Performance test reorg to run automatically 2015-10-23 16:25:16 -06:00
Jason Turner
40b1549b3b Fix use of broken bitset implementation in g++ 2015-10-21 09:30:22 -06:00
Jason Turner
c9a5bf6f83 fix warning from GCC for unknown flag 2015-10-20 18:19:03 -06:00
Jason Turner
8496a86043 Use a bitset instead of bools for type_info flags 2015-10-20 18:14:42 -06:00
Jason Turner
bc388e59da Fix style warning from cppcheck 2015-10-17 09:23:05 -06:00
Jason Turner
09748275db Fix warnings from clang 2015-10-17 09:22:13 -06:00
Jason Turner
eec0299cbc Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-10-17 09:04:48 -06:00
Jason Turner
19ecfdfec5 Merge branch 'add_examples' into develop 2015-10-17 09:04:02 -06:00
Jason Turner
7ba7b81a5c Implement option explicit for dynamic objects.
Closes #218
2015-10-16 21:41:54 -06:00
Jason Turner
882cbf2dfb Add option explicit code, but don't throw yet
Work towards #218
2015-10-16 18:47:26 -06:00
Jason Turner
38b98c55cc Add test for dynamic object option explicit 2015-10-16 18:37:02 -06:00
Jason Turner
3a675bf379 Add config option for compiling with gprof output 2015-10-16 18:21:49 -06:00
Jason Turner
985b62705f Add support for != bools
closes #217
2015-10-15 22:06:06 -06:00
Jason Turner
5aecb7f17b Add boolean comparison tests #217 2015-10-15 21:59:46 -06:00
Jason Turner
ad69bf7d38 Get vector push_back_ref working as expected 2015-10-15 21:42:25 -06:00
Jason Turner
84554ed0a5 Add another vector assignment test 2015-10-15 21:32:16 -06:00
Jason Turner
36765df3c0 Fix vector element assignment issues 2015-10-15 21:20:12 -06:00
Jason Turner
b11ebf9e8f Add failing test for vector assignment operations 2015-10-15 21:13:17 -06:00
Jason Turner
84e2d449b9 Support default case in the non-last position 2015-10-15 15:02:49 -06:00
Jason Turner
3e62a99f82 Add factory example with scripted callbacks 2015-10-07 09:55:15 -06:00
Jason Turner
64dd349e32 Merge pull request #213 from ChaiScript/fix_binary_literal_sizing
Fix binary literal sizing
2015-10-04 20:38:37 -06:00
Jason Turner
1add4c4b0f Fix issues with integer parsing on MSVC
See #212
2015-10-04 14:32:23 -06:00
Jason Turner
14b3870efb Fix integer overflow and bad numeric parses 2015-10-04 08:53:22 -06:00
Jason Turner
d2cf12f948 Add tests for binary literals 2015-10-03 21:01:52 -06:00
Jason Turner
e221ceaa4c Greatly simplify integer sizing code 2015-10-03 17:11:03 -06:00
Jason Turner
beedf13d01 Make binary literals sized like other integer types 2015-10-03 16:38:41 -06:00
Jason Turner
9d18360333 Older compiler backport issues 2015-10-02 12:46:50 -06:00
Jason Turner
18e5ee0ba2 Wrap up generic string escape support
Closes #211
2015-10-02 12:16:44 -06:00
Jason Turner
41e9027d9a Octal escape codes supported #211 2015-10-02 11:45:28 -06:00
Jason Turner
8d9dc2b0a3 Reduce redundant escape code parsing #211 2015-10-02 10:35:37 -06:00
Jason Turner
6a4647af43 Add last test for json support
Closes #207
2015-10-02 08:12:50 -06:00
Jason Turner
5a651e2b8a Fix numeric overload resolution
Closes #209
2015-10-01 09:56:53 -06:00
Jason Turner
d9fa5605ac Add operator overload tests 2015-10-01 09:39:03 -06:00
Jason Turner
3a8cb581cc Merge branch 'add_json_support' into develop 2015-09-30 14:39:21 -06:00
Jason Turner
b434d26a5d Add json tests 2015-09-30 14:24:56 -06:00
Jason Turner
ba30d4f483 Add support for == for Map 2015-09-30 08:57:36 -06:00
Jason Turner
b4ffcd594d Fix long long type usage
Closes #208
2015-09-30 06:49:03 -06:00
Jason Turner
ca35128503 Add failing test for long long conversions 2015-09-30 06:32:34 -06:00
Jason Turner
681f18ee62 backport JSON for G++4.6 2015-09-21 12:27:33 -06:00
Jason Turner
e62a38b39f JSON output working 2015-09-21 09:27:23 -06:00
Jason Turner
85ac1052dd Initial support for export to JSON 2015-09-20 16:19:11 -06:00
Jason Turner
8024edeadf Fix some JSON parsing bug with short strings 2015-09-20 15:46:05 -06:00
Jason Turner
f9f1d5807a Basic support for parsing of JSON objects 2015-09-20 15:35:53 -06:00
Jason Turner
14227475b2 Merge remote-tracking branch 'origin/cpp_fun_call_performance' into develop 2015-09-18 13:41:44 -06:00
Jason Turner
e1a80fb5ce A couple of MSVC fixes 2015-09-16 10:28:05 -06:00
Jason Turner
aabe53c934 Make var work with move-only types 2015-09-12 22:21:05 -06:00
Jason Turner
f3dbb7ed87 Control how fast global vectors grow 2015-08-31 11:09:03 -06:00
Jason Turner
52e11bf001 Fun location caching phase2
This shows ~25% performance over develop
2015-08-31 11:00:56 -06:00
Jason Turner
f06e5cdcd6 Cache function lookups 2015-08-31 09:44:47 -06:00
Jason Turner
15eb78bd8f Move to indexed function storage 2015-08-31 08:41:47 -06:00
Jason Turner
9f362608b7 Eliminate extra unneeded scope 2015-08-28 21:19:00 -06:00
Jason Turner
e21c8f87b4 Add profile test for cpp call perf 2015-08-28 10:33:26 -06:00
Jason Turner
0a143d1cd3 Make push_* consistant with inplace vector 2015-08-27 15:30:02 -06:00
Jason Turner
08935beaf3 Add tests for pushing move only values 2015-08-27 15:23:36 -06:00
Jason Turner
c9625b09b0 Fix magic 'this' values 2015-08-26 18:41:46 -06:00
Jason Turner
800c7fb37b Fix functor scope - break magic 'this' 2015-08-26 13:18:42 -06:00
Jason Turner
179eaefafe Add failing test for functor scope 2015-08-25 17:10:45 -06:00
Jason Turner
28f5a74e98 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-08-15 19:28:45 -06:00
Jason Turner
781d62d3a5 Make result of dynamic constructor marked as return value 2015-08-15 07:29:07 -06:00
Jason Turner
8ed2158709 Merge pull request #203 from msbroadf/develop
Update chaiscript_engine.hpp
2015-08-13 14:12:38 -06:00
Jason Turner
8f98e16e5e Reset return value flag on reference assignment 2015-08-13 13:45:31 -06:00
msbroadf
3a595ef912 Update chaiscript_engine.hpp 2015-08-13 13:45:33 +10:00
Jason Turner
5aa0bfcea4 Add some convenience functions for parsing 2015-08-11 19:20:18 -06:00
Jason Turner
04e2256c92 Fix error caused by last fix 2015-08-02 18:21:48 -06:00
Jason Turner
38ba00e55c Get MSVC2015 quieted down on warnings
re @arBmind
2015-08-02 16:52:43 -06:00
Jason Turner
8931346230 Eradicate internal exceptions during object clone 2015-08-01 13:47:25 -06:00
Jason Turner
8bdd2deb19 Add exceptions test to cmakelist 2015-08-01 12:47:43 -06:00
Jason Turner
535055eff8 Add test to see how many exceptions are during simple use 2015-08-01 12:44:22 -06:00
Jason Turner
913d2fd20f Add test for variable scope in functor calls
For bug #191
2015-08-01 11:03:55 -06:00
Jason Turner
0c4951d742 Fix parsing of operators
* Only parse valid operators
 * Don't swallow a symbol if it would produce an invalid operator

Closes #198
2015-08-01 10:05:38 -06:00
Jason Turner
9d17b18f26 add failing tests for #198
1<-1 fails to parse
2015-08-01 10:04:42 -06:00
Jason Turner
31b3195c17 Don't allow conversion to std::function on arity mismatch 2015-07-30 20:23:34 -06:00
Jason Turner
0d4e4090a0 Massive reorg of file position tracking
- Should make iterator errors almost impossible in the future
 - Fixes tracking of current line number
2015-07-30 16:53:27 -06:00
Jason Turner
b946af42cc Update fuzzy_tests to take into acount parsing fixes 2015-07-24 12:09:20 -06:00
Jason Turner
22339d10db Make order of params eval well defined 2015-07-24 12:07:46 -06:00
Jason Turner
b3d2350f33 Add test for order of operations 2015-07-24 11:49:23 -06:00
Jason Turner
3cae2aed1d Remove unused Inplace Eval ast node 2015-07-23 15:34:45 -06:00
Jason Turner
c6f262c675 Parse in-string eval at regular parse time
- don't delay and overcomplicate with an eval
2015-07-23 15:21:39 -06:00
Jason Turner
8239206ec5 Update fuzzy_tests now with more parser fixes in 2015-07-22 15:42:31 -06:00
Jason Turner
a2ff672b34 Memory error fixes
* prevent recognizing . as a number
 * do all checked iterator operations for incrementing through input
   stream
 * Verify that all is as expected when building up a dot notation call
2015-07-22 11:13:10 -06:00
Jason Turner
9a0a12d230 Bump version number to 5.7.2 2015-07-20 19:50:13 -06:00
Jason Turner
7d3c23fc22 Merge pull request #196 from ChaiScript/develop
Make release v5.7.1
2015-07-17 15:40:54 -06:00
115 changed files with 3244 additions and 1314 deletions

View File

@@ -2,7 +2,8 @@ compilers:
- name: "clang"
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "clang"
build_tag: "LibC++"
version: "3.5"
@@ -12,7 +13,7 @@ compilers:
build_tag: AddressSanitizer
version: "3.6"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
cmake_extra_flags: -DRUN_FUZZY_TESTS:BOOL=TRUE -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
- name: "clang"
build_tag: ThreadSanitizer
version: "3.6"
@@ -20,11 +21,21 @@ compilers:
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
- name: "gcc"
version: "4.8"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
build_tag: "NoThreads"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF
collect_performance_results: true
- name: "gcc"
version: "4.8"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "gcc"
version: "4.6"
skip_packaging: true
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: cppcheck
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:cmake*" --suppress="*:unittests/catch.hpp" --force
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:unittests/catch.hpp" --force --suppress="unusedFunction:*"
- name: custom_check
commands:
- ./contrib/check_for_tabs.rb

View File

@@ -20,6 +20,7 @@ option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE)
mark_as_advanced(USE_STD_MAKE_SHARED)
@@ -68,6 +69,13 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
endif()
option(GPROF_OUTPUT "Generate profile data" FALSE)
if (GPROF_OUTPUT)
add_definitions(-pg)
set(LINKER_FLAGS "${LINKER_FLAGS} -pg")
endif()
option(PROFILE_GENERATE "Generate profile data" FALSE)
if (PROFILE_GENERATE)
add_definitions(-fprofile-generate)
@@ -94,8 +102,8 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 7)
set(CPACK_PACKAGE_VERSION_PATCH 1)
set(CPACK_PACKAGE_VERSION_MINOR 8)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -115,16 +123,12 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest)
include(CPack)
include(cmake/CheckCXX11Features.cmake)
if(NOT MINGW)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
endif()
if(HAS_CXX11_VARIADIC_TEMPLATES)
message(STATUS "Variadic Template support detected")
else()
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
if (UNIX AND NOT APPLE)
find_program(VALGRIND NAMES valgrind PATH /usr/bin /usr/local/bin)
endif()
enable_testing()
@@ -174,7 +178,7 @@ else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-Weverything -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors)
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
else()
add_definitions(-Wnoexcept)
endif()
@@ -206,7 +210,7 @@ endif()
include_directories(include)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -253,10 +257,14 @@ add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
if(BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
target_link_libraries(test_num_exceptions ${LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS})
add_executable(inheritance samples/inheritance.cpp)
target_link_libraries(inheritance ${LIBS})
add_executable(factory samples/factory.cpp)
target_link_libraries(factory ${LIBS})
add_executable(fun_call_performance samples/fun_call_performance.cpp)
target_link_libraries(fun_call_performance ${LIBS})
endif()
@@ -272,6 +280,9 @@ endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
list(SORT UNIT_TESTS)
file(GLOB PERFORMANCE_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/ ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/*.chai)
list(SORT PERFORMANCE_TESTS)
if (RUN_FUZZY_TESTS)
@@ -336,8 +347,8 @@ if(BUILD_TESTING)
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
foreach(hit ${found_tests})
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
add_test(${test_name} "${executable}" ${test_name})
set_tests_properties(${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
add_test(compiled.${test_name} "${executable}" ${test_name})
set_tests_properties(compiled.${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
endforeach()
endif()
endif()
@@ -371,12 +382,32 @@ if(BUILD_TESTING)
)
set(TESTS "")
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})
message(STATUS "Adding unit test ${filename}")
add_test(unit.${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
list(APPEND TESTS unit.${filename})
endforeach()
set_property(TEST ${UNIT_TESTS}
if (RUN_PERFORMANCE_TESTS)
foreach(filename ${PERFORMANCE_TESTS})
message(STATUS "Adding performance test ${filename}")
add_test(NAME performance.${filename} COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.${filename} $<TARGET_FILE:chai> ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/${filename})
list(APPEND TESTS performance.${filename})
endforeach()
add_executable(profile_cpp_calls_2 performance_tests/profile_cpp_calls_2.cpp)
target_link_libraries(profile_cpp_calls_2 ${LIBS})
add_test(NAME performance.profile_cpp_calls_2 COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_cpp_calls_2 $<TARGET_FILE:profile_cpp_calls_2>)
add_executable(profile_fun_wrappers performance_tests/profile_fun_wrappers.cpp)
target_link_libraries(profile_fun_wrappers ${LIBS})
add_test(NAME performance.profile_fun_wrappers COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_fun_wrappers $<TARGET_FILE:profile_fun_wrappers>)
endif()
set_property(TEST ${TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"

View File

@@ -1,4 +1,4 @@
Copyright 2009-2015 Jason Turner
Copyright 2009-2016 Jason Turner
Copyright 2009-2012 Jonathan Turner.
All Rights Reserved.

16
appveyor.yml Normal file
View File

@@ -0,0 +1,16 @@
version: 5.7.2.{build}
os: Visual Studio 2015
environment:
matrix:
- {}
build_script:
- cmd: >-
mkdir build
cd build
cmake c:\Projects\chaiscript -G "Visual Studio 14"
cmake --build . --config Debug
test_script:
- cmd: ctest -C Debug

View File

@@ -77,7 +77,7 @@ chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
```
chai.add(chaiscript::user_type<MyClass>, "MyClass");
chai.add(chaiscript::user_type<MyClass>(), "MyClass");
```
## Adding Type Conversions
@@ -90,6 +90,13 @@ A helper function exists for strongly typed and ChaiScript `Vector` function con
chai.add(chaiscript::vector_conversion<std::vector<int>>());
```
A helper function also exists for strongly typed and ChaiScript `Map` function conversion definition:
```
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
```
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
## Adding Objects
@@ -100,8 +107,9 @@ chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared
auto shareddouble = std::make_shared<double>(4.3);
chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai
chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const, throws if object exists
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists
chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object
```
# Using STL
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
@@ -221,11 +229,13 @@ var k = 5; // initialized to 5 (integer)
var l := k; // reference to k
auto &m = k; // reference to k
GLOBAL g = 5; // creates a global variable. If global already exists, it is not re-added
GLOBAL g = 2; // global 'g' now equals 2
global g = 5; // creates a global variable. If global already exists, it is not re-added
global g = 2; // global 'g' now equals 2
GLOBAL g2;
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once
global g2;
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hit more than once
GLOBAL g3; // all upper case version also accepted
```
## Built in Types
@@ -354,6 +364,19 @@ o.f = fun(y) { print(this.x + y); }
o.f(10); // prints 13
```
### Option Explicit
If you want to disable dynamic parameter definitions, you can `set_explicit`.
```
class My_Class {
def My_Class() {
this.set_explicit(true);
this.x = 2; // this would fail with explicit set to true
}
};
```
## method_missing
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate

View File

@@ -1,103 +0,0 @@
# 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

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

View File

@@ -1,12 +0,0 @@
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

@@ -1,19 +0,0 @@
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

@@ -1,10 +0,0 @@
#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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,15 +0,0 @@
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

@@ -1,14 +0,0 @@
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

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

View File

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

View File

@@ -1,23 +0,0 @@
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;
}

11
contrib/check_for_tabs.rb Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env ruby
require 'json'
`grep -rPIHn '\t' src/* include/* samples/*`.lines { |line|
if /(?<filename>.+(hpp|cpp|chai)):(?<linenumber>[0-9]+):(?<restofline>.+)/ =~ line
puts(JSON.dump({:line => linenumber, :filename => filename, :tool => "tab_checker", :message => "Source Code Line Contains Tabs", :messagetype => "warning"}))
end
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_

View File

@@ -1,18 +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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DEFINES_HPP_
#define CHAISCRIPT_DEFINES_HPP_
#ifdef _MSC_VER
#define CHAISCRIPT_STRINGIZE(x) "" #x
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEC
#if _MSC_VER <= 1800
#define CHAISCRIPT_MSVC_12
#endif
#else
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
#endif
#ifndef CHAISCRIPT_MSVC_12
@@ -29,7 +33,25 @@
#define CHAISCRIPT_WINDOWS
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
#if defined(_WIN32)
#if defined(__llvm__)
#define CHAISCRIPT_COMPILER_NAME "clang(windows)"
#elif defined(__GNUC__)
#define CHAISCRIPT_COMPILER_NAME "gcc(mingw)"
#else
#define CHAISCRIPT_COMPILER_NAME "msvc"
#endif
#else
#if defined(__llvm__)
#define CHAISCRIPT_COMPILER_NAME "clang"
#elif defined(__GNUC__)
#define CHAISCRIPT_COMPILER_NAME "gcc"
#else
#define CHAISCRIPT_COMPILER_NAME "unknown"
#endif
#endif
#if (defined(CHAISCRIPT_MSVC) && !defined(CHAISCRIPT_MSVC_12)) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
/// Currently only g++>=4.8 supports this natively
/// \todo Make this support other compilers when possible
#define CHAISCRIPT_HAS_THREAD_LOCAL
@@ -39,7 +61,11 @@
#define CHAISCRIPT_GCC_4_6
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__)
#if defined(__llvm__)
#define CHAISCRIPT_CLANG
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG)
#define CHAISCRIPT_OVERRIDE override
#else
#define CHAISCRIPT_OVERRIDE
@@ -52,7 +78,7 @@
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#ifdef CHAISCRIPT_MSVC
#ifdef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_NOEXCEPT throw()
#define CHAISCRIPT_CONSTEXPR
#else
@@ -60,12 +86,22 @@
#define CHAISCRIPT_CONSTEXPR constexpr
#endif
#ifdef _DEBUG
#define CHAISCRIPT_DEBUG true
#else
#define CHAISCRIPT_DEBUG false
#endif
#include <memory>
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 7;
static const int version_patch = 1;
static const int version_minor = 8;
static const int version_patch = 0;
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
static const bool debug_build = CHAISCRIPT_DEBUG;
template<typename B, typename D, typename ...Arg>
inline std::shared_ptr<B> make_shared(Arg && ... arg)

View File

@@ -19,6 +19,7 @@
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.chai"
#include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS
#include <future>
@@ -51,6 +52,8 @@ namespace chaiscript
lib->add(chaiscript::fun([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
#endif
lib->add(json_wrap::library());
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
return lib;

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_
@@ -45,14 +45,14 @@ namespace chaiscript
class unique_lock : public std::unique_lock<T>
{
public:
unique_lock(T &t) : std::unique_lock<T>(t) {}
explicit 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) {}
explicit shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
@@ -60,7 +60,7 @@ namespace chaiscript
class lock_guard : public std::lock_guard<T>
{
public:
lock_guard(T &t) : std::lock_guard<T>(t) {}
explicit lock_guard(T &t) : std::lock_guard<T>(t) {}
};
class shared_mutex : public std::mutex { };
@@ -77,7 +77,7 @@ namespace chaiscript
{
public:
Thread_Storage(void *t_key)
explicit Thread_Storage(void *t_key)
: m_key(t_key)
{
}
@@ -129,7 +129,7 @@ namespace chaiscript
{
public:
Thread_Storage(void *)
explicit Thread_Storage(void *)
{
}
@@ -160,13 +160,14 @@ namespace chaiscript
{
unique_lock<mutex> lock(m_mutex);
auto itr = m_instances.find(std::this_thread::get_id());
const auto id = std::this_thread::get_id();
auto itr = m_instances.find(id);
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(std::make_shared<T>());
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
m_instances.insert(std::make_pair(id, new_instance));
return new_instance;
}
@@ -182,7 +183,7 @@ namespace chaiscript
class unique_lock
{
public:
unique_lock(T &) {}
explicit unique_lock(T &) {}
void lock() {}
void unlock() {}
};
@@ -191,7 +192,7 @@ namespace chaiscript
class shared_lock
{
public:
shared_lock(T &) {}
explicit shared_lock(T &) {}
void lock() {}
void unlock() {}
};
@@ -200,7 +201,7 @@ namespace chaiscript
class lock_guard
{
public:
lock_guard(T &) {}
explicit lock_guard(T &) {}
};
class shared_mutex { };
@@ -212,7 +213,7 @@ namespace chaiscript
class Thread_Storage
{
public:
Thread_Storage(void *)
explicit Thread_Storage(void *)
{
}

View File

@@ -46,7 +46,7 @@ namespace chaiscript {
private:
struct Data
{
Data(const std::type_info &t_type)
explicit Data(const std::type_info &t_type)
: m_type(t_type)
{
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
@@ -40,7 +40,7 @@ namespace chaiscript
{
}
bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(nullptr), m_what(std::move(t_what))
{
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BIND_FIRST_HPP_

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
@@ -440,6 +440,8 @@ namespace chaiscript
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
@@ -450,7 +452,13 @@ namespace chaiscript
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
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->eval(R""(
def Dynamic_Object::clone() {
auto &new_o = Dynamic_Object(this.get_type_name());
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
new_o;
}
)"");
m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard");
@@ -460,9 +468,12 @@ namespace chaiscript
m->add(fun(&Boxed_Value::is_const), "is_var_const");
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
m->add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m->add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
@@ -485,6 +496,7 @@ namespace chaiscript
basic_constructors<bool>("bool", m);
operators::assign<bool>(m);
operators::equal<bool>(m);
operators::not_equal<bool>(m);
m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
m->add(fun(&Bootstrap::bool_to_string), "to_string");
@@ -502,6 +514,8 @@ namespace chaiscript
bootstrap_pod_type<long>("long", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<long long>("long_long", m);
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<wchar_t>("wchar_t", m);
@@ -556,13 +570,14 @@ namespace chaiscript
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<std::shared_ptr<const chaiscript::AST_Node>>);
return retval;
})), "call_stack"} }
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
return retval;
})), "call_stack"} }
);
@@ -588,7 +603,7 @@ namespace chaiscript
std::vector<Boxed_Value> retval;
std::transform(t_node.children.begin(), t_node.children.end(),
std::back_inserter(retval),
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
return retval;
})), "children"},
{fun(&AST_Node::replace_child), "replace_child"}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
/// \file
@@ -334,7 +334,12 @@ namespace chaiscript
"# Pushes the second value onto the container while making a clone of the value\n"
"def push_back(" + type + " container, x)\n"
"{ \n"
" container.push_back_ref(clone(x)) \n"
" if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_back_ref(x) \n"
" } else { \n"
" container.push_back_ref(clone(x)); \n"
" }\n"
"} \n"
);
@@ -370,7 +375,12 @@ namespace chaiscript
"# Pushes the second value onto the front of container while making a clone of the value\n"
"def push_front(" + type + " container, x)\n"
"{ \n"
" container.push_front_ref(clone(x)) \n"
" if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_front_ref(x) \n"
" } else { \n"
" container.push_front_ref(clone(x)); \n"
" }\n"
"} \n"
);
return "push_front_ref";
@@ -460,6 +470,30 @@ namespace chaiscript
m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
{
m->eval(R"(
def Map::`==`(Map rhs) {
if ( rhs.size() != this.size() ) {
return false;
} else {
auto r1 = range(this);
auto r2 = range(rhs);
while (!r1.empty())
{
if (!eq(r1.front().first, r2.front().first) || !eq(r1.front().second, r2.front().second))
{
return false;
}
r1.pop_front();
r2.pop_front();
}
true;
}
} )"
);
}
container_type<MapType>(type, m);
default_constructible_type<MapType>(type, m);
assignable_type<MapType>(type, m);
@@ -515,7 +549,7 @@ namespace chaiscript
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
{
m->eval(R"(
def Vector::`==`(rhs) : type_match(rhs, this) {
def Vector::`==`(Vector rhs) {
if ( rhs.size() != this.size() ) {
return false;
} else {

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
@@ -69,9 +69,9 @@ namespace chaiscript
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
{
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !t_conversions->convertable_type<Type>())) {
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
@@ -79,18 +79,18 @@ namespace chaiscript
}
if (t_conversions && t_conversions->convertable_type<Type>())
if (t_conversions && (*t_conversions)->convertable_type<Type>())
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions);
} catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
@@ -16,7 +16,7 @@
namespace chaiscript
{
class Type_Conversions;
class Type_Conversions_State;
namespace detail
{
@@ -33,14 +33,14 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner
{
typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
typedef typename std::add_const<Result>::type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return std::cref(*static_cast<const Result *>(p));
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
@@ -52,23 +52,17 @@ namespace chaiscript
{
};
/// Cast_Helper_Inner for casting to a const & type
template<typename Result>
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
{
};
/// Cast_Helper_Inner for casting to a const * type
template<typename Result>
struct Cast_Helper_Inner<const Result *>
{
typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
return static_cast<const Result *>(ob.get_const_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
@@ -80,11 +74,40 @@ namespace chaiscript
struct Cast_Helper_Inner<Result *>
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
{
return static_cast<Result *>(throw_if_null(ob.get_ptr()));
return static_cast<Result *>(ob.get_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
template<typename Result>
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
{
};
template<typename Result>
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
{
};
/// Cast_Helper_Inner for casting to a & type
template<typename Result>
struct Cast_Helper_Inner<const Result &>
{
typedef const Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
@@ -99,7 +122,7 @@ namespace chaiscript
{
typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
@@ -116,7 +139,7 @@ namespace chaiscript
{
typedef std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob.get().cast<std::shared_ptr<Result> >();
}
@@ -128,7 +151,7 @@ namespace chaiscript
{
typedef std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const())
{
@@ -166,9 +189,9 @@ namespace chaiscript
template<>
struct Cast_Helper_Inner<Boxed_Value>
{
typedef const Boxed_Value & Result_Type;
typedef Boxed_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob;
}
@@ -178,11 +201,11 @@ namespace chaiscript
template<>
struct Cast_Helper_Inner<Boxed_Value &>
{
typedef Boxed_Value& Result_Type;
typedef std::reference_wrapper<Boxed_Value> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return const_cast<Boxed_Value &>(ob);
return std::ref(const_cast<Boxed_Value &>(ob));
}
};
@@ -236,7 +259,7 @@ namespace chaiscript
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
@@ -100,6 +100,7 @@ namespace chaiscript
:(Common_Types::t_uint64);
}
static Common_Types get_common_type(const Boxed_Value &t_bv)
{
const Type_Info &inp_ = t_bv.get_type_info();
@@ -120,8 +121,12 @@ namespace chaiscript
return get_common_type(sizeof(unsigned int), false);
} else if (inp_ == typeid(long)) {
return get_common_type(sizeof(long), true);
} else if (inp_ == typeid(long long)) {
return get_common_type(sizeof(long long), true);
} else if (inp_ == typeid(unsigned long)) {
return get_common_type(sizeof(unsigned long), false);
} else if (inp_ == typeid(unsigned long long)) {
return get_common_type(sizeof(unsigned long long), false);
} else if (inp_ == typeid(std::int8_t)) {
return Common_Types::t_int8;
} else if (inp_ == typeid(std::int16_t)) {
@@ -513,6 +518,21 @@ namespace chaiscript
validate_boxed_number(bv);
}
static bool is_floating_point(const Boxed_Value &t_bv)
{
const Type_Info &inp_ = t_bv.get_type_info();
if (inp_ == typeid(double)) {
return true;
} else if (inp_ == typeid(long double)) {
return true;
} else if (inp_ == typeid(float)) {
return true;
} else {
return false;
}
}
Boxed_Number get_as(const Type_Info &inp_) const
{
if (inp_.bare_equal_type_info(typeid(int))) {
@@ -537,8 +557,12 @@ namespace chaiscript
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(long long))) {
return Boxed_Number(get_as<long 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(unsigned long long))) {
return Boxed_Number(get_as<unsigned long long>());
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
return Boxed_Number(get_as<int8_t>());
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {
@@ -987,7 +1011,7 @@ namespace chaiscript
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
@@ -297,6 +297,13 @@ namespace chaiscript
return *this;
}
Boxed_Value &clone_attrs(const Boxed_Value &t_obj)
{
copy_attrs(t_obj);
reset_return_value();
return *this;
}
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
@@ -330,9 +337,9 @@ namespace chaiscript
///
/// @sa @ref adding_objects
template<typename T>
Boxed_Value var(T t)
Boxed_Value var(T &&t)
{
return Boxed_Value(t);
return Boxed_Value(std::forward<T>(t));
}
namespace detail {

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
@@ -61,6 +61,17 @@ namespace chaiscript {
Ret (Class::*m_func)(Param...);
};
template<typename T>
struct Arity
{
};
template<typename Ret, typename ... Params>
struct Arity<Ret (Params...)>
{
static const size_t arity = sizeof...(Params);
};
template<typename T>
struct Function_Signature

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
@@ -314,7 +314,7 @@ namespace chaiscript
return arity;
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
@@ -326,7 +326,7 @@ namespace chaiscript
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dispatch::dispatch(m_funcs, params, t_conversions);
}
@@ -417,9 +417,9 @@ namespace chaiscript
struct State
{
std::map<std::string, std::vector<Proxy_Function> > m_functions;
std::map<std::string, Proxy_Function> m_function_objects;
std::map<std::string, Boxed_Value> m_boxed_functions;
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> m_functions;
std::vector<std::pair<std::string, Proxy_Function>> m_function_objects;
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
@@ -442,7 +442,8 @@ namespace chaiscript
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);
Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
return chaiscript::boxed_cast<Type>(bv, &state);
}
/// Add a new conversion for upcasting to a base class
@@ -482,24 +483,31 @@ namespace chaiscript
add_object(name, std::move(obj));
}
/// Adds a named object to the current scope
/// \warning This version does not check the validity of the name
/// it is meant for internal use only
void add_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
{
auto &stack_elem = get_stack_data(t_holder).back();
if (std::any_of(stack_elem.begin(), stack_elem.end(),
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == t_name;
}))
{
throw chaiscript::exception::name_conflict_error(t_name);
}
get_stack_data(t_holder).back().emplace_back(t_name, std::move(obj));
}
/// Adds a named object to the current scope
/// \warning This version does not check the validity of the name
/// it is meant for internal use only
void add_object(const std::string &name, Boxed_Value obj)
{
auto &stack_elem = get_stack_data().back();
if (std::any_of(stack_elem.begin(), stack_elem.end(),
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == name;
}))
{
throw chaiscript::exception::name_conflict_error(name);
}
get_stack_data().back().emplace_back(name, std::move(obj));
add_object(name, std::move(obj), get_stack_holder());
}
/// Adds a new global shared object, between all the threads
@@ -511,7 +519,7 @@ namespace chaiscript
throw chaiscript::exception::global_non_const();
}
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
{
@@ -526,7 +534,7 @@ namespace chaiscript
{
validate_object_name(name);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto itr = m_state.m_global_objects.find(name);
if (itr == m_state.m_global_objects.end())
@@ -544,7 +552,7 @@ namespace chaiscript
{
validate_object_name(name);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
{
@@ -554,6 +562,21 @@ namespace chaiscript
}
}
/// Updates an existing global shared object or adds a new global shared object if not found
void set_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_mutex);
const auto itr = m_state.m_global_objects.find(name);
if (itr != m_state.m_global_objects.end())
{
itr->second.assign(obj);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
}
}
/// Adds a new scope to the stack
void new_scope()
@@ -589,13 +612,13 @@ namespace chaiscript
/// Pushes a new stack on to the list of stacks
void new_stack(Stack_Holder &t_holder)
static void new_stack(Stack_Holder &t_holder)
{
// add a new Stack with 1 element
t_holder.stacks.emplace_back(1);
}
void pop_stack(Stack_Holder &t_holder)
static void pop_stack(Stack_Holder &t_holder)
{
t_holder.stacks.pop_back();
}
@@ -641,19 +664,21 @@ namespace chaiscript
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
}
// Is the value we are looking for a global?
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
// Is the value we are looking for a global or function?
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto itr = m_state.m_global_objects.find(name);
if (itr != m_state.m_global_objects.end())
{
return itr->second;
}
const auto itr = m_state.m_global_objects.find(name);
if (itr != m_state.m_global_objects.end())
{
return itr->second;
}
// If all that failed, then check to see if it's a function
return get_function_object(name);
// no? is it a function object?
auto obj = get_function_object_int(name, loc);
if (obj.first != loc) t_loc.store(uint_fast32_t(obj.first), std::memory_order_relaxed);
return obj.second;
}
/// Registers a new named type
@@ -711,20 +736,29 @@ namespace chaiscript
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
}
std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
{
uint_fast32_t method_missing_loc = m_method_missing_loc.load(std::memory_order_relaxed);
auto method_missing_funs = get_function("method_missing", method_missing_loc);
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc.store(uint_fast32_t(method_missing_funs.first), std::memory_order_relaxed);
return std::move(method_missing_funs.second);
}
/// Return a function by name
std::vector< Proxy_Function > get_function(const std::string &t_name) const
std::pair<size_t, std::shared_ptr<std::vector< Proxy_Function>>> get_function(const std::string &t_name, const size_t t_hint) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto &funs = get_functions_int();
auto itr = funs.find(t_name);
auto itr = find_keyed_value(funs, t_name, t_hint);
if (itr != funs.end())
{
return itr->second;
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else {
return std::vector<Proxy_Function>();
return std::make_pair(size_t(0), std::make_shared<std::vector<Proxy_Function>>());
}
}
@@ -732,28 +766,36 @@ namespace chaiscript
/// \throws std::range_error if it does not
Boxed_Value get_function_object(const std::string &t_name) const
{
// std::cout << "Getting function object: " << t_name << '\n';
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return get_function_object_int(t_name, 0).second;
}
/// \returns a function object (Boxed_Value wrapper) if it exists
/// \throws std::range_error if it does not
/// \warn does not obtain a mutex lock. \sa get_function_object for public version
std::pair<size_t, Boxed_Value> get_function_object_int(const std::string &t_name, const size_t t_hint) const
{
const auto &funs = get_boxed_functions_int();
auto itr = funs.find(t_name);
auto itr = find_keyed_value(funs, t_name, t_hint);
if (itr != funs.end())
{
return itr->second;
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else {
throw std::range_error("Object not found: " + t_name);
}
}
/// Return true if a function exists
bool function_exists(const std::string &name) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto &functions = get_functions_int();
return functions.find(name) != functions.end();
return find_keyed_value(functions, name) != functions.end();
}
/// \returns All values in the local thread state in the parent scope, or if it doesn't exist,
@@ -810,11 +852,8 @@ namespace chaiscript
}
// add the global values
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
}
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
return retval;
}
@@ -851,7 +890,7 @@ namespace chaiscript
for (const auto & function : functions)
{
for (const auto & internal_func : function.second)
for (const auto & internal_func : *function.second)
{
rets.emplace_back(function.first, internal_func);
}
@@ -873,7 +912,7 @@ namespace chaiscript
}
bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
bool t_has_params) const
bool t_has_params, const Type_Conversions_State &t_conversions) const
{
if (!t_has_params || t_params.empty()) {
return false;
@@ -881,7 +920,7 @@ namespace chaiscript
for (const auto &fun : t_funs) {
if (fun->is_attribute_function()) {
if (fun->compare_first_type(t_params[0], m_conversions)) {
if (fun->compare_first_type(t_params[0], t_conversions)) {
return true;
}
}
@@ -896,38 +935,55 @@ namespace chaiscript
#pragma warning(push)
#pragma warning(disable : 4715)
#endif
Boxed_Value call_member(const std::string &t_name, const std::vector<Boxed_Value> &params, bool t_has_params) const
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params, bool t_has_params,
const Type_Conversions_State &t_conversions)
{
const auto funs = get_function(t_name);
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
const auto do_attribute_call =
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
{
std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
std::vector<Boxed_Value> remaining_params{l_params.begin() + l_num_params, l_params.end()};
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
if (!remaining_params.empty() || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
if (l_num_params < int(l_params.size()) || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
struct This_Foist {
This_Foist(Dispatch_Engine &e, const Boxed_Value &t_bv) : m_e(e) {
m_e.get().new_scope();
m_e.get().add_object("__this", t_bv);
}
~This_Foist() {
m_e.get().pop_scope();
}
std::reference_wrapper<Dispatch_Engine> m_e;
};
This_Foist fi(*this, l_params.front());
auto func = boxed_cast<std::shared_ptr<const dispatch::Proxy_Function_Base>>(bv);
try {
return (*func)(remaining_params, l_conversions);
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
} catch (const chaiscript::exception::bad_boxed_cast &) {
} catch (const chaiscript::exception::arity_error &) {
} catch (const chaiscript::exception::guard_error &) {
}
throw chaiscript::exception::dispatch_error(remaining_params, std::vector<Const_Proxy_Function>{func});
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector<Const_Proxy_Function>{func});
} else {
return bv;
}
};
if (is_attribute_call(funs, params, t_has_params)) {
return do_attribute_call(1, params, funs, m_conversions);
if (is_attribute_call(*funs.second, params, t_has_params, t_conversions)) {
return do_attribute_call(1, params, *funs.second, t_conversions);
} else {
std::exception_ptr except;
if (!funs.empty()) {
if (!funs.second->empty()) {
try {
return dispatch::dispatch(funs, params, m_conversions);
return dispatch::dispatch(*funs.second, params, t_conversions);
} catch(chaiscript::exception::dispatch_error&) {
except = std::current_exception();
}
@@ -939,9 +995,11 @@ namespace chaiscript
const auto functions = [&]()->std::vector<Proxy_Function> {
std::vector<Proxy_Function> fs;
for (const auto &f : get_function("method_missing"))
const auto method_missing_funs = get_method_missing_functions();
for (const auto &f : *method_missing_funs)
{
if(f->compare_first_type(params[0], m_conversions)) {
if(f->compare_first_type(params[0], t_conversions)) {
fs.push_back(f);
}
}
@@ -961,12 +1019,17 @@ namespace chaiscript
}();
if (!functions.empty()) {
if (is_no_param) {
std::vector<Boxed_Value> tmp_params(params);
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
return do_attribute_call(2, tmp_params, functions, m_conversions);
} else {
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
try {
if (is_no_param) {
std::vector<Boxed_Value> tmp_params(params);
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
return do_attribute_call(2, tmp_params, functions, t_conversions);
} else {
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, t_conversions);
}
} catch (const dispatch::option_explicit_set &e) {
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
e.what());
}
}
@@ -975,7 +1038,7 @@ namespace chaiscript
if (except) {
std::rethrow_exception(except);
} else {
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.begin(), funs.end()));
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()));
}
}
}
@@ -985,30 +1048,15 @@ namespace chaiscript
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params,
const Type_Conversions_State &t_conversions) const
{
Boxed_Value bv = dispatch::dispatch(get_function(t_name), params, m_conversions);
// the result of a clone is never to be marked as a return_value
if (t_name == "clone") {
bv.reset_return_value();
}
return bv;
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
return dispatch::dispatch(*funs.second, params, t_conversions);
}
Boxed_Value call_function(const std::string &t_name) const
{
return call_function(t_name, std::vector<Boxed_Value>());
}
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1) const
{
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1)}));
}
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1, Boxed_Value p2) const
{
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1), std::move(p2)}));
}
/// Dump object info to stdout
void dump_object(const Boxed_Value &o) const
@@ -1052,7 +1100,7 @@ namespace chaiscript
/// 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)
Boxed_Value call_exists(const std::vector<Boxed_Value> &params) const
{
if (params.empty())
{
@@ -1060,8 +1108,9 @@ namespace chaiscript
}
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves());
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
}
/// Dump all system info to stdout
@@ -1119,7 +1168,6 @@ namespace chaiscript
State get_state() const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_global_object_mutex);
return m_state;
}
@@ -1127,17 +1175,16 @@ namespace chaiscript
void set_state(const State &t_state)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_global_object_mutex);
m_state = t_state;
}
void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
static void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
{
t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(t_params));
}
void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
static void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
{
for (auto &&param : t_params)
{
@@ -1145,7 +1192,7 @@ namespace chaiscript
}
}
void save_function_params(Stack_Holder &t_s, const std::vector<Boxed_Value> &t_params)
static void save_function_params(Stack_Holder &t_s, const std::vector<Boxed_Value> &t_params)
{
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end());
}
@@ -1165,19 +1212,19 @@ namespace chaiscript
save_function_params(*m_stack_holder, t_params);
}
void new_function_call(Stack_Holder &t_s)
void new_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
{
if (t_s.call_depth == 0)
{
m_conversions.enable_conversion_saves(true);
m_conversions.enable_conversion_saves(t_saves, true);
}
++t_s.call_depth;
save_function_params(m_conversions.take_saves());
save_function_params(m_conversions.take_saves(t_saves));
}
void pop_function_call(Stack_Holder &t_s)
void pop_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
{
--t_s.call_depth;
@@ -1186,18 +1233,18 @@ namespace chaiscript
if (t_s.call_depth == 0)
{
t_s.call_params.back().clear();
m_conversions.enable_conversion_saves(false);
m_conversions.enable_conversion_saves(t_saves, false);
}
}
void new_function_call()
{
new_function_call(*m_stack_holder);
new_function_call(*m_stack_holder, m_conversions.conversion_saves());
}
void pop_function_call()
{
pop_function_call(*m_stack_holder);
pop_function_call(*m_stack_holder, m_conversions.conversion_saves());
}
Stack_Holder &get_stack_holder()
@@ -1205,7 +1252,6 @@ namespace chaiscript
return *m_stack_holder;
}
private:
/// Returns the current stack
/// make const/non const versions
const StackData &get_stack_data() const
@@ -1213,7 +1259,7 @@ namespace chaiscript
return m_stack_holder->stacks.back();
}
StackData &get_stack_data(Stack_Holder &t_holder)
static StackData &get_stack_data(Stack_Holder &t_holder)
{
return t_holder.stacks.back();
}
@@ -1223,32 +1269,34 @@ namespace chaiscript
return m_stack_holder->stacks.back();
}
const std::map<std::string, Boxed_Value> &get_boxed_functions_int() const
private:
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
{
return m_state.m_boxed_functions;
}
std::map<std::string, Boxed_Value> &get_boxed_functions_int()
std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int()
{
return m_state.m_boxed_functions;
}
const std::map<std::string, Proxy_Function> &get_function_objects_int() const
const std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() const
{
return m_state.m_function_objects;
}
std::map<std::string, Proxy_Function> &get_function_objects_int()
std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int()
{
return m_state.m_function_objects;
}
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
const std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() const
{
return m_state.m_functions;
}
std::map<std::string, std::vector<Proxy_Function> > &get_functions_int()
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int()
{
return m_state.m_functions;
}
@@ -1362,6 +1410,49 @@ namespace chaiscript
}
}
template<typename Container, typename Key, typename Value>
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
{
auto itr = find_keyed_value(t_c, t_key);
if (itr == t_c.end()) {
t_c.reserve(t_c.size() + 1); // tightly control growth of memory usage here
t_c.emplace_back(t_key, std::forward<Value>(t_value));
} else {
typedef typename Container::value_type value_type;
*itr = value_type(t_key, std::forward<Value>(t_value));
}
}
template<typename Container, typename Key>
static typename Container::iterator find_keyed_value(Container &t_c, const Key &t_key)
{
return std::find_if(t_c.begin(), t_c.end(),
[&t_key](const typename Container::value_type &o) {
return o.first == t_key;
});
}
template<typename Container, typename Key>
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key)
{
return std::find_if(t_c.begin(), t_c.end(),
[&t_key](const typename Container::value_type &o) {
return o.first == t_key;
});
}
template<typename Container, typename Key>
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
{
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
return t_c.begin() + t_hint;
} else {
return find_keyed_value(t_c, t_key);
}
}
/// Implementation detail for adding a function.
/// \throws exception::name_conflict_error if there's a function matching the given one being added
void add_function(const Proxy_Function &t_f, const std::string &t_name)
@@ -1370,16 +1461,13 @@ namespace chaiscript
auto &funcs = get_functions_int();
auto itr = funcs.find(t_name);
auto &func_objs = get_function_objects_int();
auto &boxed_funcs = get_boxed_functions_int();
auto itr = find_keyed_value(funcs, t_name);
Proxy_Function new_func =
[&]() -> Proxy_Function {
if (itr != funcs.end())
{
auto &vec = itr->second;
auto vec = *itr->second;
for (const auto &func : vec)
{
if ((*t_f) == *(func))
@@ -1388,33 +1476,35 @@ namespace chaiscript
}
}
vec.reserve(vec.size() + 1); // tightly control vec growth
vec.push_back(t_f);
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
return std::make_shared<Dispatch_Function>(vec);
itr->second = std::make_shared<std::vector<Proxy_Function>>(vec);
return std::make_shared<Dispatch_Function>(std::move(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({t_f});
funcs.insert(std::make_pair(t_name, vec));
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(vec));
return std::make_shared<Dispatch_Function>(std::move(vec));
} else {
funcs.insert(std::make_pair(t_name, std::vector<Proxy_Function>{t_f}));
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(std::initializer_list<Proxy_Function>({t_f})));
return t_f;
}
}();
boxed_funcs[t_name] = const_var(new_func);
func_objs[t_name] = std::move(new_func);
add_keyed_value(get_boxed_functions_int(), t_name, const_var(new_func));
add_keyed_value(get_function_objects_int(), t_name, std::move(new_func));
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;
mutable chaiscript::detail::threading::shared_mutex m_global_object_mutex;
Type_Conversions m_conversions;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
mutable std::atomic_uint_fast32_t m_method_missing_loc;
State m_state;
};
@@ -1424,7 +1514,8 @@ namespace chaiscript
public:
Dispatch_State(Dispatch_Engine &t_engine)
: m_engine(t_engine),
m_stack_holder(t_engine.get_stack_holder())
m_stack_holder(t_engine.get_stack_holder()),
m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves())
{
}
@@ -1440,9 +1531,22 @@ namespace chaiscript
return m_stack_holder.get();
}
const Type_Conversions_State &conversions() const {
return m_conversions;
}
Type_Conversions::Conversion_Saves &conversion_saves() const {
return m_conversions.saves();
}
void add_object(const std::string &t_name, Boxed_Value obj) const {
m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
}
private:
std::reference_wrapper<Dispatch_Engine> m_engine;
std::reference_wrapper<Stack_Holder> m_stack_holder;
Type_Conversions_State m_conversions;
};
}
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
@@ -24,23 +24,55 @@ namespace chaiscript
{
namespace dispatch
{
struct option_explicit_set : std::runtime_error {
option_explicit_set(const std::string &t_param_name)
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
{
}
option_explicit_set(const option_explicit_set &) = default;
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
};
class Dynamic_Object
{
public:
Dynamic_Object(std::string t_type_name)
: m_type_name(std::move(t_type_name))
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
{
}
Dynamic_Object() : m_type_name("")
Dynamic_Object() : m_type_name(""), m_option_explicit(false)
{
}
bool is_explicit() const
{
return m_option_explicit;
}
void set_explicit(const bool t_explicit)
{
m_option_explicit = t_explicit;
}
std::string get_type_name() const
{
return m_type_name;
}
const Boxed_Value &operator[](const std::string &t_attr_name) const
{
return get_attr(t_attr_name);
}
Boxed_Value &operator[](const std::string &t_attr_name)
{
return get_attr(t_attr_name);
}
const Boxed_Value &get_attr(const std::string &t_attr_name) const
{
auto a = m_attrs.find(t_attr_name);
@@ -59,11 +91,19 @@ namespace chaiscript
Boxed_Value &method_missing(const std::string &t_method_name)
{
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
throw option_explicit_set(t_method_name);
}
return get_attr(t_method_name);
}
const Boxed_Value &method_missing(const std::string &t_method_name) const
{
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
throw option_explicit_set(t_method_name);
}
return get_attr(t_method_name);
}
@@ -75,6 +115,7 @@ namespace chaiscript
private:
std::string m_type_name;
bool m_option_explicit;
std::map<std::string, Boxed_Value> m_attrs;
};

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
@@ -84,7 +84,7 @@ namespace chaiscript
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
@@ -106,7 +106,7 @@ namespace chaiscript
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
@@ -116,7 +116,7 @@ namespace chaiscript
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
}
@@ -134,7 +134,7 @@ namespace chaiscript
}
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
{
if (bv.get_type_info().bare_equal(m_doti))
{
@@ -156,7 +156,7 @@ namespace chaiscript
}
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
{
if (bvs.size() > 0)
{
@@ -216,7 +216,7 @@ namespace chaiscript
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
@@ -230,9 +230,9 @@ namespace chaiscript
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
auto bv = var(Dynamic_Object(m_type_name));
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
std::vector<Boxed_Value> new_params{bv};
new_params.insert(new_params.end(), params.begin(), params.end());

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
@@ -32,7 +32,7 @@ namespace chaiscript
protected:
template<typename T>
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
@@ -14,10 +14,11 @@
#include "boxed_cast.hpp"
#include "function_call_detail.hpp"
#include "proxy_functions.hpp"
#include "callable_traits.hpp"
namespace chaiscript {
class Boxed_Value;
class Type_Conversions;
class Type_Conversions_State;
namespace detail {
template <typename T> struct Cast_Helper;
} // namespace detail
@@ -35,8 +36,17 @@ namespace chaiscript
/// \param[in] funcs the set of functions to dispatch on.
template<typename FunctionType>
std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
{
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
[](const Const_Proxy_Function &f) {
return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
});
if (!has_arity_match) {
throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
}
FunctionType *p=nullptr;
return detail::build_function_caller_helper(p, funcs, t_conversions);
}
@@ -54,7 +64,7 @@ namespace chaiscript
/// \param[in] func A function to execute.
template<typename FunctionType>
std::function<FunctionType>
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
}
@@ -63,7 +73,7 @@ namespace chaiscript
/// and creating a typesafe C++ function caller from it.
template<typename FunctionType>
std::function<FunctionType>
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
}
@@ -76,7 +86,7 @@ namespace chaiscript
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@@ -93,7 +103,7 @@ namespace chaiscript
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@@ -110,7 +120,7 @@ namespace chaiscript
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
@@ -31,9 +31,15 @@ namespace chaiscript
struct Function_Caller_Ret
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions *t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions);
if (t_conversions) {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
}
}
};
@@ -44,9 +50,15 @@ namespace chaiscript
struct Function_Caller_Ret<Ret, true>
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions *t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as<Ret>();
if (t_conversions) {
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
}
}
};
@@ -58,9 +70,15 @@ namespace chaiscript
struct Function_Caller_Ret<void, false>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions *t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions());
if (t_conversions) {
dispatch::dispatch(t_funcs, params, *t_conversions);
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
dispatch::dispatch(t_funcs, params, state);
}
}
};
@@ -79,11 +97,18 @@ namespace chaiscript
template<typename ... P>
Ret operator()(P&& ... param)
{
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, m_conversions
);
if (m_conversions) {
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, &state
);
} else {
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, nullptr
);
}
}
@@ -114,7 +139,7 @@ namespace chaiscript
/// \todo what happens if t_conversions is deleted out from under us?!
template<typename Ret, typename ... Params>
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
{
/*
if (funcs.size() == 1)
@@ -132,7 +157,7 @@ namespace chaiscript
}
*/
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions));
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
}
}
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_OPERATORS_HPP_

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -43,7 +43,7 @@ namespace chaiscript
namespace dispatch
{
template<typename FunctionType>
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions *t_conversions);
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions_State *t_conversions);
class Param_Types
{
@@ -72,7 +72,7 @@ namespace chaiscript
return m_types == t_rhs.m_types;
}
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
{
if (!m_has_types) return true;
if (vals.size() != m_types.size()) return false;
@@ -147,7 +147,7 @@ namespace chaiscript
public:
virtual ~Proxy_Function_Base() {}
Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Type_Conversions &t_conversions) const
Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Type_Conversions_State &t_conversions) const
{
if (m_arity < 0 || size_t(m_arity) == params.size()) {
return do_call(params, t_conversions);
@@ -163,7 +163,7 @@ namespace chaiscript
const std::vector<Type_Info> &get_param_types() const { return m_types; }
virtual bool operator==(const Proxy_Function_Base &) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
virtual bool is_attribute_function() const { return false; }
@@ -179,7 +179,7 @@ namespace chaiscript
//! Return true if the function is a possible match
//! to the passed in values
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
{
if (m_arity < 0)
{
@@ -206,15 +206,15 @@ namespace chaiscript
virtual std::string annotation() const = 0;
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
{
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(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|| ti.bare_equal(bv.get_type_info())
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|| t_conversions.converts(ti, bv.get_type_info())
|| t_conversions->converts(ti, bv.get_type_info())
)
)
)
@@ -225,13 +225,13 @@ namespace chaiscript
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const
{
return compare_type_to_param(m_types[1], bv, t_conversions);
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const = 0;
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const = 0;
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
@@ -248,7 +248,7 @@ namespace chaiscript
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs, const Type_Conversions_State &t_conversions)
{
if (tis.size() - 1 != bvs.size())
{
@@ -257,10 +257,7 @@ namespace chaiscript
const size_t size = bvs.size();
for (size_t i = 0; i < size; ++i)
{
if (!(tis[i+1].bare_equal(bvs[i].get_type_info()) && tis[i+1].is_const() >= bvs[i].get_type_info().is_const() ))
{
return false;
}
if (!compare_type_to_param(tis[i + 1], bvs[i], t_conversions)) { return false; }
}
}
return true;
@@ -330,7 +327,7 @@ namespace chaiscript
&& this->m_param_types == prhs->m_param_types);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
&& test_guard(vals, t_conversions);
@@ -354,7 +351,7 @@ namespace chaiscript
protected:
bool test_guard(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const
bool test_guard(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const
{
if (m_guard)
{
@@ -422,7 +419,7 @@ namespace chaiscript
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
{
@@ -472,7 +469,7 @@ namespace chaiscript
virtual ~Bound_Function() {}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return m_f->call_match(build_param_list(vals), t_conversions);
}
@@ -551,7 +548,7 @@ namespace chaiscript
return retval;
}
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return (*m_f)(build_param_list(params), t_conversions);
}
@@ -576,12 +573,12 @@ namespace chaiscript
return "";
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions));
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions));
}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
};
@@ -599,7 +596,7 @@ namespace chaiscript
virtual ~Proxy_Function_Callable_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
@@ -611,7 +608,7 @@ namespace chaiscript
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
typedef typename detail::Function_Signature<Func>::Return_Type Return_Type;
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
@@ -651,7 +648,7 @@ namespace chaiscript
virtual ~Assignable_Proxy_Function_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
@@ -671,7 +668,7 @@ namespace chaiscript
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::Do_Call<typename std::function<Func>::result_type>::template go<Func>(m_f.get(), params, t_conversions);
}
@@ -708,7 +705,7 @@ namespace chaiscript
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const CHAISCRIPT_OVERRIDE
{
if (vals.size() != 1)
{
@@ -724,7 +721,7 @@ namespace chaiscript
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
@@ -763,6 +760,14 @@ namespace chaiscript
{
}
dispatch_error(std::vector<Boxed_Value> t_parameters,
std::vector<Const_Proxy_Function> t_functions,
const std::string &t_desc)
: std::runtime_error(t_desc), parameters(std::move(t_parameters)), functions(std::move(t_functions))
{
}
dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
@@ -777,7 +782,7 @@ namespace chaiscript
{
template<typename FuncType>
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
const Type_Conversions &t_conversions)
const Type_Conversions_State &t_conversions)
{
const std::vector<Type_Info> &types = t_func->get_param_types();
@@ -796,7 +801,7 @@ namespace chaiscript
template<typename InItr, typename Funcs>
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
const Type_Conversions &t_conversions, const Funcs &t_funcs)
const Type_Conversions_State &t_conversions, const Funcs &t_funcs)
{
InItr matching_func(end);
@@ -873,7 +878,7 @@ namespace chaiscript
*/
template<typename Funcs>
Boxed_Value dispatch(const Funcs &funcs,
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
{
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
ordered_funcs.reserve(funcs.size());

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
@@ -19,7 +19,7 @@
#include "callable_traits.hpp"
namespace chaiscript {
class Type_Conversions;
class Type_Conversions_State;
namespace exception {
class bad_boxed_cast;
} // namespace exception
@@ -77,7 +77,7 @@ namespace chaiscript
template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...>
{
static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions &t_conversions)
static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions_State &t_conversions)
{
boxed_cast<Param>(params[generation], &t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
@@ -88,7 +88,7 @@ namespace chaiscript
template<>
struct Try_Cast<>
{
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions &)
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions_State &)
{
}
};
@@ -101,7 +101,7 @@ namespace chaiscript
*/
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
Try_Cast<Params...>::do_try(params, 0, t_conversions);
@@ -118,7 +118,7 @@ namespace chaiscript
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
}
@@ -133,7 +133,7 @@ namespace chaiscript
#endif
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
const std::vector<Boxed_Value> &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
}
@@ -150,7 +150,7 @@ namespace chaiscript
*/
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
if (params.size() == sizeof...(Params))
{
@@ -190,7 +190,7 @@ namespace chaiscript
*/
template<typename Ret, typename ... Params, size_t ... I>
bool compare_types_cast(Indexes<I...>, Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
(void)params; (void)t_conversions;
@@ -204,7 +204,7 @@ namespace chaiscript
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*f)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return compare_types_cast(indexes(), f, params, t_conversions);
@@ -213,7 +213,7 @@ namespace chaiscript
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
(void)params; (void)t_conversions;
return f(boxed_cast<Params>(params[I], &t_conversions)...);
@@ -228,7 +228,7 @@ namespace chaiscript
*/
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return call_func(sig, indexes(), f, params, t_conversions);
@@ -252,7 +252,7 @@ namespace chaiscript
struct Do_Call
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
}
@@ -262,7 +262,7 @@ namespace chaiscript
struct Do_Call<void>
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
@@ -310,12 +310,21 @@ namespace chaiscript
private:
Callable m_func;
};
}
class Type_Conversions
{
public:
struct Conversion_Saves
{
Conversion_Saves()
: enabled(false)
{}
bool enabled;
std::vector<Boxed_Value> saves;
};
struct Less_Than
{
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
@@ -387,15 +396,14 @@ namespace chaiscript
} else {
return false;
}
}
template<typename To>
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
{
try {
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
if (t_saves.enabled) t_saves.saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
@@ -405,11 +413,11 @@ namespace chaiscript
}
template<typename From>
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
{
try {
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
if (t_saves.enabled) t_saves.saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
@@ -418,15 +426,15 @@ namespace chaiscript
}
}
void enable_conversion_saves(bool t_val)
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val)
{
m_conversion_saves->enabled = t_val;
t_saves.enabled = t_val;
}
std::vector<Boxed_Value> take_saves()
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves)
{
std::vector<Boxed_Value> ret;
std::swap(ret, m_conversion_saves->saves);
std::swap(ret, t_saves.saves);
return ret;
}
@@ -450,6 +458,10 @@ namespace chaiscript
}
}
Conversion_Saves &conversion_saves() const {
return *m_conversion_saves;
}
private:
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
const Type_Info &to, const Type_Info &from) const
@@ -459,7 +471,6 @@ namespace chaiscript
{
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
;
}
);
}
@@ -483,15 +494,6 @@ namespace chaiscript
}
struct Conversion_Saves
{
Conversion_Saves()
: enabled(false)
{}
bool enabled;
std::vector<Boxed_Value> saves;
};
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
@@ -501,6 +503,33 @@ namespace chaiscript
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
};
class Type_Conversions_State
{
public:
Type_Conversions_State(const Type_Conversions &t_conversions,
Type_Conversions::Conversion_Saves &t_saves)
: m_conversions(t_conversions),
m_saves(t_saves)
{
}
const Type_Conversions *operator->() const {
return &m_conversions.get();
}
const Type_Conversions *get() const {
return &m_conversions.get();
}
Type_Conversions::Conversion_Saves &saves() const {
return m_saves;
}
private:
std::reference_wrapper<const Type_Conversions> m_conversions;
std::reference_wrapper<Type_Conversions::Conversion_Saves> m_saves;
};
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
@@ -582,7 +611,7 @@ namespace chaiscript
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
To vec;
vec.reserve(from_vec.size());
for (const Boxed_Value &bv : from_vec) {
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
}
@@ -593,6 +622,22 @@ namespace chaiscript
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
}
template<typename To>
Type_Conversion map_conversion()
{
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
To map;
for (const std::pair<std::string, Boxed_Value> &p : from_map) {
map.insert(std::make_pair(p.first, detail::Cast_Helper<typename To::mapped_type>::cast(p.second, nullptr)));
}
return Boxed_Value(std::move(map));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
}
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
@@ -32,17 +32,17 @@ namespace chaiscript
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_is_undef(false)
m_flags((t_is_const << is_const_flag)
+ (t_is_reference << is_reference_flag)
+ (t_is_pointer << is_pointer_flag)
+ (t_is_void << is_void_flag)
+ (t_is_arithmetic << is_arithmetic_flag))
{
}
CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(nullptr), m_bare_type_info(nullptr),
m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_is_arithmetic(false),
m_is_undef(true)
m_flags(1 << is_undef_flag)
{
}
@@ -83,12 +83,12 @@ namespace chaiscript
&& (*m_bare_type_info) == ti;
}
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_const_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_reference_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_void_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_undef_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_pointer_flag)) != 0; }
std::string name() const
{
@@ -118,12 +118,13 @@ namespace chaiscript
private:
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_const;
bool m_is_reference;
bool m_is_pointer;
bool m_is_void;
bool m_is_arithmetic;
bool m_is_undef;
unsigned int m_flags;
static const int is_const_flag = 0;
static const int is_reference_flag = 1;
static const int is_pointer_flag = 2;
static const int is_void_flag = 3;
static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5;
};
namespace detail

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_
@@ -34,7 +34,7 @@ namespace chaiscript
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
enum Type { Error, Int, Float, Id, Char, Str, Eol, 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,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
@@ -47,7 +47,7 @@ namespace chaiscript
/// 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",
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "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",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
@@ -582,12 +582,12 @@ namespace chaiscript
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_function_call(m_ds.get().stack_holder());
m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
}
~Function_Push_Pop()
{
m_ds.get()->pop_function_call(m_ds.get().stack_holder());
m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
}
void save_params(const std::vector<Boxed_Value> &t_params)

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ENGINE_HPP_
@@ -36,7 +36,9 @@
#else
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#endif
@@ -175,11 +177,11 @@ namespace chaiscript
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
nullptr,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<StringType>(&lpMsgBuf),
0, NULL ) != 0 && lpMsgBuf)
0, nullptr ) != 0 && lpMsgBuf)
{
retval = lpMsgBuf;
LocalFree(lpMsgBuf);
@@ -284,14 +286,7 @@ namespace chaiscript
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
/// Evaluates the given file and looks in the 'use' paths
const Boxed_Value internal_eval_file(const std::string &t_filename) {
@@ -347,6 +342,7 @@ namespace chaiscript
m_engine.add_reserved_word("class");
m_engine.add_reserved_word("attr");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("global");
m_engine.add_reserved_word("GLOBAL");
m_engine.add_reserved_word("_");
@@ -372,11 +368,15 @@ namespace chaiscript
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
//
//
m_engine.add(fun(
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
return t_fun(t_params, this->m_engine.conversions());
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
return t_fun(t_params, s);
}), "call");
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
@@ -396,16 +396,21 @@ namespace chaiscript
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return internal_eval_ast(t_ast); }), "eval");
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
m_engine.add(fun(&parse), "parse");
m_engine.add(fun(&ChaiScript::version_major), "version_major");
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
m_engine.add(fun(&ChaiScript::version), "version");
m_engine.add(fun(&ChaiScript::compiler_version), "compiler_version");
m_engine.add(fun(&ChaiScript::compiler_name), "compiler_name");
m_engine.add(fun(&ChaiScript::compiler_id), "compiler_id");
m_engine.add(fun(&ChaiScript::debug_build), "debug_build");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
}
@@ -517,6 +522,28 @@ namespace chaiscript
build_eval_system(ModulePtr());
}
const Boxed_Value eval(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
static AST_NodePtr parse(const std::string &t_input)
{
parser::ChaiScript_Parser parser;
if (parser.parse(t_input, "PARSE")) {
//parser.show_match_stack();
return parser.optimized_ast();
} else {
throw chaiscript::exception::eval_error("Unknown error while parsing");
}
}
static int version_major()
{
return chaiscript::version_major;
@@ -534,11 +561,36 @@ namespace chaiscript
static std::string version()
{
std::stringstream ss;
ss << version_major() << "." << version_minor() << "." << version_patch();
return ss.str();
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
{
return chaiscript::compiler_name;
}
static bool debug_build()
{
return chaiscript::debug_build;
}
std::string get_type_name(const Type_Info &ti) const
{
return m_engine.get_type_name(ti);
@@ -608,6 +660,12 @@ namespace chaiscript
return *this;
}
ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name)
{
m_engine.set_global(t_bv, t_name);
return *this;
}
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
/// \warning State object does not contain the user defined type conversions of the engine. They
/// are left out due to performance considerations involved in tracking the state

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_EVAL_HPP_
@@ -44,16 +44,33 @@ namespace chaiscript
namespace detail
{
/// Helper function that will set up the scope around a function call, including handling the named function parameters
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> &t_locals=std::map<std::string, Boxed_Value>()) {
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr) {
chaiscript::detail::Dispatch_State state(t_ss);
chaiscript::eval::detail::Scope_Push_Pop spp(state);
for (const auto &local : t_locals) {
t_ss.add_object(local.first, local.second);
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
auto &stack = t_ss.get_stack_data(state.stack_holder()).back();
if (!stack.empty() && stack.back().first == "__this") {
return &stack.back().second;
} else if (!t_vals.empty()) {
return &t_vals[0];
} else {
return nullptr;
}
}();
chaiscript::eval::detail::Stack_Push_Pop tpp(state);
if (thisobj) state.add_object("this", *thisobj);
if (t_locals) {
for (const auto &local : *t_locals) {
state.add_object(local.first, local.second);
}
}
for (size_t i = 0; i < t_param_names.size(); ++i) {
t_ss.add_object(t_param_names[i], t_vals[i]);
if (t_param_names[i] != "this") {
state.add_object(t_param_names[i], t_vals[i]);
}
}
try {
@@ -73,9 +90,9 @@ namespace chaiscript
virtual ~Binary_Operator_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, m_oper, text,
this->children[0]->eval(t_ss),
this->children[1]->eval(t_ss));
auto lhs = this->children[0]->eval(t_ss);
auto rhs = this->children[1]->eval(t_ss);
return do_oper(t_ss, m_oper, text, lhs, rhs);
}
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
@@ -101,8 +118,7 @@ namespace chaiscript
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({t_lhs, t_rhs});
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
return t_ss->call_function(t_oper_string, t_lhs, t_rhs);
return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions());
}
}
catch(const exception::dispatch_error &e){
@@ -112,13 +128,14 @@ namespace chaiscript
private:
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
};
struct Int_AST_Node : public AST_Node {
public:
Int_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)),
m_value(std::move(t_bv)) { }
m_value(std::move(t_bv)) { assert(text != ""); }
virtual ~Int_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
return m_value;
@@ -236,8 +253,7 @@ namespace chaiscript
Boxed_Value fn(this->children[0]->eval(t_ss));
try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss->conversions());
return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@@ -286,73 +302,6 @@ namespace chaiscript
/// Used in the context of in-string ${} evals, so that no new scope is created
struct Inplace_Fun_Call_AST_Node : public AST_Node {
public:
Inplace_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(t_ast_node_text, AST_Node_Type::Inplace_Fun_Call, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 2); }
virtual ~Inplace_Fun_Call_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
std::vector<Boxed_Value> params;
params.reserve(this->children[1]->children.size());
for (const auto &child : this->children[1]->children) {
params.push_back(child->eval(t_ss));
}
Const_Proxy_Function fn;
try {
Boxed_Value bv = this->children[0]->eval(t_ss);
try {
fn = t_ss->boxed_cast<const Const_Proxy_Function &>(bv);
} catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
}
return (*fn)(params, t_ss->conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
}
catch(const exception::bad_boxed_cast &){
// handle the case where there is only 1 function to try to call and dispatch fails on it
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {fn}, false, *t_ss);
}
catch(const exception::arity_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
}
catch(const exception::guard_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
}
catch(detail::Return_Value &rv) {
return rv.retval;
}
}
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
int count = 0;
for (const auto &child : this->children) {
oss << child->pretty_print();
if (count == 0)
{
oss << "(";
}
++count;
}
oss << ")";
return oss.str();
}
};
struct Arg_AST_Node : public AST_Node {
public:
Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
@@ -448,6 +397,8 @@ namespace chaiscript
{ assert(children.size() == 3); }
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_clone_loc;
virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
@@ -483,14 +434,14 @@ namespace chaiscript
} else {
if (!rhs.is_return_value())
{
rhs = t_ss->call_function("clone", rhs);
rhs = t_ss->call_function("clone", m_clone_loc, {rhs}, t_ss.conversions());
}
rhs.reset_return_value();
}
}
try {
return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs);
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
@@ -503,13 +454,14 @@ namespace chaiscript
else if (this->children[1]->text == ":=") {
if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) {
lhs.assign(rhs);
lhs.reset_return_value();
} else {
throw exception::eval_error("Mismatched types in equation");
}
}
else {
try {
return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs);
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
} catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
}
@@ -560,7 +512,7 @@ namespace chaiscript
try {
Boxed_Value bv;
t_ss->add_object(idname, bv);
t_ss.add_object(idname, bv);
return bv;
}
catch (const exception::reserved_word_error &) {
@@ -591,9 +543,8 @@ namespace chaiscript
std::vector<Boxed_Value> params{children[0]->eval(t_ss), children[1]->eval(t_ss)};
try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
fpp.save_params(params);
return t_ss->call_function("[]", params);
return t_ss->call_function("[]", m_loc, params, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
@@ -615,6 +566,8 @@ namespace chaiscript
return oss.str();
}
mutable std::atomic_uint_fast32_t m_loc;
};
struct Dot_Access_AST_Node : public AST_Node {
@@ -629,6 +582,7 @@ namespace chaiscript
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value retval = children[0]->eval(t_ss);
std::vector<Boxed_Value> params{retval};
@@ -643,9 +597,7 @@ namespace chaiscript
fpp.save_params(params);
try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
t_ss->add_object("this", retval);
retval = t_ss->call_member(m_fun_name, std::move(params), has_function_params);
retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
if (e.functions.empty())
@@ -661,7 +613,7 @@ namespace chaiscript
if (this->children[2]->identifier == AST_Node_Type::Array_Call) {
try {
retval = t_ss->call_function("[]", retval, this->children[2]->children[1]->eval(t_ss));
retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
@@ -672,6 +624,8 @@ namespace chaiscript
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_array_loc;
std::string m_fun_name;
};
@@ -745,7 +699,7 @@ namespace chaiscript
dispatch::make_dynamic_proxy_function(
[engine, lambda_node, param_names, captures](const std::vector<Boxed_Value> &t_params)
{
return detail::eval_function(engine, lambda_node, param_names, t_params, captures);
return detail::eval_function(engine, lambda_node, param_names, t_params, &captures);
},
static_cast<int>(numparams), lambda_node, param_types
)
@@ -876,7 +830,7 @@ namespace chaiscript
/// \todo do this better
// put class name in current scope so it can be looked up by the attrs and methods
t_ss->add_object("_current_class_name", const_var(children[0]->text));
t_ss.add_object("_current_class_name", const_var(children[0]->text));
children[1]->eval(t_ss);
@@ -985,7 +939,7 @@ namespace chaiscript
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
try {
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) {
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) {
this->children[currentCase]->eval(t_ss);
hasMatched = true;
}
@@ -996,7 +950,7 @@ namespace chaiscript
}
else if (this->children[currentCase]->identifier == AST_Node_Type::Default) {
this->children[currentCase]->eval(t_ss);
breaking = true;
hasMatched = true;
}
}
catch (detail::Break_Loop &) {
@@ -1006,6 +960,8 @@ namespace chaiscript
}
return Boxed_Value();
}
mutable std::atomic_uint_fast32_t m_loc;
};
struct Case_AST_Node : public AST_Node {
@@ -1049,10 +1005,11 @@ namespace chaiscript
try {
std::vector<Boxed_Value> vec;
if (!children.empty()) {
vec.reserve(children[0]->children.size());
for (const auto &child : children[0]->children) {
auto obj = child->eval(t_ss);
if (!obj.is_return_value()) {
vec.push_back(t_ss->call_function("clone", obj));
vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()));
} else {
vec.push_back(std::move(obj));
}
@@ -1069,6 +1026,8 @@ namespace chaiscript
{
return "[" + AST_Node::pretty_print() + "]";
}
mutable std::atomic_uint_fast32_t m_loc;
};
struct Inline_Map_AST_Node : public AST_Node {
@@ -1083,7 +1042,7 @@ namespace chaiscript
for (const auto &child : children[0]->children) {
auto obj = child->children[1]->eval(t_ss);
if (!obj.is_return_value()) {
obj = t_ss->call_function("clone", obj);
obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions());
}
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj);
@@ -1096,6 +1055,7 @@ namespace chaiscript
}
}
mutable std::atomic_uint_fast32_t m_loc;
};
struct Return_AST_Node : public AST_Node {
@@ -1148,7 +1108,7 @@ namespace chaiscript
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
Boxed_Value bv;
t_ss->add_object(this->children[0]->text, bv);
t_ss.add_object(this->children[0]->text, bv);
return bv;
}
catch (const exception::reserved_word_error &) {
@@ -1177,9 +1137,8 @@ namespace chaiscript
return Boxed_Number::do_oper(m_oper, bv);
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
fpp.save_params({bv});
return t_ss->call_function(children[0]->text, std::move(bv));
return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)}, t_ss.conversions());
}
} catch (const exception::dispatch_error &e) {
throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@@ -1188,6 +1147,7 @@ namespace chaiscript
private:
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
};
struct Break_AST_Node : public AST_Node {
@@ -1248,15 +1208,16 @@ namespace chaiscript
virtual ~Inline_Range_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
return t_ss->call_function("generate_range",
children[0]->children[0]->children[0]->eval(t_ss),
children[0]->children[0]->children[1]->eval(t_ss));
auto oper1 = children[0]->children[0]->children[0]->eval(t_ss);
auto oper2 = children[0]->children[0]->children[1]->eval(t_ss);
return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions());
}
catch (const exception::dispatch_error &e) {
throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss);
}
}
mutable std::atomic_uint_fast32_t m_loc;
};
struct Annotation_AST_Node : public AST_Node {
@@ -1294,9 +1255,9 @@ namespace chaiscript
if (dispatch::Param_Types(
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)}
).match(std::vector<Boxed_Value>{t_except}, t_ss->conversions()))
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()))
{
t_ss->add_object(name, t_except);
t_ss.add_object(name, t_except);
if (catch_block->children.size() == 2) {
//Variable capture, no guards
@@ -1433,7 +1394,7 @@ namespace chaiscript
if (guardnode) {
guard = dispatch::make_dynamic_proxy_function(
[engine, t_param_names, guardnode](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params, std::map<std::string, Boxed_Value>());
return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params);
},
static_cast<int>(numparams), guardnode);
}
@@ -1450,7 +1411,7 @@ namespace chaiscript
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
dispatch::make_dynamic_proxy_function(
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params, std::map<std::string, Boxed_Value>());
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
},
static_cast<int>(numparams), node, param_types, l_annotation, guard
)
@@ -1466,7 +1427,7 @@ namespace chaiscript
t_ss->add(std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
dispatch::make_dynamic_proxy_function(
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params, std::map<std::string, Boxed_Value>());
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
},
static_cast<int>(numparams), node, param_types, l_annotation, guard), type),
function_name);

File diff suppressed because it is too large Load Diff

View File

@@ -41,25 +41,25 @@ def new(x) {
}
def clone(double x) {
double(x).copy_var_attrs(x)
double(x).clone_var_attrs(x)
}
def clone(string x) {
string(x).copy_var_attrs(x)
string(x).clone_var_attrs(x)
}
def clone(vector x) {
vector(x).copy_var_attrs(x)
vector(x).clone_var_attrs(x)
}
def clone(int x) {
int(x).copy_var_attrs(x)
int(x).clone_var_attrs(x)
}
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x).copy_var_attrs(x);
eval(type_name(x))(x).clone_var_attrs(x);
}
@@ -145,11 +145,6 @@ def reverse(container) {
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)
{
clone(r);
}
def range(r) : call_exists(range_internal, r)
{
@@ -158,6 +153,13 @@ def range(r) : call_exists(range_internal, r)
ri;
}
# 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)
{
clone(r);
}
# The retro attribute that contains the underlying range
attr retro::m_range;

View File

@@ -0,0 +1,663 @@
// From github.com/nbsdx/SimpleJSON.
// Released under the DWTFYW PL
//
#pragma once
#ifndef SIMPLEJSON_HPP
#define SIMPLEJSON_HPP
#include <cstdint>
#include <cmath>
#include <cctype>
#include <string>
#include <deque>
#include <map>
#include <type_traits>
#include <initializer_list>
#include <ostream>
#include <iostream>
#include "../chaiscript_defines.hpp"
namespace json {
using std::map;
using std::deque;
using std::string;
using std::enable_if;
using std::initializer_list;
using std::is_same;
using std::is_convertible;
using std::is_integral;
using std::is_floating_point;
namespace {
string json_escape( const string &str ) {
string output;
for( unsigned i = 0; i < str.length(); ++i )
switch( str[i] ) {
case '\"': output += "\\\""; break;
case '\\': output += "\\\\"; break;
case '\b': output += "\\b"; break;
case '\f': output += "\\f"; break;
case '\n': output += "\\n"; break;
case '\r': output += "\\r"; break;
case '\t': output += "\\t"; break;
default : output += str[i]; break;
}
return output;
}
bool isspace(const char c)
{
#ifdef CHAISCRIPT_MSVC
// MSVC warns on these line in some circumstances
#pragma warning(push)
#pragma warning(disable : 6330)
#endif
return ::isspace(c) != 0;
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
}
class JSON
{
union BackingData {
BackingData( double d ) : Float( d ){}
BackingData( long l ) : Int( l ){}
BackingData( bool b ) : Bool( b ){}
BackingData( string s ) : String( new string( s ) ){}
BackingData() : Int( 0 ){}
deque<JSON> *List;
map<string,JSON> *Map;
string *String;
double Float;
long Int;
bool Bool;
} Internal;
public:
enum class Class {
Null,
Object,
Array,
String,
Floating,
Integral,
Boolean
};
template <typename Container>
class JSONWrapper {
Container *object;
public:
JSONWrapper( Container *val ) : object( val ) {}
JSONWrapper( std::nullptr_t ) : object( nullptr ) {}
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); }
typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); }
};
template <typename Container>
class JSONConstWrapper {
const Container *object;
public:
JSONConstWrapper( const Container *val ) : object( val ) {}
JSONConstWrapper( std::nullptr_t ) : object( nullptr ) {}
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); }
typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); }
};
JSON() : Internal(), Type( Class::Null ){}
explicit JSON(Class type)
: Internal(), Type(Class::Null)
{
SetType( type );
}
JSON( initializer_list<JSON> list )
: Internal(), Type(Class::Null)
{
SetType( Class::Object );
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i )
operator[]( i->ToString() ) = *std::next( i );
}
JSON( JSON&& other )
: Internal( other.Internal )
, Type( other.Type )
{ other.Type = Class::Null; other.Internal.Map = nullptr; }
JSON& operator=( JSON&& other ) {
Internal = other.Internal;
Type = other.Type;
other.Internal.Map = nullptr;
other.Type = Class::Null;
return *this;
}
JSON( const JSON &other ) {
switch( other.Type ) {
case Class::Object:
Internal.Map =
new map<string,JSON>( other.Internal.Map->begin(),
other.Internal.Map->end() );
break;
case Class::Array:
Internal.List =
new deque<JSON>( other.Internal.List->begin(),
other.Internal.List->end() );
break;
case Class::String:
Internal.String =
new string( *other.Internal.String );
break;
default:
Internal = other.Internal;
}
Type = other.Type;
}
JSON& operator=( const JSON &other ) {
if (&other == this) return *this;
switch( other.Type ) {
case Class::Object:
Internal.Map =
new map<string,JSON>( other.Internal.Map->begin(),
other.Internal.Map->end() );
break;
case Class::Array:
Internal.List =
new deque<JSON>( other.Internal.List->begin(),
other.Internal.List->end() );
break;
case Class::String:
Internal.String =
new string( *other.Internal.String );
break;
default:
Internal = other.Internal;
}
Type = other.Type;
return *this;
}
~JSON() {
switch( Type ) {
case Class::Array:
delete Internal.List;
break;
case Class::Object:
delete Internal.Map;
break;
case Class::String:
delete Internal.String;
break;
default:;
}
}
template <typename T>
JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = 0 ) : Internal( b ), Type( Class::Boolean ){}
template <typename T>
JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = 0 ) : Internal( long(i) ), Type( Class::Integral ){}
template <typename T>
JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = 0 ) : Internal( double(f) ), Type( Class::Floating ){}
template <typename T>
JSON( T s, typename enable_if<is_convertible<T,string>::value>::type* = 0 ) : Internal( string( s ) ), Type( Class::String ){}
JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){}
static JSON Make( Class type ) {
return JSON(type);
}
static JSON Load( const string & );
template <typename T>
void append( T arg ) {
SetType( Class::Array ); Internal.List->emplace_back( arg );
}
template <typename T, typename... U>
void append( T arg, U... args ) {
append( arg ); append( args... );
}
template <typename T>
typename enable_if<is_same<T,bool>::value, JSON&>::type operator=( T b ) {
SetType( Class::Boolean ); Internal.Bool = b; return *this;
}
template <typename T>
typename enable_if<is_integral<T>::value && !is_same<T,bool>::value, JSON&>::type operator=( T i ) {
SetType( Class::Integral ); Internal.Int = i; return *this;
}
template <typename T>
typename enable_if<is_floating_point<T>::value, JSON&>::type operator=( T f ) {
SetType( Class::Floating ); Internal.Float = f; return *this;
}
template <typename T>
typename enable_if<is_convertible<T,string>::value, JSON&>::type operator=( T s ) {
SetType( Class::String ); *Internal.String = string( s ); return *this;
}
JSON& operator[]( const string &key ) {
SetType( Class::Object ); return Internal.Map->operator[]( key );
}
JSON& operator[]( const size_t index ) {
SetType( Class::Array );
if( index >= Internal.List->size() ) Internal.List->resize( index + 1 );
return Internal.List->operator[]( index );
}
JSON &at( const string &key ) {
return operator[]( key );
}
const JSON &at( const string &key ) const {
return Internal.Map->at( key );
}
JSON &at( unsigned index ) {
return operator[]( index );
}
const JSON &at( unsigned index ) const {
return Internal.List->at( index );
}
int length() const {
if( Type == Class::Array )
return static_cast<int>(Internal.List->size());
else
return -1;
}
bool hasKey( const string &key ) const {
if( Type == Class::Object )
return Internal.Map->find( key ) != Internal.Map->end();
return false;
}
int size() const {
if( Type == Class::Object )
return static_cast<int>(Internal.Map->size());
else if( Type == Class::Array )
return static_cast<int>(Internal.List->size());
else
return -1;
}
Class JSONType() const { return Type; }
/// Functions for getting primitives from the JSON object.
bool IsNull() const { return Type == Class::Null; }
string ToString() const { bool b; return ToString( b ); }
string ToString( bool &ok ) const {
ok = (Type == Class::String);
return ok ? *Internal.String : string("");
}
double ToFloat() const { bool b; return ToFloat( b ); }
double ToFloat( bool &ok ) const {
ok = (Type == Class::Floating);
return ok ? Internal.Float : 0.0;
}
long ToInt() const { bool b; return ToInt( b ); }
long ToInt( bool &ok ) const {
ok = (Type == Class::Integral);
return ok ? Internal.Int : 0;
}
bool ToBool() const { bool b; return ToBool( b ); }
bool ToBool( bool &ok ) const {
ok = (Type == Class::Boolean);
return ok ? Internal.Bool : false;
}
JSONWrapper<map<string,JSON>> ObjectRange() {
if( Type == Class::Object )
return JSONWrapper<map<string,JSON>>( Internal.Map );
return JSONWrapper<map<string,JSON>>( nullptr );
}
JSONWrapper<deque<JSON>> ArrayRange() {
if( Type == Class::Array )
return JSONWrapper<deque<JSON>>( Internal.List );
return JSONWrapper<deque<JSON>>( nullptr );
}
JSONConstWrapper<map<string,JSON>> ObjectRange() const {
if( Type == Class::Object )
return JSONConstWrapper<map<string,JSON>>( Internal.Map );
return JSONConstWrapper<map<string,JSON>>( nullptr );
}
JSONConstWrapper<deque<JSON>> ArrayRange() const {
if( Type == Class::Array )
return JSONConstWrapper<deque<JSON>>( Internal.List );
return JSONConstWrapper<deque<JSON>>( nullptr );
}
string dump( int depth = 1, string tab = " ") const {
switch( Type ) {
case Class::Null:
return "null";
case Class::Object: {
string pad = "";
for( int i = 0; i < depth; ++i, pad += tab );
string s = "{\n";
bool skip = true;
for( auto &p : *Internal.Map ) {
if( !skip ) s += ",\n";
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
skip = false;
}
s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ;
return s;
}
case Class::Array: {
string s = "[";
bool skip = true;
for( auto &p : *Internal.List ) {
if( !skip ) s += ", ";
s += p.dump( depth + 1, tab );
skip = false;
}
s += "]";
return s;
}
case Class::String:
return "\"" + json_escape( *Internal.String ) + "\"";
case Class::Floating:
return std::to_string( Internal.Float );
case Class::Integral:
return std::to_string( Internal.Int );
case Class::Boolean:
return Internal.Bool ? "true" : "false";
}
throw std::runtime_error("Unhandled JSON type");
}
friend std::ostream& operator<<( std::ostream&, const JSON & );
private:
void SetType( Class type ) {
if( type == Type )
return;
switch( Type ) {
case Class::Object: delete Internal.Map; break;
case Class::Array: delete Internal.List; break;
case Class::String: delete Internal.String; break;
default:;
}
switch( type ) {
case Class::Null: Internal.Map = nullptr; break;
case Class::Object: Internal.Map = new map<string,JSON>(); break;
case Class::Array: Internal.List = new deque<JSON>(); break;
case Class::String: Internal.String = new string(); break;
case Class::Floating: Internal.Float = 0.0; break;
case Class::Integral: Internal.Int = 0; break;
case Class::Boolean: Internal.Bool = false; break;
}
Type = type;
}
private:
Class Type;
};
inline JSON Array() {
return JSON::Make( JSON::Class::Array );
}
template <typename... T>
inline JSON Array( T... args ) {
JSON arr = JSON::Make( JSON::Class::Array );
arr.append( args... );
return arr;
}
inline JSON Object() {
return JSON::Make( JSON::Class::Object );
}
inline std::ostream& operator<<( std::ostream &os, const JSON &json ) {
os << json.dump();
return os;
}
namespace {
JSON parse_next( const string &, size_t & );
void consume_ws( const string &str, size_t &offset ) {
while( isspace( str[offset] ) ) ++offset;
}
JSON parse_object( const string &str, size_t &offset ) {
JSON Object = JSON::Make( JSON::Class::Object );
++offset;
consume_ws( str, offset );
if( str[offset] == '}' ) {
++offset; return Object;
}
for (;offset<str.size();) {
JSON Key = parse_next( str, offset );
consume_ws( str, offset );
if( str[offset] != ':' ) {
throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str[offset] + "'\n");
}
consume_ws( str, ++offset );
JSON Value = parse_next( str, offset );
Object[Key.ToString()] = Value;
consume_ws( str, offset );
if( str[offset] == ',' ) {
++offset; continue;
}
else if( str[offset] == '}' ) {
++offset; break;
}
else {
throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str[offset] + "'\n");
}
}
return Object;
}
JSON parse_array( const string &str, size_t &offset ) {
JSON Array = JSON::Make( JSON::Class::Array );
unsigned index = 0;
++offset;
consume_ws( str, offset );
if( str[offset] == ']' ) {
++offset; return Array;
}
for (;offset < str.size();) {
Array[index++] = parse_next( str, offset );
consume_ws( str, offset );
if( str[offset] == ',' ) {
++offset; continue;
}
else if( str[offset] == ']' ) {
++offset; break;
}
else {
throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str[offset] + "'\n");
}
}
return Array;
}
JSON parse_string( const string &str, size_t &offset ) {
string val;
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) {
if( c == '\\' ) {
switch( str[ ++offset ] ) {
case '\"': val += '\"'; break;
case '\\': val += '\\'; break;
case '/' : val += '/' ; break;
case 'b' : val += '\b'; break;
case 'f' : val += '\f'; break;
case 'n' : val += '\n'; break;
case 'r' : val += '\r'; break;
case 't' : val += '\t'; break;
case 'u' : {
val += "\\u" ;
for( unsigned i = 1; i <= 4; ++i ) {
c = str[offset+i];
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
val += c;
else {
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
}
}
offset += 4;
} break;
default : val += '\\'; break;
}
}
else
val += c;
}
++offset;
return JSON(val);
}
JSON parse_number( const string &str, size_t &offset ) {
JSON Number;
string val, exp_str;
char c = '\0';
bool isDouble = false;
long exp = 0;
for (; offset < str.size() ;) {
c = str[offset++];
if( (c == '-') || (c >= '0' && c <= '9') )
val += c;
else if( c == '.' ) {
val += c;
isDouble = true;
}
else
break;
}
if( offset < str.size() && (c == 'E' || c == 'e' )) {
c = str[ offset++ ];
if( c == '-' ) { exp_str += '-';}
else if( c == '+' ) { }
else --offset;
for (; offset < str.size() ;) {
c = str[ offset++ ];
if( c >= '0' && c <= '9' )
exp_str += c;
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
}
else
break;
}
exp = std::stol( exp_str );
}
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
}
--offset;
if( isDouble )
Number = std::stod( val ) * std::pow( 10, exp );
else {
if( !exp_str.empty() )
Number = std::stol( val ) * std::pow( 10, exp );
else
Number = std::stol( val );
}
return Number;
}
JSON parse_bool( const string &str, size_t &offset ) {
JSON Bool;
if( str.substr( offset, 4 ) == "true" ) {
offset += 4;
Bool = true;
} else if( str.substr( offset, 5 ) == "false" ) {
offset += 5;
Bool = false;
} else {
throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'");
}
return Bool;
}
JSON parse_null( const string &str, size_t &offset ) {
if( str.substr( offset, 4 ) != "null" ) {
throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'");
}
offset += 4;
return JSON();
}
JSON parse_next( const string &str, size_t &offset ) {
char value;
consume_ws( str, offset );
value = str[offset];
switch( value ) {
case '[' : return parse_array( str, offset );
case '{' : return parse_object( str, offset );
case '\"': return parse_string( str, offset );
case 't' :
case 'f' : return parse_bool( str, offset );
case 'n' : return parse_null( str, offset );
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
return parse_number( str, offset );
}
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
}
}
inline JSON JSON::Load( const string &str ) {
size_t offset = 0;
return parse_next( str, offset );
}
} // End Namespace json
#endif

View File

@@ -0,0 +1,158 @@
#ifndef CHAISCRIPT_SIMPLEJSON_WRAP_HPP
#define CHAISCRIPT_SIMPLEJSON_WRAP_HPP
#include "json.hpp"
namespace chaiscript
{
class json_wrap
{
public:
static ModulePtr library(ModulePtr m = std::make_shared<Module>())
{
m->add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
m->add(chaiscript::fun(&json_wrap::to_json), "to_json");
return m;
}
private:
static Boxed_Value from_json(const json::JSON &t_json)
{
switch( t_json.JSONType() ) {
case json::JSON::Class::Null:
return Boxed_Value();
case json::JSON::Class::Object:
{
std::map<std::string, Boxed_Value> m;
for (const auto &p : t_json.ObjectRange())
{
m.insert(std::make_pair(p.first, from_json(p.second)));
}
return Boxed_Value(m);
}
case json::JSON::Class::Array:
{
std::vector<Boxed_Value> vec;
for (const auto &p : t_json.ArrayRange())
{
vec.emplace_back(from_json(p));
}
return Boxed_Value(vec);
}
case json::JSON::Class::String:
return Boxed_Value(t_json.ToString());
case json::JSON::Class::Floating:
return Boxed_Value(t_json.ToFloat());
case json::JSON::Class::Integral:
return Boxed_Value(t_json.ToInt());
case json::JSON::Class::Boolean:
return Boxed_Value(t_json.ToBool());
}
throw std::runtime_error("Unknown JSON type");
}
static Boxed_Value from_json(const std::string &t_json)
{
return from_json( json::JSON::Load(t_json) );
}
static std::string to_json(const Boxed_Value &t_bv)
{
return to_json_object(t_bv).dump();
}
static json::JSON to_json_object(const Boxed_Value &t_bv)
{
try {
const std::map<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(t_bv);
json::JSON obj;
for (const auto &o : m)
{
obj[o.first] = to_json_object(o.second);
}
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a map
}
try {
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
json::JSON obj;
for (size_t i = 0; i < v.size(); ++i)
{
obj[i] = to_json_object(v[i]);
}
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a vector
}
try {
Boxed_Number bn(t_bv);
json::JSON obj;
if (Boxed_Number::is_floating_point(t_bv))
{
obj = bn.get_as<double>();
} else {
obj = bn.get_as<long>();
}
return obj;
} catch (const chaiscript::detail::exception::bad_any_cast &) {
// not a number
}
try {
bool b = boxed_cast<bool>(t_bv);
json::JSON obj;
obj = b;
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a bool
}
try {
std::string s = boxed_cast<std::string>(t_bv);
json::JSON obj;
obj = s;
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a string
}
try {
const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(t_bv);
json::JSON obj;
for (const auto &attr : o.get_attrs())
{
obj[attr.first] = to_json_object(attr.second);
}
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a dynamic object
}
throw std::runtime_error("Unknown object type to convert to JSON");
}
};
}
#endif

View File

@@ -1,19 +1,21 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
#include "../dispatchkit/operators.hpp"
namespace chaiscript
@@ -62,6 +64,42 @@ namespace chaiscript
t_module.add(fun.first, fun.second);
}
}
template<typename Enum, typename ModuleType>
typename std::enable_if<std::is_enum<Enum>::value, void>::type
add_class(ModuleType &t_module,
const std::string &t_class_name,
#ifdef CHAISCRIPT_GCC_4_6
const std::vector<std::pair<int, std::string>> &t_constants
#else
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants
#endif
)
{
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
using namespace chaiscript::bootstrap::operators;
t_module.add([](){
// add some comparison and assignment operators
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
}());
#ifdef CHAISCRIPT_GCC_4_6
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
#else
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
#endif
for (const auto &constant : t_constants)
{
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
}
}
}
}

View File

@@ -1,4 +1,4 @@
Copyright 2009-2015 Jason Turner
Copyright 2009-2016 Jason Turner
Copyright 2009-2012 Jonathan Turner.
All Rights Reserved.

View File

@@ -0,0 +1,26 @@
var test_str = "bob was a string";
for( var i = 0; i < 200000; ++i)
{
test_str.size();
// test_str.find("a", i);
test_str.c_str();
test_str.erase_at(1);
test_str.erase_at(1);
test_str.erase_at(1);
test_str.erase_at(1);
test_str.erase_at(1);
test_str.erase_at(1);
size(test_str);
// test_str.find("a", i);
c_str(test_str);
erase_at(test_str, 1);
erase_at(test_str, 1);
erase_at(test_str, 1);
erase_at(test_str, 1);
erase_at(test_str, 1);
erase_at(test_str, 1);
test_str = "bob was a string";
}

View File

@@ -0,0 +1,20 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
double f(const std::string &, double, bool) noexcept {
return .0;
}
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&f), "f");
chai.eval(R"(
for (var i = 0; i < 100000; ++i) {
f("str", 1.2, false);
}
)");
}

View File

@@ -0,0 +1,20 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
double f(const std::string &, double, bool) noexcept {
return .0;
}
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&f), "f");
const auto f = chai.eval<std::function<void ()>>(R"(fun(){ f("str", 1.2, false); })");
for (int i = 0; i < 100000; ++i) {
f();
}
}

View File

@@ -12,7 +12,7 @@ ChaiScript
http://www.chaiscript.com
(c) 2009-2012 Jonathan Turner
(c) 2009-2015 Jason Turner
(c) 2009-2016 Jason Turner
Release under the BSD license, see "license.txt" for details.

View File

@@ -1,6 +1,29 @@
Notes:
=======
Current Version: 5.7.1
Current Version: 5.8.0
### Changes since 5.7.1
* Make all parser iterator operations range checked
* Parse in-string eval statements once, not once for each execution
* Fix parsing of operators (ie 1<-1 now parses)
* Fix variable scoping for functors
* Exception reduction
* Various object lifetime fixes
* Add JSON support for load / save #207
* Numeric overload resolution fixes #209
* Fix long long #208
* Add octal escapes in strings #211
* Fixed sizing of binary literals #213
* Added support for != with bool values #217
* Various value assignment vector fixes
* Fixed broken hex escape sequences from @ChristianKaeser
* Multiply defined symbols fixes #232 @RaptorFactor
* Add add_class<Enum> helper #233 @vrennert
* Cheatsheet fixes #235 @mlamby
* Fix parsing of strings inside of in-string eval statements
* Allow lower-case global keyword
* Enable thread-local on MSVC (should be significant performance boost)
### Changes since 5.7.0
* Build time reduction

103
samples/factory.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
class Entity
{
public:
int width;
int height;
int x;
int y;
std::string name;
std::function<void (Entity &)> updater;
Entity(const int t_width, const int t_height, const int t_x, const int t_y, std::string t_name)
: width(t_width), height(t_height), x(t_x), y(t_y), name(std::move(t_name))
{
}
};
class Factory
{
public:
// we may as well pass the parameters for the entity to the factory method, this does the initialization
// in one step.
Entity *make_entity(const int width, const int height, const int x, const int y, const std::string &name)
{
auto entity = entities.insert({name, Entity{width, height, x, y, name}});
return &(entity.first->second);
}
Entity *get_entity(const std::string &name)
{
return &entities.at(name);
}
// loop over all entities and all their updater function (if it exists)
void update_entities()
{
for (auto &entity : entities)
{
if (entity.second.updater) {
entity.second.updater(entity.second);
}
}
}
private:
// we cannot store the entities in a std::vector if we want to return a pointer to them,
// because a vector automatically resizing itself can invalidate the pointer that was returned.
// using a map guarantees that the memory assigned to the entity will never change, plus
// lets us easily look up an entity by name
std::map<std::string, Entity> entities;
};
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&Entity::width), "width");
chai.add(chaiscript::fun(&Entity::height), "height");
chai.add(chaiscript::fun(&Entity::x), "x");
chai.add(chaiscript::fun(&Entity::y), "y");
chai.add(chaiscript::fun(&Entity::name), "name");
chai.add(chaiscript::fun(&Entity::updater), "updater");
chai.add(chaiscript::user_type<Entity>(), "Entity"); // this isn't strictly necessary but makes error messages nicer
chai.add(chaiscript::fun(&Factory::make_entity), "make_entity");
chai.add(chaiscript::fun(&Factory::get_entity), "get_entity");
chai.add(chaiscript::fun(&Factory::update_entities), "update_entities");
chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
Factory f;
chai.add(chaiscript::var(&f), "f");
std::string script = R""(
f.make_entity(10,10,1,1,"entity1").updater = fun(e){ e.x += 1; e.y += 1 };
f.make_entity(10,10,10,10,"entity2").updater = fun(e){ e.x += 2; e.y += 2 };
f.make_entity(10,10,20,20,"entity3");
print(f.get_entity("entity1").x == 1)
print(f.get_entity("entity2").x == 10)
print(f.get_entity("entity3").x == 20)
f.update_entities(); // this runs the function objects we set in the previous lines
// we should now see the updated values
print(f.get_entity("entity1").x == 2)
print(f.get_entity("entity2").x == 12)
print(f.get_entity("entity3").x == 20) // this one has no updater, so it stays the same
)"";
chai.eval(script);
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
@@ -316,7 +316,7 @@ int main(int argc, char *argv[])
////for (int i = 0; i < 1000; i++)
////{
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
////}
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");

View File

@@ -0,0 +1,34 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/dispatchkit/function_call.hpp>
int main( int /*argc*/ , char * /*argv*/[] )
{
chaiscript::ChaiScript ch( chaiscript::Std_Lib::library( ) );
try
{
static const char script[ ] =
R""(
class Rectangle
{
def Rectangle() { }
}
var rect = Rectangle( );
)"";
ch.eval( script );
}
catch ( const std::exception &e )
{
printf( " >>> Exception thrown: %s \n" , e.what( ) );
}
return 1;
}

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
@@ -66,7 +66,7 @@ std::vector<std::string> default_search_paths()
#ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
std::string exepath(path, size);
@@ -344,17 +344,16 @@ int main(int argc, char *argv[])
mode = eFile;
}
chaiscript::Boxed_Value val ;
try {
switch ( mode ) {
case eInteractive:
interactive(chai);
break;
case eCommand:
val = chai.eval(arg);
chai.eval(arg);
break;
case eFile:
val = chai.eval_file(arg);
chai.eval_file(arg);
}
}
catch (const chaiscript::exception::eval_error &ee) {

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-2015, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp>

View File

@@ -0,0 +1,3 @@
var v = [[[15]]]
assert_true(v[0][0][0] == 15)

View File

@@ -0,0 +1,12 @@
assert_true(true == true)
assert_false(true == false)
assert_true(true != false)
assert_true(false != true)
assert_true(false || true)
assert_true(true || false)
assert_false(true && false)
assert_false(false && true)
assert_true(!false)
assert_false(!true)

View File

@@ -13,9 +13,9 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
try {
To ret = chaiscript::boxed_cast<To>(bv);
use(ret);
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
} catch (const chaiscript::exception::bad_boxed_cast &e) {
if (expectedpass) {
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
return false;
} else {
return true;

View File

@@ -2,6 +2,7 @@
// caught in other cpp files if chaiscript causes them
#include <chaiscript/utility/utility.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
@@ -396,7 +397,7 @@ class Short_Comparison_Test {
public:
Short_Comparison_Test() : value_(5) {}
short get_value() { return value_; }
short get_value() const { return value_; }
short value_;
};
@@ -518,6 +519,65 @@ TEST_CASE("Utility_Test utility class wrapper")
}
enum Utility_Test_Numbers
{
ONE,
TWO,
THREE
};
void do_something_with_enum_vector(const std::vector<Utility_Test_Numbers> &v)
{
CHECK(v.size() == 3);
CHECK(v[0] == ONE);
CHECK(v[1] == THREE);
CHECK(v[2] == TWO);
}
TEST_CASE("Utility_Test utility class wrapper for enum")
{
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
using namespace chaiscript;
chaiscript::utility::add_class<Utility_Test_Numbers>(*m,
"Utility_Test_Numbers",
{ { ONE, "ONE" },
{ TWO, "TWO" },
{ THREE, "THREE" }
}
);
chaiscript::ChaiScript chai;
chai.add(m);
CHECK(chai.eval<Utility_Test_Numbers>("ONE ") == 0);
CHECK(chai.eval<Utility_Test_Numbers>("TWO ") == 1);
CHECK(chai.eval<Utility_Test_Numbers>("THREE ") == 2);
CHECK(chai.eval<bool>("ONE == 0"));
chai.add(chaiscript::fun(&do_something_with_enum_vector), "do_something_with_enum_vector");
chai.add(chaiscript::vector_conversion<std::vector<Utility_Test_Numbers>>());
CHECK_NOTHROW(chai.eval("var a = [ONE, TWO, THREE]"));
CHECK_NOTHROW(chai.eval("do_something_with_enum_vector([ONE, THREE, TWO])"));
CHECK_NOTHROW(chai.eval("[ONE]"));
const auto v = chai.eval<std::vector<Utility_Test_Numbers>>("a");
CHECK(v.size() == 3);
CHECK(v.at(1) == TWO);
CHECK(chai.eval<bool>("ONE == ONE"));
CHECK(chai.eval<bool>("ONE != TWO"));
CHECK_NOTHROW(chai.eval("var o = ONE; o = TWO"));
}
////// Object copy count test
class Object_Copy_Count_Test
@@ -743,3 +803,139 @@ TEST_CASE("Test Derived->Base with non-polymorphic classes")
chai.add(chaiscript::fun(&myfunction), "myfunction");
CHECK(chai.eval<int>("myfunction(d)") == 2);
}
struct TestCppVariableScope
{
void print()
{
std::cout << "Printed" << std::endl;
}
};
TEST_CASE("Variable Scope When Calling From C++")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::user_type<TestCppVariableScope>(), "Test");
chai.add(chaiscript::constructor<TestCppVariableScope()>(), "Test");
chai.add(chaiscript::fun(&TestCppVariableScope::print), "print");
chai.eval(R"(var t := Test();
def func()
{
t.print();
}
)");
CHECK_THROWS(chai.eval("func()"));
chai.eval("dump_object(t)");
auto func = chai.eval<std::function<void()>>("func");
CHECK_THROWS(func());
}
TEST_CASE("Variable Scope When Calling From C++ 2")
{
chaiscript::ChaiScript chai;
chai.eval("var obj = 2;");
auto func = chai.eval<std::function<void()>>("fun(){ return obj; }");
CHECK_THROWS(func());
}
void ulonglong(unsigned long long i) {
std::cout << i << '\n';
}
void longlong(long long i) {
std::cout << i << '\n';
}
TEST_CASE("Test long long dispatch")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&longlong), "longlong");
chai.add(chaiscript::fun(&ulonglong), "ulonglong");
chai.eval("longlong(15)");
chai.eval("ulonglong(15)");
}
struct Returned_Converted_Config
{
int num_iterations;
int something_else;
std::string a_string;
std::function<int (const std::string &)> a_function;
};
TEST_CASE("Return of converted type from script")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::constructor<Returned_Converted_Config ()>(), "Returned_Converted_Config");
chai.add(chaiscript::fun(&Returned_Converted_Config::num_iterations), "num_iterations");
chai.add(chaiscript::fun(&Returned_Converted_Config::something_else), "something_else");
chai.add(chaiscript::fun(&Returned_Converted_Config::a_string), "a_string");
chai.add(chaiscript::fun(&Returned_Converted_Config::a_function), "a_function");
chai.add(chaiscript::vector_conversion<std::vector<Returned_Converted_Config>>());
auto c = chai.eval<std::vector<Returned_Converted_Config>>(R"(
var c = Returned_Converted_Config();
c.num_iterations = 5;
c.something_else = c.num_iterations * 2;
c.a_string = "string";
c.a_function = fun(s) { s.size(); }
print("making vector");
var v = [];
print("adding config item");
v.push_back_ref(c);
print("returning vector");
v;
)");
std::cout << typeid(decltype(c)).name() << std::endl;
std::cout << "Info: " << c.size() << " " << &c[0] << std::endl;
std::cout << "num_iterations " << c[0].num_iterations << '\n'
<< "something_else " << c[0].something_else << '\n'
<< "a_string " << c[0].a_string << '\n'
<< "a_function " << c[0].a_function("bob") << '\n';
chai.add(chaiscript::user_type<Returned_Converted_Config>(), "Returned_Converted_Config");
}
int get_value_a(const std::map<std::string, int> &t_m)
{
return t_m.at("a");
}
TEST_CASE("Map conversions")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
chai.add(chaiscript::fun(&get_value_a), "get_value_a");
const auto c = chai.eval<int>(R"(
var m = ["a": 42];
get_value_a(m);
)");
CHECK(c == 42);
}

View File

@@ -0,0 +1,14 @@
class MyClass {
def MyClass()
{
this.set_explicit(true);
}
};
var o = MyClass();
assert_true(o.is_explicit());
assert_throws("error", fun[o](){o.x = 2})

View File

@@ -8,3 +8,17 @@ def myFun()
}
myFun();
def myFun2()
{
assert_equal(j, 7)
}
set_global(7, "j")
myFun2();
set_global(5, "j")
myFun();

View File

@@ -0,0 +1,18 @@
// Test global
global g = 3;
assert_true(g == 3);
var v := g;
assert_true(v == 3);
global g = 2;
assert_true(g == 2);
assert_true(v == 2);
def f() {
assert_true(g == 2);
}
f();

View File

@@ -0,0 +1,7 @@
assert_equal("\x39", "9")
assert_equal("\x39ec", "9ec")
assert_equal("\x39g", "9g")
assert_equal("b\x39g", "b9g")
assert_equal("\x39\x38g", "98g")

View File

@@ -0,0 +1 @@
assert_equal("a string", "${"a string"}")

View File

@@ -5,9 +5,10 @@
template<typename T>
bool test_literal(T val, const std::string &str)
{
std::cout << "Comparing : " << val;
chaiscript::ChaiScript chai;
T val2 = chai.eval<T>(str);
std::cout << "Comparing : " << val << " " << val2 << '\n';
std::cout << " " << val2 << '\n';
return val == val2;
}
@@ -74,6 +75,39 @@ int main()
&& TEST_LITERAL(177777777777777777)
&& TEST_LITERAL(1777777777777777777)
&& test_literal(0xF, "0b1111")
&& test_literal(0xFF, "0b11111111")
&& test_literal(0xFFF, "0b111111111111")
&& test_literal(0xFFFF, "0b1111111111111111")
&& test_literal(0xFFFFF, "0b11111111111111111111")
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7, "0b111")
&& test_literal(0x7F, "0b1111111")
&& test_literal(0x7FF, "0b11111111111")
&& test_literal(0x7FFF, "0b111111111111111")
&& test_literal(0x7FFFF, "0b1111111111111111111")
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
)
{
return EXIT_SUCCESS;

3
unittests/json_1.chai Normal file
View File

@@ -0,0 +1,3 @@
assert_true(from_json("null").is_var_null())

1
unittests/json_10.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("\"This is a\\n\\nMultiline string\""), "This is a\n\nMultiline string")

14
unittests/json_11.chai Normal file
View File

@@ -0,0 +1,14 @@
assert_equal(from_json(
"{\n" +
" \"T1\" : \"Value With a Quote : \\\"\",\n" +
" \"T2\" : \"Value With a Rev Solidus : \\/\",\n" +
" \"T3\" : \"Value with a Solidus : \\\\\",\n" +
" \"T4\" : \"Value with a Backspace : \\b\",\n" +
" \"T5\" : \"Value with a Formfeed : \\f\",\n" +
" \"T6\" : \"Value with a Newline : \\n\",\n" +
" \"T7\" : \"Value with a Carriage Return : \\r\",\n" +
" \"T8\" : \"Value with a Horizontal Tab : \\t\"\n" +
"}"), [ "T1" : "Value With a Quote : \"", "T2" : "Value With a Rev Solidus : /", "T3" : "Value with a Solidus : \\", "T4" : "Value with a Backspace : \b", "T5" : "Value with a Formfeed : \f", "T6" : "Value with a Newline : \n", "T7" : "Value with a Carriage Return : \r", "T8" : "Value with a Horizontal Tab : \t" ]);

1
unittests/json_12.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("\"\""), "")

1
unittests/json_13.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("1.20E+2"), 1.20e2)

3
unittests/json_2.chai Normal file
View File

@@ -0,0 +1,3 @@
assert_true(from_json("true"))

1
unittests/json_3.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("100"), 100)

1
unittests/json_4.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("1.234"), 1.234)

1
unittests/json_5.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("\"StringTest\""), "StringTest")

1
unittests/json_6.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("{}"), Map())

4
unittests/json_7.chai Normal file
View File

@@ -0,0 +1,4 @@
assert_equal(from_json("\n" +
"{\n" +
" \"Key\" : \"Value\"\n" +
"}\n"), ["Key":"Value"])

1
unittests/json_8.chai Normal file
View File

@@ -0,0 +1 @@
assert_equal(from_json("[]"), [])

2
unittests/json_9.chai Normal file
View File

@@ -0,0 +1,2 @@
assert_equal(from_json("[1,2,3]"), [1,2,3])

View File

@@ -0,0 +1,6 @@
var m = ["a" : 1, "b" : [ 1, 2, 3 ], "c" : [1, "a string", ["d" : 15.4]]]
assert_equal(from_json(to_json(m)), m)

View File

@@ -6,3 +6,7 @@ x.push_back("A")
assert_equal(3, x.front());
assert_equal("A", x.back());

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