Compare commits

...

573 Commits

Author SHA1 Message Date
Jason Turner
fd2539145a Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-05-06 14:16:04 -06:00
Jason Turner
25f9dcf13e Add release notes for 5.7.0 2015-05-06 14:15:29 -06:00
Jason Turner
fc4b739839 Merge pull request #175 from totalgee/develop
Added elapsed time helper to chai executable
2015-05-06 09:50:06 -06:00
Glen Fraser
bd176cfde2 Renamed timer function to now(), added perf unit test 2015-05-06 11:37:37 +02:00
Jason Turner
04f01eee98 Add notes about literal numerics 2015-05-05 09:51:16 -06:00
Jason Turner
cf4efacbe8 Add 'GLOBAL' keyword #122
Also provides functionality that makes things like overriding the built in
'print' possible. See #67
2015-05-04 11:47:36 -06:00
Glen Fraser
b818799800 Added getTimeInSeconds() helper to chai executable 2015-05-04 19:41:25 +02:00
Jason Turner
fdcc5959c7 Fix tests failing w/MSVC2013 because of formatting 2015-05-03 10:31:10 -06:00
Jason Turner
74a992fad9 VS2015 thread_local doesn't seem ready for primetime yet 2015-05-03 08:43:43 -06:00
Jason Turner
d210f0e4e1 Enable thread_local in more cases, ignore clang warnings 2015-05-02 21:05:45 -06:00
Jason Turner
c0dd0a3041 Use static const true/false on platforms with magic statics 2015-05-02 15:27:51 -06:00
Jason Turner
45baf6f8e9 Global const values for booleans
- Reduces number of Boxed_Value constructions greatly
2015-05-02 13:08:23 -06:00
Jason Turner
e64e4b0877 Fix tests broken by last cleanup 2015-05-01 19:54:14 -06:00
Jason Turner
e286b9a9aa Never access data after moving it! 2015-05-01 07:22:43 -06:00
Jason Turner
d77921f1b5 Reorg of parsing code for maintainability / performance 2015-04-30 22:05:56 -06:00
Jason Turner
ebc6468178 Remove all /analyze from VS12, it's too slow
But still use it on VS14
2015-04-29 16:59:17 -06:00
Jason Turner
3e5034ecf8 Merge branch 'smaller_make_shared' into develop 2015-04-29 16:58:34 -06:00
Jason Turner
c52ad3d827 Merge pull request #174 from totalgee/develop
Support scientific notation for floating point (issue #173)
2015-04-29 16:50:39 -06:00
Glen Fraser
8fc61bf51c Fixing build error with tolower() on Windows 2015-04-29 21:52:34 +02:00
Jason Turner
dc6d039a72 Add documentation note workaround for libc++ 2015-04-29 13:41:58 -06:00
Jason Turner
2e72fde0ba Horrible workaround for libc++
Libc++ appears to have a problem with dynamic_casting between types
where one of them is a template that has been forward declared. This is
the only case that I see this problem coming up.

Due to the existing interdependencies between header files, I *must*
forward declare the Assignable_Proxy_Function_Impl. I don't see any
other way around this than to work around the standard library bug.
2015-04-29 13:39:57 -06:00
Glen Fraser
d762ef08b6 Support scientific notation for floating point 2015-04-29 19:40:58 +02:00
Jason Turner
8bbcceed88 Attempt better data layout of AST_Node 2015-04-28 08:56:20 -06:00
Jason Turner
aaf80ac8cf Merge branch 'develop' into smaller_make_shared 2015-04-27 16:24:17 -06:00
Jason Turner
86ec14c2c8 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-04-27 16:19:41 -06:00
Jason Turner
dbe546fefb Simplify and reduce eval code where possible 2015-04-27 16:17:01 -06:00
Jason Turner
50e0ce36be Clean up missing <string> include 2015-04-27 14:12:23 -06:00
Jason Turner
986699a3fe Merge branch 'develop' into smaller_make_shared
And also apply cleanups suggested from resharper

Conflicts:
	include/chaiscript/language/chaiscript_parser.hpp
2015-04-27 11:55:12 -06:00
Jason Turner
8889324b2d Code simplifications and spelling fixes found by clion 2015-04-27 08:09:31 -06:00
Jason Turner
7a13b6b801 Merge branch 'develop' into smaller_make_shared 2015-04-25 08:53:47 -06:00
Jason Turner
b2b604e2ad Merge branch 'reduce_function_scope_creation' into develop 2015-04-25 08:52:00 -06:00
Jason Turner
4f5f46a2e5 Don't use scopes around arithmetic operators 2015-04-24 22:36:22 -06:00
Jason Turner
dde7d27b96 A smaller make_shared derived types 2015-04-24 21:35:56 -06:00
Jason Turner
fa16bcd08e More warning management 2015-04-24 16:10:44 -06:00
Jason Turner
5c4de7e43c More catch() analysis warning cleanups 2015-04-24 14:29:15 -06:00
Jason Turner
bc7668c700 More windows warning fixes because of Catch 2015-04-24 09:53:06 -06:00
Jason Turner
a9d94968d0 Remove redundant /analyze on msvc configs 2015-04-24 07:39:04 -06:00
Jason Turner
1a37343e8b Check more compiler/analyzer warnings 2015-04-24 06:50:34 -06:00
Jason Turner
ddc6ac8e00 Eliminate unnecessary warnings on MSVC (catch)
Mostly caused by catch
2015-04-23 16:27:43 -06:00
Jason Turner
0e41e373c6 Clean up warnings generated by catch 2015-04-23 15:29:14 -06:00
Jason Turner
9ab0b1108a Wrap up method_missing docs and tests 2015-04-23 15:03:08 -06:00
Jason Turner
606c1d9d00 Merge remote-tracking branch 'origin/method_missing' into develop 2015-04-23 09:13:28 -06:00
Jason Turner
28f89475b0 Reduce build time for tests 2015-04-22 22:19:57 -06:00
Jason Turner
1a396be69d Minor unitest cleanups #168 2015-04-22 12:40:17 -06:00
Jason Turner
a542ec01f6 Update method_missing support to reduce exceptions 2015-04-22 12:15:15 -06:00
Jason Turner
f3943f215f Merge remote-tracking branch 'origin/develop' into method_missing 2015-04-22 07:29:46 -06:00
Jason Turner
0f4bd2b889 Merge pull request #172 from ChaiScript/libcxx_ubuntu_14_04
Libcxx ubuntu 14 04
2015-04-22 07:26:10 -06:00
Jason Turner
650889eae7 Fix issue affecting function ordering for vector 2015-04-21 23:19:15 -06:00
Jason Turner
90102cebd7 Full dynamic object system built on method_missing working 2015-04-21 22:36:48 -06:00
Jason Turner
dc746ee131 Merge branch 'method_missing' of https://github.com/arBmind/ChaiScript into method_missing
PR #164

Conflicts:
	include/chaiscript/dispatchkit/dispatchkit.hpp
2015-04-21 14:38:15 -06:00
Jason Turner
059c7bcca1 Merge branch 'fix_attr_function_calls' into develop
Conflicts:
	src/test_module.cpp
2015-04-21 12:45:59 -06:00
Jason Turner
1b7b7d6e2c Enable libc++ builds on dashboard 2015-04-21 12:39:54 -06:00
Jason Turner
7830085f5e Merge remote-tracking branch 'origin/add_array_type_support' into develop 2015-04-21 12:28:26 -06:00
Jason Turner
0ed9602ba9 Get libc++ on ubuntu 14.04 working
The std::is_member_function_pointer<> template is broken on this version
of the libc++ standard library for const member functions.

To get ChaiScript to work with this, we had to work around the use of
automatically generated std::function wrappers in many cases. This
actually cleaned up the code in a few places and muddied it up in one.
2015-04-21 12:01:29 -06:00
Jason Turner
2f531355cd Boxed_Value changes necessary for libc++ 2015-04-20 20:30:25 -06:00
Jason Turner
db34899225 Address msvc issues with #167 #165
The best we can get it down to is 2 moves in MSVC, it does not
elide the moves/copies as well as GCC and Clang do

It's not possible for us to support registering of array types in
MSVC12, but we can in MSVC14 with the latest release of the
compiler.
2015-04-18 20:51:45 -06:00
Jason Turner
71245aa703 Add array type support #167 2015-04-17 20:02:09 -06:00
Jason Turner
ecd2e523f7 attributes / members holding functions works fully now
Issue #155
2015-04-17 16:32:59 -06:00
Jason Turner
d2ed8fdcf1 Get class members that are functions working
Automatic conversion of return values into Proxy_Function objects
Issue: #155
2015-04-17 12:18:47 -06:00
Jason Turner
2f444542ab Add test for attr calls specifically 2015-04-17 07:35:12 -06:00
Jason Turner
268868f102 Add failing tests 2015-04-16 20:00:48 -06:00
Jason Turner
f3090c3857 Add test for number of moves/copies made
For #165
2015-04-12 19:20:24 -06:00
Jason Turner
3c7b0ea069 Revert change to example.cpp library loading 2015-04-10 10:38:49 -06:00
Jason Turner
2e769d81cf Get return_value_handling fully working 2015-04-10 09:32:01 -06:00
Jason Turner
a3f88b43ce Merge branch 'return_value_handling' into develop 2015-04-10 08:20:55 -06:00
Jason Turner
b489ffe3ed Fix errors with eval/use of scripts 2015-04-10 08:20:30 -06:00
Andreas Reischuck
cbeeadd6f3 Merge branch 'develop' into method_missing 2015-04-08 16:52:34 +02:00
Jason Turner
63684d0042 Add the ability to get the return value from 'use' 2015-04-08 08:17:33 -06:00
Jason Turner
1f74bfd9b3 Attempt to create the concept of "return values"
to reduce clones of values. This doesn't quite work
2015-04-07 13:54:38 -06:00
Jason Turner
5114ca9d35 Fix double pointer cast test 2015-04-07 11:09:47 -06:00
Jason Turner
79181fe41e Reduce copies of UDTs 2015-04-07 10:23:43 -06:00
Jason Turner
962bdf4b3c Reduce exceptions on startup to minimum
This still has some exceptions thrown during the loading of modules
since I have no way of knowing where the operating system
`dlopen` and `LoadLibrary` functions will search for me to pre-check
it.

Closes #158
2015-04-06 13:17:41 -06:00
Jason Turner
f953f9b297 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-04-06 07:22:55 -06:00
Jason Turner
1557dabf4f Fixes array access with arithmetic conversions
Closes #156
2015-04-06 07:21:32 -06:00
Jason Turner
9422bc7b2d Add failing test for size_t vector access 2015-04-06 06:40:03 -06:00
Jason Turner
7f1cd29a2c Various cleanups 2015-04-02 15:40:45 -06:00
Jason Turner
8f2e56a681 Initial sublime text support 2015-04-01 09:47:27 -06:00
Jason Turner
88e765bd4e Create LICENSE 2015-04-01 08:07:19 -06:00
Jason Turner
59103b5a22 Apply some IIFE to reduce copies 2015-03-29 21:58:14 -06:00
Andreas Reischuck
b67dc4e09a Merge branch 'develop' into method_missing 2015-03-27 21:36:25 +01:00
Jason Turner
d514fa3346 Create cheatsheet.md 2015-03-27 10:24:47 -06:00
Jason Turner
95ead0dbfb Various warning cleanups 2015-03-25 17:30:19 -06:00
Jason Turner
c32a944b9d Fix macos clang builds 2015-03-25 14:04:42 -06:00
Jason Turner
62337062bf Reduce the number of exceptions created at runtime 2015-03-25 13:36:02 -06:00
Jason Turner
a75117c007 Merge branch 'master' of github.com:ChaiScript/ChaiScript into ast_optimizations 2015-03-25 11:58:43 -06:00
Jason Turner
4fe536e65b Add performance test for type conversions 2015-03-25 11:58:24 -06:00
Jason Turner
d396f8e6a0 Enhancements for > 1 param function dispatch 2015-03-25 10:01:36 -06:00
Jason Turner
6ba3e92d6e Various tree optimizations 2015-03-24 14:15:47 -06:00
Jason Turner
bd1b5c0687 Disable block optimization - it didn't handle stack 2015-03-24 10:15:08 -06:00
Jason Turner
40e2bf4099 Test optimizing the AST 2015-03-23 21:43:57 -06:00
Jason Turner
5b9878b070 Minor speed improvements 2015-03-23 20:07:07 -06:00
Jason Turner
0b28603cdc Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-03-23 14:16:48 -06:00
Jason Turner
91bcaaa037 Reduce use of mem_fn when possible 2015-03-23 14:16:23 -06:00
Jason Turner
04bceedf64 Reduce versions of shared_ptr created 2015-03-23 13:44:40 -06:00
Jason Turner
9326539f3b Fix gcc 4.6 errors/issues 2015-03-22 08:14:59 -06:00
Jason Turner
1113cafca2 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop
Conflicts:
	CMakeLists.txt
2015-03-21 21:04:03 -06:00
Jason Turner
98e36ab836 Minor cleanups, increment to 5.7.0 2015-03-21 20:56:28 -06:00
Jason Turner
976e4ec46c Enable parsing of lambda captures
Closes #161
2015-03-21 20:30:52 -06:00
Jason Turner
c416ca1e4d Add failing lambda test with bind variable 2015-03-21 19:52:03 -06:00
Jason Turner
9963933f51 Normalize the number of child nodes in a Lambda node 2015-03-21 19:50:04 -06:00
Andreas Reischuck
4e614729dc using copy construction 2015-03-22 00:23:49 +01:00
Andreas Reischuck
d0e763d77e fixed method_missing parameter order 2015-03-22 00:17:53 +01:00
Jason Turner
63c243dec8 Set CMake policy, closes #162 2015-03-21 16:35:59 -06:00
Andreas Reischuck
c15e0174c9 added "method_missing" feature 2015-03-21 22:29:16 +01:00
Jason Turner
ec47a35e9f Merge branch 'master' into develop 2015-03-21 14:15:31 -06:00
Jason Turner
9c1f5b6830 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-03-21 14:15:06 -06:00
Jason Turner
735088dc96 Merge branch 'master' into develop 2015-03-21 14:14:33 -06:00
Jason Turner
f14be9660a Update biicode and get master updated to v5.6.0 2015-03-19 20:03:12 -06:00
Jason Turner
6a5f78240a Merge tag 'v5.6.0' 2015-03-19 20:02:56 -06:00
Jason Turner
230e399d92 Merge branch 'master' of github.com:ChaiScript/ChaiScript 2015-03-18 19:26:29 -06:00
Jason Turner
dace26cae1 add support for biicode 2015-03-18 19:23:04 -06:00
Jason Turner
e6d71373b8 Correct travis yaml 2015-03-18 09:04:36 -06:00
Jason Turner
27e861c7b9 Hook travis up to gitter 2015-03-18 07:49:06 -06:00
Jason Turner
516ca8eec2 Merge branch 'master' into develop 2015-03-13 22:28:24 -06:00
Jason Turner
b71f9db5c2 MSVC Fixes 2015-03-13 22:27:51 -06:00
Jason Turner
aa0ed17e43 Merge tag 'v5.6.0' 2015-03-13 21:59:37 -06:00
Jason Turner
34e3551ebd Fix spelling error in document examples 2015-02-19 08:27:22 -07:00
Jason Turner
c584c29951 Simplification 2015-01-31 16:12:19 -07:00
Jason Turner
c285c4d40b Reduce code in assignment oper eval 2015-01-31 15:07:17 -07:00
Jason Turner
b5188b9eda Cleanup assignment eval 2015-01-31 14:40:26 -07:00
Jason Turner
d558019bb3 Simplify logical && || operator eval 2015-01-31 13:41:29 -07:00
Jason Turner
722e9ed3d1 Various code cleanups 2015-01-31 10:10:35 -07:00
Jason Turner
76ac7c36fe Simplify redundant bool condition checking 2015-01-31 07:28:37 -07:00
Jason Turner
f0ed3a5cf7 Add 'var' 'auto' and typed param documentation 2015-01-19 09:19:31 -07:00
Jason Turner
343264944a Update releasenotes.md 2015-01-17 14:28:06 -07:00
Jason Turner
b436791272 Change to TBZ2 for MacOS packages 2015-01-17 07:09:47 -07:00
Jason Turner
9b19aa3b6e Get ready for 5.6.0 release
- Update copyrights to 2015
 - Set version to 5.6.0
 - Update release notes
2015-01-17 07:05:10 -07:00
Jason Turner
e86fc96b2f Merge branch 'AddMoreWarningFlags' into develop
Conflicts:
	include/chaiscript/dispatchkit/boxed_number.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/language/chaiscript_eval.hpp
2015-01-16 19:32:53 -07:00
Jason Turner
66801349a8 Merge remote-tracking branch 'origin/OptionalTypedArgs' into develop 2015-01-16 10:19:27 -07:00
Jason Turner
bde4eb04b6 Merge remote-tracking branch 'origin/DivideByZeroProtection' into develop 2015-01-16 10:18:50 -07:00
Jason Turner
c3f343450d Fix issues found with cppcheck inconclusive 2015-01-16 10:10:14 -07:00
Jason Turner
8dc2c55acd Merge branch 'AddMoreWarningFlags' of https://github.com/ChaiScript/ChaiScript into AddMoreWarningFlags 2015-01-15 17:51:23 -07:00
Jason Turner
adfc56db8b Warning cleanups 2015-01-15 17:49:26 -07:00
Jason Turner
c7b2b3095a Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into AddMoreWarningFlags 2015-01-15 15:45:45 -07:00
Jason Turner
9449fca22f Memory leak error fixes. Various compiler fixes. 2015-01-15 15:42:35 -07:00
Jason Turner
759d6fc42f Remove [[ noreturn ]], MSVC14 doesn't yet support attributes? 2015-01-15 15:15:02 -07:00
Jason Turner
f95ca75aca Clean up more warnings with stricter warning levels 2015-01-15 14:24:39 -07:00
Jason Turner
41a45ce8b5 Enable warnings (and fix up some things) 2015-01-14 21:07:40 -07:00
Jason Turner
5b6e6042f3 Work around MSVC 2014 issue with future
have to wrap std::future::valid in a lambda due to noexcept?!
2015-01-14 20:41:41 -07:00
Jason Turner
1552d36d7a Fix spelling of ANALYZE to analyze 2015-01-14 20:01:32 -07:00
Jason Turner
26bf531cab Remove unused parameter 2015-01-13 17:07:46 -07:00
Jason Turner
7761ceb736 Clean up some numeric processing code 2015-01-13 17:04:34 -07:00
Jason Turner
497dd89046 Add typed exception unit tests 2015-01-13 14:08:46 -07:00
Jason Turner
ef69e4a2f1 Allow typing of exception handlers 2015-01-13 14:05:41 -07:00
Jason Turner
3f23e57a3d Fix build error 2015-01-13 12:07:08 -07:00
Jason Turner
f66b4aafc1 Fix g++ 4.6 initializers 2015-01-13 11:58:23 -07:00
Jason Turner
3d1edbf38f Add missing dynamic_object_detail 2015-01-13 11:44:13 -07:00
Jason Turner
c1f47cbc16 Update prelude to use new typed params 2015-01-13 11:39:24 -07:00
Jason Turner
4761a68d06 Enable optional typing of function params 2015-01-13 11:24:40 -07:00
Jason Turner
31ef683ced Use SFINAE to clean up divide by zero protection 2015-01-12 10:06:42 -07:00
Jason Turner
9b3bb493e9 Clean up some MSVC warnings 2015-01-10 07:18:10 -07:00
Jason Turner
2f90b3ae6b Correct exception specifier for arithmetic_error 2015-01-09 20:31:40 -07:00
Jason Turner
420ba68b94 Make sure floating point returns Infinity 2015-01-09 20:20:38 -07:00
Jason Turner
576816e3b1 Add unit test for divide by zero protection 2015-01-09 20:17:20 -07:00
Jason Turner
25b15a3449 Only apply divide by zero protection to integers
Also allow arithmetic error to bubble up to the caller.
2015-01-09 20:06:04 -07:00
Jason Turner
8746a9eea5 Make divide by zero protection the default 2015-01-09 19:38:27 -07:00
Jason Turner
0695eec3ca Limit scope of #ifdefs, remove macros
Macros do not fit within the ChaiScript coding standards because
they do not respect namespaces and are more difficult to debug
of something goes wrong.
2015-01-09 19:30:28 -07:00
Jason Turner
1a4dec0df0 Remove redundant/unnecessary constructors and object copies. 2015-01-09 19:06:08 -07:00
Jason Turner
de09489355 Fix formatting (tabs vs spaces) in divide/0 protection 2015-01-09 19:02:56 -07:00
Jason Turner
440ceeebbb Merge branch 'develop' of https://github.com/lufinkey/ChaiScript into DivideByZeroProtection 2015-01-09 19:01:58 -07:00
Jason Turner
12533ce3e1 Add note about State tracking of Type_Conversions 2015-01-09 16:14:47 -07:00
Jason Turner
2e02273673 Add .bundle to module search extensions 2015-01-09 10:40:20 -07:00
Jason Turner
d91294b989 Add warning for c-style casts to gcc 2015-01-07 13:56:48 -07:00
Jason Turner
52d03a66b1 Add future support, and fix returning of r-values 2015-01-06 15:31:06 -07:00
Jason Turner
a32a180a06 wq
Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop
2015-01-06 14:25:44 -07:00
Jason Turner
e61612e416 Fix Doxygen configuration 2015-01-06 13:35:52 -07:00
Jason Turner
7478d57264 Merge remote-tracking branch 'origin/master' into develop 2014-12-21 13:15:12 -07:00
Jason Turner
bab3701c2f Update release notes 2014-12-21 13:14:47 -07:00
Jason Turner
e225654289 Tick version up to 5.5.1 2014-12-21 13:12:56 -07:00
Jason Turner
019ea57cb6 Merge pull request #151 from ChaiScript/performance_test
Performance test
2014-12-17 09:46:28 -07:00
Jason Turner
60fe242fb6 Skip packaging of MSVC 14 builds 2014-12-12 06:52:47 -07:00
Jason Turner
6c10f18e4c Merge pull request #149 from gitter-badger/gitter-badge
Add a Gitter chat badge to readme.md
2014-12-11 08:50:51 -07:00
The Gitter Badger
d5a221a468 Added Gitter badge 2014-12-11 15:47:26 +00:00
Jason Turner
6ec3afc687 Only package 4.8 gcc on linux 2014-12-02 14:33:56 -07:00
Jason Turner
049cd12127 Add "skip_packaging" to macos debug build 2014-12-02 11:23:29 -07:00
Jason Turner
8b34066dd5 Put to use new skip_packaging and build_tag features 2014-12-01 21:22:45 -07:00
Jason Turner
9fb74762ad Remove extraneous std::cout messages 2014-11-23 20:14:12 -07:00
Jason Turner
7b7e7176f5 Merge remote-tracking branch 'origin/develop' into performance_test 2014-11-17 14:17:28 -07:00
Jason Turner
81146d6b0f Clean up compiler warnings 2014-11-17 14:17:07 -07:00
Jason Turner
423e872720 Work around bug in gcc 4.6 for initializer_list
Hopefully also fixes MSVC 2012
2014-11-17 07:02:52 -07:00
Jason Turner
1e8c0ab93e Reduce redundant parsing / error code 2014-11-16 21:22:55 -07:00
Jason Turner
c90fe16858 Clean up Prefix() implementation
Reducing redundant code
2014-11-16 21:02:28 -07:00
Jason Turner
161652b5d9 Reworking of binary operators
- Eliminates re-parsing of operator strings
- Reduces much redundant code

Results

1. smaller binaries
2. less runtime memory usage
4. faster runtime
2014-11-16 20:28:44 -07:00
Jason Turner
cc5bf45b3b Merge branch 'develop' into performance_test 2014-11-14 21:37:07 -07:00
Jason Turner
28124e4b33 Fix stack memory management
From 747M to 6.2M for profiling tests.
2014-11-14 20:28:53 -07:00
Jason Turner
db207b345b Merge branch 'add_object_lifetime_test' into develop 2014-11-14 14:57:27 -07:00
Jason Turner
684d724103 Add object lifetime test that failed in v5.4.0 2014-11-14 14:54:57 -07:00
Jason Turner
283152a880 Speed up print functions 2014-11-14 09:45:49 -07:00
Jason Turner
dc3ef087e2 Merge branch 'performance_evaluations' into performance_test 2014-11-14 08:00:08 -07:00
Jason Turner
032ba63b8a Add fun_call_performance samples 2014-11-14 07:41:43 -07:00
Jason Turner
cf49b1b30c Make def more efficient, fix to_string(string) 2014-11-13 12:28:52 -07:00
Jason Turner
63a083b47b Remove uses of std::endl, which imply a flush 2014-11-13 10:13:51 -07:00
Jason Turner
4a3315cfd1 Merge pull request #144 from ChaiScript/develop
Merge release 5.5.0 to master
2014-11-10 12:48:25 -07:00
Jason Turner
8a30581eaf Update release notes for version 5.5.0 2014-11-10 12:45:49 -07:00
Jason Turner
a51281a5be Merge branch 'develop' of http://github.com/ChaiScript/ChaiScript into develop 2014-11-06 15:13:51 -07:00
Jason Turner
e0919f7228 Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-11-06 15:13:30 -07:00
Jason Turner
fa5966bd04 Enable optimizations options for LTO and profile 2014-11-06 15:12:53 -07:00
Jason Turner
f4f2391801 Add support for clang/gcc MemorySanitizer 2014-11-04 15:22:09 -07:00
Jason Turner
5daf837037 Increment version number to 5.5.0 2014-11-04 09:47:32 -07:00
Jason Turner
99396ba05c Add \r skipping code from @jespada 2014-11-03 21:37:25 -07:00
Jason Turner
f5304ac75c Merge branch 'develop' of http://github.com/ChaiScript/ChaiScript into develop 2014-11-03 18:36:10 -07:00
Jason Turner
3f460fdd20 Fix 64bit msvc warning 2014-11-03 18:34:33 -07:00
Jason Turner
4f972bcf67 Refine lifetime of parameters to functions
Fixes crash caused when making function calls in a global context, and
probably fixes other things.
2014-11-03 09:13:30 -07:00
Jason Turner
5d5e881971 Fix arity of functions
A value was being accessed after it was moved.
2014-11-03 08:24:02 -07:00
Jason Turner
5515d058bb Fix some warnings for clang / 64bit windows 2014-11-03 07:33:53 -07:00
Jason Turner
79c5f71975 Fix compilation on gcc 4.6 2014-11-02 21:47:42 -07:00
Jason Turner
c876a89030 Fix crash during user_defined_conversions_2
Temporaries created during user conversion operations were being dropped
before the result of the conversion was able to be used. This fixes that
by temporarily storing the result of the conversion inside the
current Function_Push_Pop context.
2014-11-02 21:37:01 -07:00
Jason Turner
20c0e6016e Add type_conversion helper and failing unit test 2014-11-02 14:08:57 -07:00
Jason Turner
dd12785b72 Reduce virtual calls for get_arity
Saves compiled code size and some minor runtime differences
2014-11-01 18:40:42 -06:00
Jason Turner
87cee688a8 Fix broken type conversion call implementation
- We need to properly order the function so that the one with the least
   number if type differences is the one that is tried first.
2014-11-01 15:52:02 -06:00
Jason Turner
e2cf8a48be Correct check for which types might have conversions 2014-10-29 07:07:12 -06:00
Jason Turner
7c766f87a4 Add thread specific cache of type info
Reduces the number of locks necessary to check of a user defined type
conversion should be scanned for / applied.
2014-10-28 22:12:03 -06:00
Jason Turner
e85be6eb3d Add C++ test for user defined conversion 2014-10-28 20:23:19 -06:00
Jason Turner
7b42d5307a Add ability to register a user defined type conversion
Currently this adds a fair bit of overhead. It will need to be evaluated
further before it's merged.
2014-10-28 14:52:24 -06:00
Jason Turner
43d6f0cf16 Rename dynamic_cast into type_conversion
Prep work for getting user defined type conversions implemented
2014-10-28 12:43:30 -06:00
Jason Turner
86e26966c1 More code cleanups 2014-10-28 10:53:29 -06:00
Luis Finke
b41c0f432b Added (optional) protection against divide by zero exceptions
defining the preprocessor CHAISCRIPT_PROTECT_DIVIDEBYZERO adds checking of right side values before division arithmetic, allowing the user to safely catch a divide by zero error, rather than dealing with a SIGFPE and having the entire program exit without a choice
2014-10-24 17:41:33 -04:00
Jason Turner
9e8b833d11 Code cleanups 2014-10-18 16:18:56 -06:00
Jason Turner
48c97bce9c Add faux-inheritance example 2014-10-12 22:13:40 -07:00
Jason Turner
021e2a7949 Fix returning of boolean values from functors 2014-10-12 22:12:54 -07:00
Jason Turner
78cd980067 Work around broken Apple clang implementation
This line of code does not cause an error on clang-3.4 or clang-3.5
on Linux. Apple's clang is somewhere between the two, no way to know
where.

For an unknown reason, specifying default move operations in 'Data'
causes the compiler to think that Boxed_Value is an incomplete type.

This is highly illogical since Data is only used via a shared_ptr, so
the size / type of Boxed_Value should be fully known (and is known on
every other compiler/platform combination).
2014-10-01 15:49:11 -06:00
Jason Turner
58d9e69479 Work around missing move operations in MSVC12 2014-10-05 21:53:44 -06:00
Jason Turner
935e9de19e GCC 4.6 fixes to cleanups 2014-10-05 14:58:27 -06:00
Jason Turner
f547b4bb10 Enable moving of data into Boxed_Values when possible 2014-10-05 12:11:46 -06:00
Jason Turner
87e40237d3 Enable moving of Any objects 2014-10-05 11:47:50 -06:00
Jason Turner
5619f2602d Eliminate extra dynamic allocation in the Stack 2014-10-05 08:58:29 -06:00
Jason Turner
5986531bba dispatchkit modernization 2014-10-04 22:59:52 -06:00
Jason Turner
8ecc11c275 First pass of modernization of chaiscript_eval.hpp done 2014-10-04 18:31:08 -06:00
Jason Turner
81dc4949d2 1/4 through modernization of chaiscript_eval.hpp 2014-10-04 15:34:32 -06:00
Jason Turner
9a7d03df05 Modernization of chaiscript_parser 2014-10-04 09:37:33 -06:00
Jason Turner
4f5a6da280 Move constructor and noexcept correctness 2014-09-21 14:19:41 -06:00
Jason Turner
e4b9be6e09 Merge remote-tracking branch 'origin/develop' into code_cleanups
Conflicts:
	.decent_ci-Linux.yaml
2014-09-20 14:27:37 -06:00
Jason Turner
0a7e7b3a0d Merge pull request #137 from ChaiScript/enable_decent_ci
Enable decent ci
2014-09-20 14:24:24 -06:00
Jason Turner
e1b80abac4 Update documenation to-dos regarding gcc 4.6 2014-09-20 14:20:37 -06:00
Jason Turner
b6e8605aee Attempt again to satisfy gcc 4.6 2014-09-20 14:17:41 -06:00
Jason Turner
0e381e333e Attempt to satisfy G++4.6 and decltype usage 2014-09-20 08:31:18 -06:00
Jason Turner
8c31255012 Windows and GCC 4.6 error cleanups 2014-09-20 07:21:30 -06:00
Jason Turner
01cf906e18 Clean up 32bit windows warnings 2014-09-19 21:58:28 -06:00
Jason Turner
e55700b86b Remove static in bind_first - VS12 warns on it 2014-09-19 21:52:18 -06:00
Jason Turner
81184cbbd7 Rollback template alias, not supported in gcc 4.6 2014-09-19 21:46:52 -06:00
Jason Turner
c00c38bc22 Fix spelling of "USE_LIBCXX" flag 2014-09-19 10:34:51 -06:00
Jason Turner
ae1897e2ea Update to force CI rebuild 2014-09-19 10:25:04 -06:00
Jason Turner
93c1cfde99 Try out some alias templates for cleanup 2014-09-18 20:48:34 -06:00
Jason Turner
2321f1d709 Enable clang linux builds 2014-09-18 20:07:15 -06:00
Jason Turner
cfd4a73a89 Add VS 2014 CI Support 2014-09-16 13:30:47 -06:00
Jason Turner
04782b6a33 Add gcc-4.6 to test configuration 2014-09-16 08:02:12 -06:00
Jason Turner
5861c45fc1 C++11 related cleanup and improvments 2014-09-15 21:16:44 -06:00
Jason Turner
d62a452a9d Correct -I path for cppcheck run 2014-09-15 07:12:19 -06:00
Jason Turner
3ccb155358 Fix up usage of cppcheck, enable samples build 2014-09-14 21:57:07 -06:00
Jason Turner
6c2ccf3869 Various cleanups prefering lambda to bind 2014-09-14 21:53:11 -06:00
Jason Turner
f02a9fa885 Merge remote-tracking branch 'origin/enable_decent_ci' into code_cleanups 2014-09-14 20:10:52 -06:00
Jason Turner
0036ebfe5d Update .decent_ci-Windows.yaml 2014-09-14 12:44:20 -06:00
Jason Turner
7b28f9ef57 Fix results location 2014-09-13 23:11:17 -06:00
Jason Turner
bd8a78eccc Initial decent_ci files 2014-09-13 21:53:12 -06:00
Jason Turner
9436533ddb Merge commit '243f400' into develop
Conflicts:
	include/chaiscript/dispatchkit/bind_first.hpp
2014-09-12 15:18:38 -06:00
Jason Turner
243f4001d1 Code cleanups 2014-09-12 15:16:24 -06:00
Jason Turner
3bd2a9c00d Clean up bind_first implementation 2014-09-10 07:40:16 -06:00
Jason Turner
fde90ad980 Throw exception if user attempts to use null Boxed_Value 2014-09-09 13:43:05 -06:00
Jason Turner
308eb34d05 Correct test_module changes 2014-09-08 21:15:02 -06:00
Jason Turner
4a70ffe599 Add failing unit test for accessing member of null object 2014-09-08 18:23:53 -06:00
Jason Turner
52179d8333 Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-09-08 11:11:35 -06:00
Jason Turner
eed90b521d Spelling corrections and comment fixes 2014-09-08 11:10:53 -06:00
Jason Turner
166f3501c3 Ignore missing system include files 2014-09-05 08:41:58 -06:00
Jason Turner
29b1fca76c Use g++-4.8 for cppcheck building 2014-09-05 08:09:22 -06:00
Jason Turner
8d36b66c89 Fix call to cppcheck 2014-09-05 07:45:36 -06:00
Jason Turner
f78fb77128 Merge pull request #135 from ChaiScript/develop
Develop
2014-08-31 20:03:18 -06:00
Jason Turner
bb08cc3699 Add documenation for "class" keyword 2014-08-31 19:54:43 -06:00
Jason Turner
6692607507 Update version number to 5.4.0, update releasenotes 2014-08-31 19:45:07 -06:00
Jason Turner
6bea42c1c0 Speed up to_string performance by relying on C++ versions
Addresses #134, fixing issues introduced by #132
2014-08-31 16:03:42 -06:00
Jason Turner
251790f144 Fix some MSVC warnings 2014-08-31 12:04:02 -06:00
Jason Turner
4ee9ba9c96 Make up some of the performance losses #132 2014-08-30 14:49:31 -06:00
Jason Turner
a71903f185 Add strong reference to range objects #132 2014-08-30 13:36:36 -06:00
Jason Turner
3fe80d70c6 Roll back name of range class, it's half baked from the range fix 2014-08-27 12:24:46 -06:00
Jason Turner
9c05779fac Add failing range test
Crash occurs if the user attempts to use a range and the source
of the range has gone out of scope. #132
2014-08-27 12:15:47 -06:00
Jason Turner
a6e3fd5b42 Make reflection API part of stdlib
removes the reflection module completely. Reflection and the
ability to catch eval errors is too useful.
2014-08-27 12:05:03 -06:00
Jason Turner
6a3f19d575 Add copy constructor for Type_Info 2014-08-26 09:28:51 -06:00
Jason Turner
9b7e4d2e78 Let a subscript out of range be catchable from chaiscript 2014-08-26 08:51:02 -06:00
Jason Turner
f546e46582 Update to cppcheck 1.66 2014-08-22 21:29:14 -06:00
Jason Turner
fa1f4b795b Add class keyword for easier user defined types.
Issue #118
2014-08-22 21:11:49 -06:00
Jason Turner
cb1c7730cf Add the ability to look up user defined typenames
Closes #124
2014-08-17 09:05:29 -06:00
Jason Turner
3a775097dd Reduce size of Any template wrapper. 2014-08-17 06:52:11 -06:00
Jason Turner
5692dfc58a Move to unique_ptr for Any implemenation
Speed and size improvements
2014-08-15 20:38:35 -06:00
Jason Turner
c5f6c549ec Reduce compiled size with template reductions 2014-08-15 20:14:15 -06:00
Jason Turner
14a280713f Update version to 5.3.2 2014-06-11 15:15:51 -06:00
Jason Turner
e7b6ee6cf9 Update release notes for 5.3.1 2014-06-11 15:11:21 -06:00
Jason Turner
32a9aa9c3c Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-05-29 20:44:35 -06:00
Jason Turner
f57a14e3de Allow user to add globals from within script. 2014-05-29 20:44:05 -06:00
Jason Turner
4018c873dc Spelling fixes, phase 1. 2014-05-29 20:16:47 -06:00
Jason Turner
b4ea27d28a Add unsupported build support for Haiku 2014-05-27 06:51:38 +00:00
Jason Turner
e5d723621f Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-05-23 09:57:29 -06:00
Jason Turner
46e7d0ab99 Clean up tab vs space issues
discovered by @axelstudios
2014-05-23 09:56:55 -06:00
Jason Turner
d5378f50af Fix cygwin builds #121
Cygwin claims to be POSIX but only implementes part of
the dl_open interface.

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

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

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

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

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

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

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

This fixes that.
2014-05-09 17:46:06 -06:00
Jason Turner
c2d08457ad Fix thread-unsafe builds 2014-05-09 15:55:29 -06:00
Alex Swindler
d3084ed136 Formatted CMakeLists.txt 2014-05-07 15:02:21 -06:00
Jason Turner
62b8977abe Correct linking of modules for coverage testing 2014-05-04 21:52:27 -06:00
Jason Turner
b87c37032b Add version numbers that can be queried at runtime 2014-05-04 10:14:42 -06:00
Jason Turner
7932cb18f3 Clean up linker flags and add sanitizer options
Sanitizers are features now built into gcc and clang to check for
runtime problems such as data races, memory errors or undefined
behavior.
2014-05-04 07:55:36 -06:00
Jason Turner
706b5aaa45 Merge remote-tracking branch 'origin/release-4.x' into develop
Conflicts:
	releasenotes.md
2014-05-04 07:16:27 -06:00
Jason Turner
41bf96c42e Update release notes for release 4.3.1 2014-05-03 17:44:54 -06:00
Jason Turner
67b5d989cb Merge remote-tracking branch 'origin/release-4.x' into develop 2014-04-22 19:52:01 -06:00
Jason Turner
fcc9bd9bbb Start porting of documentatation to markdown style 2014-04-13 19:16:51 -06:00
Jason Turner
825c28521e Update doxyfile to latest template 2014-04-13 19:16:23 -06:00
Jason Turner
5da1475082 Port is_prime.chai to run on pre-cpp11 versions 2014-04-13 19:15:39 -06:00
Jason Turner
c9a244019e Enhance the inheritance unit tests #117 2014-04-13 08:05:46 -06:00
Jason Turner
2bd1910c70 ~30% performance improvement with threading enabled 2014-04-05 22:49:50 -06:00
Jason Turner
4ace508339 Update travis token 2014-04-02 14:13:19 -06:00
Jason Turner
926e962fc0 Merge remote-tracking branch 'origin/release-4.x'
Conflicts:
	.travis.yml
	CMakeLists.txt
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/language/chaiscript_common.hpp
2014-03-29 07:30:14 -06:00
Jason Turner
caf4495cff Add unit tests for inheritance with multiple layers 2014-03-29 06:16:21 -06:00
Jason Turner
6b0e0dc7ae Removed erroneously kept debug output 2014-03-28 07:04:51 -06:00
Jason Turner
65b0846e41 Address some of the issues found by cppcheck 2014-03-26 16:59:41 -06:00
Jason Turner
296769ee24 Version number bump, cppcheck fix 2014-03-26 15:20:06 -06:00
Jason Turner
d9bdad714f Fix syntax problem with .travis.yml 2014-03-26 14:45:01 -06:00
Jason Turner
12de955a47 Post cppcheck results to pull request 2014-03-26 13:56:02 -06:00
Jason Turner
a652a7e564 Only post comment if this is a pull request 2014-03-26 13:37:51 -06:00
Jason Turner
611692646f Add travis support for testing with cppcheck 2014-03-26 13:32:25 -06:00
Jason Turner
96acf5e833 Update travis in 4.x branch for coveralls support 2014-03-26 11:37:37 -06:00
Jason Turner
656b438002 First cast up chain, if that fails, cast down 2014-03-26 10:52:56 -06:00
Jason Turner
56b036052f Add test for automatic casting down in inheritance 2014-03-26 09:14:06 -06:00
Jason Turner
7fade8e841 Allow for automatic conversion of arithmetic types
for returns from chaiscript function wrappers
2014-03-26 08:11:37 -06:00
Jason Turner
db8be03cee Add tests for returning of arithmetic types with conversions 2014-03-26 07:26:23 -06:00
Jason Turner
372cf73548 Correct typo in travis logic 2014-03-25 08:24:25 -06:00
Jason Turner
0213039ee7 Install gcc-4.8 in travis matrix and test both 4.6 & 4.8 2014-03-25 08:12:07 -06:00
Jason Turner
e8fcb3f68b Revert back to cpp and use ubuntu for builds with travis 2014-03-24 21:29:11 -06:00
Jason Turner
8d8df1f5bd Attempt objective-c for building on macos travis 2014-03-24 21:17:40 -06:00
Jason Turner
f40f9d8441 Fix call to gcov for older gcov ver / travis 2014-03-24 19:41:41 -06:00
Jason Turner
8879a89490 Utilize 2 cores on travis during build 2014-03-24 18:55:01 -06:00
Jason Turner
e4a3b3f620 Update coveralls execution to merge all data and ignore cpp 2014-03-24 18:51:25 -06:00
Jason Turner
d6c8b36eeb Update readme.md 2014-03-24 14:23:44 -06:00
Jason Turner
de86e79df2 Merge pull request #106 from ChaiScript/ChaiScript_5_0_CPP_11
Chai script 5 0 cpp 11
2014-03-24 14:16:38 -06:00
Jason Turner
8d96abe730 Fix test for overload registration with add_class utility 2014-03-24 14:09:20 -06:00
Jason Turner
c021cc931c Disable travis clang again, it seems to not be up to it 2014-03-23 18:55:57 -06:00
Jason Turner
782c3040cc Add badge display for coveralls status, update travis 2014-03-23 18:42:17 -06:00
Jason Turner
4dbe9df21e Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2014-03-23 16:51:59 -06:00
Jason Turner
a1fc7416e1 Update travis to also push coverage results 2014-03-23 16:51:32 -06:00
Jason Turner
bf0737a35c Cleanup search for chaiscript_stdlib and fix some bugs 2014-03-23 16:42:04 -06:00
Jason Turner
00c8bf4973 Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2014-03-22 16:26:51 -06:00
Jason Turner
593ce462f7 Re-enable C++11 registration utility
The latest VisualStudio 2013 CTP2 sworks with this now. Be sure to install it to build chaiscript
2014-03-22 16:24:16 -06:00
Jason Turner
304e34002b Merge remote-tracking branch 'origin' into ChaiScript_5_0_CPP_11
Conflicts:
	readme.md
2014-03-11 08:59:32 -06:00
Jason Turner
385465cf3f Update readme.md 2014-03-10 15:05:54 -06:00
Jason Turner
27307b17d1 Update readme.md 2014-03-10 15:04:47 -06:00
Jason Turner
4bdf854a9c Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	.travis.yml
2014-03-10 14:49:47 -06:00
Jason Turner
0162757158 Add missing boost dependency for travis 2014-03-10 14:48:59 -06:00
Jason Turner
b0a882d57e Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	.travis.yml
2014-03-10 14:31:58 -06:00
Jason Turner
d22fb19e0e Add travis-ci support for master branch 2014-03-10 14:31:02 -06:00
Jason Turner
8b134c65d1 Add travis script for automated testing 2014-03-10 14:16:56 -06:00
Jason Turner
ee35eb1512 Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2014-03-04 11:21:25 -07:00
Jason Turner
ebbcc5cbdb Catch missing virtual destructors, enable g++ warnings 2014-03-04 11:20:45 -07:00
Jason Turner
dbd9534bd9 Eliminate warnings on MSVC 2013
Note that this required ignoring a few warnings with pragmas, changing the
parameter type and return types of std::string::find functions to size_t
from int and a new global warning disable on MSVC.

I've managed to avoid global warning disables up to this point in the
code, but I don't see a way around the "decorated name too long (C4503)" warning.

Closes #100
2014-03-02 08:18:36 -07:00
Jason Turner
daf5480c48 Fix up the pthread usage on broken ubuntu gcc4.8.1
For more information:

http://stackoverflow.com/questions/19463602/compiling-multithread-code-with-g
2014-03-01 16:03:01 -07:00
Jason Turner
1f2c9b0c77 Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2014-03-01 14:13:39 -07:00
Jason Turner
a38d89cb41 Add fixes for parsing of inplace vectors with newlines
from jespada
2014-03-01 13:49:03 -07:00
Jason Turner
3d76e980cc Attempt to detect if g++ is old and we should use --c++0x 2014-03-01 07:42:32 -07:00
Jason Turner
cb42bffbf9 Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2014-02-26 10:51:36 -07:00
Jason Turner
b2b9efebe3 Add unit test to make sure heap allocation of chai works 2014-02-26 10:51:31 -07:00
Jason Turner
b97c5c13c1 Update to version 5.3.0
Merge branch 'master' into ChaiScript_5_0_CPP_11

Conflicts:
	CMakeLists.txt
	releasenotes.txt
2014-02-23 07:17:51 -07:00
Jason Turner
8c70fff02b Update version to 4.3.0 2014-02-23 07:10:03 -07:00
Jason Turner
9cf5064a3b Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
	src/reflection.cpp
2014-02-22 16:41:28 -07:00
Jason Turner
af44da916a Fix warnings and errors on VisualStudio 2013
Interestingly, VS2013 with Boost 1.55 exhibited the issues complained
about in issue #92, so I was able to provide an appropriate fix. It would
appear to be bugs in both compilers, which seems very odd.
2014-02-22 16:09:34 -07:00
Jason Turner
20b40d3970 Merge branch 'master' into ChaiScript_5_0_CPP_11 2014-02-22 14:44:38 -07:00
Jason Turner
1e0cd4f63a Merge remote-tracking branch 'origin' into ChaiScript_5_0_CPP_11 2014-02-22 14:44:25 -07:00
Jason Turner
04131d208b Fix type on range.chai 2014-02-22 14:44:07 -07:00
Jason Turner
9c35ede59a Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2014-02-18 13:02:28 -07:00
Jason Turner
8aedd80e1a Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2014-02-18 13:02:06 -07:00
Jason Turner
52bb08f4d5 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
	include/chaiscript/language/chaiscript_engine.hpp
	include/chaiscript/language/chaiscript_prelude.hpp
2014-02-17 16:31:16 -07:00
Jason Turner
71348b7967 Update copyrights to 2014 and some comment formatting 2014-02-17 16:24:29 -07:00
Jason Turner
3a6caeb1c5 Fix #98 for unavoidable C style returns in modules 2014-01-23 13:08:08 -07:00
Jason Turner
3f78af9a3d Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	src/main.cpp
2014-01-23 12:54:28 -07:00
Jason Turner
31a4900765 Merge pull request #99 from da2ce7/master
force no unicode in search parth windows
2014-01-23 18:11:00 -08:00
Jason Turner
eb1a1c0275 Port windows unicode fix from @da2ce7 to 4.x branch 2014-01-23 12:28:33 -07:00
Jason Turner
8724e0cb80 Fix build error on 4.x branch if readline is found 2014-01-23 12:17:06 -07:00
Cameron Garnham
a195fac4ca force no unicode in search parth windows 2014-01-17 14:36:36 -08:00
Jason Turner
2a2a469a1b Merge pull request #96 from kanzure/fix-readline-build
Make main.cpp compile when readline is available
2014-01-16 12:05:35 -08:00
Bryan Bishop
ac21c8b063 fix building main.cpp when readline is available
This changes around the pragma conditionals to make sure that certain
symbols (such as "default_search_path") are defined even if the system
has readline available during builds.
2014-01-07 17:35:58 -06:00
Jason Turner
5272a64be9 Fix (legit) warning in VisualStudio 2014-01-05 16:27:32 -07:00
Jason Turner
3b1213a2b0 Merge branch 'master' into ChaiScript_5_0_CPP_11
Fix for issue #94

Conflicts:
	src/main.cpp
2014-01-05 15:12:54 -07:00
Jason Turner
b872a50acc Add module search path relative to current exe #94 2014-01-05 14:59:31 -07:00
Jason Turner
c6a1d1ea75 Merge branch 'master' into ChaiScript_5_0_CPP_11 2014-01-05 12:23:30 -07:00
Jason Turner
36466a4ac5 Add unit tests for string size() fixes #93 #95 2014-01-05 12:22:44 -07:00
Jason Turner
e667b4df5f Fix missing empty, clear and size methods for strings
Fixes bugs #95 and #93
2014-01-05 11:52:59 -07:00
Jason Turner
7cebc8d748 Make map::count() properly const. #90 2013-11-27 09:36:50 -07:00
Jason Turner
189ae82cb7 Merge branch 'master' into ChaiScript_5_0_CPP_11 2013-11-27 09:29:28 -07:00
Jason Turner
bf83969723 Add unit test for calling 'count' on const map object. #90 2013-11-27 09:28:23 -07:00
Jason Turner
5cb78ecd68 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
	include/chaiscript/dispatchkit/boxed_number.hpp
2013-11-27 09:18:08 -07:00
Jason Turner
41f6ca18ea Prevent the user from naming an object with "::" #91 2013-11-27 08:53:34 -07:00
Jason Turner
a26d628e5c Cleanup (indentation, comments) for non-const global support
@Zoomulator - I pulled in your non-const global commits.
2013-11-27 08:19:26 -07:00
Jason Turner
d5fef3121a Merge remote-tracking branch 'zoomulator/master'
Adding zoomulator's patches for allowing of non-const globals if the user
wants to.
2013-11-27 08:06:39 -07:00
Jason Turner
16f09794cf Fixes #88: Linking error on MacOS Mavericks
The c++ library implementation on MacOS is broken, it does not allow you to
correctly use points to members of std::string. We work around this by not
directly using member pointers and instead wrapping the method calls
with our own functions.
2013-11-27 08:00:23 -07:00
Jason Turner
26722d648d Merge pull request #87 from bmario/ChaiScript_5_0_CPP_11
Fixes build issue for Boxed_Value
2013-11-26 16:12:57 -08:00
Jason Turner
95e3093df3 Update -std=c++0x to -std=c++11 2013-11-02 10:55:36 -06:00
Jason Turner
510d550d64 Fix static analysis issue 2013-11-02 08:18:09 -06:00
Jason Turner
73b3762f7a Get ChaiScript ported to MSVC 2013. See Notes in code. 2013-11-02 07:42:06 -06:00
Jason Turner
d44de49fb1 Add explicit tests for accessing data members of const objects 2013-09-27 20:19:16 -06:00
Mario Bielert
21e3d1cc0a Fixes build issue for Boxed_Value
This ixes the problem, that one has to include chaiscript.hpp to build
compilation units, which only use Boxed_Value and boxed_cast.
You can now just include boxed_cast.hpp. This decreases build time
significant.
2013-07-22 21:24:16 +02:00
Jason Turner
1708024372 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/chaiscript_threading.hpp
	include/chaiscript/dispatchkit/boxed_value.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
	samples/example.cpp
	src/test_module.cpp
	unittests/multithreaded_test.cpp
2013-05-27 08:48:59 -06:00
Jason Turner
101225aa68 - Fix legit threading issue which shows itself on clang / macos mostly
- Fix all warnings that I can / ignore those caused by boost
2013-05-26 22:47:23 -06:00
Jason Turner
6e71409a52 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2013-04-25 16:17:51 -06:00
Jason Turner
feb344e744 Fix various warnings found by MSVC 2013-04-25 15:39:03 -06:00
Jason Turner
494a67c9a0 Fix linking for C++11 builds on macos 2013-04-25 15:04:44 -06:00
Jason Turner
1a48dd9480 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/dynamic_object.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2013-04-25 12:42:00 -06:00
Jason Turner
12d842ca5a Fix some additional warnings on MacOS 2013-04-25 12:21:41 -06:00
Jason Turner
9ac58a942e Fix clang identification 2013-04-25 10:32:40 -06:00
Jason Turner
d0ce78061c Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
	include/chaiscript/dispatchkit/function_call.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2013-04-25 09:40:22 -06:00
Jason Turner
e68599920a Move to pointers for Dynamic_Cast_Conversions to avoid problems with using the class before it's defined 2013-04-25 09:15:09 -06:00
Jason Turner
58a8854009 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	CMakeLists.txt
2013-03-28 22:00:41 -06:00
Jason Turner
1e1385bc52 Do not link dl if on FreeBSD 2013-03-28 21:59:36 -06:00
Jason Turner
ae1221d46d Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2013-03-28 21:18:44 -06:00
Jason Turner
9d59098015 Merge branch 'ChaiScript_5_0_CPP_11' of https://github.com/ChaiScript/ChaiScript into ChaiScript_5_0_CPP_11 2013-03-28 21:07:19 -06:00
Jason
6fea178f5d Merge branch 'master' into ChaiScript_5_0_CPP_11 2013-03-28 21:02:22 -06:00
Jason Turner
81edebc074 Merge pull request #81 from windoze/ChaiScript_5_0_CPP_11
C++11 needs constexpr constructor when object used in constexpr expression
2013-03-28 19:28:32 -07:00
Jason Turner
4fc51dfe05 Merge pull request #82 from mgee/master
Fix pretty_print for inline arrays.
2013-03-28 19:25:50 -07:00
Markus Groß
241ca75204 Correct pretty_print for inline arrays. 2013-02-28 17:39:30 +01:00
Windoze
88f7bffc4f FreeBSD hasn't libdl, functions included in libc 2013-02-27 14:01:09 +08:00
Windoze
1f1656a6c2 C++11 needs constexpr constructor when object used in constexpr expression 2013-02-27 13:33:27 +08:00
Jason Turner
47e44d2f9e Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/boxed_cast_helper.hpp
	include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
	include/chaiscript/dispatchkit/dynamic_object.hpp
	include/chaiscript/dispatchkit/exception_specification.hpp
	include/chaiscript/dispatchkit/function_call.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
	include/chaiscript/language/chaiscript_engine.hpp
	include/chaiscript/language/chaiscript_eval.hpp
2013-02-25 12:08:32 -07:00
Jason Turner
2afc09dad4 Eradicate global base_class registrations to prevent problems with threading and general memory management issues with knowing how and when to clean them up. 2013-02-25 11:00:14 -07:00
Jason Turner
95b69b7572 Merge branch 'master' into ChaiScript_5_0_CPP_11 2013-02-24 15:19:16 -07:00
Jason Turner
1858885010 Add example of wrapping data members of a class #79 2013-02-24 15:11:06 -07:00
Jason Turner
f338066298 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
2013-02-24 14:30:41 -07:00
Jason Turner
d068ce472c Clean up constuctors for AST_Node types 2013-02-24 13:55:20 -07:00
Jason Turner
380b94a8d2 Clean up implementation of for and while loops to make them easier to read and reduce code copying 2013-02-24 09:01:26 -07:00
Jason Turner
dd79534de1 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_parser.hpp
2013-02-23 21:37:50 -07:00
Jason Turner
fd72b2951a Correct broken unit test for vector of suffixed numbers 2013-02-23 21:27:01 -07:00
Jason Turner
48f538438d Get all for loop related unit tests passing and expand the types of expressions
that can exist in a for loop
2013-02-23 21:14:37 -07:00
Jason Turner
c9995480e6 Add 'continue' command for loops. Also enhance for() unit tests which are now breaking and need to be fixed 2013-02-23 14:49:20 -07:00
Jason Turner
e298333ac6 Add unit test of suffixed number inside of vector initialization 2013-02-23 08:53:25 -07:00
Jason Turner
d225e09d5d Add profile for calling functions on members of a heterogeneous array 2013-02-23 08:49:31 -07:00
Jason Turner
e4f4b64cc8 Update to 5.2.0
Merge branch 'master' into ChaiScript_5_0_CPP_11

Conflicts:
	CMakeLists.txt
	releasenotes.txt
2012-11-30 20:40:39 -07:00
Jason Turner
59df213e66 Update version to 4.2.0 2012-11-30 20:38:17 -07:00
Jason Turner
691e002f90 Update to support building with MinGW #78
We cannot call MinGW a fully supported platform for C++11 yet:

 - Concurrency is not yet supported by MinGW, so it is disabled by default
 - A problem in the memory model / library loader is preventing derived type
   casts from working. This may be able to be worked around, but has not been
   yet.
2012-11-28 16:06:45 -07:00
Jason Turner
47ab27fd11 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/proxy_functions.hpp
	releasenotes.txt
2012-11-27 21:42:21 -07:00
Jason Turner
0ea8931b21 Add ability to call functions requiring arithmetic value conversions
- Conversions are only attempted on a dispatch
 - Conversions are only attempted after a normal dispatch has failed
 - Conversions are only attempted if exactly one function matches
   the signature of the parameters passed in - excluding the mismatched
   arithmetic parameters
 - This feature should not be relied on in performance critical code
   overhead is added for each function call that requires a conversion
   to execute, see the tests performed above.
2012-11-27 21:21:37 -07:00
Jason Turner
f24d376fa5 Update for release 4.1.1 2012-11-17 20:48:25 -07:00
Jason Turner
4754462048 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
2012-11-17 20:41:45 -07:00
Jason Turner
7917ea02dc Fix linux build error discovered with 4.0.0 release 2012-11-17 20:30:53 -07:00
Jason Turner
455324bf13 Merge branch 'master' into ChaiScript_5_0_CPP_11 / update version numbers
Conflicts:
	CMakeLists.txt
	releasenotes.txt
2012-11-17 18:33:13 -07:00
Jason Turner
85ba42849b Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
	include/chaiscript/language/chaiscript_parser.hpp
	unittests/multithreaded_test.cpp
2012-11-16 16:32:39 -07:00
Jason Turner
6bb90f9d6d Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
2012-11-10 16:59:32 -07:00
Jason Turner
57c6d72a79 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bind_first.hpp
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2012-11-07 17:04:54 -07:00
Jason Turner
c5a86401aa Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
2012-11-07 13:47:09 -07:00
Kim Simmons
abcc6c9e3e Chai::add_global was added
Just a modification of the add_global_const. I don't see the point in
limiting the user to binding only constants to the global scope if the user
wishes to have a thread safe mutable object as a global. This was my case
anyway.
2012-11-06 17:20:56 +01:00
Jason Turner
87c9006174 Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	CMakeLists.txt
	readme.md
2012-08-14 12:07:45 -06:00
Jason Turner
d47cd63fec One more round of updates to readme.md 2012-08-14 11:45:00 -06:00
Jason Turner
193151f52e Minor syntax updates for C++11 readme.md 2012-08-14 11:43:11 -06:00
Jason Turner
6642e02496 Update readme for C++11 2012-08-14 11:37:58 -06:00
Jason Turner
d84b4c0b37 Merge branch 'master' into ChaiScript_5_0_CPP_11 2012-07-18 07:30:34 -06:00
Jason Turner
84e17b8d06 Port Boxed_Number enhancements from mgee to C++11 branch. #53 2012-07-16 22:24:25 -06:00
Jason Turner
32fab64882 Merge branch 'master' into 2011-09-09-CxScript 2012-07-16 22:17:37 -06:00
Jason Turner
8cb49e9494 Merge branch 'master' into 2011-09-09-CxScript 2012-07-16 22:12:29 -06:00
Jason Turner
7052234650 Revert "Use unique_ptr instead of shared_ptr in our any implementation, >10% speed improvement"
This reverts commit f27739cf71.
2012-07-13 13:54:48 -06:00
Jason Turner
c2934caad6 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
	src/multithreaded.cpp
2012-07-13 13:32:29 -06:00
Jason Turner
199b1f5233 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/boxed_value.hpp
2012-07-13 12:36:08 -06:00
Jason Turner
f27739cf71 Use unique_ptr instead of shared_ptr in our any implementation, >10% speed improvement 2012-07-09 16:20:55 -06:00
Jason Turner
a6924bcc9e Use C++11 Raw Strings for chaiscript prelude 2012-06-28 21:24:51 -06:00
Jason Turner
a3b50d4151 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
2012-06-25 16:50:21 -06:00
Jason Turner
d3b8daeff0 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	CMakeLists.txt
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_engine.hpp
	include/chaiscript/language/chaiscript_eval.hpp
2012-06-25 15:40:19 -06:00
Jason Turner
6cda1140c4 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/language/chaiscript_common.hpp
	include/chaiscript/language/chaiscript_eval.hpp
	include/chaiscript/language/chaiscript_parser.hpp
2012-06-22 18:12:51 -06:00
Jason Turner
949f54b9c4 Use constexpr where possible in user_type() functions
- Task #52
 - Gives some performance improvement
2012-06-22 14:19:52 -06:00
Jason Turner
f6e53dd42d Correct some threading issues
- prototype avoiding a lock with __thread in g++
 - pass -pthread and -lpthread when building to get threading actually working
2012-06-22 14:18:44 -06:00
Jason Turner
d55439a7ac Fix multithreaded.cpp to compile / run with C++11 2012-06-19 09:40:51 -06:00
Jason Turner
953c4e4847 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	CMakeLists.txt
2012-06-13 21:54:48 -06:00
Jason Turner
a67022e31e Prep for 5.0.0 release 2012-06-07 20:04:14 -06:00
Jason Turner
a951d2b0af Fix crash discovered by the move to using stdlib for all tests. 2012-06-04 07:32:05 -06:00
Jason Turner
b7e1cf41e5 Move to using the new constructor that searched for the stdlib
to improve compile time.
2012-06-04 07:31:20 -06:00
Jason Turner
30104cc3ed Add missing file 2012-06-03 18:50:51 -06:00
Jason Turner
5a380abc68 Merge branch 'master' into 2011-09-09-CxScript
Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/dispatchkit.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
	src/multithreaded.cpp
2012-06-03 09:27:05 -06:00
Jason Turner
4ebfe264e9 Make stdlib
* Build the standard library as a module .so
 * Locate and load lib at runtime as a module
   if it is not provided to the ChaiScript
   constructor.

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

30
.decent_ci-Linux.yaml Normal file
View File

@@ -0,0 +1,30 @@
compilers:
- name: "clang"
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "clang"
build_tag: "LibC++"
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "clang"
build_tag: AddressSanitizer
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
- name: "clang"
build_tag: ThreadSanitizer
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
- name: "gcc"
version: "4.8"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "gcc"
version: "4.6"
skip_packaging: true
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: cppcheck
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:cmake*" --suppress="*:unittests/catch.hpp" --force

9
.decent_ci-MacOS.yaml Normal file
View File

@@ -0,0 +1,9 @@
compilers:
- name: clang
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
build_package_generator: TBZ2
- name: clang
build_type: Debug
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
skip_packaging: true

20
.decent_ci-Windows.yaml Normal file
View File

@@ -0,0 +1,20 @@
compilers:
- name: Visual Studio
version: 14
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true
- name: Visual Studio
version: 14
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true
- name: Visual Studio
version: 12
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 12
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%

4
.decent_ci.yaml Normal file
View File

@@ -0,0 +1,4 @@
results_repository : ChaiScript/ChaiScript-BuildResults
results_path : _posts
results_base_url : https://chaiscript.github.io/ChaiScript-BuildResults
aging_pull_requests_notification: true

39
.travis.yml Normal file
View File

@@ -0,0 +1,39 @@
language: cpp
compiler:
- gcc
env:
- GCC_VER=4.6
- GCC_VER=4.8
before_install:
- sudo pip install cpp-coveralls
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update
- sudo apt-get install -qq g++-4.8
- if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; else export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi
script:
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug .
- make -j2
- make test
- mkdir gcov
- find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \;
- $GCOV -d -o gcov gcov/*.gcda
- coveralls -n -E ".*\.cpp"
after_script:
- contrib/codeanalysis/runcppcheck.sh
notifications:
email:
recipients:
- jason@emptycrate.com
on_success: always
on_failure: always
webhooks:
urls:
- https://webhooks.gitter.im/e/4be9a2720eaa1bb2a6c9
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
env:
global:
secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=

View File

@@ -1,10 +1,86 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW)
endif()
IF(BIICODE)
INIT_BIICODE_BLOCK()
ADD_BIICODE_TARGETS()
ELSE()
# Your regular CMakeLists configuration here
project(chaiscript) project(chaiscript)
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE) option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE)
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE) option(BUILD_SAMPLES "Build Samples Folder" FALSE)
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
mark_as_advanced(USE_STD_MAKE_SHARED)
if(USE_STD_MAKE_SHARED)
add_definitions(-DCHAISCRIPT_USE_STD_MAKE_SHARED)
endif()
if(CMAKE_COMPILER_IS_GNUCC)
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
if(ENABLE_COVERAGE)
add_definitions(--coverage -O0)
set(LINKER_FLAGS "${LINKER_FLAGS} --coverage")
endif()
endif()
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
option(ENABLE_THREAD_SANITIZER "Enable thread sanitizer testing in gcc/clang" FALSE)
if(ENABLE_THREAD_SANITIZER)
add_definitions(-fsanitize=thread -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=thread")
endif()
option(ENABLE_ADDRESS_SANITIZER "Enable address sanitizer testing in gcc/clang" FALSE)
if(ENABLE_ADDRESS_SANITIZER)
add_definitions(-fsanitize=address -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
endif()
option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE)
if(ENABLE_MEMORY_SANITIZER)
add_definitions(-fsanitize=memory -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=memory")
endif()
option(ENABLE_UNDEFINED_SANITIZER "Enable undefined behavior sanitizer testing in gcc/clang" FALSE)
if(ENABLE_UNDEFINED_SANITIZER)
add_definitions(-fsanitize=undefined -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined")
endif()
option(ENABLE_LTO "Enable Link Time Optimization" FALSE)
if (ENABLE_LTO)
add_definitions(-flto)
set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
endif()
option(PROFILE_GENERATE "Generate profile data" FALSE)
if (PROFILE_GENERATE)
add_definitions(-fprofile-generate)
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-generate")
endif()
option(PROFILE_USE "Use profile data" FALSE)
if (PROFILE_USE)
add_definitions(-fprofile-use)
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-use")
endif()
endif()
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}") list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn") list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn")
@@ -16,21 +92,20 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md") 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_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 4) set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 1) set(CPACK_PACKAGE_VERSION_MINOR 7)
set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com") set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com") set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An embedded scripting language for C++") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An embedded scripting language for C++")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-dev (>=1.36.0)")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel") set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_RPM_PACKAGE_LICENSE "BSD") set(CPACK_RPM_PACKAGE_LICENSE "BSD")
set(CPACK_RPM_PACKAGE_GROUP "Programming") set(CPACK_RPM_PACKAGE_GROUP "Programming")
set(CPACK_RPM_PACKAGE_REQUIRES "boost-devel >= 1.36.0, boost-thread >= 1.36.0")
set(CHAI_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}) set(CHAI_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
@@ -39,111 +114,211 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest) include(CTest)
include(CPack) include(CPack)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib) include(cmake/CheckCXX11Features.cmake)
if(NOT MINGW)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
endif()
if(HAS_CXX11_VARIADIC_TEMPLATES)
message(STATUS "Variadic Template support detected")
else()
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
endif()
enable_testing() enable_testing()
message(STATUS "Detecting readline support") message(STATUS "Detecting readline support")
if (READLINE_LIBRARY) if(READLINE_LIBRARY)
message(STATUS "Found: ${READLINE_LIBRARY}") message(STATUS "Found: ${READLINE_LIBRARY}")
set (READLINE_LIB readline) set(READLINE_LIB readline)
add_definitions(/DREADLINE_AVAILABLE) add_definitions(/DREADLINE_AVAILABLE)
else(READLINE_LIBRARY) else()
message(STATUS "Not Found") message(STATUS "Not Found")
set (READLINE_LIB ) set(READLINE_LIB)
set (READLINE_FLAG ) set(READLINE_FLAG)
endif(READLINE_LIBRARY) endif()
if(CMAKE_COMPILER_IS_GNUCC)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_LESS 4.8)
set(CPP11_FLAG "-std=c++0x")
else()
set(CPP11_FLAG "-std=c++11")
endif()
else()
set(CPP11_FLAG "-std=c++11")
endif()
if(MSVC) if(MSVC)
add_definitions(/W4) add_definitions(/W4)
if(CMAKE_CL_64)
add_definitions(/bigobj)
endif()
else()
add_definitions(-Wall -Wextra -Wshadow -pedantic)
if (APPLE) # VS2013 doesn't have magic statics
# -Wno-missing-field-initializers is for boost on macos if (MSVC_VERSION STREQUAL "1800")
add_definitions(-Wno-missing-field-initializers -Wno-sign-compare) add_definitions(/w44640)
endif() endif()
add_definitions(/bigobj)
# Note on MSVC compiler flags.
# The code base selective disables warnings as necessary when the compiler is complaining too much
# about something that is perfectly valid, or there is simply no technical way around it
# This particular warning, C4503 is in regards to the decorated names that MSVC generates internally.
# The error did not come up until the move to C++11, but the compiler doesn't give enough information
# to determine where the error is coming from, and the internet provides no real information for
# how to workaround or fix the error. So I'm disabling it globally.
add_definitions(/wd4503)
else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -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)
else()
add_definitions(-Wnoexcept)
endif()
if(APPLE)
add_definitions(-Wno-sign-compare)
endif()
endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
option(USE_LIBCXX "Use clang's libcxx" TRUE)
if(USE_LIBCXX)
add_definitions(-stdlib=libc++)
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG} -stdlib=libc++")
else()
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC)
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
endif()
# limitations in MinGW require us to make an optimized build
# for the sake of object sizes or something
if(MINGW OR CYGWIN)
add_definitions(-O3)
endif() endif()
include_directories(include) include_directories(include)
set(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
set(Boost_USE_MULTITHREADED ON)
set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp) set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
if (MULTITHREAD_SUPPORT_ENABLED) if(NOT MULTITHREAD_SUPPORT_ENABLED)
find_package(Boost 1.36.0 COMPONENTS thread system)
if (Boost_FOUND)
link_directories( ${Boost_LIBRARY_DIRS} )
else()
message(FATAL_ERROR "Can not find Boost")
endif(Boost_FOUND)
if (CMAKE_HOST_UNIX)
add_definitions(-pthread)
list(APPEND LIBS "pthread")
endif()
else()
add_definitions(-DCHAISCRIPT_NO_THREADS) add_definitions(-DCHAISCRIPT_NO_THREADS)
endif() endif()
if (CMAKE_HOST_UNIX) if(CMAKE_HOST_UNIX)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
list(APPEND LIBS "dl") list(APPEND LIBS "dl")
endif(CMAKE_HOST_UNIX) endif()
if(MULTITHREAD_SUPPORT_ENABLED)
if(CMAKE_COMPILER_IS_GNUCC)
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE GCC_FULL_VERSION)
if(GCC_FULL_VERSION MATCHES "4.8.1.*ubuntu")
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--no-as-needed -pthread")
else()
set(LINKER_FLAGS "${LINKER_FLAGS} -pthread")
endif()
else()
set(LINKER_FLAGS "${LINKER_FLAGS} -pthread")
endif()
add_definitions(-pthread)
endif()
endif()
list(APPEND LIBS ${READLINE_LIB}) list(APPEND LIBS ${READLINE_LIB})
if (NOT MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
# Boost on MSVC does automatic linking set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
list(APPEND LIBS ${Boost_LIBRARIES}) set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
endif()
if (CMAKE_COMPILER_2005)
# vs2005 is a bit too loud about possible loss of data warnings
# ADD_DEFINITIONS(/wd4244)
endif()
include_directories(${Boost_INCLUDE_DIRS}) add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib.cpp)
include_directories(${Boost_INCLUDE_DIR}) target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
add_executable(chai src/main.cpp ${Chai_INCLUDES}) add_executable(chai src/main.cpp ${Chai_INCLUDES})
target_link_libraries(chai ${LIBS}) target_link_libraries(chai ${LIBS})
add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
if (BUILD_SAMPLES) if(BUILD_SAMPLES)
add_executable(example samples/example.cpp) add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS}) target_link_libraries(example ${LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp) add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS}) target_link_libraries(memory_leak_test ${LIBS})
add_executable(inheritance samples/inheritance.cpp)
target_link_libraries(inheritance ${LIBS})
add_executable(fun_call_performance samples/fun_call_performance.cpp)
target_link_libraries(fun_call_performance ${LIBS})
endif() endif()
if (BUILD_MODULES) if(BUILD_MODULES)
add_library(stl_extra MODULE src/stl_extra.cpp) add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS}) target_link_libraries(stl_extra ${LIBS})
add_library(reflection MODULE src/reflection.cpp) set(MODULES stl_extra)
target_link_libraries(reflection ${LIBS})
set(MODULES stl_extra reflection)
endif() endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai) file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
list(SORT UNIT_TESTS) list(SORT UNIT_TESTS)
if(BUILD_TESTING) if(BUILD_TESTING)
# Add catch tests macro
macro(ADD_CATCH_TESTS executable)
if (MSVC)
file(TO_NATIVE_PATH "${QT_LIBRARY_DIR}" QT_LIB_PATH)
set(NEWPATH "${QT_LIB_PATH};$ENV{PATH}")
else()
set(NEWPATH $ENV{PATH})
endif()
get_target_property(target_files ${executable} SOURCES)
foreach(source ${target_files})
if(NOT "${source}" MATCHES "/moc_.*cxx")
string(REGEX MATCH .*cpp source "${source}")
if(source)
file(READ "${source}" contents)
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}")
endforeach()
endif()
endif()
endforeach()
endmacro()
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE) option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
add_test(version_check chai -c "if(\"\\\${ version() };\\\${version_major()};\\\${version_minor()};\\\${version_patch()}\" != \"${CHAI_VERSION};${CPACK_PACKAGE_VERSION_MAJOR};${CPACK_PACKAGE_VERSION_MINOR};${CPACK_PACKAGE_VERSION_PATCH}\") { exit(-1) }")
set_property(TEST version_check
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
foreach(filename ${UNIT_TESTS}) foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}") message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename}) add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach(filename) endforeach()
set_property(TEST ${UNIT_TESTS} set_property(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT PROPERTY ENVIRONMENT
@@ -151,59 +326,20 @@ if(BUILD_TESTING)
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
) )
if (NOT UNIT_TEST_LIGHT) if(NOT UNIT_TEST_LIGHT)
add_executable(utility_test unittests/utility_test.cpp) add_executable(compiled_tests unittests/compiled_tests.cpp)
target_link_libraries(utility_test ${LIBS}) target_link_libraries(compiled_tests ${LIBS})
add_test(NAME Utility_Test COMMAND utility_test) ADD_CATCH_TESTS(compiled_tests)
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
target_link_libraries(dynamic_object_test ${LIBS})
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
target_link_libraries(functor_creation_test ${LIBS})
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
target_link_libraries(functor_cast_test ${LIBS})
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp) add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
target_link_libraries(boxed_cast_test ${LIBS}) target_link_libraries(boxed_cast_test ${LIBS})
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test) add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
target_link_libraries(object_lifetime_test ${LIBS})
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
target_link_libraries(function_ordering_test ${LIBS})
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
add_executable(type_info_test unittests/type_info_test.cpp) add_executable(type_info_test unittests/type_info_test.cpp)
target_link_libraries(type_info_test ${LIBS}) target_link_libraries(type_info_test ${LIBS})
add_test(NAME Type_Info_Test COMMAND type_info_test) add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
target_link_libraries(eval_catch_exception_test ${LIBS})
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
target_link_libraries(short_comparison_test ${LIBS})
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
target_link_libraries(expected_eval_errors_test ${LIBS})
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
add_executable(set_state_test unittests/set_state_test.cpp)
target_link_libraries(set_state_test ${LIBS})
add_test(NAME Set_State_Test COMMAND set_state_test)
add_executable(simultaneous_chaiscript_test unittests/simultaneous_chaiscript_test.cpp)
target_link_libraries(simultaneous_chaiscript_test ${LIBS})
add_test(NAME Simultaneous_Chaiscript_Test COMMAND simultaneous_chaiscript_test)
add_executable(c_linkage_test unittests/c_linkage_test.cpp) add_executable(c_linkage_test unittests/c_linkage_test.cpp)
target_link_libraries(c_linkage_test ${LIBS}) target_link_libraries(c_linkage_test ${LIBS})
add_test(NAME C_Linkage_Test COMMAND c_linkage_test) add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
@@ -212,7 +348,7 @@ if(BUILD_TESTING)
target_link_libraries(integer_literal_test ${LIBS}) target_link_libraries(integer_literal_test ${LIBS})
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test) add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
if (MULTITHREAD_SUPPORT_ENABLED) if(MULTITHREAD_SUPPORT_ENABLED)
add_executable(multithreaded_test unittests/multithreaded_test.cpp) add_executable(multithreaded_test unittests/multithreaded_test.cpp)
target_link_libraries(multithreaded_test ${LIBS}) target_link_libraries(multithreaded_test ${LIBS})
add_test(NAME Multithreaded_Test COMMAND multithreaded_test) add_test(NAME Multithreaded_Test COMMAND multithreaded_test)
@@ -225,8 +361,11 @@ if(BUILD_TESTING)
endif() endif()
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp add_executable(multifile_test
unittests/multifile_test_module.cpp) unittests/multifile_test_main.cpp
unittests/multifile_test_chai.cpp
unittests/multifile_test_module.cpp
)
target_link_libraries(multifile_test ${LIBS}) target_link_libraries(multifile_test ${LIBS})
add_test(NAME MultiFile_Test COMMAND multifile_test) add_test(NAME MultiFile_Test COMMAND multifile_test)
@@ -235,9 +374,10 @@ if(BUILD_TESTING)
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript) install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
endif() endif()
endif(BUILD_TESTING) endif()
install(TARGETS chai chaiscript_stdlib-${CHAI_VERSION} ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
install(DIRECTORY include/chaiscript DESTINATION include install(DIRECTORY include/chaiscript DESTINATION include
PATTERN "*.hpp" PATTERN "*.hpp"
PATTERN "*/.svn*" EXCLUDE PATTERN "*/.svn*" EXCLUDE
@@ -259,3 +399,6 @@ configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @O
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc" install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
DESTINATION lib/pkgconfig) DESTINATION lib/pkgconfig)
ENDIF()

File diff suppressed because it is too large Load Diff

29
LICENSE Normal file
View File

@@ -0,0 +1,29 @@
Copyright 2009-2015 Jason Turner
Copyright 2009-2012 Jonathan Turner.
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Jason Turner nor Jonathan Turner nor the
name of contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

5
biicode.conf Normal file
View File

@@ -0,0 +1,5 @@
[paths]
include
[parent]
ChaiScript/ChaiScript: 0

334
cheatsheet.md Normal file
View File

@@ -0,0 +1,334 @@
# Initializing ChaiScript
```
chaiscript::ChaiScript chai; // loads stdlib from loadable module on file system
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdlib
```
# Adding Things To The Engine
## Adding a Function / Method / Member
### General
```
chai.add(chaiscript::fun(&function_name), "function_name");
chai.add(chaiscript::fun(&Class::method_name), "method_name");
chai.add(chaiscript::fun(&Class::member_name), "member_name");
```
### With Overloads
#### Preferred
```
chai.add(chaiscript::fun<ReturnType (ParamType1, ParamType2)>(&function_with_overloads), "function_name");
```
#### Alternative
```
chai.add(chaiscript::fun(std::static_cast<ReturnType (*)(ParamType1, ParamType2)>(&function_with_overloads)), "function_name");
```
### Lambda
```
chai.add(
chaiscript::fun<std::string (bool)>(
[](bool type) {
if (type) { return "x"; }
else { return "y"; }
}), "function_name");
```
### Constructors
```
chai.add(chaiscript::constructor<MyType ()>(), "MyType");
chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
```
## Adding Types
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");
```
## Adding Objects
```
chai.add(chaiscript::var(somevar), "somevar"); // copied in
chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared between C++ and chai
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
```
# Executing Script
## General
```
chai.eval("print(\"Hello World\")");
chai.eval(R"(print("Hello World"))");
```
## Unboxing Return Values
### Prefered
```
chai.eval<double>("5.3 + 2.1"); // returns 7.4 as a C++ double
```
### Alternative
```
auto v = chai.eval("5.3 + 2.1");
chai.boxed_cast<double>(v); // extracts double value from boxed_value and applies known conversions
chaiscript::boxed_cast<double>(v); // free function version, does not know about conversions
```
### Converting Between Algebraic Types
```
chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with any number type
// which is equivalent to, but much more automatic than:
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
```
## Sharing Values
```
double &d = chai.eval("var i = 5.2; i"); // d is now a reference to i in the script
std::shared_ptr<double> d = chai.eval("var i = 5.2; i"); // same result but reference counted
d = 3;
chai.eval("print(i)"); // prints 3
```
## Catching Eval Errors
```
try {
chai.eval("2.3 + \"String\"");
} catch (const chaiscript::exception::eval_error &e) {
std::cout << "Error\n" << e.pretty_print() << '\n';
}
```
## Catching Errors Thrown From Script
```
try {
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
} catch (const double e) {
} catch (int) {
} catch (float) {
} catch (const std::string &) {
} catch (const std::exception &e) {
// This is the one what will be called in the specific throw() above
}
```
## Sharing Functions
```
auto p = chai.eval<std::function<std::string (double)>>("to_string");
p(5); // calls chaiscript's 'to_string' function, returning std::string("5")
```
Note: backtick treats operators as normal functions
```
auto p = chai.eval<std::function<int (int, int)>>(`+`);
p(5, 6); // calls chaiscript's '+' function, returning 11
```
```
auto p = chai.eval<std::function<std::string (int, double)>>(fun(x,y) { to_string(x) + to_string(y); });
p(3,4.2); // evaluates the lambda function, returning the string "34.2" to C++
```
# Language Reference
## Variables
```
var i; // uninitialized variable, can take any value on first assignment;
auto j; // equiv to var
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 g2;
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once
```
## Built in Types
```
var v = [1,2,3u,4ll,"16", `+`]; // creates vector of heterogenous values
var m = ["a":1, "b":2]; // map of string:value pairs
```
Floating point values default to `double` type and integers default to `int` type. All C++ suffixes
such as `f`, `ll`, `u` as well as scientific notion is supported
```
1.0 // double
1.0f // float
1.0l // long double
1 // int
1u // unsigned int
1ul // unsigned long
1ull // unsigned long long
```
Literals are automatically sized, just as in C++. For example: `10000000000` is > 32bits and the appropriate type is used to hold it
on your platform.
## Functions
### General
```
def myfun(x, y) { x + y; } // last statement in body is the return value
def myfun(x, y) { return x + y; } // equiv
```
### Optionally Typed
```
def myfun(x, int y) { x + y; } // requires y to be an int
```
### With Guards
```
def myfun(x, int y) : y > 5 { x - y; } // only called if y > 5
```
### Methods
Methods and functions are mostly equivalent
```
def string::add(int y) { this + to_string(y); }
def add(string s, int y) { s + to_string(y); } //equiv functionality
// calling new function/method
"a".add(1); // returns a1
add("a", 1); // returns a1, either calling syntax works with either def above
```
### Lambdas
```
var l = fun(x) { x * 15; }
l(2) // returns 30
var a = 13
var m = fun[a](x) { x * a; }
m(3); // a was captured (by reference), returns 39
var n = bind(fun(x,y) { x * y; }, _, 10);
n(2); // returns 20
```
## ChaiScript Defined Types
Define a type called "MyType" with one member value "a" and a getter
### Preferred
```
class MyType {
var value;
def MyType() { this.value = "a"; }
def get_value() { "Value Is: " + this.value; }
};
```
### Alternative
```
attr MyType::value;
def MyType::MyType() { this.value = "a"; }
def MyType::get_value() { "Value Is: " + this.value; }
```
### Using
```
var m = MyType(); // calls constructor
print(m.get_value()); // prints "Value Is: a"
print(get_value(m)); // prints "Value Is: a"
```
## Dynamic Objects
All ChaiScript defined types and generic Dynamic_Object support dynamic parameters
```
var o = Dynamic_Object();
o.f = fun(x) { print(x); }
o.f(3); // prints "3"
```
Implicit 'this' is allowed:
```
var o = Dynamic_Object();
o.x = 3;
o.f = fun(y) { print(this.x + y); }
o.f(10); // prints 13
```
## method_missing
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate
method cannot be found
```
def method_missing(int i, string name, Vector v) {
print("method_missing(${i}, ${name}), ${v.size()} params");
}
5.bob(1,2,3); // prints "method_missing(5, bob, 3 params)"
```
`method_missing` signature can be either 2 parameters or 3 parameters. If the signature contains two parameters
it is treated as a property. If the property contains a function then additional parameters are passed to
the contained function.
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
# Built In Functions
## Evaluation
```
eval("4 + 5") // dynamically eval script string and returns value of last statement
eval_file("filename") // evals file and returns value of last statement
use("filename") // evals file exactly once and returns value of last statement
// if the file had already been 'used' nothing happens and undefined is returned
```
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -22,4 +22,5 @@ def primes(n)
var N = 5000 var N = 5000
print("primes: " + primes(N).to_string()) print("primes: " + primes(N).to_string())

View File

@@ -0,0 +1,16 @@
#!/bin/bash
pushd ..
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
tar -xvf cppcheck-1.66.tar.bz2
cd cppcheck-1.66
CXX=g++-4.8 make -j2
popd
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
echo -n '{ "body": " ' > output.json
echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json
echo -n '"}' >> output.json
if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; else curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/issues/${TRAVIS_PULL_REQUEST}/comments; fi

View File

@@ -0,0 +1,22 @@
load_module("test_module")
auto t := TestBaseType();
// This uses the TestBaseType to Type2 user type
// conversion which was added in the module and then calls
// "get_val()" which exists on the Type2 type
//assert_equal(t.get_val(), 10);
//print("Made it past test 1");
var t2 := Type2(t);
//dump_system();
for (var i = 0; i < 50000; ++i) {
var str = string(get_str(t2));
size(get_str(t2));
t2.get_str().size();
t.get_str().size();
}

View File

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

View File

@@ -0,0 +1,93 @@
# [PackageDev] target_format: plist, ext: tmLanguage
---
comment: 'ChaiScript Syntax: version 2.0'
fileTypes: [chai]
firstLineMatch: ^#!/usr/bin/env node
foldingStartMarker: ^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$
foldingStopMarker: ^\s*\}
keyEquivalent: ^~J
name: ChaiScript
patterns:
- {comment: chaiscript shebang, match: ^#, name: comment.line.chai}
- {match: '\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b', name: constant.numeric.chai}
- begin: ''''
beginCaptures:
'0': {name: punctuation.definition.string.begin.chai}
end: ''''
endCaptures:
'0': {name: punctuation.definition.string.end.chai}
name: string.quoted.single.chai
patterns:
- {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai}
- begin: '"'
beginCaptures:
'0': {name: punctuation.definition.string.begin.chai}
end: '"'
endCaptures:
'0': {name: punctuation.definition.string.end.chai}
name: string.quoted.double.chai
patterns:
- {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai}
- begin: /\*\*(?!/)
captures:
'0': {name: punctuation.definition.comment.chai}
end: \*/
name: comment.block.documentation.chai
- begin: /\*
captures:
'0': {name: punctuation.definition.comment.chai}
end: \*/
name: comment.block.chai
- captures:
'1': {name: punctuation.definition.comment.chai}
match: (//).*$\n?
name: comment.line.double-slash.chai
- captures:
'0': {name: punctuation.definition.comment.html.chai}
'2': {name: punctuation.definition.comment.html.chai}
match: (<!--|-->)
name: comment.block.html.chai
- {match: \b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b,
name: storage.type.chai}
- {match: \b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b,
name: keyword.control.chai}
- {match: \b(delete|in|instanceof|new|typeof|with)\b, name: keyword.operator.chai}
- {match: \btrue\b, name: constant.language.boolean.true.chai}
- {match: \bfalse\b, name: constant.language.boolean.false.chai}
- {match: \bnull\b, name: constant.language.null.chai}
- {match: \b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b,
name: support.class.chai}
- {match: '\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()',
name: support.function.chai}
- {match: '\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()',
name: support.function.dom.chai}
- {match: '(?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b',
name: support.constant.chai}
- {match: '(?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b',
name: support.constant.dom.chai}
- {match: \b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b,
name: support.constant.dom.chai}
- {match: '\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b',
name: support.function.event-handler.chai}
- {match: '!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|void)\b',
name: keyword.operator.chai}
- {match: \b(Infinity|NaN|undefined)\b, name: constant.language.chai}
- begin: (?<=[=(:]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?])
beginCaptures:
'1': {name: punctuation.definition.string.begin.chai}
end: (/)[igm]*
endCaptures:
'1': {name: punctuation.definition.string.end.chai}
name: string.regexp.chai
patterns:
- {match: \\., name: constant.character.escape.chai}
- {match: \;, name: punctuation.terminator.statement.chai}
- {match: ',[ |\t]*', name: meta.delimiter.object.comma.chai}
- {match: \., name: meta.delimiter.method.period.chai}
- {match: '\{|\}', name: meta.brace.curly.chai}
- {match: \(|\), name: meta.brace.round.chai}
- {match: '\[|\]', name: meta.brace.square.chai}
scopeName: source.chai
uuid: 93E017CC-6F27-11D9-90EB-000D93589AF6
...

View File

@@ -0,0 +1,333 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>comment</key>
<string>ChaiScript Syntax: version 2.0</string>
<key>fileTypes</key>
<array>
<string>chai</string>
</array>
<key>firstLineMatch</key>
<string>^#!/usr/bin/env node</string>
<key>foldingStartMarker</key>
<string>^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$</string>
<key>foldingStopMarker</key>
<string>^\s*\}</string>
<key>keyEquivalent</key>
<string>^~J</string>
<key>name</key>
<string>ChaiScript</string>
<key>patterns</key>
<array>
<dict>
<key>comment</key>
<string>chaiscript shebang</string>
<key>match</key>
<string>^#</string>
<key>name</key>
<string>comment.line.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b</string>
<key>name</key>
<string>constant.numeric.chai</string>
</dict>
<dict>
<key>begin</key>
<string>'</string>
<key>beginCaptures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.string.begin.chai</string>
</dict>
</dict>
<key>end</key>
<string>'</string>
<key>endCaptures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.string.end.chai</string>
</dict>
</dict>
<key>name</key>
<string>string.quoted.single.chai</string>
<key>patterns</key>
<array>
<dict>
<key>match</key>
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
<key>name</key>
<string>constant.character.escape.chai</string>
</dict>
</array>
</dict>
<dict>
<key>begin</key>
<string>"</string>
<key>beginCaptures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.string.begin.chai</string>
</dict>
</dict>
<key>end</key>
<string>"</string>
<key>endCaptures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.string.end.chai</string>
</dict>
</dict>
<key>name</key>
<string>string.quoted.double.chai</string>
<key>patterns</key>
<array>
<dict>
<key>match</key>
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
<key>name</key>
<string>constant.character.escape.chai</string>
</dict>
</array>
</dict>
<dict>
<key>begin</key>
<string>/\*\*(?!/)</string>
<key>captures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.comment.chai</string>
</dict>
</dict>
<key>end</key>
<string>\*/</string>
<key>name</key>
<string>comment.block.documentation.chai</string>
</dict>
<dict>
<key>begin</key>
<string>/\*</string>
<key>captures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.comment.chai</string>
</dict>
</dict>
<key>end</key>
<string>\*/</string>
<key>name</key>
<string>comment.block.chai</string>
</dict>
<dict>
<key>captures</key>
<dict>
<key>1</key>
<dict>
<key>name</key>
<string>punctuation.definition.comment.chai</string>
</dict>
</dict>
<key>match</key>
<string>(//).*$\n?</string>
<key>name</key>
<string>comment.line.double-slash.chai</string>
</dict>
<dict>
<key>captures</key>
<dict>
<key>0</key>
<dict>
<key>name</key>
<string>punctuation.definition.comment.html.chai</string>
</dict>
<key>2</key>
<dict>
<key>name</key>
<string>punctuation.definition.comment.html.chai</string>
</dict>
</dict>
<key>match</key>
<string>(&lt;!--|--&gt;)</string>
<key>name</key>
<string>comment.block.html.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b</string>
<key>name</key>
<string>storage.type.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b</string>
<key>name</key>
<string>keyword.control.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(delete|in|instanceof|new|typeof|with)\b</string>
<key>name</key>
<string>keyword.operator.chai</string>
</dict>
<dict>
<key>match</key>
<string>\btrue\b</string>
<key>name</key>
<string>constant.language.boolean.true.chai</string>
</dict>
<dict>
<key>match</key>
<string>\bfalse\b</string>
<key>name</key>
<string>constant.language.boolean.false.chai</string>
</dict>
<dict>
<key>match</key>
<string>\bnull\b</string>
<key>name</key>
<string>constant.language.null.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b</string>
<key>name</key>
<string>support.class.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()</string>
<key>name</key>
<string>support.function.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()</string>
<key>name</key>
<string>support.function.dom.chai</string>
</dict>
<dict>
<key>match</key>
<string>(?&lt;=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b</string>
<key>name</key>
<string>support.constant.chai</string>
</dict>
<dict>
<key>match</key>
<string>(?&lt;=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b</string>
<key>name</key>
<string>support.constant.dom.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b</string>
<key>name</key>
<string>support.constant.dom.chai</string>
</dict>
<dict>
<key>match</key>
<string>\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b</string>
<key>name</key>
<string>support.function.event-handler.chai</string>
</dict>
<dict>
<key>match</key>
<string>!|\$|%|&amp;|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\|\||\?\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(in|instanceof|new|delete|typeof|void)\b</string>
<key>name</key>
<string>keyword.operator.chai</string>
</dict>
<dict>
<key>match</key>
<string>\b(Infinity|NaN|undefined)\b</string>
<key>name</key>
<string>constant.language.chai</string>
</dict>
<dict>
<key>begin</key>
<string>(?&lt;=[=(:]|^|return|&amp;&amp;|\|\||!)\s*(/)(?![/*+{}?])</string>
<key>beginCaptures</key>
<dict>
<key>1</key>
<dict>
<key>name</key>
<string>punctuation.definition.string.begin.chai</string>
</dict>
</dict>
<key>end</key>
<string>(/)[igm]*</string>
<key>endCaptures</key>
<dict>
<key>1</key>
<dict>
<key>name</key>
<string>punctuation.definition.string.end.chai</string>
</dict>
</dict>
<key>name</key>
<string>string.regexp.chai</string>
<key>patterns</key>
<array>
<dict>
<key>match</key>
<string>\\.</string>
<key>name</key>
<string>constant.character.escape.chai</string>
</dict>
</array>
</dict>
<dict>
<key>match</key>
<string>\;</string>
<key>name</key>
<string>punctuation.terminator.statement.chai</string>
</dict>
<dict>
<key>match</key>
<string>,[ |\t]*</string>
<key>name</key>
<string>meta.delimiter.object.comma.chai</string>
</dict>
<dict>
<key>match</key>
<string>\.</string>
<key>name</key>
<string>meta.delimiter.method.period.chai</string>
</dict>
<dict>
<key>match</key>
<string>\{|\}</string>
<key>name</key>
<string>meta.brace.curly.chai</string>
</dict>
<dict>
<key>match</key>
<string>\(|\)</string>
<key>name</key>
<string>meta.brace.round.chai</string>
</dict>
<dict>
<key>match</key>
<string>\[|\]</string>
<key>name</key>
<string>meta.brace.square.chai</string>
</dict>
</array>
<key>scopeName</key>
<string>source.chai</string>
<key>uuid</key>
<string>93E017CC-6F27-11D9-90EB-000D93589AF6</string>
</dict>
</plist>

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
// 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)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DEFINES_HPP_
#define CHAISCRIPT_DEFINES_HPP_
#ifdef _MSC_VER
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEC
#if _MSC_VER <= 1800
#define CHAISCRIPT_MSVC_12
#endif
#endif
#ifndef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_HAS_MAGIC_STATICS
#endif
#include <vector>
#if defined( _LIBCPP_VERSION )
#define CHAISCRIPT_LIBCPP
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
#define CHAISCRIPT_WINDOWS
#endif
#if (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
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__)
#define CHAISCRIPT_OVERRIDE override
#else
#define CHAISCRIPT_OVERRIDE
#endif
#ifdef CHAISCRIPT_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
#else
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#ifdef CHAISCRIPT_MSVC
#define CHAISCRIPT_NOEXCEPT throw()
#define CHAISCRIPT_CONSTEXPR
#else
#define CHAISCRIPT_NOEXCEPT noexcept
#define CHAISCRIPT_CONSTEXPR constexpr
#endif
#include <memory>
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 7;
static const int version_patch = 0;
template<typename B, typename D, typename ...Arg>
inline std::shared_ptr<B> make_shared(Arg && ... arg)
{
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
return std::make_shared<D>(std::forward<Arg>(arg)...);
#else
return std::shared_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
#endif
}
}
#endif

View File

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

View File

@@ -1,18 +1,24 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_ #ifndef CHAISCRIPT_THREADING_HPP_
#define CHAISCRIPT_THREADING_HPP_ #define CHAISCRIPT_THREADING_HPP_
#include <unordered_map>
#ifndef CHAISCRIPT_NO_THREADS #ifndef CHAISCRIPT_NO_THREADS
#include <boost/thread.hpp> #include <thread>
#include <mutex>
#else #else
#pragma message ("ChaiScript is compiling without thread safety.") #pragma message ("ChaiScript is compiling without thread safety.")
#endif #endif
#include "chaiscript_defines.hpp"
/// \file /// \file
/// ///
/// This file contains code necessary for thread support in ChaiScript. /// This file contains code necessary for thread support in ChaiScript.
@@ -25,56 +31,157 @@ namespace chaiscript
{ {
namespace detail namespace detail
{ {
/// If threading is enabled, then this namespace contains boost::thread classes. /// If threading is enabled, then this namespace contains std thread classes.
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided. /// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
/// This allows us to avoid \#ifdef code in the sections that need thread safety. /// This allows us to avoid \#ifdef code in the sections that need thread safety.
namespace threading namespace threading
{ {
#ifndef CHAISCRIPT_NO_THREADS #ifndef CHAISCRIPT_NO_THREADS
using boost::unique_lock;
using boost::shared_lock;
using boost::lock_guard;
using boost::shared_mutex;
using boost::recursive_mutex;
template<typename T>
class unique_lock : public std::unique_lock<T>
{
public:
unique_lock(T &t) : std::unique_lock<T>(t) {}
};
/// Typesafe thread specific storage. If threading is enabled, this class uses boost::thread_specific_ptr<T>. If template<typename T>
class shared_lock : public std::unique_lock<T>
{
public:
shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
template<typename T>
class lock_guard : public std::lock_guard<T>
{
public:
lock_guard(T &t) : std::lock_guard<T>(t) {}
};
class shared_mutex : public std::mutex { };
using std::mutex;
using std::recursive_mutex;
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from. /// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
template<typename T> template<typename T>
class Thread_Storage class Thread_Storage
{ {
public: public:
Thread_Storage(void *t_key)
: m_key(t_key)
{
}
~Thread_Storage() ~Thread_Storage()
{ {
m_thread_storage.reset(); t().erase(m_key);
} }
inline T *operator->() const inline const T *operator->() const
{ {
if (!m_thread_storage.get()) return &(t()[m_key]);
{
m_thread_storage.reset(new T());
} }
return m_thread_storage.get(); inline const T &operator*() const
{
return t()[m_key];
} }
inline T &operator*() const inline T *operator->()
{ {
return *(this->operator->()); return &(t()[m_key]);
} }
inline T &operator*()
{
return t()[m_key];
}
void *m_key;
private: private:
mutable boost::thread_specific_ptr<T> m_thread_storage; static std::unordered_map<void*, T> &t()
{
thread_local static std::unordered_map<void *, T> my_t;
return my_t;
}
}; };
#else #else
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// This version is used if the compiler does not support thread_local
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *)
{
}
inline const T *operator->() const
{
return get_tls().get();
}
inline const T &operator*() const
{
return *get_tls();
}
inline T *operator->()
{
return get_tls().get();
}
inline T &operator*()
{
return *get_tls();
}
private:
std::shared_ptr<T> get_tls() const
{
unique_lock<mutex> lock(m_mutex);
auto itr = m_instances.find(std::this_thread::get_id());
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(std::make_shared<T>());
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
return new_instance;
}
mutable mutex m_mutex;
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
};
#endif // threading enabled but no tls
#else // threading disabled
template<typename T> template<typename T>
class unique_lock class unique_lock
{ {
public: public:
unique_lock(T &) {} unique_lock(T &) {}
void lock() {}
void unlock() {}
}; };
template<typename T> template<typename T>
@@ -82,6 +189,7 @@ namespace chaiscript
{ {
public: public:
shared_lock(T &) {} shared_lock(T &) {}
void lock() {}
void unlock() {} void unlock() {}
}; };
@@ -101,6 +209,10 @@ namespace chaiscript
class Thread_Storage class Thread_Storage
{ {
public: public:
Thread_Storage(void *)
{
}
inline T *operator->() const inline T *operator->() const
{ {
return &obj; return &obj;

View File

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

View File

@@ -1,14 +1,22 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_ #ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_ #define CHAISCRIPT_BAD_BOXED_CAST_HPP_
#include <string>
#include <typeinfo>
#include "../chaiscript_defines.hpp"
#include "type_info.hpp" #include "type_info.hpp"
namespace chaiscript {
class Type_Info;
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
namespace exception namespace exception
@@ -21,26 +29,27 @@ namespace chaiscript
class bad_boxed_cast : public std::bad_cast class bad_boxed_cast : public std::bad_cast
{ {
public: public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to, bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
const std::string &t_what) throw() std::string t_what) CHAISCRIPT_NOEXCEPT
: from(t_from), to(&t_to), m_what(t_what) : from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
{ {
} }
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw() bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast") : from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast")
{ {
} }
bad_boxed_cast(const std::string &t_what) throw() bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(0), m_what(t_what) : to(nullptr), m_what(std::move(t_what))
{ {
} }
virtual ~bad_boxed_cast() throw() {} bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occured /// \brief Description of what error occurred
virtual const char * what() const throw() virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{ {
return m_what.c_str(); return m_what.c_str();
} }

View File

@@ -1,94 +1,74 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#define param(z,n,text) BOOST_PP_CAT(text, BOOST_PP_INC(n))
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_BIND_FIRST_HPP_ #ifndef CHAISCRIPT_BIND_FIRST_HPP_
#define CHAISCRIPT_BIND_FIRST_HPP_ #define CHAISCRIPT_BIND_FIRST_HPP_
#include <boost/function.hpp> #include <functional>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#define BOOST_PP_ITERATION_LIMITS ( 0, 8 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/bind_first.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
# define m BOOST_PP_INC(n)
namespace chaiscript namespace chaiscript
{ {
namespace detail namespace detail
{ {
/// \brief Helper function for binding the first parameter of a class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function. template<typename T>
/// T* get_pointer(T *t)
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
{ {
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _)); return t;
} }
/// \brief Helper function for binding the first parameter of a const class method pointer. Used in chaiscript::fun overloads template<typename T>
/// that take 1 or 2 parameters to pre-bind to the function. T* get_pointer(const std::reference_wrapper<T> &t)
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)) const, const O &o)
{ {
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _)); return &t.get();
} }
/// \brief Helper function for binding the first parameter of a function pointer. Used in chaiscript::fun overloads template<typename O, typename Ret, typename P1, typename ... Param>
/// that take 1 or 2 parameters to pre-bind to the function. std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
{ {
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _)); return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(std::forward<O>(o), std::forward<Param>(param)...);
}
);
} }
/// \brief Helper function for binding the first parameter of a boost::function object. Used in chaiscript::fun overloads template<typename O, typename Ret, typename Class, typename ... Param>
/// that take 1 or 2 parameters to pre-bind to the function. std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)
{ {
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _)); return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
} }
);
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(o, std::forward<Param>(param)...);
});
}
} }
} }
#undef n
#undef m
#undef param
#endif #endif

View File

@@ -1,19 +1,38 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_ #ifndef CHAISCRIPT_BOOTSTRAP_HPP_
#define CHAISCRIPT_BOOTSTRAP_HPP_ #define CHAISCRIPT_BOOTSTRAP_HPP_
#include "dispatchkit.hpp" #include <cstdint>
#include "dynamic_object.hpp" #include <exception>
#include "register_function.hpp" #include <functional>
#include "operators.hpp" #include <memory>
#include "boxed_number.hpp"
#include <boost/function_types/result_type.hpp>
#include <sstream> #include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>
#include <iterator>
#include "bad_boxed_cast.hpp"
#include "boxed_cast.hpp"
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "dispatchkit.hpp"
#include "type_conversions.hpp"
#include "dynamic_object.hpp"
#include "operators.hpp"
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "proxy_functions_detail.hpp"
#include "register_function.hpp"
#include "type_info.hpp"
#include "../utility/utility.hpp"
#include "../language/chaiscript_common.hpp"
namespace chaiscript namespace chaiscript
{ {
@@ -26,23 +45,56 @@ namespace chaiscript
/// \param[in] v Boxed_Number to copy into the new object /// \param[in] v Boxed_Number to copy into the new object
/// \returns The newly created object. /// \returns The newly created object.
template<typename P1> template<typename P1>
boost::shared_ptr<P1> construct_pod(Boxed_Number v) std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
{ {
boost::shared_ptr<P1> p(new P1()); return std::make_shared<P1>(v.get_as<P1>());
Boxed_Value bv(p);
Boxed_Number nb(bv);
nb = v;
return p;
} }
} }
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
ModulePtr array(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
typedef typename std::remove_extent<T>::type ReturnType;
const auto extent = std::extent<T>::value;
m->add(user_type<T>(), type);
m->add(fun<ReturnType& (T &, size_t)>(
[extent](T& t, size_t index)->ReturnType &{
if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
} else {
return t[index];
}
}
), "[]"
);
m->add(fun<const ReturnType& (const T &, size_t)>(
[extent](const T &t, size_t index)->const ReturnType &{
if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
} else {
return t[index];
}
}
), "[]"
);
m->add(fun<size_t (const T &)>(
[extent](const T &) {
return extent;
}), "size");
return m;
}
/// \brief Adds a copy constructor for the given type to the given Model /// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type". /// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to /// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for /// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used /// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T> template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(constructor<T (const T &)>(), type); m->add(constructor<T (const T &)>(), type);
return m; return m;
@@ -53,7 +105,7 @@ namespace chaiscript
/// \param[in,out] m module to add comparison operators to /// \param[in,out] m module to add comparison operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used. /// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T> template<typename T>
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module())) ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
{ {
operators::equal<T>(m); operators::equal<T>(m);
operators::greater_than<T>(m); operators::greater_than<T>(m);
@@ -74,7 +126,7 @@ namespace chaiscript
/// \sa copy_constructor /// \sa copy_constructor
/// \sa constructor /// \sa constructor
template<typename T> template<typename T>
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(constructor<T ()>(), type); m->add(constructor<T ()>(), type);
copy_constructor<T>(type, m); copy_constructor<T>(type, m);
@@ -86,16 +138,14 @@ namespace chaiscript
/// \param[in] type The name of the type /// \param[in] type The name of the type
/// \param[in,out] m The Module to add the constructor to /// \param[in,out] m The Module to add the constructor to
template<typename T> template<typename T>
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&detail::construct_pod<T>), type); m->add(fun(&detail::construct_pod<T>), type);
return m; return m;
} }
/** /// to_string function for internal use. Uses ostream operator<<
* to_string function for internal use. Uses ostream operator<<
*/
template<typename Input> template<typename Input>
std::string to_string(Input i) std::string to_string(Input i)
{ {
@@ -104,10 +154,8 @@ namespace chaiscript
return ss.str(); return ss.str();
} }
/** /// Internal function for converting from a string to a value
* Internal function for converting from a string to a value /// uses ostream operator >> to perform the conversion
* uses ostream operator >> to perform the conversion
*/
template<typename Input> template<typename Input>
Input parse_string(const std::string &i) Input parse_string(const std::string &i)
{ {
@@ -118,59 +166,51 @@ namespace chaiscript
} }
/// Add all common functions for a POD type. All operators, and
/// common conversions
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T> template<typename T>
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module())) ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<T>(), name); m->add(user_type<T>(), name);
m->add(constructor<T ()>(), name); m->add(constructor<T()>(), name);
construct_pod<T>(name, m); construct_pod<T>(name, m);
m->add(fun(&to_string<T>), "to_string"); auto to_s = fun(&to_string<T>);
if (!m->has_function(to_s, "to_string")) {
m->add(to_s, "to_string");
}
m->add(fun(&parse_string<T>), "to_" + name); m->add(fun(&parse_string<T>), "to_" + name);
return m; return m;
} }
/** /// "clone" function for a shared_ptr type. This is used in the case
* "clone" function for a shared_ptr type. This is used in the case /// where you do not want to make a deep copy of an object during cloning
* where you do not want to make a deep copy of an object during cloning /// but want to instead maintain the shared_ptr. It is needed internally
* but want to instead maintain the shared_ptr. It is needed internally /// for handling of Proxy_Function object (that is,
* for handling of Proxy_Function object (that is, /// function variables.
* function variables.
*/
template<typename Type> template<typename Type>
boost::shared_ptr<Type> shared_ptr_clone(const boost::shared_ptr<Type> &p) std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
{ {
return p; return p;
} }
/** /// Specific version of shared_ptr_clone just for Proxy_Functions
* Specific version of shared_ptr_clone just for Proxy_Functions
*/
template<typename Type> template<typename Type>
boost::shared_ptr<typename boost::remove_const<Type>::type> std::shared_ptr<typename std::remove_const<Type>::type>
shared_ptr_unconst_clone(const boost::shared_ptr<typename boost::add_const<Type>::type> &p) shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
{ {
return boost::const_pointer_cast<typename boost::remove_const<Type>::type>(p); return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
} }
/** /// Assignment function for shared_ptr objects, does not perform a copy of the
* Assignment function for shared_ptr objects, does not perform a copy of the /// object pointed to, instead maintains the shared_ptr concept.
* object pointed to, instead maintains the shared_ptr concept. /// Similar to shared_ptr_clone. Used for Proxy_Function.
* Similar to shared_ptr_clone. Used for Proxy_Function.
*/
template<typename Type> template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<Type> &rhs) Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
{ {
if (lhs.is_undef() if (lhs.is_undef()
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get()))) || (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
@@ -182,16 +222,12 @@ namespace chaiscript
} }
} }
/** /// Class consisting of only static functions. All default bootstrapping occurs
* Class consisting of only static functions. All default bootstrapping occurs /// from this class.
* from this class.
*/
class Bootstrap class Bootstrap
{ {
private: private:
/** /// Function allowing for assignment of an unknown type to any other value
* Function allowing for assignment of an unknown type to any other value
*/
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
{ {
if (lhs.is_undef()) if (lhs.is_undef())
@@ -204,19 +240,17 @@ namespace chaiscript
static void print(const std::string &s) static void print(const std::string &s)
{ {
std::cout << s; fwrite(s.c_str(), 1, s.size(), stdout);
} }
static void println(const std::string &s) static void println(const std::string &s)
{ {
std::cout << s << std::endl; puts(s.c_str());
} }
/** /// Add all arithmetic operators for PODs
* Add all arithmetic operators for PODs static void opers_arithmetic_pod(ModulePtr m = std::make_shared<Module>())
*/
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
{ {
m->add(fun(&Boxed_Number::equals), "=="); m->add(fun(&Boxed_Number::equals), "==");
m->add(fun(&Boxed_Number::less_than), "<"); m->add(fun(&Boxed_Number::less_than), "<");
@@ -255,11 +289,8 @@ namespace chaiscript
} }
/** /// Create a bound function object. The first param is the function to bind
* Create a bound function object. The first param is the function to bind /// the remaining parameters are the args to bind into the result
* the remaining parameters are the args to bind into the
* result
*/
static Boxed_Value bind_function(const std::vector<Boxed_Value> &params) static Boxed_Value bind_function(const std::vector<Boxed_Value> &params)
{ {
if (params.size() < 2) if (params.size() < 2)
@@ -269,71 +300,38 @@ namespace chaiscript
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]); Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f, return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
std::vector<Boxed_Value>(params.begin() + 1, params.end())))); std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
} }
/**
* Returns true if a call can be made that consists of the first parameter
* (the function) with the remaining parameters as its arguments.
*/
static Boxed_Value call_exists(const std::vector<Boxed_Value> &params)
{
if (params.size() < 1)
{
throw exception::arity_error(static_cast<int>(params.size()), 1);
}
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
}
static bool has_guard(const Const_Proxy_Function &t_pf) static bool has_guard(const Const_Proxy_Function &t_pf)
{ {
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf); auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf) return pf && pf->get_guard();
{
return pf->get_guard();
} else {
return false;
}
} }
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf) static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
{ {
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf); const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf) if (pf && pf->get_guard())
{
if (pf->get_guard())
{ {
return pf->get_guard(); return pf->get_guard();
} else { } else {
throw std::runtime_error("Function does not have a guard"); throw std::runtime_error("Function does not have a guard");
} }
} else {
throw std::runtime_error("Function does not have a guard");
}
} }
static void throw_exception(const Boxed_Value &bv) { static void throw_exception(const Boxed_Value &bv) {
throw bv; throw bv;
} }
static boost::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(boost::shared_ptr<chaiscript::detail::Dispatch_Engine> e = boost::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
{
e->add(user_type<void>(), "void");
return e;
}
static std::string what(const std::exception &e) static std::string what(const std::exception &e)
{ {
return e.what(); return e.what();
} }
/** /// Boolean specialization of internal to_string function
* Boolean specialization of internal to_string function
*/
static std::string bool_to_string(bool b) static std::string bool_to_string(bool b)
{ {
if (b) if (b)
@@ -348,42 +346,61 @@ namespace chaiscript
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f, static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
const dispatch::Proxy_Function_Base *b) const dispatch::Proxy_Function_Base *b)
{ {
typedef typename boost::function_types::result_type<FunctionType>::type Vector; auto v = (b->*f)();
Vector v = (b->*f)();
std::vector<Boxed_Value> vbv; std::vector<Boxed_Value> vbv;
for (typename Vector::const_iterator itr = v.begin();
itr != v.end(); for (const auto &o: v)
++itr)
{ {
vbv.push_back(const_var(*itr)); vbv.push_back(const_var(o));
} }
return vbv; return vbv;
} }
template<typename Function>
static boost::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f) static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{ {
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1); const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
return pf && pf->get_parse_tree();
} }
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf && pf->get_parse_tree())
{
return pf->get_parse_tree();
} else {
throw std::runtime_error("Function does not have a parse tree");
}
}
template<typename Function>
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
{
return [f](const dispatch::Proxy_Function_Base *b) {
return do_return_boxed_value_vector(f, b);
};
}
public: public:
/// \brief perform all common bootstrap functions for std::string, void and POD types /// \brief perform all common bootstrap functions for std::string, void and POD types
/// \param[in,out] m Module to add bootstrapped functions to /// \param[in,out] m Module to add bootstrapped functions to
/// \returns passed in ModulePtr, or newly created one if default argument is used /// \returns passed in ModulePtr, or newly created one if default argument is used
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module())) static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<void>(), "void"); m->add(user_type<void>(), "void");
m->add(user_type<bool>(), "bool"); m->add(user_type<bool>(), "bool");
m->add(user_type<Boxed_Value>(), "Object"); m->add(user_type<Boxed_Value>(), "Object");
m->add(user_type<Boxed_Number>(), "Number"); m->add(user_type<Boxed_Number>(), "Number");
m->add(user_type<Proxy_Function>(), "Function"); m->add(user_type<Proxy_Function>(), "Function");
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
m->add(user_type<std::exception>(), "exception"); m->add(user_type<std::exception>(), "exception");
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity"); m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation"); m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "=="); m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
@@ -394,17 +411,25 @@ namespace chaiscript
m->add(user_type<std::runtime_error>(), "runtime_error"); m->add(user_type<std::runtime_error>(), "runtime_error");
m->add(chaiscript::base_class<std::exception, std::runtime_error>()); m->add(chaiscript::base_class<std::exception, std::runtime_error>());
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error"); m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what"); m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object"); m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object"); m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
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_type_name), "get_type_name");
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs"); m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::get_attr), "get_attr");
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }"); m->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");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
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->add(fun(&has_guard), "has_guard"); m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard"); m->add(fun(&get_guard), "get_guard");
@@ -415,9 +440,12 @@ namespace chaiscript
m->add(fun(&Boxed_Value::is_ref), "is_var_reference"); 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_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_type), "is_type"); m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info"); m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info"); m->add(user_type<Type_Info>(), "Type_Info");
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
operators::equal<Type_Info>(m); operators::equal<Type_Info>(m);
@@ -437,8 +465,8 @@ namespace chaiscript
operators::assign<bool>(m); operators::assign<bool>(m);
operators::equal<bool>(m); operators::equal<bool>(m);
m->add(fun(&to_string<const std::string &>), "internal_to_string"); m->add(fun<std::string (const std::string &t_ss)>([](const std::string &s) -> std::string { return s; }), "to_string");
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string"); m->add(fun(&Bootstrap::bool_to_string), "to_string");
m->add(fun(&unknown_assign), "="); m->add(fun(&unknown_assign), "=");
m->add(fun(&throw_exception), "throw"); m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what"); m->add(fun(&what), "what");
@@ -452,14 +480,14 @@ namespace chaiscript
bootstrap_pod_type<unsigned long>("unsigned_long", m); bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<size_t>("size_t", m); bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m); bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<boost::int8_t>("int8_t", m); bootstrap_pod_type<std::int8_t>("int8_t", m);
bootstrap_pod_type<boost::int16_t>("int16_t", m); bootstrap_pod_type<std::int16_t>("int16_t", m);
bootstrap_pod_type<boost::int32_t>("int32_t", m); bootstrap_pod_type<std::int32_t>("int32_t", m);
bootstrap_pod_type<boost::int64_t>("int64_t", m); bootstrap_pod_type<std::int64_t>("int64_t", m);
bootstrap_pod_type<boost::uint8_t>("uint8_t", m); bootstrap_pod_type<std::uint8_t>("uint8_t", m);
bootstrap_pod_type<boost::uint16_t>("uint16_t", m); bootstrap_pod_type<std::uint16_t>("uint16_t", m);
bootstrap_pod_type<boost::uint32_t>("uint32_t", m); bootstrap_pod_type<std::uint32_t>("uint32_t", m);
bootstrap_pod_type<boost::uint64_t>("uint64_t", m); bootstrap_pod_type<std::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m); operators::logical_compliment<bool>(m);
@@ -469,17 +497,86 @@ namespace chaiscript
m->add(fun(&print), "print_string"); m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string"); m->add(fun(&println), "println_string");
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&bind_function, _1))), m->add(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Dynamic_Proxy_Function>(&bind_function), "bind");
"bind");
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone"); m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "="); m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "="); m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
m->add(fun<void (dispatch::Assignable_Proxy_Function &, const std::shared_ptr<const dispatch::Proxy_Function_Base> &)>(
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
t_lhs.assign(t_rhs);
}
), "="
);
m->add(fun(&Boxed_Value::type_match), "type_match");
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<std::shared_ptr<const chaiscript::AST_Node>>);
return retval;
})), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
{ {fun(&File_Position::line), "line"},
{fun(&File_Position::column), "column"} }
);
chaiscript::utility::add_class<AST_Node>(*m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
{fun(&AST_Node::identifier), "identifier"},
{fun(&AST_Node::filename), "filename"},
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::to_string), "to_string"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_node.children.begin(), t_node.children.end(),
std::back_inserter(retval),
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
return retval;
})), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
"call_exists");
m->add(fun(&type_match), "type_match");
return m; return m;
} }

View File

@@ -1,23 +1,31 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
/** /// \file
* \file /// This file contains utility functions for registration of STL container
* This file contains utility functions for registration of STL container /// classes. The methodology used is based on the SGI STL concepts.
* classes. The methodology used is based on the SGI STL concepts. /// http://www.sgi.com/tech/stl/table_of_contents.html
* http://www.sgi.com/tech/stl/table_of_contents.html
*/
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_ #ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_ #define CHAISCRIPT_BOOTSTRAP_STL_HPP_
#include <functional>
#include <memory>
#include <stdexcept>
#include <typeinfo>
#include <vector>
#include "bootstrap.hpp"
#include "boxed_value.hpp"
#include "dispatchkit.hpp" #include "dispatchkit.hpp"
#include "operators.hpp"
#include "proxy_constructors.hpp"
#include "register_function.hpp" #include "register_function.hpp"
#include "type_info.hpp"
namespace chaiscript namespace chaiscript
{ {
@@ -25,11 +33,10 @@ namespace chaiscript
{ {
namespace standard_library namespace standard_library
{ {
/**
* Bidir_Range, based on the D concept of ranges. /// Bidir_Range, based on the D concept of ranges.
* \todo Update the Range code to base its capabilities on /// \todo Update the Range code to base its capabilities on
* the user_typetraits of the iterator passed in /// the user_typetraits of the iterator passed in
*/
template<typename Container> template<typename Container>
struct Bidir_Range struct Bidir_Range
{ {
@@ -147,87 +154,11 @@ namespace chaiscript
}; };
namespace detail { namespace detail {
template<typename T>
int return_int_impl(const boost::function<typename T::size_type (const T *)> &t_func, const T *t_obj)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T> template<typename T>
boost::function<int (const T *)> return_int(size_t (T::*t_func)() const) size_t count(const T &t_target, const typename T::key_type &t_key)
{ {
return boost::bind(&return_int_impl<T>, boost::function<size_t (const T *)>(boost::mem_fn(t_func)), _1); return t_target.count(t_key);
}
template<typename T, typename P1>
int return_int_impl(const boost::function<typename T::size_type (const T *, P1)> &t_func, const T *t_obj, P1 p1)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T, typename P1>
int return_int_impl_non_const(const boost::function<typename T::size_type (T *, P1)> &t_func, T *t_obj, P1 p1)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename T, typename P1>
boost::function<int (const T *, P1)> return_int(size_t (T::*t_func)(P1) const)
{
return boost::bind(&return_int_impl<T, P1>, boost::function<size_t (const T *, P1)>(boost::mem_fn(t_func)), _1, _2);
}
template<typename T, typename P1>
boost::function<int (T *, P1)> return_int(size_t (T::*t_func)(P1) )
{
return boost::bind(&return_int_impl_non_const<T, P1>, boost::function<size_t (T*, P1)>(boost::mem_fn(t_func)), _1, _2);
}
template<typename T, typename P1, typename P2>
int return_int_impl(const boost::function<typename T::size_type (const T *, P1, P2)> &t_func, const T *t_obj, P1 p1, P2 p2)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
return t_func(t_obj, p1, p2);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<typename StringType, StringType (StringType::*Func)(typename StringType::size_type, typename StringType::size_type) const >
StringType substr_helper(const StringType &str, int begin, int end)
{
return (str.*Func)(begin, end);
}
template<typename T, typename P1, typename P2>
boost::function<int (const T *, P1, P2)> return_int(size_t (T::*t_func)(P1, P2) const)
{
return boost::bind(&return_int_impl<T, P1, P2>, boost::function<size_t (const T *, P1, P2)>(boost::mem_fn(t_func)), _1, _2, _3);
} }
template<typename T> template<typename T>
@@ -244,18 +175,15 @@ namespace chaiscript
/// Add Bidir_Range support for the given ContainerType
/**
* Add Bidir_Range support for the given ContainerType
*/
template<typename Bidir_Type> template<typename Bidir_Type>
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<Bidir_Type>(), type + "_Range"); m->add(user_type<Bidir_Type>(), type + "_Range");
copy_constructor<Bidir_Type>(type + "_Range", m); copy_constructor<Bidir_Type>(type + "_Range", m);
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range"); m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
m->add(fun(&Bidir_Type::empty), "empty"); m->add(fun(&Bidir_Type::empty), "empty");
m->add(fun(&Bidir_Type::pop_front), "pop_front"); m->add(fun(&Bidir_Type::pop_front), "pop_front");
@@ -266,14 +194,13 @@ namespace chaiscript
return m; return m;
} }
/**
* Algorithm for inserting at a specific position into a container /// Algorithm for inserting at a specific position into a container
*/
template<typename Type> template<typename Type>
void insert_at(Type &container, int pos, const typename Type::value_type &v) void insert_at(Type &container, int pos, const typename Type::value_type &v)
{ {
typename Type::iterator itr = container.begin(); auto itr = container.begin();
typename Type::iterator end = container.end(); auto end = container.end();
if (pos < 0 || std::distance(itr, end) < pos) if (pos < 0 || std::distance(itr, end) < pos)
{ {
@@ -284,14 +211,13 @@ namespace chaiscript
container.insert(itr, v); container.insert(itr, v);
} }
/**
* Algorithm for erasing a specific position from a container /// Algorithm for erasing a specific position from a container
*/
template<typename Type> template<typename Type>
void erase_at(Type &container, int pos) void erase_at(Type &container, int pos)
{ {
typename Type::iterator itr = container.begin(); auto itr = container.begin();
typename Type::iterator end = container.end(); auto end = container.end();
if (pos < 0 || std::distance(itr, end) < (pos-1)) if (pos < 0 || std::distance(itr, end) < (pos-1))
{ {
@@ -301,73 +227,67 @@ namespace chaiscript
std::advance(itr, pos); std::advance(itr, pos);
container.erase(itr); container.erase(itr);
} }
} }
template<typename ContainerType> template<typename ContainerType>
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m); detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m); detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
return m; return m;
} }
/**
* Add random_access_container concept to the given ContainerType /// Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html /// http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{ {
// cppcheck-suppress syntaxError
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t); typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const;
//In the interest of runtime safety for the m, we prefer the at() method for [] access, //In the interest of runtime safety for the m, we prefer the at() method for [] access,
//to throw an exception in an out of bounds condition. //to throw an exception in an out of bounds condition.
m->add( m->add(
fun(boost::function<typename ContainerType::reference (ContainerType *, int)> fun(std::function<typename ContainerType::reference (ContainerType *, int)>
(boost::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]"); (std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
m->add( m->add(
fun(boost::function<typename ContainerType::const_reference (const ContainerType *, int)> fun<typename ContainerType::const_reference (const ContainerType *, int)>(
(boost::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]"); [](const ContainerType *c, int index) -> typename ContainerType::const_reference {
return c->at(index);
}), "[]");
return m; return m;
} }
/**
* Add assignable concept to the given ContainerType /// Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html /// http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType> template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
basic_constructors<ContainerType>(type, m); copy_constructor<ContainerType>(type, m);
operators::assign<ContainerType>(m); operators::assign<ContainerType>(m);
return m; return m;
} }
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
m->add(fun(f), "size");
// m->add(fun(boost::function<int (const ContainerType *)>(boost::mem_fn(&ContainerType::size))), "size");
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
/// Add container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Container.html
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{
m->add(fun<size_t (const ContainerType *)>([](const ContainerType *a) { return a->size(); } ), "size");
m->add(fun<bool (const ContainerType *)>([](const ContainerType *a) { return a->empty(); } ), "empty");
m->add(fun<void (ContainerType *)>([](ContainerType *a) { a->clear(); } ), "clear");
return m; return m;
} }
/**
* Add default constructable concept to the given Type /// Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html /// http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type> template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(constructor<Type ()>(), type); m->add(constructor<Type ()>(), type);
return m; return m;
@@ -375,85 +295,84 @@ namespace chaiscript
/**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
insert_name = "insert_ref_at";
} else {
insert_name = "insert_at";
}
m->add(fun(&detail::insert_at<ContainerType>), insert_name); /// Add sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Sequence.html
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&detail::insert_at<ContainerType>),
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "insert_ref_at";
} else {
return "insert_at";
}
}());
m->add(fun(&detail::erase_at<ContainerType>), "erase_at"); m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
return m; return m;
} }
/**
* Add back insertion sequence concept to the given ContainerType /// Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html /// http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType> template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{ {
typedef typename ContainerType::reference (ContainerType::*backptr)(); typedef typename ContainerType::reference (ContainerType::*backptr)();
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back"); m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
std::string push_back_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
typedef void (ContainerType::*pushback)(const typename ContainerType::value_type &); typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
m->add(fun(static_cast<pushback>(&ContainerType::push_back)), push_back_name); m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "push_back_ref";
} else {
return "push_back";
}
}());
m->add(fun(&ContainerType::pop_back), "pop_back"); m->add(fun(&ContainerType::pop_back), "pop_back");
return m; return m;
} }
/**
*Front insertion sequence /// Front insertion sequence
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html /// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
*/
template<typename ContainerType> template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module())) ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = std::make_shared<Module>())
{ {
typedef typename ContainerType::reference (ContainerType::*frontptr)(); typedef typename ContainerType::reference (ContainerType::*front_ptr)();
typedef void (ContainerType::*pushptr)(typename ContainerType::const_reference); typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
typedef void (ContainerType::*popptr)(); typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
typedef void (ContainerType::*pop_ptr)();
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front"); m->add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
std::string push_front_name; m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) []()->std::string{
{ if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
push_front_name = "push_front_ref"; return "push_front_ref";
} else { } else {
push_front_name = "push_front"; return "push_front";
} }
}());
m->add(fun(static_cast<pushptr>(&ContainerType::push_front)), push_front_name); m->add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
m->add(fun(static_cast<popptr>(&ContainerType::pop_front)), "pop_front");
return m; return m;
} }
/**
* bootstrap a given PairType /// bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html /// http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType> template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<PairType>(), type); m->add(user_type<PairType>(), type);
@@ -471,61 +390,59 @@ namespace chaiscript
} }
/**
* Add pair associative container concept to the given ContainerType /// Add pair associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html /// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
pair_type<typename ContainerType::value_type>(type + "_Pair", m); pair_type<typename ContainerType::value_type>(type + "_Pair", m);
return m; return m;
} }
/**
* Add unique associative container concept to the given ContainerType /// Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html /// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(&ContainerType::count))), "count"); m->add(fun(detail::count<ContainerType>), "count");
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
typedef size_t (ContainerType::*erase)(const typename ContainerType::key_type &); m->add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
erase eraseptr(&ContainerType::erase);
m->add(fun(boost::function<int (ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(eraseptr))), "erase");
m->add(fun(&detail::insert<ContainerType>), "insert"); m->add(fun(&detail::insert<ContainerType>), "insert");
std::string insert_name; m->add(fun(&detail::insert_ref<ContainerType>),
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) []()->std::string{
{ if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
insert_name = "insert_ref"; return "insert_ref";
} else { } else {
insert_name = "insert"; return "insert";
} }
}());
m->add(fun(&detail::insert_ref<ContainerType>), insert_name);
return m; return m;
} }
/**
* Add a MapType container /// Add a MapType container
* http://www.sgi.com/tech/stl/Map.html /// http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType> template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<MapType>(), type); m->add(user_type<MapType>(), type);
typedef typename MapType::mapped_type &(MapType::*elemaccess)(const typename MapType::key_type &); typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
m->add(fun(static_cast<elemaccess>(&MapType::operator[])), "[]"); m->add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
container_type<MapType>(type, m); container_type<MapType>(type, m);
default_constructible_type<MapType>(type, m);
assignable_type<MapType>(type, m); assignable_type<MapType>(type, m);
unique_associative_container_type<MapType>(type, m); unique_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m); pair_associative_container_type<MapType>(type, m);
@@ -534,12 +451,11 @@ namespace chaiscript
return m; return m;
} }
/**
* hopefully working List type /// hopefully working List type
* http://www.sgi.com/tech/stl/List.html /// http://www.sgi.com/tech/stl/List.html
*/
template<typename ListType> template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<ListType>(), type); m->add(user_type<ListType>(), type);
@@ -554,17 +470,19 @@ namespace chaiscript
return m; return m;
} }
/**
* Create a vector type with associated concepts /// Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html /// http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType> template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<VectorType>(), type); m->add(user_type<VectorType>(), type);
typedef typename VectorType::reference (VectorType::*frontptr)(); typedef typename VectorType::reference (VectorType::*frontptr)();
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front"); m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
back_insertion_sequence_type<VectorType>(type, m); back_insertion_sequence_type<VectorType>(type, m);
@@ -577,35 +495,35 @@ namespace chaiscript
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>)) if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
{ {
m->eval("def Vector::`==`(rhs) : type_match(rhs, this) { \ m->eval(R"(
if ( rhs.size() != this.size() ) { \ def Vector::`==`(rhs) : type_match(rhs, this) {
return false; \ if ( rhs.size() != this.size() ) {
} else { \ return false;
var r1 = range(this); \ } else {
var r2 = range(rhs); \ auto r1 = range(this);
while (!r1.empty()) \ auto r2 = range(rhs);
{ \ while (!r1.empty())
if (!eq(r1.front(), r2.front())) \ {
{ \ if (!eq(r1.front(), r2.front()))
return false; \ {
} \ return false;
r1.pop_front(); \ }
r2.pop_front(); \ r1.pop_front();
} \ r2.pop_front();
return true; \ }
} \ true;
}"); }
} )"
);
} }
return m; return m;
} }
/** /// Add a String container
* Add a String container /// http://www.sgi.com/tech/stl/basic_string.html
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String> template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{ {
m->add(user_type<String>(), type); m->add(user_type<String>(), type);
operators::addition<String>(m); operators::addition<String>(m);
@@ -614,39 +532,54 @@ namespace chaiscript
random_access_container_type<String>(type, m); random_access_container_type<String>(type, m);
sequence_type<String>(type, m); sequence_type<String>(type, m);
default_constructible_type<String>(type, m); default_constructible_type<String>(type, m);
container_type<String>(type, m); // container_type<String>(type, m);
assignable_type<String>(type, m); assignable_type<String>(type, m);
input_range_type<String>(type, m); input_range_type<String>(type, m);
//Special case: add push_back to string (which doesn't support other back_insertion operations //Special case: add push_back to string (which doesn't support other back_insertion operations
std::string push_back_name; m->add(fun(&String::push_back),
if (typeid(typename String::value_type) == typeid(Boxed_Value)) []()->std::string{
{ if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
push_back_name = "push_back_ref"; return "push_back_ref";
} else { } else {
push_back_name = "push_back"; return "push_back";
} }
m->add(fun(&String::push_back), push_back_name); }());
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
typedef boost::function<int (const String *, const String &, int)> find_func;
typedef String (String::*substr_ptr)(typename String::size_type, typename String::size_type) const;
typedef boost::function<String (const String *, int, int)> substr_func;
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find)))), "find");
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_of)))), "find_last_of");
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
m->add(fun(&detail::substr_helper<String, static_cast<substr_ptr>(&String::substr)>), "substr"); typedef std::function<size_t (const String *, const String &, size_t)> find_func;
m->add(fun(&String::c_str), "c_str");
m->add(fun(&String::data), "data");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find(f, pos); } )), "find");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ) ), "rfind");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ) ), "find_first_of");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ) ), "find_last_of");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of");
m->add(fun( std::function<void (String *)>( [](String *s) { return s->clear(); } ) ), "clear");
m->add(fun( std::function<bool (const String *)>( [](const String *s) { return s->empty(); } ) ), "empty");
m->add(fun( std::function<size_t (const String *)>( [](const String *s) { return s->size(); } ) ), "size");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->c_str(); } ) ), "c_str");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->data(); } ) ), "data");
m->add(fun( std::function<String (const String *, size_t, size_t)>( [](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ) ), "substr");
return m;
}
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
template<typename FutureType>
ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<FutureType>(), type);
m->add(fun<bool (const FutureType &)>([](const FutureType &t) { return t.valid(); }), "valid");
m->add(fun(&FutureType::get), "get");
m->add(fun(&FutureType::wait), "wait");
return m; return m;
} }
@@ -656,3 +589,5 @@ namespace chaiscript
#endif #endif

View File

@@ -1,26 +1,27 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HPP_ #ifndef CHAISCRIPT_BOXED_CAST_HPP_
#define CHAISCRIPT_BOXED_CAST_HPP_ #define CHAISCRIPT_BOXED_CAST_HPP_
#include "type_info.hpp" #include "../chaiscript_defines.hpp"
#include "boxed_value.hpp" #include "bad_boxed_cast.hpp"
#include "boxed_cast_helper.hpp" #include "boxed_cast_helper.hpp"
#include "dynamic_cast_conversion.hpp" #include "boxed_value.hpp"
#include "type_conversions.hpp"
#include "type_info.hpp"
#include "../chaiscript_threading.hpp" namespace chaiscript {
#include <boost/shared_ptr.hpp> class Type_Conversions;
#include <boost/any.hpp> namespace detail {
#include <boost/function.hpp> namespace exception {
#include <boost/ref.hpp> class bad_any_cast;
#include <boost/cstdint.hpp> } // namespace exception
#include <boost/type_traits/add_const.hpp> } // namespace detail
#include <boost/type_traits/is_polymorphic.hpp> } // namespace chaiscript
#include <boost/integer_traits.hpp>
namespace chaiscript namespace chaiscript
{ {
@@ -31,77 +32,86 @@ namespace chaiscript
/// \returns Type equivalent to the requested type /// \returns Type equivalent to the requested type
/// \throws exception::bad_boxed_cast If the requested conversion is not possible /// \throws exception::bad_boxed_cast If the requested conversion is not possible
/// ///
/// boxed_cast will attempt to make conversions between value, &, *, boost::shared_ptr, boost::reference_wrapper, /// boxed_cast will attempt to make conversions between value, &, *, std::shared_ptr, std::reference_wrapper,
/// and boost::function (const and non-const) where possible. boxed_cast is used internally during function /// and std::function (const and non-const) where possible. boxed_cast is used internally during function
/// dispatch. This means that all of these conversions will be attempted automatically for you during /// dispatch. This means that all of these conversions will be attempted automatically for you during
/// ChaiScript function calls. /// ChaiScript function calls.
/// ///
/// \li non-const values can be extracted as const or non-const /// \li non-const values can be extracted as const or non-const
/// \li const values can be extracted only as const /// \li const values can be extracted only as const
/// \li Boxed_Value constructed from pointer or boost::reference_wrapper can be extracted as reference, /// \li Boxed_Value constructed from pointer or std::reference_wrapper can be extracted as reference,
/// pointer or value types /// pointer or value types
/// \li Boxed_Value constructed from boost::shared_ptr or value types can be extracted as reference, /// \li Boxed_Value constructed from std::shared_ptr or value types can be extracted as reference,
/// pointer, value, or boost::shared_ptr types /// pointer, value, or std::shared_ptr types
/// ///
/// Conversions to boost::function objects are attempted as well /// Conversions to std::function objects are attempted as well
/// ///
/// Example: /// Example:
/// \code /// \code
/// // All of the following should succeed /// // All of the following should succeed
/// chaiscript::Boxed_Value bv(1); /// chaiscript::Boxed_Value bv(1);
/// boost::shared_ptr<int> spi = chaiscript::boxed_cast<boost::shared_ptr<int> >(bv); /// std::shared_ptr<int> spi = chaiscript::boxed_cast<std::shared_ptr<int> >(bv);
/// int i = chaiscript::boxed_cast<int>(bv); /// int i = chaiscript::boxed_cast<int>(bv);
/// int *ip = chaiscript::boxed_cast<int *>(bv); /// int *ip = chaiscript::boxed_cast<int *>(bv);
/// int &ir = chaiscript::boxed_cast<int &>(bv); /// int &ir = chaiscript::boxed_cast<int &>(bv);
/// boost::shared_ptr<const int> cspi = chaiscript::boxed_cast<boost::shared_ptr<const int> >(bv); /// std::shared_ptr<const int> cspi = chaiscript::boxed_cast<std::shared_ptr<const int> >(bv);
/// const int ci = chaiscript::boxed_cast<const int>(bv); /// const int ci = chaiscript::boxed_cast<const int>(bv);
/// const int *cip = chaiscript::boxed_cast<const int *>(bv); /// const int *cip = chaiscript::boxed_cast<const int *>(bv);
/// const int &cir = chaiscript::boxed_cast<const int &>(bv); /// const int &cir = chaiscript::boxed_cast<const int &>(bv);
/// \endcode /// \endcode
/// ///
/// boost::function conversion example /// std::function conversion example
/// \code /// \code
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in /// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
/// boost::function<int (int, int)> f = chaiscript::boxed_cast<boost::function<int (int, int)> >(bv); /// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
/// int i = f(2,3); /// int i = f(2,3);
/// assert(i == 5); /// assert(i == 5);
/// \endcode /// \endcode
template<typename Type> template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
{ {
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !t_conversions->convertable_type<Type>())) {
try { try {
return detail::Cast_Helper<Type>::cast(bv); return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const boost::bad_any_cast &) { } catch (const chaiscript::detail::exception::bad_any_cast &) {
}
}
#ifdef BOOST_MSVC
#ifdef CHAISCRIPT_MSVC
//Thank you MSVC, yes we know that a constant value is being used in the if //Thank you MSVC, yes we know that a constant value is being used in the if
// statment in THIS VERSION of the template instantiation // statment in THIS VERSION of the template instantiation
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4127) #pragma warning(disable : 4127)
#endif #endif
if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value) if (t_conversions && t_conversions->convertable_type<Type>())
{ {
try { 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 // 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 // either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv)); return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
} catch (const boost::bad_any_cast &) { } catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
} }
}
} else { } else {
// If it's not polymorphic, just throw the error, don't waste the time on the // If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast // attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
} }
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif
}
} }
} }

View File

@@ -1,51 +1,48 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
#include "type_info.hpp" #include <memory>
#include "boxed_value.hpp" #include <type_traits>
#include "boxed_value.hpp"
#include "type_info.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/ref.hpp>
#include <boost/type_traits/add_const.hpp>
namespace chaiscript namespace chaiscript
{ {
class Type_Conversions;
namespace detail namespace detail
{ {
// Cast_Helper_Inner helper classes // Cast_Helper_Inner helper classes
/** template<typename T>
* Generic Cast_Helper_Inner, for casting to any type T* throw_if_null(T *t)
*/ {
if (t) return t;
throw std::runtime_error("Attempted to dereference null Boxed_Value");
}
/// Generic Cast_Helper_Inner, for casting to any type
template<typename Result> template<typename Result>
struct Cast_Helper_Inner struct Cast_Helper_Inner
{ {
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type; typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{ {
if (ob.is_ref()) if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{ {
if (!ob.get_type_info().is_const()) auto p = throw_if_null(ob.get_const_ptr());
{ return std::cref(*static_cast<const Result *>(p));
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
} else { } else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get()); throw chaiscript::detail::exception::bad_any_cast();
}
} else {
if (!ob.get_type_info().is_const())
{
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<const Result> >(ob.get())));
}
} }
} }
}; };
@@ -55,160 +52,143 @@ namespace chaiscript
{ {
}; };
/** /// Cast_Helper_Inner for casting to a const & type
* Cast_Helper_Inner for casting to a const & type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result> struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
{ {
}; };
/** /// Cast_Helper_Inner for casting to a const * type
* Cast_Helper_Inner for casting to a const * type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const Result *> struct Cast_Helper_Inner<const Result *>
{ {
typedef const Result * Result_Type; typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{ {
if (ob.is_ref()) if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{ {
if (!ob.get_type_info().is_const()) return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
} else { } else {
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer(); throw chaiscript::detail::exception::bad_any_cast();
}
} else {
if (!ob.get_type_info().is_const())
{
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
} else {
return (boost::any_cast<boost::shared_ptr<const Result> >(ob.get())).get();
}
} }
} }
}; };
/** /// Cast_Helper_Inner for casting to a * type
* Cast_Helper_Inner for casting to a * type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<Result *> struct Cast_Helper_Inner<Result *>
{ {
typedef Result * Result_Type; typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
static Result_Type cast(const Boxed_Value &ob)
{ {
if (ob.is_ref()) if (ob.is_ref())
{ {
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer(); return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else { } else {
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get(); return (ob.get().cast<std::shared_ptr<Result> >()).get();
} }
} }
}; };
/**
* Cast_Helper_Inner for casting to a & type
*/ /// Cast_Helper_Inner for casting to a & type
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<Result &> struct Cast_Helper_Inner<Result &>
{ {
typedef typename boost::reference_wrapper<Result> Result_Type; typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{ {
if (ob.is_ref()) if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
{ {
return boost::any_cast<boost::reference_wrapper<Result> >(ob.get()); return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
} else { } else {
return boost::ref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get()))); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
/** /// Cast_Helper_Inner for casting to a std::shared_ptr<> type
* Cast_Helper_Inner for casting to a boost::shared_ptr<> type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<typename boost::shared_ptr<Result> > struct Cast_Helper_Inner<std::shared_ptr<Result> >
{ {
typedef typename boost::shared_ptr<Result> Result_Type; typedef std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{ {
return boost::any_cast<boost::shared_ptr<Result> >(ob.get()); return ob.get().cast<std::shared_ptr<Result> >();
} }
}; };
/** /// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
* Cast_Helper_Inner for casting to a boost::shared_ptr<const> type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<typename boost::shared_ptr<const Result> > struct Cast_Helper_Inner<std::shared_ptr<const Result> >
{ {
typedef typename boost::shared_ptr<const Result> Result_Type; typedef std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{ {
if (!ob.get_type_info().is_const()) if (!ob.get_type_info().is_const())
{ {
return boost::const_pointer_cast<const Result>(boost::any_cast<boost::shared_ptr<Result> >(ob.get())); return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
} else { } else {
return boost::any_cast<boost::shared_ptr<const Result> >(ob.get()); return ob.get().cast<std::shared_ptr<const Result> >();
} }
} }
}; };
/** /// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
* Cast_Helper_Inner for casting to a const boost::shared_ptr<> & type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<Result> > : Cast_Helper_Inner<boost::shared_ptr<Result> > struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<Result> &> : Cast_Helper_Inner<boost::shared_ptr<Result> > struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
{ {
}; };
/** /// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
* Cast_Helper_Inner for casting to a const boost::shared_ptr<const> & type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> > : Cast_Helper_Inner<boost::shared_ptr<const Result> > struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> &> : Cast_Helper_Inner<boost::shared_ptr<const Result> > struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
{ {
}; };
/** /// Cast_Helper_Inner for casting to a Boxed_Value type
* Cast_Helper_Inner for casting to a Boxed_Value type
*/
template<> template<>
struct Cast_Helper_Inner<Boxed_Value> struct Cast_Helper_Inner<Boxed_Value>
{ {
typedef const Boxed_Value & Result_Type; typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{ {
return ob; return ob;
} }
}; };
/** /// Cast_Helper_Inner for casting to a Boxed_Value & type
* Cast_Helper_Inner for casting to a const Boxed_Value & type template<>
*/ struct Cast_Helper_Inner<Boxed_Value &>
{
typedef Boxed_Value& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
return const_cast<Boxed_Value &>(ob);
}
};
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
template<> template<>
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value> struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
{ {
@@ -220,50 +200,46 @@ namespace chaiscript
}; };
/** /// Cast_Helper_Inner for casting to a std::reference_wrapper type
* Cast_Helper_Inner for casting to a boost::reference_wrapper type
*/
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &> struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &> struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &> struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &> struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &> struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{ {
}; };
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &> struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
{ {
}; };
/** /// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
* The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
*/
template<typename T> template<typename T>
struct Cast_Helper struct Cast_Helper
{ {
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type; typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
{ {
return Cast_Helper_Inner<T>::cast(ob); return Cast_Helper_Inner<T>::cast(ob, t_conversions);
} }
}; };
} }

View File

@@ -1,34 +1,82 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
#define CHAISCRIPT_BOXED_NUMERIC_HPP_ #define CHAISCRIPT_BOXED_NUMERIC_HPP_
#include "boxed_value.hpp" #include <cstdint>
#include <sstream>
#include <string>
#include "../language/chaiscript_algebraic.hpp" #include "../language/chaiscript_algebraic.hpp"
#include <boost/cstdint.hpp> #include "any.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Type_Conversions;
} // namespace chaiscript
namespace chaiscript
{
namespace exception
{
struct arithmetic_error : std::runtime_error
{
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
arithmetic_error(const arithmetic_error &) = default;
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
};
}
}
namespace chaiscript namespace chaiscript
{ {
#ifdef BOOST_MSVC // Due to the nature of generating every possible arithmetic operation, there
// are going to be warnings generated on every platform regarding size and sign,
// this is OK, so we're disabling size/and sign type warnings
#ifdef CHAISCRIPT_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4244 4018 4389 4146) #pragma warning(disable : 4244 4018 4389 4146 4365)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif #endif
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_Number class Boxed_Number
{ {
private: private:
template<typename T>
static void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr)
{
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
if (t == 0) {
throw chaiscript::exception::arithmetic_error("divide by zero");
}
#endif
}
template<typename T>
static void check_divide_by_zero(T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr)
{
}
struct boolean struct boolean
{ {
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
template<typename T, typename U> template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{ {
@@ -47,7 +95,7 @@ namespace chaiscript
case Operators::not_equal: case Operators::not_equal:
return const_var(t != u); return const_var(t != u);
default: default:
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@@ -75,13 +123,14 @@ namespace chaiscript
t += u; t += u;
break; break;
case Operators::assign_quotient: case Operators::assign_quotient:
check_divide_by_zero(u);
t /= u; t /= u;
break; break;
case Operators::assign_difference: case Operators::assign_difference:
t -= u; t -= u;
break; break;
default: default:
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
return t_lhs; return t_lhs;
@@ -108,13 +157,14 @@ namespace chaiscript
t >>= u; t >>= u;
break; break;
case Operators::assign_remainder: case Operators::assign_remainder:
check_divide_by_zero(u);
t %= u; t %= u;
break; break;
case Operators::assign_bitwise_xor: case Operators::assign_bitwise_xor:
t ^= u; t ^= u;
break; break;
default: default:
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
return t_lhs; return t_lhs;
} }
@@ -132,6 +182,7 @@ namespace chaiscript
case Operators::shift_right: case Operators::shift_right:
return const_var(t >> u); return const_var(t >> u);
case Operators::remainder: case Operators::remainder:
check_divide_by_zero(u);
return const_var(t % u); return const_var(t % u);
case Operators::bitwise_and: case Operators::bitwise_and:
return const_var(t & u); return const_var(t & u);
@@ -142,7 +193,7 @@ namespace chaiscript
case Operators::bitwise_complement: case Operators::bitwise_complement:
return const_var(~t); return const_var(~t);
default: default:
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@@ -157,6 +208,7 @@ namespace chaiscript
case Operators::sum: case Operators::sum:
return const_var(t + u); return const_var(t + u);
case Operators::quotient: case Operators::quotient:
check_divide_by_zero(u);
return const_var(t / u); return const_var(t / u);
case Operators::product: case Operators::product:
return const_var(t * u); return const_var(t * u);
@@ -167,7 +219,7 @@ namespace chaiscript
case Operators::unary_plus: case Operators::unary_plus:
return const_var(+t); return const_var(+t);
default: default:
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@@ -180,16 +232,16 @@ namespace chaiscript
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
{ {
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) { } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const()) { } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_int::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return binary_int::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
return const_binary_int::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return const_binary_int::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::const_flag) { } else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else { } else {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@@ -202,16 +254,16 @@ namespace chaiscript
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
{ {
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) { } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} else if (t_oper > Operators::const_flag) { } else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs); return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else { } else {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
}; };
@@ -219,7 +271,7 @@ namespace chaiscript
template<typename LHS, bool Float> template<typename LHS, bool Float>
static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{ {
const Type_Info &inp_ = t_rhs.get_type_info(); const auto &inp_ = t_rhs.get_type_info();
if (inp_ == typeid(int)) { if (inp_ == typeid(int)) {
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
@@ -237,24 +289,24 @@ namespace chaiscript
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) { } else if (inp_ == typeid(unsigned long)) {
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) { } else if (inp_ == typeid(std::int8_t)) {
return Go<LHS, boost::int8_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) { } else if (inp_ == typeid(std::int16_t)) {
return Go<LHS, boost::int16_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) { } else if (inp_ == typeid(std::int32_t)) {
return Go<LHS, boost::int32_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) { } else if (inp_ == typeid(std::int64_t)) {
return Go<LHS, boost::int64_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) { } else if (inp_ == typeid(std::uint8_t)) {
return Go<LHS, boost::uint8_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) { } else if (inp_ == typeid(std::uint16_t)) {
return Go<LHS, boost::uint16_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) { } else if (inp_ == typeid(std::uint32_t)) {
return Go<LHS, boost::uint32_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) { } else if (inp_ == typeid(std::uint64_t)) {
return Go<LHS, boost::uint64_t, Float>::go(t_oper, t_lhs, t_rhs); return Go<LHS, std::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else { } else {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
@@ -278,24 +330,24 @@ namespace chaiscript
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs); return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) { } else if (inp_ == typeid(unsigned long)) {
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs); return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) { } else if (inp_ == typeid(std::int8_t)) {
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) { } else if (inp_ == typeid(std::int16_t)) {
return oper_rhs<boost::int16_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::int16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) { } else if (inp_ == typeid(std::int32_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) { } else if (inp_ == typeid(std::int64_t)) {
return oper_rhs<boost::int64_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::int64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) { } else if (inp_ == typeid(std::uint8_t)) {
return oper_rhs<boost::uint8_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::uint8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) { } else if (inp_ == typeid(std::uint16_t)) {
return oper_rhs<boost::uint16_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::uint16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) { } else if (inp_ == typeid(std::uint32_t)) {
return oper_rhs<boost::uint32_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::uint32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) { } else if (inp_ == typeid(std::uint64_t)) {
return oper_rhs<boost::uint64_t, false>(t_oper, t_lhs, t_rhs); return oper_rhs<std::uint64_t, false>(t_oper, t_lhs, t_rhs);
} else { } else {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
@@ -306,32 +358,78 @@ namespace chaiscript
} }
template<typename Source> template<typename Source>
std::string to_string_aux(const Boxed_Value &v) const static std::string to_string_aux(const Boxed_Value &v)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << *static_cast<const Source *>(v.get_const_ptr()); oss << *static_cast<const Source *>(v.get_const_ptr());
return oss.str(); return oss.str();
} }
public: public:
Boxed_Number() Boxed_Number()
: bv(Boxed_Value(0)) : bv(Boxed_Value(0))
{ {
} }
Boxed_Number(const Boxed_Value &v) Boxed_Number(Boxed_Value v)
: bv(v) : bv(std::move(v))
{ {
validate_boxed_number(v); validate_boxed_number(bv);
} }
Boxed_Number(const Boxed_Number &) = default;
#if !defined(_MSC_VER) || _MSC_VER != 1800
Boxed_Number(Boxed_Number &&) = default;
Boxed_Number& operator=(Boxed_Number &&) = default;
#endif
template<typename T> explicit Boxed_Number(T t) template<typename T> explicit Boxed_Number(T t)
: bv(Boxed_Value(t)) : bv(Boxed_Value(t))
{ {
validate_boxed_number(bv); validate_boxed_number(bv);
} }
Boxed_Number get_as(const Type_Info &inp_) const
{
if (inp_.bare_equal_type_info(typeid(int))) {
return Boxed_Number(get_as<int>());
} else if (inp_.bare_equal_type_info(typeid(double))) {
return Boxed_Number(get_as<double>());
} else if (inp_.bare_equal_type_info(typeid(float))) {
return Boxed_Number(get_as<float>());
} else if (inp_.bare_equal_type_info(typeid(long double))) {
return Boxed_Number(get_as<long double>());
} else if (inp_.bare_equal_type_info(typeid(char))) {
return Boxed_Number(get_as<char>());
} else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
return Boxed_Number(get_as<unsigned int>());
} else if (inp_.bare_equal_type_info(typeid(long))) {
return Boxed_Number(get_as<long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
return Boxed_Number(get_as<unsigned long>());
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
return Boxed_Number(get_as<int8_t>());
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {
return Boxed_Number(get_as<int16_t>());
} else if (inp_.bare_equal_type_info(typeid(int32_t))) {
return Boxed_Number(get_as<int32_t>());
} else if (inp_.bare_equal_type_info(typeid(int64_t))) {
return Boxed_Number(get_as<int64_t>());
} else if (inp_.bare_equal_type_info(typeid(uint8_t))) {
return Boxed_Number(get_as<uint8_t>());
} else if (inp_.bare_equal_type_info(typeid(uint16_t))) {
return Boxed_Number(get_as<uint16_t>());
} else if (inp_.bare_equal_type_info(typeid(uint32_t))) {
return Boxed_Number(get_as<uint32_t>());
} else if (inp_.bare_equal_type_info(typeid(uint64_t))) {
return Boxed_Number(get_as<uint64_t>());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename Target> Target get_as() const template<typename Target> Target get_as() const
{ {
const Type_Info &inp_ = bv.get_type_info(); const Type_Info &inp_ = bv.get_type_info();
@@ -352,24 +450,24 @@ namespace chaiscript
return get_as_aux<Target, long>(); return get_as_aux<Target, long>();
} else if (inp_ == typeid(unsigned long)) { } else if (inp_ == typeid(unsigned long)) {
return get_as_aux<Target, unsigned long>(); return get_as_aux<Target, unsigned long>();
} else if (inp_ == typeid(boost::int8_t)) { } else if (inp_ == typeid(std::int8_t)) {
return get_as_aux<Target, boost::int8_t>(); return get_as_aux<Target, std::int8_t>();
} else if (inp_ == typeid(boost::int16_t)) { } else if (inp_ == typeid(std::int16_t)) {
return get_as_aux<Target, boost::int16_t>(); return get_as_aux<Target, std::int16_t>();
} else if (inp_ == typeid(boost::int32_t)) { } else if (inp_ == typeid(std::int32_t)) {
return get_as_aux<Target, boost::int32_t>(); return get_as_aux<Target, std::int32_t>();
} else if (inp_ == typeid(boost::int64_t)) { } else if (inp_ == typeid(std::int64_t)) {
return get_as_aux<Target, boost::int64_t>(); return get_as_aux<Target, std::int64_t>();
} else if (inp_ == typeid(boost::uint8_t)) { } else if (inp_ == typeid(std::uint8_t)) {
return get_as_aux<Target, boost::uint8_t>(); return get_as_aux<Target, std::uint8_t>();
} else if (inp_ == typeid(boost::uint16_t)) { } else if (inp_ == typeid(std::uint16_t)) {
return get_as_aux<Target, boost::uint16_t>(); return get_as_aux<Target, std::uint16_t>();
} else if (inp_ == typeid(boost::uint32_t)) { } else if (inp_ == typeid(std::uint32_t)) {
return get_as_aux<Target, boost::uint32_t>(); return get_as_aux<Target, std::uint32_t>();
} else if (inp_ == typeid(boost::uint64_t)) { } else if (inp_ == typeid(std::uint64_t)) {
return get_as_aux<Target, boost::uint64_t>(); return get_as_aux<Target, std::uint64_t>();
} else { } else {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
@@ -393,24 +491,24 @@ namespace chaiscript
return to_string_aux<long>(bv); return to_string_aux<long>(bv);
} else if (inp_ == typeid(unsigned long)) { } else if (inp_ == typeid(unsigned long)) {
return to_string_aux<unsigned long>(bv); return to_string_aux<unsigned long>(bv);
} else if (inp_ == typeid(boost::int8_t)) { } else if (inp_ == typeid(std::int8_t)) {
return to_string_aux<int>(Boxed_Value(get_as_aux<int, boost::int8_t>())); return to_string_aux<int>(Boxed_Value(get_as_aux<int, std::int8_t>()));
} else if (inp_ == typeid(boost::int16_t)) { } else if (inp_ == typeid(std::int16_t)) {
return to_string_aux<boost::int16_t>(bv); return to_string_aux<std::int16_t>(bv);
} else if (inp_ == typeid(boost::int32_t)) { } else if (inp_ == typeid(std::int32_t)) {
return to_string_aux<boost::int32_t>(bv); return to_string_aux<std::int32_t>(bv);
} else if (inp_ == typeid(boost::int64_t)) { } else if (inp_ == typeid(std::int64_t)) {
return to_string_aux<boost::int64_t>(bv); return to_string_aux<std::int64_t>(bv);
} else if (inp_ == typeid(boost::uint8_t)) { } else if (inp_ == typeid(std::uint8_t)) {
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, boost::uint8_t>())); return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, std::uint8_t>()));
} else if (inp_ == typeid(boost::uint16_t)) { } else if (inp_ == typeid(std::uint16_t)) {
return to_string_aux<boost::uint16_t>(bv); return to_string_aux<std::uint16_t>(bv);
} else if (inp_ == typeid(boost::uint32_t)) { } else if (inp_ == typeid(std::uint32_t)) {
return to_string_aux<boost::uint32_t>(bv); return to_string_aux<std::uint32_t>(bv);
} else if (inp_ == typeid(boost::uint64_t)) { } else if (inp_ == typeid(std::uint64_t)) {
return to_string_aux<boost::uint64_t>(bv); return to_string_aux<std::uint64_t>(bv);
} else { } else {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
@@ -479,20 +577,21 @@ namespace chaiscript
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv); return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
} }
void validate_boxed_number(const Boxed_Value &v) static void validate_boxed_number(const Boxed_Value &v)
{ {
const Type_Info &inp_ = v.get_type_info(); const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool)) if (inp_ == typeid(bool))
{ {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
if (!inp_.is_arithmetic()) if (!inp_.is_arithmetic())
{ {
throw boost::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
} }
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Value &v) Boxed_Number operator=(const Boxed_Value &v)
{ {
validate_boxed_number(v); validate_boxed_number(v);
@@ -500,6 +599,7 @@ namespace chaiscript
return *this; return *this;
} }
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Number &t_rhs) const Boxed_Number operator=(const Boxed_Number &t_rhs) const
{ {
return oper(Operators::assign, this->bv, t_rhs.bv); return oper(Operators::assign, this->bv, t_rhs.bv);
@@ -772,38 +872,36 @@ namespace chaiscript
namespace detail namespace detail
{ {
/** /// Cast_Helper for converting from Boxed_Value to Boxed_Number
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<> template<>
struct Cast_Helper<Boxed_Number> struct Cast_Helper<Boxed_Number>
{ {
typedef Boxed_Number Result_Type; typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{ {
return Boxed_Number(ob); return Boxed_Number(ob);
} }
}; };
/** /// Cast_Helper for converting from Boxed_Value to Boxed_Number
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<> template<>
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number> struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
{ {
}; };
/** /// Cast_Helper for converting from Boxed_Value to Boxed_Number
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<> template<>
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number> struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
{ {
}; };
} }
#ifdef BOOST_MSVC #ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

@@ -1,26 +1,19 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_ #ifndef CHAISCRIPT_BOXED_VALUE_HPP_
#define CHAISCRIPT_BOXED_VALUE_HPP_ #define CHAISCRIPT_BOXED_VALUE_HPP_
#include "type_info.hpp"
#include "../chaiscript_threading.hpp"
#include <map> #include <map>
#include <boost/shared_ptr.hpp> #include <memory>
#include <boost/make_shared.hpp> #include <type_traits>
#include <boost/any.hpp>
#include <boost/function.hpp> #include "../chaiscript_defines.hpp"
#include <boost/ref.hpp> #include "any.hpp"
#include <boost/bind.hpp> #include "type_info.hpp"
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/integer_traits.hpp>
namespace chaiscript namespace chaiscript
{ {
@@ -30,25 +23,23 @@ namespace chaiscript
class Boxed_Value class Boxed_Value
{ {
public: public:
/** /// used for explicitly creating a "void" object
* used for explicitly creating a "void" object
*/
struct Void_Type struct Void_Type
{ {
}; };
private: private:
/** /// structure which holds the internal state of a Boxed_Value
* structure which holds the internal state of a Boxed_Value /// \todo Get rid of Any and merge it with this, reducing an allocation in the process
*/
struct Data struct Data
{ {
Data(const Type_Info &ti, Data(const Type_Info &ti,
const boost::any &to, chaiscript::detail::Any to,
bool tr, bool tr,
const void *t_void_ptr) const void *t_void_ptr,
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?0:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr), bool t_return_value)
m_is_ref(tr) : m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
m_is_ref(tr), m_return_value(t_return_value)
{ {
} }
@@ -59,211 +50,285 @@ namespace chaiscript
m_is_ref = rhs.m_is_ref; m_is_ref = rhs.m_is_ref;
m_data_ptr = rhs.m_data_ptr; m_data_ptr = rhs.m_data_ptr;
m_const_data_ptr = rhs.m_const_data_ptr; m_const_data_ptr = rhs.m_const_data_ptr;
m_return_value = rhs.m_return_value;
if (rhs.m_attrs)
{
m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*rhs.m_attrs));
}
return *this; return *this;
} }
~Data() Data(const Data &) = delete;
{
} #if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
Data(Data &&) = default;
Data &operator=(Data &&rhs) = default;
#endif
Type_Info m_type_info; Type_Info m_type_info;
boost::any m_obj; chaiscript::detail::Any m_obj;
void *m_data_ptr; void *m_data_ptr;
const void *m_const_data_ptr; const void *m_const_data_ptr;
std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>> m_attrs;
bool m_is_ref; bool m_is_ref;
bool m_return_value;
}; };
struct Object_Data struct Object_Data
{ {
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type) static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
{ {
return boost::make_shared<Data>( return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(), detail::Get_Type_Info<void>::get(),
boost::any(), chaiscript::detail::Any(),
false, false,
static_cast<void *>(0)); nullptr,
t_return_value)
;
} }
template<typename T> template<typename T>
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj) static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
{ {
return get(*obj); return get(*obj, t_return_value);
} }
template<typename T> template<typename T>
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj) static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
{ {
return boost::make_shared<Data>( return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(), detail::Get_Type_Info<T>::get(),
boost::any(obj), chaiscript::detail::Any(obj),
false, false,
obj.get()); obj.get(),
t_return_value
);
} }
template<typename T> template<typename T>
static boost::shared_ptr<Data> get(T *t) static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
{ {
return get(boost::ref(*t)); auto ptr = obj.get();
} return std::make_shared<Data>(
template<typename T>
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
{
return boost::make_shared<Data>(
detail::Get_Type_Info<T>::get(), detail::Get_Type_Info<T>::get(),
boost::any(obj), chaiscript::detail::Any(std::move(obj)),
false,
ptr,
t_return_value
);
}
template<typename T>
static std::shared_ptr<Data> get(T *t, bool t_return_value)
{
return get(std::ref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
{
return get(std::cref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
{
auto p = &obj.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
true, true,
obj.get_pointer()); p,
t_return_value
);
} }
template<typename T> template<typename T>
static boost::shared_ptr<Data> get(const T& t) static std::shared_ptr<Data> get(T t, bool t_return_value)
{ {
boost::shared_ptr<T> p(new T(t)); auto p = std::make_shared<T>(std::move(t));
return boost::make_shared<Data>( auto ptr = p.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(), detail::Get_Type_Info<T>::get(),
boost::any(p), chaiscript::detail::Any(std::move(p)),
false, false,
p.get()); ptr,
t_return_value
);
} }
static boost::shared_ptr<Data> get() static std::shared_ptr<Data> get()
{ {
return boost::make_shared<Data>( return std::make_shared<Data>(
Type_Info(), Type_Info(),
boost::any(), chaiscript::detail::Any(),
false, false,
static_cast<void *>(0)); nullptr,
false
);
} }
}; };
public: public:
/** /// Basic Boxed_Value constructor
* Basic Boxed_Value constructor template<typename T,
*/ typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
template<typename T> explicit Boxed_Value(T &&t, bool t_return_value = false)
explicit Boxed_Value(T t) : m_data(Object_Data::get(std::forward<T>(t), t_return_value))
: m_data(Object_Data::get(t))
{ {
} }
/** /// Unknown-type constructor
* Copy constructor - each copy shares the same data pointer
*/
Boxed_Value(const Boxed_Value &t_so)
: m_data(t_so.m_data)
{
}
/**
* Unknown-type constructor
*/
Boxed_Value() Boxed_Value()
: m_data(Object_Data::get()) : m_data(Object_Data::get())
{ {
} }
~Boxed_Value() #if !defined(_MSC_VER) || _MSC_VER != 1800
{ Boxed_Value(Boxed_Value&&) = default;
} Boxed_Value& operator=(Boxed_Value&&) = default;
#endif
Boxed_Value(const Boxed_Value&) = default;
Boxed_Value& operator=(const Boxed_Value&) = default;
void swap(Boxed_Value &rhs) void swap(Boxed_Value &rhs)
{ {
std::swap(m_data, rhs.m_data); std::swap(m_data, rhs.m_data);
} }
/** /// Copy the values stored in rhs.m_data to m_data.
* copy the values stored in rhs.m_data to m_data /// m_data pointers are not shared in this case
* m_data pointers are not shared in this case
*/
Boxed_Value assign(const Boxed_Value &rhs) Boxed_Value assign(const Boxed_Value &rhs)
{ {
(*m_data) = (*rhs.m_data); (*m_data) = (*rhs.m_data);
return *this; return *this;
} }
/** const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
* shared data assignment, same as copy construction
*/
Boxed_Value &operator=(const Boxed_Value &rhs)
{
Boxed_Value temp(rhs);
swap(temp);
return *this;
}
const Type_Info &get_type_info() const
{ {
return m_data->m_type_info; return m_data->m_type_info;
} }
/** /// return true if the object is uninitialized
* return true if the object is uninitialized bool is_undef() const CHAISCRIPT_NOEXCEPT
*/
bool is_undef() const
{ {
return m_data->m_type_info.is_undef(); return m_data->m_type_info.is_undef();
} }
bool is_const() const bool is_const() const CHAISCRIPT_NOEXCEPT
{ {
return m_data->m_type_info.is_const(); return m_data->m_type_info.is_const();
} }
bool is_type(const Type_Info &ti) const bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{ {
return m_data->m_type_info.bare_equal(ti); return m_data->m_type_info.bare_equal(ti);
} }
bool is_null() const bool is_null() const CHAISCRIPT_NOEXCEPT
{ {
return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0); return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
} }
const boost::any & get() const const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
{ {
return m_data->m_obj; return m_data->m_obj;
} }
bool is_ref() const bool is_ref() const CHAISCRIPT_NOEXCEPT
{ {
return m_data->m_is_ref; return m_data->m_is_ref;
} }
bool is_pointer() const bool is_return_value() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_return_value;
}
void reset_return_value() const CHAISCRIPT_NOEXCEPT
{
m_data->m_return_value = false;
}
bool is_pointer() const CHAISCRIPT_NOEXCEPT
{ {
return !is_ref(); return !is_ref();
} }
void *get_ptr() const void *get_ptr() const CHAISCRIPT_NOEXCEPT
{ {
return m_data->m_data_ptr; return m_data->m_data_ptr;
} }
const void *get_const_ptr() const const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
{ {
return m_data->m_const_data_ptr; return m_data->m_const_data_ptr;
} }
Boxed_Value get_attr(const std::string &t_name)
{
if (!m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>());
}
auto &attr = (*m_data->m_attrs)[t_name];
if (attr) {
return Boxed_Value(attr, Internal_Construction());
} else {
Boxed_Value bv; //default construct a new one
attr = bv.m_data;
return bv;
}
}
Boxed_Value &copy_attrs(const Boxed_Value &t_obj)
{
if (t_obj.m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*t_obj.m_data->m_attrs));
}
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
{
return l.get_type_info() == r.get_type_info();
}
private: private:
boost::shared_ptr<Data> m_data; // necessary to avoid hitting the templated && constructor of Boxed_Value
struct Internal_Construction{};
Boxed_Value(const std::shared_ptr<Data> &t_data, Internal_Construction)
: m_data(t_data) {
}
std::shared_ptr<Data> m_data;
}; };
/// \brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, boost::shared_ptr, or boost::reference_type /// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
/// a copy is not made. /// a copy is not made.
/// \param t The value to box /// @param t The value to box
/// ///
/// Example: /// Example:
/// \code ///
/// ~~~{.cpp}
/// int i; /// int i;
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::var(i), "i"); /// chai.add(chaiscript::var(i), "i");
/// chai.add(chaiscript::var(&i), "ip"); /// chai.add(chaiscript::var(&i), "ip");
/// \endcode /// ~~~
/// ///
/// \sa \ref addingobjects /// @sa @ref adding_objects
template<typename T> template<typename T>
Boxed_Value var(T t) Boxed_Value var(T t)
{ {
@@ -278,7 +343,7 @@ namespace chaiscript
template<typename T> template<typename T>
Boxed_Value const_var_impl(const T &t) Boxed_Value const_var_impl(const T &t)
{ {
return Boxed_Value(boost::shared_ptr<typename boost::add_const<T>::type >(new T(t))); return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
} }
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value. /// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
@@ -289,33 +354,33 @@ namespace chaiscript
template<typename T> template<typename T>
Boxed_Value const_var_impl(T *t) Boxed_Value const_var_impl(T *t)
{ {
return Boxed_Value( const_cast<typename boost::add_const<T>::type *>(t) ); return Boxed_Value( const_cast<typename std::add_const<T>::type *>(t) );
} }
/// \brief Takes a boost::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value. /// \brief Takes a std::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
/// Does not copy the pointed to value. /// Does not copy the pointed to value.
/// \param[in] t Pointer to make immutable /// \param[in] t Pointer to make immutable
/// \returns Immutable Boxed_Value /// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const /// \sa Boxed_Value::is_const
template<typename T> template<typename T>
Boxed_Value const_var_impl(const boost::shared_ptr<T> &t) Boxed_Value const_var_impl(const std::shared_ptr<T> &t)
{ {
return Boxed_Value( boost::const_pointer_cast<typename boost::add_const<T>::type>(t) ); return Boxed_Value( std::const_pointer_cast<typename std::add_const<T>::type>(t) );
} }
/// \brief Takes a boost::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value. /// \brief Takes a std::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
/// Does not copy the referenced value. /// Does not copy the referenced value.
/// \param[in] t Reference object to make immutable /// \param[in] t Reference object to make immutable
/// \returns Immutable Boxed_Value /// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const /// \sa Boxed_Value::is_const
template<typename T> template<typename T>
Boxed_Value const_var_impl(const boost::reference_wrapper<T> &t) Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
{ {
return Boxed_Value( boost::cref(t.get()) ); return Boxed_Value( std::cref(t.get()) );
} }
} }
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a boost::reference or pointer type /// \brief Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer type
/// the value is not copied. If it is an object type, it is copied. /// the value is not copied. If it is an object type, it is copied.
/// \param[in] t Object to make immutable /// \param[in] t Object to make immutable
/// \returns Immutable Boxed_Value /// \returns Immutable Boxed_Value
@@ -336,20 +401,27 @@ namespace chaiscript
/// chai.add(chaiscript::const_var(Green), "Green"); /// chai.add(chaiscript::const_var(Green), "Green");
/// \endcode /// \endcode
/// ///
/// \sa \ref addingobjects /// \todo support C++11 strongly typed enums
/// \sa \ref adding_objects
template<typename T> template<typename T>
Boxed_Value const_var(const T &t) Boxed_Value const_var(const T &t)
{ {
return detail::const_var_impl(t); return detail::const_var_impl(t);
} }
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
inline Boxed_Value const_var(bool b) {
static auto t = detail::const_var_impl(true);
static auto f = detail::const_var_impl(false);
if (b) {
/// \returns true if the two Boxed_Values share the same internal type return t;
static bool type_match(Boxed_Value l, Boxed_Value r) } else {
{ return f;
return l.get_type_info() == r.get_type_info();
} }
}
#endif
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,290 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#include "type_info.hpp"
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include "bad_boxed_cast.hpp"
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace chaiscript
{
namespace exception
{
class bad_boxed_dynamic_cast : public bad_boxed_cast
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) throw()
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) throw()
: bad_boxed_cast(w)
{
}
virtual ~bad_boxed_dynamic_cast() throw() {}
};
}
namespace detail
{
class Dynamic_Conversion
{
public:
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
const Type_Info &base()
{
return m_base;
}
const Type_Info &derived()
{
return m_derived;
}
protected:
Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived)
: m_base(t_base), m_derived(t_derived)
{
}
virtual ~Dynamic_Conversion() {}
private:
Type_Info m_base;
Type_Info m_derived;
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Dynamic_Conversion
{
public:
Dynamic_Conversion_Impl()
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
{
}
virtual Boxed_Value convert(const Boxed_Value &t_derived)
{
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
{
if (t_derived.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
boost::shared_ptr<const Base> data
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
} else {
boost::shared_ptr<Base> data
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_derived.is_const())
{
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
const Base &data = dynamic_cast<const Base &>(d);
return Boxed_Value(boost::cref(data));
} else {
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
Base &data = dynamic_cast<Base &>(d);
return Boxed_Value(boost::ref(data));
}
}
} else {
throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
}
}
};
class Dynamic_Conversions
{
public:
static inline Dynamic_Conversions &get()
{
static Dynamic_Conversions obj;
return obj;
}
template<typename Base, typename Derived>
static boost::shared_ptr<Dynamic_Conversion> create()
{
boost::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
/// \todo this is a hack and a kludge. The idea is to make sure that
/// the conversion is registered both in the module's notion of the static conversion object
/// and in the global notion of the static conversion object
/// someday this will almost certainly have to change. Maybe it is time for ChaiScript
/// to become a library?
Dynamic_Conversions::get().add_conversion(conversion);
return conversion;
}
template<typename InItr>
void cleanup(InItr begin, const InItr &end)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
while (begin != end)
{
if (begin->unique())
{
m_conversions.erase(begin->get());
}
++begin;
}
}
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion.get());
}
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end();
}
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<Dynamic_Conversion *>::const_iterator itr =
find(base, derived);
if (itr != m_conversions.end())
{
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
}
}
private:
Dynamic_Conversions() {}
std::set<Dynamic_Conversion *>::const_iterator find(
const Type_Info &base, const Type_Info &derived) const
{
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
itr != m_conversions.end();
++itr)
{
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
{
return itr;
}
}
return m_conversions.end();
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<Dynamic_Conversion *> m_conversions;
};
}
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
/// want automatic conversions up your inheritance hierarchy.
///
/// Create a new base class registration for applying to a module or to the chaiscript engine
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
/// if you have a type that is introduced in a loadable module and is used by multiple modules
/// (through a tertiary dll that is shared between the modules, static linking the new type
/// into both loadable modules would not be portable), you need to register the base type
/// relationship in all modules that use the newly added type in a polymorphic way.
///
/// Example:
/// \code
/// class Base
/// {};
/// class Derived : public Base
/// {};
///
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<Base, Derived>());
/// \endcode
///
/// \todo Move share static type registration code into a mechanism that allows it to be properly
/// shared by all modules
template<typename Base, typename Derived>
Dynamic_Cast_Conversion base_class()
{
//Can only be used with related polymorphic types
//may be expanded some day to support conversions other than child -> parent
BOOST_STATIC_ASSERT((boost::is_base_of<Base,Derived>::value));
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
return detail::Dynamic_Conversions::create<Base, Derived>();
}
namespace detail
{
template<typename Base, typename Derived>
bool dynamic_cast_converts()
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
{
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
{
try {
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
}
}
#endif

View File

@@ -1,13 +1,24 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_ #ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_ #define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#include <boost/optional.hpp> #include <map>
#include <string>
#include <utility>
#include "boxed_value.hpp"
namespace chaiscript {
class Type_Conversions;
namespace dispatch {
class Proxy_Function_Base;
} // namespace dispatch
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
@@ -16,8 +27,12 @@ namespace chaiscript
class Dynamic_Object class Dynamic_Object
{ {
public: public:
Dynamic_Object(const std::string &t_type_name) Dynamic_Object(std::string t_type_name)
: m_type_name(t_type_name) : m_type_name(std::move(t_type_name))
{
}
Dynamic_Object() : m_type_name("")
{ {
} }
@@ -26,12 +41,34 @@ namespace chaiscript
return m_type_name; return m_type_name;
} }
Boxed_Value get_attr(const std::string &t_attr_name) const Boxed_Value &get_attr(const std::string &t_attr_name) const
{
auto a = m_attrs.find(t_attr_name);
if (a != m_attrs.end()) {
return a->second;
} else {
throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
}
}
Boxed_Value &get_attr(const std::string &t_attr_name)
{ {
return m_attrs[t_attr_name]; return m_attrs[t_attr_name];
} }
std::map<std::string, Boxed_Value> get_attrs() Boxed_Value &method_missing(const std::string &t_method_name)
{
return get_attr(t_method_name);
}
const Boxed_Value &method_missing(const std::string &t_method_name) const
{
return get_attr(t_method_name);
}
std::map<std::string, Boxed_Value> get_attrs() const
{ {
return m_attrs; return m_attrs;
} }
@@ -42,228 +79,6 @@ namespace chaiscript
std::map<std::string, Boxed_Value> m_attrs; std::map<std::string, Boxed_Value> m_attrs;
}; };
namespace detail
{
/**
* A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func,
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
virtual bool operator==(const Proxy_Function_Base &f) const
{
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
if (df)
{
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
{
return m_func->call_match(vals);
} else {
return false;
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
{
std::vector<Const_Proxy_Function> fs;
fs.push_back(m_func);
return fs;
}
virtual int get_arity() const
{
return m_func->get_arity();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
if (dynamic_object_typename_match(params, m_type_name, m_ti))
{
return (*m_func)(params);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv) const
{
return dynamic_object_typename_match(bv, m_type_name, m_ti);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
{
if (t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = *t_objectti;
return types;
} else {
return t_inner_types;
}
}
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const boost::optional<Type_Info> &ti)
{
static Type_Info doti = user_type<Dynamic_Object>();
if (bv.get_type_info().bare_equal(doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
if (ti)
{
return bv.get_type_info().bare_equal(*ti);
} else {
return false;
}
}
}
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const boost::optional<Type_Info> &ti)
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
boost::optional<Type_Info> m_ti;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
const std::string &t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
m_type_name(t_type_name), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
std::vector<Type_Info>::const_iterator begin = tl.begin();
std::vector<Type_Info>::const_iterator end = tl.end();
if (begin != end)
{
++begin;
}
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
if (dc)
{
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals);
}
virtual int get_arity() const
{
// "this" is not considered part of the arity
return m_func->get_arity() - 1;
}
virtual std::string annotation() const
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
} }
} }
#endif #endif

View File

@@ -0,0 +1,253 @@
// 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)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
#include <cassert>
#include <map>
#include <memory>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "proxy_functions.hpp"
#include "type_info.hpp"
#include "dynamic_object.hpp"
namespace chaiscript {
class Type_Conversions;
namespace dispatch {
class Proxy_Function_Base;
} // namespace dispatch
} // namespace chaiscript
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
bool t_is_attribute = false)
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
m_is_attribute(t_is_attribute)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
const Type_Info &t_ti,
bool t_is_attribute = false)
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>()),
m_is_attribute(t_is_attribute)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
{
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
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
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
return m_func->call_match(vals, t_conversions);
} else {
return false;
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
{
return {m_func};
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
return (*m_func)(params, t_conversions);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
//assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = t_objectti;
return types;
}
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
{
if (bv.get_type_info().bare_equal(m_doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
if (ti)
{
return bv.get_type_info().bare_equal(*ti);
} else {
return false;
}
}
}
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
bool m_is_attribute;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
m_type_name(std::move(t_type_name)), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
auto begin = tl.begin();
auto end = tl.end();
if (begin != end)
{
++begin;
}
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
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
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
auto bv = var(Dynamic_Object(m_type_name));
std::vector<Boxed_Value> new_params{bv};
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
}
}
#endif

View File

@@ -1,79 +1,102 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ #ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ #define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#include <memory>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp" #include "boxed_cast.hpp"
namespace chaiscript {
class Boxed_Value;
namespace exception {
class bad_boxed_cast;
} // namespace exception
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
namespace detail namespace detail
{ {
/// \todo make this a variadic template
struct Exception_Handler_Base struct Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) = 0; virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
virtual ~Exception_Handler_Base() {}
protected: protected:
template<typename T> template<typename T>
void throw_type(const Boxed_Value &bv) void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
try { T t = boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {} try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
} }
}; };
template<typename T1> template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base struct Exception_Handler_Impl1 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual ~Exception_Handler_Impl1() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base struct Exception_Handler_Impl2 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual ~Exception_Handler_Impl2() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
} }
}; };
template<typename T1, typename T2, typename T3> template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base struct Exception_Handler_Impl3 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual ~Exception_Handler_Impl3() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
throw_type<T3>(bv); throw_type<T3>(bv, t_engine);
} }
}; };
template<typename T1, typename T2, typename T3, typename T4> template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base struct Exception_Handler_Impl4 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual ~Exception_Handler_Impl4() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
throw_type<T3>(bv); throw_type<T3>(bv, t_engine);
throw_type<T4>(bv); throw_type<T4>(bv, t_engine);
} }
}; };
template<typename T1, typename T2, typename T3, typename T4, typename T5> template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base struct Exception_Handler_Impl5 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual ~Exception_Handler_Impl5() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
throw_type<T3>(bv); throw_type<T3>(bv, t_engine);
throw_type<T4>(bv); throw_type<T4>(bv, t_engine);
throw_type<T5>(bv); throw_type<T5>(bv, t_engine);
} }
}; };
} }
@@ -128,7 +151,7 @@ namespace chaiscript
/// ///
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects /// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
/// \sa \ref exceptions /// \sa \ref exceptions
typedef boost::shared_ptr<detail::Exception_Handler_Base> Exception_Handler; typedef std::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing /// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions /// \sa \ref exceptions

View File

@@ -1,131 +1,122 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_ #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_HPP_ #define CHAISCRIPT_FUNCTION_CALL_HPP_
#include <boost/shared_ptr.hpp> #include <functional>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include "proxy_functions.hpp"
#include "boxed_cast.hpp"
#include "function_call_detail.hpp" #include "function_call_detail.hpp"
#include "proxy_functions.hpp"
namespace chaiscript {
#include <iostream> class Boxed_Value;
class Type_Conversions;
namespace detail {
template <typename T> struct Cast_Helper;
} // namespace detail
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
namespace dispatch namespace dispatch
{ {
/** /// Build a function caller that knows how to dispatch on a set of functions
* Build a function caller that knows how to dispatch on a set of functions /// example:
* example: /// std::function<void (int)> f =
* boost::function<void (int)> f = /// build_function_caller(dispatchkit.get_function("print"));
* build_function_caller(dispatchkit.get_function("print")); /// \returns A std::function object for dispatching
* \returns A boost::function object for dispatching /// \param[in] funcs the set of functions to dispatch on.
* \param[in] funcs the set of functions to dispatch on.
*/
template<typename FunctionType> template<typename FunctionType>
boost::function<FunctionType> std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs) functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
{ {
FunctionType *p=0; FunctionType *p=nullptr;
return detail::build_function_caller_helper(p, funcs); return detail::build_function_caller_helper(p, funcs, t_conversions);
} }
/** /// Build a function caller for a particular Proxy_Function object
* Build a function caller for a particular Proxy_Function object /// useful in the case that a function is being pass out from scripting back
* useful in the case that a function is being pass out from scripting back /// into code
* into code /// example:
* example: /// void my_function(Proxy_Function f)
* void my_function(Proxy_Function f) /// {
* { /// std::function<void (int)> local_f =
* boost::function<void (int)> local_f = /// build_function_caller(f);
* build_function_caller(f); /// }
* } /// \returns A std::function object for dispatching
* \returns A boost::function object for dispatching /// \param[in] func A function to execute.
* \param[in] func A function to execute.
*/
template<typename FunctionType> template<typename FunctionType>
boost::function<FunctionType> std::function<FunctionType>
functor(Const_Proxy_Function func) functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
{ {
std::vector<Const_Proxy_Function> funcs; return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
funcs.push_back(func);
return functor<FunctionType>(funcs);
} }
/** /// Helper for automatically unboxing a Boxed_Value that contains a function object
* Helper for automatically unboxing a Boxed_Value that contains a function object /// and creating a typesafe C++ function caller from it.
* and creating a typesafe C++ function caller from it.
*/
template<typename FunctionType> template<typename FunctionType>
boost::function<FunctionType> std::function<FunctionType>
functor(const Boxed_Value &bv) functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
{ {
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv)); return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
} }
} }
namespace detail{ namespace detail{
/** /// Cast helper to handle automatic casting to const std::function &
* Cast helper to handle automatic casting to const boost::function &
*/
template<typename Signature> template<typename Signature>
struct Cast_Helper<const boost::function<Signature> &> struct Cast_Helper<const std::function<Signature> &>
{ {
typedef boost::function<Signature> Result_Type; typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
{ {
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{ {
return dispatch::functor<Signature>(ob); return dispatch::functor<Signature>(ob, t_conversions);
} else { } else {
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob); return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
} }
} }
}; };
/** /// Cast helper to handle automatic casting to std::function
* Cast helper to handle automatic casting to boost::function
*/
template<typename Signature> template<typename Signature>
struct Cast_Helper<boost::function<Signature> > struct Cast_Helper<std::function<Signature> >
{ {
typedef boost::function<Signature> Result_Type; typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
{ {
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{ {
return dispatch::functor<Signature>(ob); return dispatch::functor<Signature>(ob, t_conversions);
} else { } else {
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob); return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
} }
} }
}; };
/** /// Cast helper to handle automatic casting to const std::function
* Cast helper to handle automatic casting to const boost::function
*/
template<typename Signature> template<typename Signature>
struct Cast_Helper<const boost::function<Signature> > struct Cast_Helper<const std::function<Signature> >
{ {
typedef boost::function<Signature> Result_Type; typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
{ {
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{ {
return dispatch::functor<Signature>(ob); return dispatch::functor<Signature>(ob, t_conversions);
} else { } else {
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob); return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
} }
} }
}; };

View File

@@ -1,24 +1,22 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define addparam(z,n,text) params.push_back((boost::is_reference<Param ## n>::value&&!(boost::is_same<chaiscript::Boxed_Value, typename boost::remove_const<typename boost::remove_reference<Param ## n>::type>::type>::value))?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ #define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#include <boost/shared_ptr.hpp> #include <functional>
#include <boost/bind.hpp> #include <memory>
#include <boost/function.hpp>
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
#include "boxed_cast.hpp"
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "type_conversions.hpp"
#include "proxy_functions.hpp" #include "proxy_functions.hpp"
namespace chaiscript namespace chaiscript
@@ -27,76 +25,80 @@ namespace chaiscript
{ {
namespace detail namespace detail
{ {
/// Internal helper class for handling the return
/** /// value of a build_function_caller
* Internal helper class for handling the return template<typename Ret, bool is_arithmetic>
* value of a build_function_caller
*/
template<typename Ret>
struct Function_Caller_Ret struct Function_Caller_Ret
{ {
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs, static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{ {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params)); return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
} }
}; };
/**
* Specialization for arithmetic return types
*/
template<typename Ret>
struct Function_Caller_Ret<Ret, true>
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
}
};
/** /**
* Specialization for void return types * Specialization for void return types
*/ */
template<> template<>
struct Function_Caller_Ret<void> struct Function_Caller_Ret<void, false>
{ {
static void call(const std::vector<Const_Proxy_Function> &t_funcs, static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{ {
dispatch::dispatch(t_funcs, params); dispatch::dispatch(t_funcs, params, t_conversions);
} }
}; };
}
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 9 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/function_call_detail.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
std::vector<Boxed_Value> params;
BOOST_PP_REPEAT(n, addparam, ~)
return Function_Caller_Ret<Ret>::call(funcs, params);
}
/** /**
* used internally for unwrapping a function call's types * used internally for unwrapping a function call's types
*/ */
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Ret, typename ... Param>
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) > struct Build_Function_Caller_Helper
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs) {
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
: m_funcs(std::move(t_funcs)),
m_conversions(t_conversions)
{
}
Ret operator()(Param...param)
{
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
}, m_conversions
);
}
std::vector<Const_Proxy_Function> m_funcs;
Type_Conversions m_conversions;
};
template<typename Ret, typename ... Params>
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
{ {
if (funcs.size() == 1) if (funcs.size() == 1)
{ {
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi = std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
(funcs[0]); (funcs[0]);
if (pfi) if (pfi)
@@ -107,15 +109,11 @@ namespace chaiscript
// we cannot make any other guesses or assumptions really, so continuing // we cannot make any other guesses or assumptions really, so continuing
} }
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_Conversions()));
BOOST_PP_ENUM_TRAILING(n, curry, ~));
} }
} }
} }
} }
#undef n
#undef addparam
#undef curry
#endif #endif

View File

@@ -1,25 +1,31 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_ #ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
#define CHAISCRIPT_HANDLE_RETURN_HPP_ #define CHAISCRIPT_HANDLE_RETURN_HPP_
#include "boxed_value.hpp" #include <functional>
#include "boxed_number.hpp" #include <memory>
#include "type_info.hpp"
#include <string> #include <string>
#include <boost/function.hpp> #include <type_traits>
#include <stdexcept> #include "boxed_number.hpp"
#include <vector> #include "boxed_value.hpp"
namespace chaiscript {
class Boxed_Number;
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
namespace dispatch namespace dispatch
{ {
template<class T> class Proxy_Function_Impl;
template<class T> class Assignable_Proxy_Function_Impl;
namespace detail namespace detail
{ {
/** /**
@@ -28,9 +34,110 @@ namespace chaiscript
template<typename Ret> template<typename Ret>
struct Handle_Return struct Handle_Return
{ {
static Boxed_Value handle(const Ret &r) template<typename T,
typename = typename std::enable_if<std::is_pod<typename std::decay<T>::type>::value>::type>
static Boxed_Value handle(T r)
{ {
return const_var(r); return Boxed_Value(std::move(r), true);
}
template<typename T,
typename = typename std::enable_if<!std::is_pod<typename std::decay<T>::type>::value>::type>
static Boxed_Value handle(T &&r)
{
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);
}
};
template<typename Ret>
struct Handle_Return<const std::function<Ret> &>
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
std::shared_ptr<dispatch::Proxy_Function_Base>(
new dispatch::Proxy_Function_Impl<Ret>(f)
)
);
}
};
template<typename Ret>
struct Handle_Return<std::function<Ret>>
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
std::shared_ptr<dispatch::Proxy_Function_Base>(
new Proxy_Function_Impl<Ret>(f)
)
);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>>>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
std::shared_ptr<Proxy_Function_Base>(
new Assignable_Proxy_Function_Impl<Ret>(
std::ref(*f),
f
)
)
);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
std::shared_ptr<Proxy_Function_Base>(
new Assignable_Proxy_Function_Impl<Ret>(
std::ref(*f),
f
)
)
);
}
};
template<typename Ret>
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
std::shared_ptr<Proxy_Function_Base>(
new Assignable_Proxy_Function_Impl<Ret>(
std::ref(*f),
f
)
)
);
}
};
template<typename Ret>
struct Handle_Return<std::function<Ret> &>
{
static Boxed_Value handle(std::function<Ret> &f) {
return Boxed_Value(
std::shared_ptr<Proxy_Function_Base>(
new Assignable_Proxy_Function_Impl<Ret>(
std::ref(f),
std::shared_ptr<std::function<Ret>>()
)
)
);
}
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
std::shared_ptr<dispatch::Proxy_Function_Base>(
new dispatch::Proxy_Function_Impl<Ret>(f)
)
);
} }
}; };
@@ -39,34 +146,43 @@ namespace chaiscript
{ {
static Boxed_Value handle(Ret *p) static Boxed_Value handle(Ret *p)
{ {
return Boxed_Value(p); return Boxed_Value(p, true);
} }
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &> struct Handle_Return<const Ret *>
{ {
static Boxed_Value handle(const boost::shared_ptr<Ret> &r) static Boxed_Value handle(const Ret *p)
{ {
return Boxed_Value(r); return Boxed_Value(p, true);
} }
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> > struct Handle_Return<std::shared_ptr<Ret> &>
{ {
static Boxed_Value handle(const boost::shared_ptr<Ret> &r) static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{ {
return Boxed_Value(r); return Boxed_Value(r, true);
} }
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &> struct Handle_Return<std::shared_ptr<Ret> >
{ {
static Boxed_Value handle(const boost::shared_ptr<Ret> &r) static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{ {
return Boxed_Value(r); return Boxed_Value(r, true);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<Ret> &>
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
} }
}; };
@@ -75,7 +191,7 @@ namespace chaiscript
{ {
static Boxed_Value handle(const Ret &r) static Boxed_Value handle(const Ret &r)
{ {
return Boxed_Value(boost::cref(r)); return Boxed_Value(std::cref(r), true);
} }
}; };
@@ -88,12 +204,12 @@ namespace chaiscript
{ {
static Boxed_Value handle(Ret &r) static Boxed_Value handle(Ret &r)
{ {
return Boxed_Value(boost::ref(r)); return Boxed_Value(std::ref(r));
} }
static Boxed_Value handle(const Ret &r) static Boxed_Value handle(const Ret &r)
{ {
return Boxed_Value(boost::cref(r)); return Boxed_Value(std::cref(r));
} }
}; };

View File

@@ -1,160 +1,167 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_OPERATORS_HPP_ #ifndef CHAISCRIPT_OPERATORS_HPP_
#define CHAISCRIPT_OPERATORS_HPP_ #define CHAISCRIPT_OPERATORS_HPP_
#include "../chaiscript_defines.hpp"
#include "register_function.hpp"
namespace chaiscript namespace chaiscript
{ {
namespace bootstrap namespace bootstrap
{ {
namespace operators namespace operators
{ {
template<typename Ret, typename L, typename R> namespace detail
Ret assign(L l, R r) {
/// \todo make this return a decltype once we drop gcc 4.6
template<typename L, typename R>
auto assign(L l, R r) -> L&
{ {
return (l = r); return (l = r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_bitwise_and(L l, R r) auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
{ {
return (l &= r); return (l &= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_xor(L l, R r) auto assign_xor(L l, R r) -> decltype((l^=r))
{ {
return (l ^= r); return (l ^= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_bitwise_or(L l, R r) auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
{ {
return (l |= r); return (l |= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_difference(L l, R r) auto assign_difference(L l, R r) -> decltype(( l -= r))
{ {
return (l -= r); return (l -= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_left_shift(L l, R r) auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
{ {
return (l <<= r); return (l <<= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_product(L l, R r) auto assign_product(L l, R r) -> decltype(( l *= r ))
{ {
return (l *= r); return (l *= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_quotient(L l, R r) auto assign_quotient(L l, R r) -> decltype(( l /= r ))
{ {
return (l /= r); return (l /= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_remainder(L l, R r) auto assign_remainder(L l, R r) -> decltype(( l %= r ))
{ {
return (l %= r); return (l %= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret assign_right_shift(L l, R r) auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
{ {
return (l >>= r); return (l >>= r);
} }
template<typename Ret, typename L, typename R> /// \todo make this return a decltype once we drop gcc 4.6
Ret assign_sum(L l, R r) template<typename L, typename R>
auto assign_sum(L l, R r) -> L&
{ {
return (l += r); return (l += r);
} }
template<typename Ret, typename L> template<typename L>
Ret prefix_decrement(L l) auto prefix_decrement(L l) -> decltype(( --l ))
{ {
return (--l); return (--l);
} }
template<typename Ret, typename L> template<typename L>
Ret prefix_increment(L l) auto prefix_increment(L l) -> decltype(( ++l ))
{ {
return (++l); return (++l);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret equal(L l, R r) auto equal(L l, R r) -> decltype(( l == r ))
{ {
return (l == r); return (l == r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret greater_than(L l, R r) auto greater_than(L l, R r) -> decltype(( l > r ))
{ {
return (l > r); return (l > r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret greater_than_equal(L l, R r) auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
{ {
return (l >= r); return (l >= r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret less_than(L l, R r) auto less_than(L l, R r) -> decltype(( l < r ))
{ {
return (l < r); return (l < r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret less_than_equal(L l, R r) auto less_than_equal(L l, R r) -> decltype(( l <= r ))
{ {
return (l <= r); return (l <= r);
} }
template<typename Ret, typename L> template<typename L>
Ret logical_compliment(L l) auto logical_compliment(L l) -> decltype(( !l ))
{ {
return (!l); return (!l);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret not_equal(L l, R r) auto not_equal(L l, R r) -> decltype(( l != r ))
{ {
return (l != r); return (l != r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret addition(L l, R r) auto addition(L l, R r) -> decltype(( l + r ))
{ {
return (l + r); return (l + r);
} }
template<typename Ret, typename L> template<typename L>
Ret unary_plus(L l) auto unary_plus(L l) -> decltype(( +l ))
{ {
return (+l); return (+l);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret subtraction(L l, R r) auto subtraction(L l, R r) -> decltype(( l - r ))
{ {
return (l - r); return (l - r);
} }
template<typename Ret, typename L> template<typename L>
Ret unary_minus(L l) auto unary_minus(L l) -> decltype(( -l ))
{ {
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4146) #pragma warning(disable : 4146)
return (-l); return (-l);
@@ -164,291 +171,291 @@ namespace chaiscript
#endif #endif
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret bitwise_and(L l, R r) auto bitwise_and(L l, R r) -> decltype(( l & r ))
{ {
return (l & r); return (l & r);
} }
template<typename Ret, typename L> template<typename L>
Ret bitwise_compliment(L l) auto bitwise_compliment(L l) -> decltype(( ~l ))
{ {
return (~l); return (~l);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret bitwise_xor(L l, R r) auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
{ {
return (l ^ r); return (l ^ r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret bitwise_or(L l, R r) auto bitwise_or(L l, R r) -> decltype(( l | r ))
{ {
return (l | r); return (l | r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret division(L l, R r) auto division(L l, R r) -> decltype(( l / r ))
{ {
return (l / r); return (l / r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret left_shift(L l, R r) auto left_shift(L l, R r) -> decltype(( l << r ))
{ {
return l << r; return l << r;
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret multiplication(L l, R r) auto multiplication(L l, R r) -> decltype(( l * r ))
{ {
return l * r; return l * r;
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret remainder(L l, R r) auto remainder(L l, R r) -> decltype(( l % r ))
{ {
return (l % r); return (l % r);
} }
template<typename Ret, typename L, typename R> template<typename L, typename R>
Ret right_shift(L l, R r) auto right_shift(L l, R r) -> decltype(( l >> r ))
{ {
return (l >> r); return (l >> r);
} }
}
template<typename T> template<typename T>
ModulePtr assign(ModulePtr m = ModulePtr(new Module())) ModulePtr assign(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign<T &, T &, const T&>), "="); m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&="); m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_xor(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_xor<T &, T &, const T&>), "^="); m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|="); m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_difference(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_difference<T &, T &, const T&>), "-="); m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_left_shift(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<="); m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_product(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_product<T &, T &, const T&>), "*="); m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_quotient(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_quotient<T &, T &, const T&>), "/="); m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_remainder(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_remainder<T &, T &, const T&>), "%="); m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_right_shift(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>="); m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module())) ModulePtr assign_sum(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&assign_sum<T &, T &, const T&>), "+="); m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module())) ModulePtr prefix_decrement(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&prefix_decrement<T &, T &>), "--"); m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module())) ModulePtr prefix_increment(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&prefix_increment<T &, T &>), "++"); m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr equal(ModulePtr m = ModulePtr(new Module())) ModulePtr equal(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&equal<bool, const T&, const T&>), "=="); m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module())) ModulePtr greater_than(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&greater_than<bool, const T&, const T&>), ">"); m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module())) ModulePtr greater_than_equal(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">="); m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr less_than(ModulePtr m = ModulePtr(new Module())) ModulePtr less_than(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&less_than<bool, const T&, const T&>), "<"); m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module())) ModulePtr less_than_equal(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<="); m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module())) ModulePtr logical_compliment(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&logical_compliment<bool, const T &>), "!"); m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module())) ModulePtr not_equal(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&not_equal<bool, const T &, const T &>), "!="); m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr addition(ModulePtr m = ModulePtr(new Module())) ModulePtr addition(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&addition<T, const T &, const T &>), "+"); m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module())) ModulePtr unary_plus(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&unary_plus<T, const T &>), "+"); m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module())) ModulePtr subtraction(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&subtraction<T, const T &, const T &>), "-"); m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module())) ModulePtr unary_minus(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&unary_minus<T, const T &>), "-"); m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module())) ModulePtr bitwise_and(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&bitwise_and<T, const T &, const T &>), "&"); m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module())) ModulePtr bitwise_compliment(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&bitwise_compliment<T, const T &>), "~"); m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module())) ModulePtr bitwise_xor(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^"); m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module())) ModulePtr bitwise_or(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&bitwise_or<T, const T &, const T &>), "|"); m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr division(ModulePtr m = ModulePtr(new Module())) ModulePtr division(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&division<T, const T &, const T &>), "/"); m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module())) ModulePtr left_shift(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&left_shift<T, const T &, const T &>), "<<"); m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module())) ModulePtr multiplication(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&multiplication<T, const T &, const T &>), "*"); m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr remainder(ModulePtr m = ModulePtr(new Module())) ModulePtr remainder(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&remainder<T, const T &, const T &>), "%"); m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
return m; return m;
} }
template<typename T> template<typename T>
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module())) ModulePtr right_shift(ModulePtr m = std::make_shared<Module>())
{ {
m->add(fun(&right_shift<T, const T &, const T &>), ">>"); m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
return m; return m;
} }
} }

View File

@@ -1,27 +1,41 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_ #ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_ #define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#include <boost/shared_ptr.hpp> #include "proxy_functions.hpp"
#include <boost/bind.hpp>
#include <boost/function.hpp>
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_constructors.hpp>
#include BOOST_PP_ITERATE()
# endif
namespace chaiscript namespace chaiscript
{ {
namespace dispatch
{
namespace detail
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class, typename ... Params>
std::shared_ptr<Class> constructor_(Params ... params)
{
return std::make_shared<Class>(params...);
}
template<typename Class, typename ... Params >
Proxy_Function build_constructor_(Class (*)(Params...))
{
typedef std::shared_ptr<Class> (sig)(Params...);
return Proxy_Function(static_cast<Proxy_Function_Impl_Base *>(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>)))));
}
}
}
/// \brief Generates a constructor function for use with ChaiScript /// \brief Generates a constructor function for use with ChaiScript
/// ///
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...) /// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
@@ -36,46 +50,11 @@ namespace chaiscript
template<typename T> template<typename T>
Proxy_Function constructor() Proxy_Function constructor()
{ {
T *f = 0; T *f = nullptr;
return (dispatch::detail::build_constructor_(f)); return (dispatch::detail::build_constructor_(f));
} }
} }
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
}
/**
* Helper function for build a constructor function
* example:
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
* \todo See if it is possible to make this not be a variadic function
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
}
}
}
#undef n
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,29 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define gettypeinfo(z,n,text) ti.push_back(chaiscript::detail::Get_Type_Info<Param ## n>::get());
#define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n])
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
#ifndef BOOST_PP_IS_ITERATING
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ #define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#include "boxed_value.hpp" #include <functional>
#include "boxed_cast.hpp"
#include "type_info.hpp"
#include "handle_return.hpp"
#include <string>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_value.hpp"
#include "handle_return.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Type_Conversions;
namespace exception {
class bad_boxed_cast;
} // namespace exception
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
namespace exception namespace exception
@@ -41,26 +40,15 @@ namespace chaiscript
{ {
} }
virtual ~arity_error() throw() {} arity_error(const arity_error &) = default;
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
int got; int got;
int expected; int expected;
}; };
} }
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions_detail.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
namespace dispatch namespace dispatch
{ {
namespace detail namespace detail
@@ -69,66 +57,109 @@ namespace chaiscript
* Used by Proxy_Function_Impl to return a list of all param types * Used by Proxy_Function_Impl to return a list of all param types
* it contains. * it contains.
*/ */
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Ret, typename ... Params>
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param))) std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
{ {
std::vector<Type_Info> ti; /// \note somehow this is responsible for a large part of the code generation
ti.push_back(chaiscript::detail::Get_Type_Info<Ret>::get()); return { user_type<Ret>(), user_type<Params>()... };
BOOST_PP_REPEAT(n, gettypeinfo, ~)
return ti;
} }
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function. // Forward declaration
* The function attempts to unbox each paramter to the expected type. template<typename ... Rest>
* if any unboxing fails the execution of the function fails and struct Try_Cast;
* the bad_boxed_cast is passed up to the caller.
*/ template<typename Param, typename ... Rest>
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> struct Try_Cast<Param, Rest...>
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params)
{ {
if (params.size() != n) static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions &t_conversions)
{ {
throw exception::arity_error(static_cast<int>(params.size()), n); boxed_cast<Param>(params[generation], &t_conversions);
} else { Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
return f(BOOST_PP_REPEAT(n, casthelper, ~));
} }
};
// 0th case
template<>
struct Try_Cast<>
{
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions &)
{
} }
};
/** /**
* Used by Proxy_Function_Impl to determine if it is equivalent to another * Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarly used to prevent * Proxy_Function_Impl object. This function is primarily used to prevent
* registration of two functions with the exact same signatures * registration of two functions with the exact same signatures
*/ */
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)), bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, )) const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{ {
try { try {
BOOST_PP_REPEAT(n, trycast, ~); Try_Cast<Params...>::do_try(params, 0, t_conversions);
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
return false; return false;
} }
return true; return true;
} }
template<typename Ret, int count, typename ... Params>
struct Call_Func
{
template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &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]);
}
};
template<typename Ret, typename ... Params>
struct Call_Func<Ret, 0, Params...>
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this
#endif
template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
};
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each parameter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
template<typename Ret, typename ... Params>
Ret call_func(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
if (params.size() == sizeof...(Params))
{
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params, t_conversions);
}
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
}
} }
} }
} }
#undef n
#undef gettypeinfo
#undef casthelper
#undef trycast
#endif
#ifndef BOOST_PP_IS_ITERATING
namespace chaiscript namespace chaiscript
{ {
@@ -140,9 +171,9 @@ namespace chaiscript
struct Do_Call struct Do_Call
{ {
template<typename Fun> template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params) static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{ {
return Handle_Return<Ret>::handle(call_func(fun, params)); return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
} }
}; };
@@ -150,9 +181,9 @@ namespace chaiscript
struct Do_Call<void> struct Do_Call<void>
{ {
template<typename Fun> template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params) static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{ {
call_func(fun, params); call_func(fun, params, t_conversions);
return Handle_Return<void>::handle(); return Handle_Return<void>::handle();
} }
}; };

View File

@@ -1,85 +1,68 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_ #define CHAISCRIPT_REGISTER_FUNCTION_HPP_
#include "dispatchkit.hpp" #include <functional>
#include <type_traits>
#include "bind_first.hpp" #include "bind_first.hpp"
#include <boost/function.hpp> #include "proxy_functions.hpp"
#include <boost/bind.hpp>
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_object_pointer.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
namespace chaiscript namespace chaiscript
{ {
namespace dispatch namespace dispatch
{ {
namespace detail namespace detail
{
template<bool Object, bool MemFn>
struct Fun_Helper
{ {
template<typename T> template<typename T>
static Proxy_Function go(T t) struct FunctionSignature
{ {
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
}; };
template<> template<typename Sig>
struct Fun_Helper<false, true> struct FunctionSignature<std::function<Sig> >
{ {
template<typename T> typedef Sig Signature;
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(boost::mem_fn(t))));
}
}; };
template<typename Ret, typename ... Args>
template<> std::function<Ret (Args...) > to_function(Ret (*func)(Args...))
struct Fun_Helper<true, false>
{ {
template<typename T, typename Class> return std::function<Ret (Args...)>(func);
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
}
} }
/// \brief Creates a new Proxy_Function object from a boost::function object template<typename Ret, typename Class, typename ... Args>
/// \param[in] f boost::function to expose to ChaiScript std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
///
/// \b Example:
/// \code
/// boost::function<int (char, float, std::string)> f = get_some_function();
/// chaiscript::ChaiScript chai;
/// chai.add(fun(f), "some_function");
/// \endcode
///
/// \sa \ref addingfunctions
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{ {
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f)); #ifdef CHAISCRIPT_MSVC
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
/// std::function for member function pointers seems to be broken in MSVC
return std::function<Ret(Class &, Args...)>(std::mem_fn(func));
#else
return std::function<Ret(Class &, Args...)>(func);
#endif
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
{
#if defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_LIBCPP)
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
/// std::function for member function pointers seems to be broken in MSVC
return std::function<Ret (const Class &, Args...)>([func](const Class &o, Args... args)->Ret {
return (o.*func)(std::forward<Args>(args)...);
});
#else
return std::function<Ret(const Class &, Args...)>(func);
#endif
}
}
} }
/// \brief Creates a new Proxy_Function object from a free function, member function or data member /// \brief Creates a new Proxy_Function object from a free function, member function or data member
@@ -101,13 +84,54 @@ namespace chaiscript
/// chai.add(fun(&MyClass::memberdata), "memberdata"); /// chai.add(fun(&MyClass::memberdata), "memberdata");
/// \endcode /// \endcode
/// ///
/// \sa \ref addingfunctions /// \sa \ref adding_functions
template<typename T> template<typename T>
Proxy_Function fun(T t) Proxy_Function fun(const T &t)
{ {
return dispatch::detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t); return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(t)) >::Signature>>(dispatch::detail::to_function(t)));
} }
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*func)(Param...) const)
{
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>>(dispatch::detail::to_function(func)));
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*func)(Param...))
{
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>>(dispatch::detail::to_function(func)));
}
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
{
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<T, Class>>(m));
}
/// \brief Creates a new Proxy_Function object from a std::function object
/// \param[in] f std::function to expose to ChaiScript
///
/// \b Example:
/// \code
/// std::function<int (char, float, std::string)> f = get_some_function();
/// chaiscript::ChaiScript chai;
/// chai.add(fun(f), "some_function");
/// \endcode
///
/// \sa \ref adding_functions
template<typename T>
Proxy_Function fun(const std::function<T> &f)
{
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<T>>(f));
}
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it /// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
/// \param[in] t Function / member to expose /// \param[in] t Function / member to expose
/// \param[in] q Value to bind to first parameter /// \param[in] q Value to bind to first parameter
@@ -122,14 +146,14 @@ namespace chaiscript
/// MyClass obj; /// MyClass obj;
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// // Add function taking only one argument, an int, and permanently bound to "obj" /// // Add function taking only one argument, an int, and permanently bound to "obj"
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj)), "memberfunction"); /// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
/// \endcode /// \endcode
/// ///
/// \sa \ref addingfunctions /// \sa \ref adding_functions
template<typename T, typename Q> template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q) Proxy_Function fun(T &&t, const Q &q)
{ {
return fun(detail::bind_first(t, q)); return fun(detail::bind_first(std::forward<T>(t), q));
} }
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it /// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
@@ -148,14 +172,14 @@ namespace chaiscript
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// // Add function taking only no arguments, and permanently bound to "obj" and "1" /// // Add function taking only no arguments, and permanently bound to "obj" and "1"
/// // memberfunction() will be equivalent to obj.memberfunction(1) /// // memberfunction() will be equivalent to obj.memberfunction(1)
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj), 1), "memberfunction"); /// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
/// \endcode /// \endcode
/// ///
/// \sa \ref addingfunctions /// \sa \ref adding_functions
template<typename T, typename Q, typename R> template<typename T, typename Q, typename R>
Proxy_Function fun(T t, const Q &q, const R &r) Proxy_Function fun(T &&t, Q &&q, R &&r)
{ {
return fun(detail::bind_first(detail::bind_first(t, q), r)); return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
} }
} }

View File

@@ -0,0 +1,464 @@
// 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)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#include <atomic>
#include <memory>
#include <set>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <typeinfo>
#include "../chaiscript_threading.hpp"
#include "bad_boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript
{
namespace exception
{
class bad_boxed_dynamic_cast : public bad_boxed_cast
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(w)
{
}
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
};
class bad_boxed_type_cast : public bad_boxed_cast
{
public:
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(w)
{
}
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
};
}
namespace detail
{
class Type_Conversion_Base
{
public:
virtual Boxed_Value convert(const Boxed_Value &from) const = 0;
virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0;
const Type_Info &to() const
{
return m_to;
}
const Type_Info &from() const
{
return m_from;
}
virtual ~Type_Conversion_Base() {}
protected:
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
: m_to(t_to), m_from(t_from)
{
}
private:
Type_Info m_to;
Type_Info m_from;
};
template<typename From, typename To>
class Dynamic_Caster
{
public:
static Boxed_Value cast(const Boxed_Value &t_from)
{
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
{
if (t_from.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
return Boxed_Value(
[&]()->std::shared_ptr<const To>{
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
} else {
throw std::bad_cast();
}
}()
);
} else {
return Boxed_Value(
[&]()->std::shared_ptr<To>{
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
} else {
#ifdef CHAISCRIPT_LIBCPP
/// \todo fix this someday after libc++ is fixed.
if (std::string(typeid(To).name()).find("Assignable_Proxy_Function") != std::string::npos) {
auto from = detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr);
if (std::string(typeid(*from).name()).find("Assignable_Proxy_Function_Impl") != std::string::npos) {
return std::static_pointer_cast<To>(from);
}
}
#endif
throw std::bad_cast();
}
}()
);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
const To &data = dynamic_cast<const To &>(d);
return Boxed_Value(std::cref(data));
} else {
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
To &data = dynamic_cast<To &>(d);
return Boxed_Value(std::ref(data));
}
}
} else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
}
}
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Type_Conversion_Base
{
public:
Dynamic_Conversion_Impl()
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
{
}
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
{
return Dynamic_Caster<Base, Derived>::cast(t_base);
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
{
return Dynamic_Caster<Derived, Base>::cast(t_derived);
}
};
template<typename Callable>
class Type_Conversion_Impl : public Type_Conversion_Base
{
public:
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
m_func(std::move(t_func))
{
}
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
{
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
}
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
{
/// \todo better handling of errors from the conversion function
return m_func(t_from);
}
private:
Callable m_func;
};
}
class Type_Conversions
{
public:
struct Less_Than
{
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
{
return *t_lhs != *t_rhs && t_lhs->before(*t_rhs);
}
};
Type_Conversions()
: m_mutex(),
m_conversions(),
m_convertableTypes(),
m_num_types(0),
m_thread_cache(this),
m_conversion_saves(this)
{
}
Type_Conversions(const Type_Conversions &t_other)
: m_mutex(),
m_conversions(t_other.get_conversions()),
m_convertableTypes(),
m_num_types(m_conversions.size()),
m_thread_cache(this),
m_conversion_saves(this)
{
}
const std::set<const std::type_info *, Less_Than> &thread_cache() const
{
auto &cache = *m_thread_cache;
if (cache.size() != m_num_types)
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
cache = m_convertableTypes;
}
return cache;
}
void add_conversion(const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
/// \todo error if a conversion already exists
m_conversions.insert(conversion);
m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()});
m_num_types = m_convertableTypes.size();
}
template<typename T>
bool convertable_type() const
{
return thread_cache().count(user_type<T>().bare_type_info()) != 0;
}
template<typename To, typename From>
bool converts() const
{
return converts(user_type<To>(), user_type<From>());
}
bool converts(const Type_Info &to, const Type_Info &from) const
{
const auto &types = thread_cache();
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0)
{
return has_conversion(to, from) || has_conversion(from, to);
} else {
return false;
}
}
template<typename To>
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
{
try {
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
}
}
template<typename From>
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
{
try {
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
}
}
void enable_conversion_saves(bool t_val)
{
m_conversion_saves->enabled = t_val;
}
std::vector<Boxed_Value> take_saves()
{
std::vector<Boxed_Value> ret;
std::swap(ret, m_conversion_saves->saves);
return ret;
}
bool has_conversion(const Type_Info &to, const Type_Info &from) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(to, from) != m_conversions.end();
}
std::shared_ptr<detail::Type_Conversion_Base> get_conversion(const Type_Info &to, const Type_Info &from) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
auto itr = find(to, from);
if (itr != m_conversions.end())
{
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name());
}
}
private:
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find(
const Type_Info &to, const Type_Info &from) const
{
return std::find_if(m_conversions.begin(), m_conversions.end(),
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
{
return conversion->to().bare_equal(to) && conversion->from().bare_equal(from);
}
);
}
std::set<std::shared_ptr<detail::Type_Conversion_Base>> get_conversions() const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return m_conversions;
}
struct Conversion_Saves
{
Conversion_Saves()
: enabled(false)
{}
bool enabled;
std::vector<Boxed_Value> saves;
};
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
std::set<const std::type_info *, Less_Than> m_convertableTypes;
std::atomic_size_t m_num_types;
mutable chaiscript::detail::threading::Thread_Storage<std::set<const std::type_info *, Less_Than>> m_thread_cache;
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
};
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
/// want automatic conversions up your inheritance hierarchy.
///
/// Create a new to class registration for applying to a module or to the ChaiScript engine
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
/// if you have a type that is introduced in a loadable module and is used by multiple modules
/// (through a tertiary dll that is shared between the modules, static linking the new type
/// into both loadable modules would not be portable), you need to register the type
/// relationship in all modules that use the newly added type in a polymorphic way.
///
/// Example:
/// \code
/// class Base
/// {};
/// class Derived : public Base
/// {};
///
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::to_class<Base, Derived>());
/// \endcode
///
template<typename Base, typename Derived>
Type_Conversion base_class()
{
//Can only be used with related polymorphic types
//may be expanded some day to support conversions other than child -> parent
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Dynamic_Conversion_Impl<Base, Derived>>();
}
template<typename Callable>
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to,
const Callable &t_func)
{
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
}
template<typename From, typename To, typename Callable>
Type_Conversion type_conversion(const Callable &t_function)
{
auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value {
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
return chaiscript::Boxed_Value(t_function(detail::Cast_Helper<const From &>::cast(t_bv, nullptr)));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
}
template<typename From, typename To>
Type_Conversion type_conversion()
{
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
return chaiscript::Boxed_Value(To(detail::Cast_Helper<From>::cast(t_bv, nullptr)));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
}
}
#endif

View File

@@ -1,25 +1,16 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_ #ifndef CHAISCRIPT_TYPE_INFO_HPP_
#define CHAISCRIPT_TYPE_INFO_HPP_ #define CHAISCRIPT_TYPE_INFO_HPP_
#include <string> #include <memory>
#include <type_traits>
#include <typeinfo> #include <typeinfo>
#include <boost/shared_ptr.hpp> #include <string>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/ref.hpp>
namespace chaiscript namespace chaiscript
{ {
@@ -29,82 +20,75 @@ namespace chaiscript
template<typename T> template<typename T>
struct Bare_Type struct Bare_Type
{ {
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type; typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
}; };
} }
/// \brief Compile time deduced information about a type /// \brief Compile time deduced information about a type
class Type_Info class Type_Info
{ {
public: public:
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti) 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_bareti), : 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_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_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_is_undef(false) m_is_undef(false)
{ {
} }
Type_Info() CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(0), m_bare_type_info(0), : m_type_info(nullptr), m_bare_type_info(nullptr),
m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_is_arithmetic(false), m_is_void(false), m_is_arithmetic(false),
m_is_undef(true) m_is_undef(true)
{ {
} }
Type_Info(const Type_Info &ti) #if !defined(_MSC_VER) || _MSC_VER != 1800
: m_type_info(ti.m_type_info), Type_Info(Type_Info&&) = default;
m_bare_type_info(ti.m_bare_type_info), Type_Info& operator=(Type_Info&&) = default;
m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference), #endif
m_is_pointer(ti.m_is_pointer),
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
m_is_undef(ti.m_is_undef)
{
}
Type_Info &operator=(const Type_Info &ti) Type_Info(const Type_Info&) = default;
{ Type_Info& operator=(const Type_Info&) = default;
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_const = ti.m_is_const;
m_is_reference = ti.m_is_reference;
m_is_pointer = ti.m_is_pointer;
m_is_void = ti.m_is_void;
m_is_arithmetic = ti.m_is_arithmetic;
m_is_undef = ti.m_is_undef;
return *this;
}
bool operator<(const Type_Info &ti) const
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{ {
return m_type_info < ti.m_type_info; return m_type_info < ti.m_type_info;
} }
bool operator==(const Type_Info &ti) const CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{ {
return ti.m_type_info == m_type_info return ti.m_type_info == m_type_info
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
} }
bool operator==(const std::type_info &ti) const CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{ {
return m_type_info != 0 && (*m_type_info) == ti; return m_type_info != nullptr && (*m_type_info) == ti;
} }
bool bare_equal(const Type_Info &ti) const CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{ {
return ti.m_bare_type_info == m_bare_type_info return ti.m_bare_type_info == m_bare_type_info
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
} }
bool is_const() const { return m_is_const; } CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
bool is_reference() const { return m_is_reference; } {
bool is_void() const { return m_is_void; } return m_bare_type_info != nullptr
bool is_arithmetic() const { return m_is_arithmetic; } && (*m_bare_type_info) == ti;
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; } }
bool is_pointer() const { return m_is_pointer; }
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
std::string name() const std::string name() const
{ {
@@ -126,6 +110,11 @@ namespace chaiscript
} }
} }
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
{
return m_bare_type_info;
}
private: private:
const std::type_info *m_type_info; const std::type_info *m_type_info;
const std::type_info *m_bare_type_info; const std::type_info *m_bare_type_info;
@@ -139,89 +128,82 @@ namespace chaiscript
namespace detail namespace detail
{ {
/** /// Helper used to create a Type_Info object
* Helper used to create a Type_Info object
*/
template<typename T> template<typename T>
struct Get_Type_Info struct Get_Type_Info
{ {
typedef T type; typedef T type;
static Type_Info get() CHAISCRIPT_CONSTEXPR static Type_Info get()
{ {
return Type_Info(boost::is_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value, return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
boost::is_void<T>::value, std::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value, std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(T), &typeid(T),
&typeid(typename Bare_Type<T>::type)); &typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T> template<typename T>
struct Get_Type_Info<boost::shared_ptr<T> > struct Get_Type_Info<std::shared_ptr<T> >
{ {
typedef T type; typedef T type;
static Type_Info get() CHAISCRIPT_CONSTEXPR static Type_Info get()
{ {
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value, return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
boost::is_void<T>::value, std::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value, std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(boost::shared_ptr<T> ), &typeid(std::shared_ptr<T> ),
&typeid(typename Bare_Type<T>::type)); &typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T> template<typename T>
struct Get_Type_Info<const boost::shared_ptr<T> &> struct Get_Type_Info<const std::shared_ptr<T> &>
{ {
typedef T type; typedef T type;
static Type_Info get() CHAISCRIPT_CONSTEXPR static Type_Info get()
{ {
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value, return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
boost::is_void<T>::value, std::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value, std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(const boost::shared_ptr<T> &), &typeid(const std::shared_ptr<T> &),
&typeid(typename Bare_Type<T>::type)); &typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T> template<typename T>
struct Get_Type_Info<boost::reference_wrapper<T> > struct Get_Type_Info<std::reference_wrapper<T> >
{ {
typedef T type; typedef T type;
static Type_Info get() CHAISCRIPT_CONSTEXPR static Type_Info get()
{ {
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value, return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
boost::is_void<T>::value, std::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value, std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(boost::reference_wrapper<T> ), &typeid(std::reference_wrapper<T> ),
&typeid(typename Bare_Type<T>::type)); &typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T> template<typename T>
struct Get_Type_Info<const boost::reference_wrapper<T> &> struct Get_Type_Info<const std::reference_wrapper<T> &>
{ {
typedef T type; typedef T type;
static Type_Info get() CHAISCRIPT_CONSTEXPR static Type_Info get()
{ {
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value, return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
boost::is_void<T>::value, std::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value, std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(const boost::reference_wrapper<T> &), &typeid(const std::reference_wrapper<T> &),
&typeid(typename Bare_Type<T>::type)); &typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T>
struct Stripped_Type
{
typedef typename Bare_Type<typename detail::Get_Type_Info<T>::type>::type type;
};
} }
/// \brief Creates a Type_Info object representing the type passed in /// \brief Creates a Type_Info object representing the type passed in
@@ -234,7 +216,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type(i); /// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode /// \endcode
template<typename T> template<typename T>
Type_Info user_type(const T &/*t*/) CHAISCRIPT_CONSTEXPR Type_Info user_type(const T &/*t*/)
{ {
return detail::Get_Type_Info<T>::get(); return detail::Get_Type_Info<T>::get();
} }
@@ -249,7 +231,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type<int>(); /// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \endcode /// \endcode
template<typename T> template<typename T>
Type_Info user_type() CHAISCRIPT_CONSTEXPR Type_Info user_type()
{ {
return detail::Get_Type_Info<T>::get(); return detail::Get_Type_Info<T>::get();
} }

View File

@@ -1,14 +1,13 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_ #ifndef CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_ #define CHAISCRIPT_ALGEBRAIC_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp> #include <string>
#include <boost/enable_shared_from_this.hpp>
namespace chaiscript namespace chaiscript
{ {

View File

@@ -1,17 +1,32 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_ #ifndef CHAISCRIPT_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_ #define CHAISCRIPT_COMMON_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp> #include <algorithm>
#include <boost/enable_shared_from_this.hpp> #include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
namespace chaiscript {
struct AST_Node;
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
/// Signature of module entry point that all binary loadable modules must implement. /// Signature of module entry point that all binary loadable modules must implement.
typedef ModulePtr (*Create_Module_Func)(); typedef ModulePtr (*Create_Module_Func)();
@@ -21,23 +36,22 @@ namespace chaiscript
public: 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, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range, Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or, Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Switch, Case, Default, Ternary_Cond Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
}; };
}; };
namespace namespace
{ {
/**
* Helper lookup to get the name of each node type /// Helper lookup to get the name of each node type
*/
const char *ast_node_type_to_string(int ast_node_type) { const char *ast_node_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", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range", "Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or", "Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or", "Switch", "Case", "Default", "Ternary Condition"}; "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
return ast_node_types[ast_node_type]; return ast_node_types[ast_node_type];
} }
@@ -54,74 +68,100 @@ namespace chaiscript
File_Position() : line(0), column(0) { } File_Position() : line(0), column(0) { }
}; };
struct Parse_Location {
Parse_Location(std::string t_fname="", const int t_start_line=0, const int t_start_col=0,
const int t_end_line=0, const int t_end_col=0)
: start(t_start_line, t_start_col),
end(t_end_line, t_end_col),
filename(std::make_shared<std::string>(std::move(t_fname)))
{
}
Parse_Location(std::shared_ptr<std::string> t_fname, const int t_start_line=0, const int t_start_col=0,
const int t_end_line=0, const int t_end_col=0)
: start(t_start_line, t_start_col),
end(t_end_line, t_end_col),
filename(std::move(t_fname))
{
}
File_Position start;
File_Position end;
std::shared_ptr<std::string> filename;
};
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr; typedef std::shared_ptr<AST_Node> AST_NodePtr;
typedef std::shared_ptr<const AST_Node> AST_NodePtr_Const;
/// \brief Classes which may be thrown during error cases when ChaiScript is executing. /// \brief Classes which may be thrown during error cases when ChaiScript is executing.
namespace exception namespace exception
{ {
/**
* Errors generated during parsing or evaluation /// Errors generated during parsing or evaluation
*/ struct eval_error : std::runtime_error {
struct eval_error : public std::runtime_error {
std::string reason; std::string reason;
File_Position start_position; File_Position start_position;
File_Position end_position;
std::string filename; std::string filename;
std::string detail; std::string detail;
std::vector<AST_NodePtr> call_stack; std::vector<AST_NodePtr_Const> call_stack;
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions, const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation, bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) : const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)), std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss)) reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
{} {}
eval_error(const std::string &t_why, eval_error(const std::string &t_why,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions, const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation, bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) : const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)), std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss)) reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
{} {}
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) : eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_where, t_fname)), std::runtime_error(format(t_why, t_where, t_fname)),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname) reason(t_why), start_position(t_where), filename(t_fname)
{} {}
eval_error(const std::string &t_why) throw() eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
: std::runtime_error("Error: \"" + t_why + "\" "), : std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why) reason(t_why)
{} {}
eval_error(const eval_error &) = default;
std::string pretty_print() const std::string pretty_print() const
{ {
std::ostringstream ss; std::ostringstream ss;
ss << what(); ss << what();
if (call_stack.size() > 0) { if (call_stack.size() > 0) {
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")" << std::endl; ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
ss << std::endl << detail << std::endl; ss << '\n' << detail << '\n';
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'"; ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
for (size_t j = 1; j < call_stack.size(); ++j) { for (size_t j = 1; j < call_stack.size(); ++j) {
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File) && id(call_stack[j]) != chaiscript::AST_Node_Type::File)
{ {
ss << std::endl; ss << '\n';
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'"; ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
} }
} }
} }
ss << std::endl; ss << '\n';
return ss.str(); return ss.str();
} }
virtual ~eval_error() throw() {} virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
private: private:
@@ -138,16 +178,16 @@ namespace chaiscript
} }
template<typename T> template<typename T>
static std::string fname(const T& t) static const std::string &fname(const T& t)
{ {
return *t->filename; return t->filename();
} }
template<typename T> template<typename T>
static std::string startpos(const T& t) static std::string startpos(const T& t)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << t->start.line << ", " << t->start.column; oss << t->start().line << ", " << t->start().column;
return oss.str(); return oss.str();
} }
@@ -205,8 +245,8 @@ namespace chaiscript
} }
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func); = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
if (dynfun) if (dynfun)
{ {
@@ -214,8 +254,7 @@ namespace chaiscript
if (f) if (f)
{ {
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
if (dynfunguard) if (dynfunguard)
{ {
retval += " : " + format_guard(dynfunguard->get_parse_tree()); retval += " : " + format_guard(dynfunguard->get_parse_tree());
@@ -238,7 +277,7 @@ namespace chaiscript
static std::string format_location(const T &t) static std::string format_location(const T &t)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << "(" << *t->filename << " " << t->start.line << ", " << t->start.column << ")"; oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
return oss.str(); return oss.str();
@@ -251,15 +290,13 @@ namespace chaiscript
std::stringstream ss; std::stringstream ss;
if (t_functions.size() == 1) if (t_functions.size() == 1)
{ {
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl; ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
} else { } else {
ss << " " << t_functions.size() << " overloads available:" << std::endl; ss << " " << t_functions.size() << " overloads available:\n";
for (std::vector<chaiscript::Const_Proxy_Function>::const_iterator itr = t_functions.begin(); for (const auto & t_function : t_functions)
itr != t_functions.end();
++itr)
{ {
ss << " " << format_types((*itr), t_dot_notation, t_ss) << std::endl; ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
} }
} }
@@ -279,7 +316,7 @@ namespace chaiscript
{ {
std::string paramstr; std::string paramstr;
for (std::vector<Boxed_Value>::const_iterator itr = t_parameters.begin(); for (auto itr = t_parameters.begin();
itr != t_parameters.end(); itr != t_parameters.end();
++itr) ++itr)
{ {
@@ -377,69 +414,84 @@ namespace chaiscript
} }
}; };
/**
* Errors generated when loading a file /// Errors generated when loading a file
*/ struct file_not_found_error : std::runtime_error {
struct file_not_found_error : public std::runtime_error { file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
file_not_found_error(const std::string &t_filename) throw()
: std::runtime_error("File Not Found: " + t_filename) : std::runtime_error("File Not Found: " + t_filename)
{ } { }
virtual ~file_not_found_error() throw() {} file_not_found_error(const file_not_found_error &) = default;
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
}; };
} }
/// \brief Struct that doubles as both a parser ast_node and an AST node. /// \brief Struct that doubles as both a parser ast_node and an AST node.
struct AST_Node : boost::enable_shared_from_this<AST_Node> { struct AST_Node : std::enable_shared_from_this<AST_Node> {
public: public:
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
const std::string text; const std::string text;
const int identifier; Parse_Location location;
boost::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children; std::vector<AST_NodePtr> children;
AST_NodePtr annotation; AST_NodePtr annotation;
const std::string &filename() const {
return *location.filename;
}
const File_Position &start() const {
return location.start;
}
const File_Position &end() const {
return location.end;
}
virtual std::string pretty_print() const virtual std::string pretty_print() const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << text; oss << text;
for (unsigned int j = 0; j < this->children.size(); ++j) { for (auto & elem : this->children) {
oss << this->children[j]->pretty_print(); oss << elem->pretty_print();
} }
return oss.str(); return oss.str();
} }
/**
* Prints the contents of an AST node, including its children, recursively /// Prints the contents of an AST node, including its children, recursively
*/ std::string to_string(const std::string &t_prepend = "") const {
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss; std::ostringstream oss;
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl; << this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
for (unsigned int j = 0; j < this->children.size(); ++j) { for (size_t j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " "); oss << this->children[j]->to_string(t_prepend + " ");
} }
return oss.str(); return oss.str();
} }
std::string internal_to_string() { Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) const
return to_string();
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
{ {
try { try {
return eval_internal(t_e); return eval_internal(t_e);
} catch (exception::eval_error &ee) { } catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this()); ee.call_stack.push_back(shared_from_this());
throw ee; throw;
}
}
static bool get_bool_condition(const Boxed_Value &t_bv) {
try {
return boxed_cast<bool>(t_bv);
}
catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("Condition not boolean");
} }
} }
@@ -449,28 +501,26 @@ namespace chaiscript
std::replace(children.begin(), children.end(), t_child, t_new_child); std::replace(children.begin(), children.end(), t_child, t_new_child);
} }
virtual ~AST_Node() {}
protected: protected:
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname, AST_Node(std::string t_ast_node_text, int t_id, Parse_Location t_loc,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) : std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
text(t_ast_node_text), identifier(t_id), filename(t_fname), identifier(t_id), text(std::move(t_ast_node_text)),
start(t_start_line, t_start_col), end(t_end_line, t_end_col) location(std::move(t_loc)),
children(std::move(t_children))
{ {
} }
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) : virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &)
{ {
throw std::runtime_error("Undispatched ast_node (internal error)"); throw std::runtime_error("Undispatched ast_node (internal error)");
} }
private: private:
// Copy and assignment explicitly unimplemented // Copy and assignment explicitly unimplemented
AST_Node(const AST_Node &); AST_Node(const AST_Node &) = delete;
AST_Node& operator=(const AST_Node &); AST_Node& operator=(const AST_Node &) = delete;
}; };
@@ -478,25 +528,32 @@ namespace chaiscript
{ {
namespace detail namespace detail
{ {
/** /// Special type for returned values
* Special type for returned values
*/
struct Return_Value { struct Return_Value {
Boxed_Value retval; Boxed_Value retval;
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { } Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
}; };
/**
* Special type indicating a call to 'break' /// Special type indicating a call to 'break'
*/
struct Break_Loop { struct Break_Loop {
Break_Loop() { } Break_Loop() { }
}; };
/// Special type indicating a call to 'continue'
struct Continue_Loop {
Continue_Loop() { }
};
/// Creates a new scope then pops it on destruction /// Creates a new scope then pops it on destruction
struct Scope_Push_Pop struct Scope_Push_Pop
{ {
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de) : m_de(t_de)
{ {
@@ -510,16 +567,16 @@ namespace chaiscript
private: private:
// explicitly unimplemented copy and assignment
Scope_Push_Pop(const Scope_Push_Pop &);
Scope_Push_Pop& operator=(const Scope_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de; chaiscript::detail::Dispatch_Engine &m_de;
}; };
/// Creates a new functon call and pops it on destruction /// Creates a new function call and pops it on destruction
struct Function_Push_Pop struct Function_Push_Pop
{ {
Function_Push_Pop(const Function_Push_Pop &) = delete;
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de) : m_de(t_de)
{ {
@@ -536,11 +593,13 @@ namespace chaiscript
m_de.save_function_params(t_params); m_de.save_function_params(t_params);
} }
void save_params(std::initializer_list<Boxed_Value> t_params)
{
m_de.save_function_params(std::move(t_params));
}
private: private:
// explicitly unimplemented copy and assignment
Function_Push_Pop(const Function_Push_Pop &);
Function_Push_Pop& operator=(const Function_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de; chaiscript::detail::Dispatch_Engine &m_de;
}; };
@@ -548,6 +607,9 @@ namespace chaiscript
/// Creates a new scope then pops it on destruction /// Creates a new scope then pops it on destruction
struct Stack_Push_Pop struct Stack_Push_Pop
{ {
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de) : m_de(t_de)
{ {
@@ -561,9 +623,6 @@ namespace chaiscript
private: private:
// explicitly unimplemented copy and assignment
Stack_Push_Pop(const Stack_Push_Pop &);
Stack_Push_Pop& operator=(const Stack_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de; chaiscript::detail::Dispatch_Engine &m_de;
}; };

View File

@@ -1,21 +1,40 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_ENGINE_HPP_ #ifndef CHAISCRIPT_ENGINE_HPP_
#define CHAISCRIPT_ENGINE_HPP_ #define CHAISCRIPT_ENGINE_HPP_
#include <cassert>
#include <exception> #include <exception>
#include <fstream> #include <fstream>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <stdexcept>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "../chaiscript_threading.hpp"
#include "../dispatchkit/boxed_cast_helper.hpp"
#include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/type_conversions.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "chaiscript_common.hpp" #include "chaiscript_common.hpp"
#ifdef _POSIX_VERSION #if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
#include <unistd.h>
#endif
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
#include <dlfcn.h> #include <dlfcn.h>
#else #else
#ifdef BOOST_WINDOWS #ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN #define VC_EXTRA_LEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
@@ -23,9 +42,9 @@
#endif #endif
#include "chaiscript_prelude.hpp"
#include "chaiscript_parser.hpp"
#include "../dispatchkit/exception_specification.hpp" #include "../dispatchkit/exception_specification.hpp"
#include "chaiscript_parser.hpp"
#include "chaiscript_prelude.chai"
namespace chaiscript namespace chaiscript
{ {
@@ -34,20 +53,19 @@ namespace chaiscript
/// \brief Thrown if an error occurs while attempting to load a binary module /// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error struct load_module_error : std::runtime_error
{ {
load_module_error(const std::string &t_reason) throw() load_module_error(const std::string &t_reason) CHAISCRIPT_NOEXCEPT
: std::runtime_error(t_reason) : std::runtime_error(t_reason)
{ {
} }
virtual ~load_module_error() throw() load_module_error(const load_module_error &) = default;
{ virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
}
}; };
} }
namespace detail namespace detail
{ {
#ifdef _POSIX_VERSION #if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
struct Loadable_Module struct Loadable_Module
{ {
struct DLModule struct DLModule
@@ -57,7 +75,7 @@ namespace chaiscript
{ {
if (!m_data) if (!m_data)
{ {
throw exception::load_module_error(dlerror()); throw chaiscript::exception::load_module_error(dlerror());
} }
} }
@@ -80,7 +98,7 @@ namespace chaiscript
{ {
if (!m_symbol) if (!m_symbol)
{ {
throw exception::load_module_error(dlerror()); throw chaiscript::exception::load_module_error(dlerror());
} }
} }
@@ -118,69 +136,67 @@ namespace chaiscript
struct Loadable_Module struct Loadable_Module
{ {
template<typename T> template<typename T>
static std::wstring towstring(const T &t_str) static std::wstring to_wstring(const T &t_str)
{ {
return std::wstring(t_str.begin(), t_str.end()); return std::wstring(t_str.begin(), t_str.end());
} }
template<typename T> template<typename T>
static std::string tostring(const T &t_str) static std::string to_string(const T &t_str)
{ {
return std::string(t_str.begin(), t_str.end()); return std::string(t_str.begin(), t_str.end());
} }
#ifdef _UNICODE #if defined(_UNICODE) || defined(UNICODE)
template<typename T> template<typename T>
static std::wstring toproperstring(const T &t_str) static std::wstring to_proper_string(const T &t_str)
{ {
return towstring(t_str); return to_wstring(t_str);
} }
#else #else
template<typename T> template<typename T>
static std::string toproperstring(const T &t_str) static std::string to_proper_string(const T &t_str)
{ {
return tostring(t_str); return to_string(t_str);
} }
#endif #endif
static std::string GetErrorMessage(DWORD t_err) static std::string get_error_message(DWORD t_err)
{ {
#ifdef _UNICODE typedef LPTSTR StringType;
typedef LPWSTR StringType;
#if defined(_UNICODE) || defined(UNICODE)
std::wstring retval = L"Unknown Error"; std::wstring retval = L"Unknown Error";
#else #else
typedef LPSTR StringType;
std::string retval = "Unknown Error"; std::string retval = "Unknown Error";
#endif #endif
StringType lpMsgBuf = 0; StringType lpMsgBuf = nullptr;
FormatMessage( if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, NULL,
t_err, t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(StringType)&lpMsgBuf, reinterpret_cast<StringType>(&lpMsgBuf),
0, NULL ); 0, NULL ) != 0 && lpMsgBuf)
if (lpMsgBuf)
{ {
retval = lpMsgBuf; retval = lpMsgBuf;
LocalFree(lpMsgBuf);
} }
LocalFree(lpMsgBuf); return to_string(retval);
return tostring(retval);
} }
struct DLModule struct DLModule
{ {
DLModule(const std::string &t_filename) DLModule(const std::string &t_filename)
: m_data(LoadLibrary(toproperstring(t_filename).c_str())) : m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
{ {
if (!m_data) if (!m_data)
{ {
throw exception::load_module_error(GetErrorMessage(GetLastError())); throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
} }
} }
@@ -200,7 +216,7 @@ namespace chaiscript
{ {
if (!m_symbol) if (!m_symbol)
{ {
throw exception::load_module_error(GetErrorMessage(GetLastError())); throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
} }
} }
@@ -223,7 +239,7 @@ namespace chaiscript
{ {
Loadable_Module(const std::string &, const std::string &) Loadable_Module(const std::string &, const std::string &)
{ {
throw exception::load_module_error("Loadable module support not available for your platform"); throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
} }
ModulePtr m_moduleptr; ModulePtr m_moduleptr;
@@ -231,7 +247,7 @@ namespace chaiscript
#endif #endif
#endif #endif
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr; typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
} }
@@ -245,27 +261,24 @@ namespace chaiscript
std::map<std::string, detail::Loadable_Module_Ptr> m_loaded_modules; std::map<std::string, detail::Loadable_Module_Ptr> m_loaded_modules;
std::set<std::string> m_active_loaded_modules; std::set<std::string> m_active_loaded_modules;
std::vector<std::string> m_modulepaths; std::vector<std::string> m_module_paths;
std::vector<std::string> m_usepaths; std::vector<std::string> m_use_paths;
chaiscript::detail::Dispatch_Engine m_engine; chaiscript::detail::Dispatch_Engine m_engine;
/// Evaluates the given string in by parsing it and running the results through the evaluator
/**
* Evaluates the given string in by parsing it and running the results through the evaluator
*/
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
{ {
try { try {
parser::ChaiScript_Parser parser; parser::ChaiScript_Parser parser;
if (parser.parse(t_input, t_filename)) { if (parser.parse(t_input, t_filename)) {
//parser.show_match_stack(); //parser.show_match_stack();
return parser.ast()->eval(m_engine); return parser.optimized_ast()->eval(m_engine);
} else { } else {
return Boxed_Value(); return Boxed_Value();
} }
} }
catch (const chaiscript::eval::detail::Return_Value &rv) { catch (chaiscript::eval::detail::Return_Value &rv) {
return rv.retval; return rv.retval;
} }
} }
@@ -281,10 +294,28 @@ namespace chaiscript
} }
} }
/// Evaluates the given file and looks in the 'use' paths
const Boxed_Value internal_eval_file(const std::string &t_filename) {
for (const auto &path : m_use_paths)
{
try {
const auto appendedpath = path + t_filename;
return do_eval(load_file(appendedpath), appendedpath, true);
} catch (const exception::file_not_found_error &) {
// failed to load, try the next path
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
/** // failed to load by any name
* Evaluates the given string, used during eval() inside of a script throw exception::file_not_found_error(t_filename);
*/
}
/// Evaluates the given string, used during eval() inside of a script
const Boxed_Value internal_eval(const std::string &t_e) { const Boxed_Value internal_eval(const std::string &t_e) {
try { try {
return do_eval(t_e, "__EVAL__", true); return do_eval(t_e, "__EVAL__", true);
@@ -293,20 +324,13 @@ namespace chaiscript
} }
} }
/// Returns the current evaluation m_engine
/**
* Returns the current evaluation m_engine
*/
chaiscript::detail::Dispatch_Engine &get_eval_engine() { chaiscript::detail::Dispatch_Engine &get_eval_engine() {
return m_engine; return m_engine;
} }
/** /// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude. void build_eval_system(const ModulePtr &t_lib) {
*/
void build_eval_system() {
using namespace bootstrap;
m_engine.add_reserved_word("auto");
m_engine.add_reserved_word("def"); m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun"); m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while"); m_engine.add_reserved_word("while");
@@ -316,56 +340,85 @@ namespace chaiscript
m_engine.add_reserved_word("&&"); m_engine.add_reserved_word("&&");
m_engine.add_reserved_word("||"); m_engine.add_reserved_word("||");
m_engine.add_reserved_word(","); m_engine.add_reserved_word(",");
m_engine.add_reserved_word(":="); m_engine.add_reserved_word("auto");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("return"); m_engine.add_reserved_word("return");
m_engine.add_reserved_word("break"); m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true"); m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false"); m_engine.add_reserved_word("false");
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("_"); m_engine.add_reserved_word("_");
add(Bootstrap::bootstrap()); if (t_lib)
{
add(t_lib);
}
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, boost::ref(m_engine)), "dump_system"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, std::ref(m_engine)), "dump_system");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, boost::ref(m_engine)), "dump_object"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, std::ref(m_engine)), "dump_object");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, boost::ref(m_engine)), "get_functions"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, boost::ref(m_engine)), "get_objects"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
m_engine.add(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Dynamic_Proxy_Function>(
[this](const std::vector<Boxed_Value> &t_params) {
return m_engine.call_exists(t_params);
}), "call_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name"); // 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<Boxed_Value (const dispatch::Proxy_Function_Base &, const std::vector<Boxed_Value> &)>(
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
return t_fun(t_params, this->m_engine.conversions());
}), "call");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type");
m_engine.add(fun<chaiscript::Type_Info (const std::string &)>([this](const std::string &t_type_name){ return this->m_engine.get_type(t_type_name, true); }), "type");
m_engine.add(fun<void(const Type_Info &, const Type_Info &, const std::function<Boxed_Value(const Boxed_Value &)> &)>(
[=](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
}
), "add_type_conversion");
typedef void (ChaiScript::*load_mod_1)(const std::string&); typedef std::string (ChaiScript::*load_mod_1)(const std::string&);
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&); typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module"); m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module"); m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
add(standard_library::string_type<std::string>("string"));
add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
m_engine.add(fun(&ChaiScript::use, this), "use"); m_engine.add(fun(&ChaiScript::use, this), "use");
m_engine.add(fun(&ChaiScript::internal_eval_file, this), "eval_file");
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval"); m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval"); m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
do_eval(chaiscript_prelude, "standard prelude"); m_engine.add(fun(&ChaiScript::version_major), "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::add_global_const, this), "add_global_const");
m_engine.add(fun(&ChaiScript::add_global, this), "add_global");
do_eval(ChaiScript_Prelude::chaiscript_prelude(), "standard prelude");
} }
/**
* Helper function for loading a file /// Helper function for loading a file
*/ static std::string load_file(const std::string &t_filename) {
std::string load_file(const std::string &t_filename) {
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary ); std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
if (!infile.is_open()) { if (!infile.is_open()) {
throw exception::file_not_found_error(t_filename); throw chaiscript::exception::file_not_found_error(t_filename);
} }
std::streampos size = infile.tellg(); const auto size = infile.tellg();
infile.seekg(0, std::ios::beg); infile.seekg(0, std::ios::beg);
assert(size >= 0); assert(size >= 0);
@@ -374,7 +427,7 @@ namespace chaiscript
{ {
return std::string(); return std::string();
} else { } else {
std::vector<char> v(static_cast<unsigned int>(size)); std::vector<char> v(static_cast<size_t>(size));
infile.read(&v[0], size); infile.read(&v[0], size);
return std::string(v.begin(), v.end()); return std::string(v.begin(), v.end());
} }
@@ -382,63 +435,162 @@ namespace chaiscript
public: public:
/// \brief Constructor for ChaiScript /// \brief Constructor for ChaiScript
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(), ChaiScript(const ModulePtr &t_lib,
const std::vector<std::string> &t_usepaths = std::vector<std::string>()) std::vector<std::string> t_modulepaths = std::vector<std::string>(),
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths) std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
{ {
if (m_modulepaths.empty()) if (m_module_paths.empty())
{ {
m_modulepaths.push_back(""); m_module_paths.push_back("");
} }
if (m_usepaths.empty()) if (m_use_paths.empty())
{ {
m_usepaths.push_back(""); m_use_paths.push_back("");
} }
build_eval_system(); build_eval_system(t_lib);
} }
/// \brief Constructor for ChaiScript.
///
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
/// at runtime generates an error if it cannot be found.
///
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
{
if (m_module_paths.empty())
{
m_module_paths.push_back("");
}
if (m_use_paths.empty())
{
m_use_paths.push_back("");
}
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
// If on Unix, add the path of the current executable to the module search path
// as windows would do
union cast_union
{
Boxed_Value (ChaiScript::*in_ptr)(const std::string&);
void *out_ptr;
};
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
cast_union u;
u.in_ptr = &ChaiScript::use;
if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
std::string dllpath(rInfo.dli_fname);
const size_t lastslash = dllpath.rfind('/');
if (lastslash != std::string::npos)
{
dllpath.erase(lastslash);
}
// Let's see if this is a link that we should expand
std::vector<char> buf(2048);
const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && pathlen < buf.size())
{
dllpath = std::string(&buf.front(), pathlen);
}
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
}
#endif
// attempt to load the stdlib
load_module("chaiscript_stdlib-" + version());
build_eval_system(ModulePtr());
}
static int version_major()
{
return chaiscript::version_major;
}
static int version_minor()
{
return chaiscript::version_minor;
}
static int version_patch()
{
return chaiscript::version_patch;
}
static std::string version()
{
std::stringstream ss;
ss << version_major() << "." << version_minor() << "." << version_patch();
return ss.str();
}
std::string get_type_name(const Type_Info &ti) const
{
return m_engine.get_type_name(ti);
}
template<typename T>
std::string get_type_name() const
{
return get_type_name(user_type<T>());
}
/// \brief Loads and parses a file. If the file is already, it is not reloaded /// \brief Loads and parses a file. If the file is already, it is not reloaded
/// The use paths specified at ChaiScript construction time are searched for the /// The use paths specified at ChaiScript construction time are searched for the
/// requested file. /// requested file.
/// ///
/// \param[in] t_filename Filename to load and evaluate /// \param[in] t_filename Filename to load and evaluate
void use(const std::string &t_filename) Boxed_Value use(const std::string &t_filename)
{ {
for (size_t i = 0; i < m_usepaths.size(); ++i) for (const auto &path : m_use_paths)
{ {
try { try {
const std::string appendedpath = m_usepaths[i] + t_filename; const auto appendedpath = path + t_filename;
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
Boxed_Value retval;
if (m_used_files.count(appendedpath) == 0) if (m_used_files.count(appendedpath) == 0)
{ {
m_used_files.insert(appendedpath);
l2.unlock(); l2.unlock();
eval_file(appendedpath); retval = eval_file(appendedpath);
l2.lock();
m_used_files.insert(appendedpath);
} }
return; // return, we loaded it, or it was already loaded return retval; // return, we loaded it, or it was already loaded
} catch (const exception::file_not_found_error &) { } catch (const exception::file_not_found_error &) {
if (i == m_usepaths.size() - 1)
{
throw exception::file_not_found_error(t_filename);
}
// failed to load, try the next path // failed to load, try the next path
} }
} }
// failed to load by any name
throw exception::file_not_found_error(t_filename);
} }
/// \brief Adds a constant object that is available in all contexts and to all threads /// \brief Adds a constant object that is available in all contexts and to all threads
/// \param[in] t_bv Boxed_Value to add as a global /// \param[in] t_bv Boxed_Value to add as a global
/// \param[in] t_name Name of the value to add /// \param[in] t_name Name of the value to add
/// \throw exception::global_non_const If t_bv is not a constant object /// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
/// \sa Boxed_Value::is_const /// \sa Boxed_Value::is_const
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
{ {
@@ -446,7 +598,20 @@ namespace chaiscript
return *this; return *this;
} }
/// \brief Adds a mutable object that is available in all contexts and to all threads
/// \param[in] t_bv Boxed_Value to add as a global
/// \param[in] t_name Name of the value to add
/// \warning The user is responsible for making sure the object is thread-safe if necessary
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
{
m_engine.add_global(t_bv, t_name);
return *this;
}
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored /// \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
/// \sa ChaiScript::get_state /// \sa ChaiScript::get_state
/// \sa ChaiScript::set_state /// \sa ChaiScript::set_state
struct State struct State
@@ -469,7 +634,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state /// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
/// \endcode /// \endcode
State get_state() State get_state() const
{ {
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex); chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
@@ -535,7 +700,7 @@ namespace chaiscript
/// chai.add(chaiscript::var(&obj), "obj"); // Add a pointer to a locally defined object /// chai.add(chaiscript::var(&obj), "obj"); // Add a pointer to a locally defined object
/// \endcode /// \endcode
/// ///
/// \sa \ref addingitems /// \sa \ref adding_items
template<typename T> template<typename T>
ChaiScript &add(const T &t_t, const std::string &t_name) ChaiScript &add(const T &t_t, const std::string &t_name)
{ {
@@ -552,7 +717,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai; /// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>()); /// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
/// \endcode /// \endcode
ChaiScript &add(const Dynamic_Cast_Conversion &d) ChaiScript &add(const Type_Conversion &d)
{ {
m_engine.add(d); m_engine.add(d);
return *this; return *this;
@@ -572,37 +737,40 @@ namespace chaiscript
/// \param[in] t_module_name Name of the module to load /// \param[in] t_module_name Name of the module to load
/// ///
/// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript) /// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript)
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|""). /// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|".bundle"|"").
/// ///
/// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>". /// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>".
/// If no file can be found matching the search criteria and containing the appropriate entry point /// If no file can be found matching the search criteria and containing the appropriate entry point
/// (the symbol mentioned above), an exception is thrown. /// (the symbol mentioned above), an exception is thrown.
/// ///
/// \throw exception::load_module_error In the event that no matching module can be found. /// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
void load_module(const std::string &t_module_name) std::string load_module(const std::string &t_module_name)
{ {
std::vector<exception::load_module_error> errors; std::vector<exception::load_module_error> errors;
std::string version_stripped_name = t_module_name;
std::vector<std::string> prefixes; size_t version_pos = version_stripped_name.find("-"+version());
prefixes.push_back("lib"); if (version_pos != std::string::npos)
prefixes.push_back("");
std::vector<std::string> postfixes;
postfixes.push_back(".dll");
postfixes.push_back(".so");
postfixes.push_back("");
for (size_t i = 0; i < m_modulepaths.size(); ++i)
{ {
for (size_t j = 0; j < prefixes.size(); ++j) version_stripped_name.erase(version_pos);
}
std::vector<std::string> prefixes{"lib", "cyg", ""};
std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
for (auto & elem : m_module_paths)
{ {
for (size_t k = 0; k < postfixes.size(); ++k) for (auto & prefix : prefixes)
{
for (auto & postfix : postfixes)
{ {
try { try {
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k]; const auto name = elem + prefix + t_module_name + postfix;
load_module(t_module_name, name); // std::cerr << "trying location: " << name << '\n';
return; load_module(version_stripped_name, name);
} catch (const exception::load_module_error &e) { return name;
} catch (const chaiscript::exception::load_module_error &e) {
// std::cerr << "error: " << e.what() << '\n';
errors.push_back(e); errors.push_back(e);
// Try next set // Try next set
} }
@@ -624,7 +792,7 @@ namespace chaiscript
errstring += itr->what(); errstring += itr->what();
} }
throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring); throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
} }
/// \brief Load a binary module from a dynamic library. Works on platforms that support /// \brief Load a binary module from a dynamic library. Works on platforms that support
@@ -658,16 +826,16 @@ namespace chaiscript
/// ///
/// \return result of the script execution /// \return result of the script execution
/// ///
/// \throw exception::eval_error In the case that evaluation fails. /// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler()) Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
{ {
try { try {
return do_eval(t_script); return do_eval(t_script);
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
@@ -681,27 +849,35 @@ namespace chaiscript
/// ///
/// \return result of the script execution /// \return result of the script execution
/// ///
/// \throw exception::eval_error In the case that evaluation fails. /// \throw chaiscript::exception::eval_error In the case that evaluation fails.
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted /// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// to the requested type. /// to the requested type.
template<typename T> template<typename T>
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__") T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
{ {
try { try {
return boxed_cast<T>(do_eval(t_input, t_filename)); return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
{
return m_engine.boxed_cast<Type>(bv);
}
/// \brief Evaluates a string. /// \brief Evaluates a string.
/// ///
/// \param[in] t_input Script to execute /// \param[in] t_input Script to execute
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful /// \param[in] t_filename Optional filename to report to the user for where the error occurred. Useful
/// in special cases where you are loading a file internally instead of using eval_file /// in special cases where you are loading a file internally instead of using eval_file
/// ///
/// \return result of the script execution /// \return result of the script execution
@@ -713,9 +889,9 @@ namespace chaiscript
return do_eval(t_input, t_filename); return do_eval(t_input, t_filename);
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
@@ -723,35 +899,35 @@ namespace chaiscript
/// \param[in] t_filename File to load and parse. /// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \return result of the script execution /// \return result of the script execution
/// \throw exception::eval_error In the case that evaluation fails. /// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try { try {
return do_eval(load_file(t_filename), t_filename); return do_eval(load_file(t_filename), t_filename);
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
/// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result. /// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
/// \tparam T Type to extract from the result value of the script execution /// \tparam T Type to extract from the result value of the script execution
/// \param[in] t_filename File to load and parse. /// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \return result of the script execution /// \return result of the script execution
/// \throw exception::eval_error In the case that evaluation fails. /// \throw chaiscript::exception::eval_error In the case that evaluation fails.
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted /// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// to the requested type. /// to the requested type.
template<typename T> template<typename T>
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try { try {
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename)); return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
}; };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
namespace ChaiScript_Language namespace ChaiScript_Language
{ {
/// \page LangStandardLibraryRef ChaiScript Language Standard Libary Reference /// \page LangStandardLibraryRef ChaiScript Language Standard Library Reference
/// ///
/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly /// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available /// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
@@ -112,7 +112,7 @@ class Map
}; };
/// \brief A concept implemented by string, Vector and Map. It is convertable to Range, default constructable and back_insertable /// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
class Container class Container
{ {
public: public:
@@ -153,10 +153,10 @@ void print(Object o);
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript. /// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
/// ///
/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string /// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string
/// using the chaiscript::boxed_cast and chaiscript::var functions. /// using the chaiscript::boxed_cast and chaiscript::var functions.
/// ///
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the /// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
/// std::string of the same name. /// std::string of the same name.
/// ///
/// \note Object and function notations are equivalent in ChaiScript. This means that /// \note Object and function notations are equivalent in ChaiScript. This means that
@@ -309,7 +309,7 @@ class Range
/// \brief Moves the front pointer forward one /// \brief Moves the front pointer forward one
/// ///
/// \post front() returne the element at front() + 1; /// \post front() returns the element at front() + 1;
void pop_front(); void pop_front();
}; };
@@ -340,7 +340,7 @@ class Const_Range
/// \brief Moves the front pointer forward one /// \brief Moves the front pointer forward one
/// ///
/// \post front() returne the element at front() + 1; /// \post front() returns the element at front() + 1;
void pop_front(); void pop_front();
}; };
@@ -519,7 +519,7 @@ class Function
/// \brief Returns a vector of Type_Info objects that represent the param types for this function. /// \brief Returns a vector of Type_Info objects that represent the param types for this function.
/// The first value in the list is the return type. /// The first value in the list is the return type.
/// ///
/// If this function is a conglomeration of several functions (get_contained_values().size() > 0) /// If this function is a conglomerate of several functions (get_contained_values().size() > 0)
/// then the function returns as many Type_Info objects as it can. If the functions contained all have /// then the function returns as many Type_Info objects as it can. If the functions contained all have
/// the same arity, then it represents the arity. If they have different arities, it returns only /// the same arity, then it represents the arity. If they have different arities, it returns only
/// one value - the return type. /// one value - the return type.
@@ -534,7 +534,7 @@ class Function
/// \endcode /// \endcode
Vector get_param_types() const; Vector get_param_types() const;
/// \brief Returns true if the function has a guard to it. Always returns falls for a conglomerate function /// \brief Returns true if the function has a guard to it. Always returns false for a conglomerate function
bool has_guard() const; bool has_guard() const;
/// \brief Calls the function with the given set of parameters and returns the value; /// \brief Calls the function with the given set of parameters and returns the value;

View File

@@ -1,96 +1,66 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_ #ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_ #define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include "../chaiscript.hpp"
#include <boost/preprocessor.hpp>
#include <string> #include <string>
#include <utility>
#include <vector>
#define CHAISCRIPT_MODULE(_info) BOOST_PP_SEQ_ELEM(0, _info) #include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
#define CHAISCRIPT_CLASS_ELEM(_info) BOOST_PP_SEQ_ELEM(1, _info)
#define CHAISCRIPT_METHOD(_info, _method) & CHAISCRIPT_CLASS_ELEM(_info) :: BOOST_PP_SEQ_ELEM(0, _method)
#define CHAISCRIPT_METHOD_NAME(_info, _method) \
BOOST_PP_SEQ_ELEM(3, _info) (BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0, _method ) ) )
#define CHAISCRIPT_CLASS_NAME(_info) \
BOOST_PP_SEQ_ELEM(2, _info) (BOOST_PP_STRINGIZE(CHAISCRIPT_CLASS_ELEM(_info) ) )
#define CHAISCRIPT_METHOD_SIGNATURE_PART(_r, _info, _i, _method_part) \
BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(_i, 1), < _method_part > )
#define CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
BOOST_PP_SEQ_FOR_EACH_I(CHAISCRIPT_METHOD_SIGNATURE_PART, _info, _method)
#define CHAISCRIPT_CLASS_CONSTRUCTOR(_r, _info, _constructor) \
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::constructor<_constructor>() BOOST_PP_COMMA() CHAISCRIPT_CLASS_NAME(_info) BOOST_PP_RPAREN() ;
#define CHAISCRIPT_CLASS_METHOD(_r, _info, _method) \
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::fun CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
BOOST_PP_LPAREN() CHAISCRIPT_METHOD(_info, _method) BOOST_PP_RPAREN() BOOST_PP_COMMA() CHAISCRIPT_METHOD_NAME(_info, _method)BOOST_PP_RPAREN() ;
#define CHAISCRIPT_CLASS_CONSTRUCTORS(_info, _constructors) \
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_CONSTRUCTOR, _info, _constructors)
#define CHAISCRIPT_CLASS_METHODS(_info, _methods) \
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_METHOD, _info, _methods)
#define CHAISCRIPT_CLASS_EX(_module, _class_name, _class_name_translator, _method_name_translator, _constructors, _methods) \
{ \
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
CHAISCRIPT_CLASS_CONSTRUCTORS((_module)(_class_name)(_class_name_translator), _constructors) \
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
}
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, _class_name_translator, _method_name_translator, _methods) \
{ \
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
}
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _constructors, _methods)
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR(_module, _class_name, _methods) \
CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
chaiscript::utility::method_name_translator, _methods)
namespace chaiscript namespace chaiscript
{ {
/// \brief Classes and functions which provide general utility to the end user.
namespace utility namespace utility
{ {
inline std::string class_name_translator(const std::string &t_name)
/// Single step command for registering a class with ChaiScript
///
/// \param[in,out] t_module Model to add class to
/// \param[in] t_class_name Name of the class being registered
/// \param[in] t_constructors Vector of constructors to add
/// \param[in] t_funcs Vector of methods to add
///
/// \example Adding a basic class to ChaiScript in one step
///
/// \code
/// chaiscript::utility::add_class<test>(*m,
/// "test",
/// { constructor<test ()>(),
/// constructor<test (const test &)>() },
/// { {fun(&test::function), "function"},
/// {fun(&test::function2), "function2"},
/// {fun(&test::function3), "function3"},
/// {fun(static_cast<std::string(test::*)(double)>(&test::function_overload)), "function_overload" },
/// {fun(static_cast<std::string(test::*)(int)>(&test::function_overload)), "function_overload" },
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
/// }
/// );
///
template<typename Class, typename ModuleType>
void add_class(ModuleType &t_module,
const std::string &t_class_name,
const std::vector<chaiscript::Proxy_Function> &t_constructors,
const std::vector<std::pair<chaiscript::Proxy_Function, std::string>> &t_funcs)
{ {
size_t colon = t_name.rfind("::"); t_module.add(chaiscript::user_type<Class>(), t_class_name);
if (colon != std::string::npos)
for(const chaiscript::Proxy_Function &ctor: t_constructors)
{ {
return t_name.substr(colon+2, std::string::npos); t_module.add(ctor, t_class_name);
} else {
return t_name;
}
} }
inline std::string method_name_translator(const std::string &t_name) for(const auto &fun: t_funcs)
{ {
size_t namestart = t_name.rfind("operator"); t_module.add(fun.first, fun.second);
namestart = (namestart == std::string::npos)?0:namestart+strlen("operator");
if (namestart == 0)
{
namestart = t_name.rfind("::");
namestart = (namestart == std::string::npos)?0:namestart+strlen("::");
} }
return t_name.substr(namestart, std::string::npos);
} }
} }
} }

View File

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

View File

@@ -1,38 +1,55 @@
Master Status: [![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=master)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=master)
Develop Status: [![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=develop)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop)
ChaiScript ChaiScript
http://www.chaiscript.com http://www.chaiscript.com
(c) 2009-2012 Jason Turner and Jonathan Turner (c) 2009-2012 Jonathan Turner
(c) 2009-2015 Jason Turner
Release under the BSD license, see "license.txt" for details. Release under the BSD license, see "license.txt" for details.
Introduction Introduction
============ ============
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/ChaiScript/ChaiScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
ChaiScript is one of the only embedded scripting language designed from the ChaiScript is one of the only embedded scripting language designed from the
ground up to directly target C++ and take advantage of modern C++ development ground up to directly target C++ and take advantage of modern C++ development
techniques, working with the developer like he expects it to work. Being a techniques, working with the developer like he expects it to work. Being a
native C++ application, it has some advantages over existing embedded scripting native C++ application, it has some advantages over existing embedded scripting
languages: languages:
1) It uses a header-only approach, which makes it easy to integrate with 1. It uses a header-only approach, which makes it easy to integrate with
existing projects. existing projects.
2) It maintains type safety between your C++ application and the user scripts. 2. It maintains type safety between your C++ application and the user scripts.
3) It supports a variety of C++ techniques including callbacks, overloaded 3. It supports a variety of C++ techniques including callbacks, overloaded
functions, class methods, and stl containers. functions, class methods, and stl containers.
Requirements Requirements
============ ============
ChaiScript requires a recent version of Boost (http://www.boost.org) to build. ChaiScript requires a C++11 compiler to build with support for variadic
templates. It has been tested with gcc 4.6 and clang 3.1 (with libcxx). MacOS
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
clang 4.0. MSVC 2013 or newer is supports also. For more information see the build
[dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html).
Usage Usage
===== =====
* Add the ChaiScript include directory to your project's header search path * Add the ChaiScript include directory to your project's header search path
* Add `#include <chaiscript/chaiscript.hpp>` to your source file * Add `#include <chaiscript/chaiscript.hpp>` to your source file
* Instantiate the ChaiScript engine in your application. For example, create * Instantiate the ChaiScript engine in your application. For example, create a
a new engine with the name `chai` like so: `chaiscript::ChaiScript chai` new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
* The default behavior is to load the ChaiScript standard library from a
loadable module. A second option is to compile the library into your code,
see below for an example.
Once instantiated, the engine is ready to start running ChaiScript source. You Once instantiated, the engine is ready to start running ChaiScript source. You
have two main options for processing ChaiScript source: a line at a time using have two main options for processing ChaiScript source: a line at a time using
@@ -80,3 +97,26 @@ The shortest complete example possible follows:
} }
Or, if you want to compile the std lib into your code, which reduces
runtime requirements.
/// main.cpp
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}

179
releasenotes.md Normal file
View File

@@ -0,0 +1,179 @@
Notes:
=======
Current Version: 5.7.0
### Changes since 5.6.0
* Significant code cleanups and reduction
* Smaller builds
* Faster compiles
* Less runtime memory usage
* ~2x faster runtimes
* biicode support
* method_missing feature added #164 @arBmind
* Generic objects with dynamic properties support
* Add ability to call functions contained in properties
* Add lambda captures
* Create [cheatsheet.md](cheatsheet.md) for all-in-one reference of features
* Fix support for libc++
* Eliminate clone of return value stored locally
* Eliminate 'return' statements when last line of function
* Reduce number of runtime exceptions occuring
* Reduce copies / moves of return values.
* make `use` statement return value of last statement in file
* Add ability to access fixed array sizes
* Add support for scientific notation floating point literals #174 @totalgee
### Changes since 5.5.1
* Throw exception on integer divide by 0
* Add optional type specification to function declarations
```
def func(int i, j, double k) {
// i must be an int.
// j can be anything
// k must be a double
// normal conversion rules still apply
}
```
* Many minor fixes for compiler warnings
* Add support for `std::future` and `std::async`
```
var f := async(someFunction);
var f2 := async(someFunction2);
// someFunction and someFunction2 are running in parallel now
f.get();
f2.get();
```
* Fully support r-value returns, supporting move-only objects and reducing object copies
### Changes since 5.5.0
* 30% performance increase
* Fix handling of object stack, resulting in greatly reduced memory usage
* Code cleanups
### Changes since 5.4.0
* 2x performance increase
* Significant code cleanups
* Throw exception if user attempts to call function on null object
* Allow user defined type conversions
* Fix object lifetime for nested function calls made at the global scope
* Fix returning of boolean values from function calls
### Changes since 5.3.1
* Decreased compile time and build size
* Make "reflection" module built in (losing some of the time / build size gains)
* Add new "class" syntax for ChaiScript defined methods and attributes see: [unittests/class.chai](unittests/class.chai) for examples
* Minor performance enhancements
* major to_string performance enhancements
* Provide API for retrieving registered type name #124
* Added strong reference to container to range object #132
### Changes since 5.3.0
* Add automatic conversion of arithmetic return types, following the same
rules as conversion of arithmetic types when passing parameters
* Add automatic casting up the inheritence hierarchy when possible.
* Enable travis.ci testing
* Allow users to add globals from within script
* Various static analysis fixes
* Code modernization to C++11
* Unofficial support for Haiku added
* Fix #121 - Inability to compile on cygwin
* Formatting fixes and spelling corrections
* Apply "include what you use" https://code.google.com/p/include-what-you-use/
* Apply clang-modernize
* Various threading fixes
* Performance improvements
### Changes since 5.2.0
* Official support for MSVC with C++11. All major platforms and compilers are now support for C++11 release
### Changes since 4.2.0
* Enhanced unit tests
* Add `continue` statement, fix various use cases for `for` loops
* Fix use of suffixed numbers in vector initialization
* Code cleanups
* Eliminate global data, which makes code more portable and thread safe
* Fix issue #79
* Merge pretty_print fixes from @mgee #82
* Compiler warning fixes for latest compiler releases
* Fix threading problems
* Fix linking error on MacOS Mavericks #88
* Allow non-const globals
* Make sure user cannot name a variable with `::` in it #91
* Fix various string / map / vector `size` and `count` calls for compilers which have weird overloads for them. #90 #93 #95
* Make module search path relative to the currently running executable
* Build and work with wstring windows builds
* fix for some new line cases in the middle of a vector initialization from jespada
### Changes since 5.1.0
* Add support for automatic conversion of arithmetic types when possible
and when no ambiguous method dispatch exists.
### Changes since 5.0.0
* Fix sizing of numeric constants to match that of the C++ standard
* Add support for u,ll,l,f suffixes for numeric constants
* Siginificant improvement in error reporting
### Changes since 4.0.0
* Dropped boost in favor of C++11
* Separated out stdlib to make more options for compile time improvements
### Changes since 3.1.0
* svenstaro: Unused variables and CMake consistency fixes
* Added support for returning pointers from functions (#13)
* Compile with -pedantic (#9)
* Fix issues with multiple ChaiScript object types having the same attribute name (#15)
* Prevent variable redeclaration in same scope (#22)
* mgee: Boxed_Number improvements (#27)
* Support switch statements (#34)
* Fix uint16 comparions (#26)
* Add ability to add const_var globals in Module objects (#14)
* Add support for ternary operators ?:
* Add headers to CMakeLists so they show up in IDEs
* Add ability to get vector of defined objects and vector of defined functions
* Fix memory leak in cyclical references
* Clean up static analysis issues discovered
* Fix vector construction to be consistent with map construction
* Increased unit tests to 161
* Performance enhancements
### Changes since 3.0.0
* Numeric operations performance increased approximately 10x
* Looping operations performance increased up to 2x
* Engine start up time decreased
* Several parsing bugs related to index operators fixed
* Added full support for all C algebraic types: double, long double, float, int, long, char,
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
* Enhanced support for capturing of exceptions thrown from ChaiScript in C++
### Changes since 2.3.3
* Code simplifications
* Fully integrate documentation with source code in doxygen style comments
* Unit tests increased from 114 to 137
* Automatic conversion between boost::function objects and ChaiScript functions
* Many bug fixes
* Minor performance improvements
* Namespace reorganization to make end user code more accessible
* clang support
* VisualStudio 2010 Support
* Support for C++ base classes and automatic upcasting
* Remove __ reserved identifiers
* Better code organization to reduce #ifdefs
* clanmills: command line options for chai eval
* clanmills: parser cleanups and code reduction
* Function introspection and reflection
* Correct function dispatch order to account for base classes and provide a defined order of dispatch
* Predictable object lifetime that emulates C++ stack lifetime
* emarcotte: pkgconfig support
* standardize on method/member naming and indentation
* 64bit Visual Studio support
* Better support for const objects
* Drastic reduction of runtime exceptions - making debug builds orders of magnitude faster
* Support for platforms with no loadable module support
* Add helper macro for registering class

View File

@@ -1,59 +0,0 @@
Changes since 4.0.0
* Fix sizing of numeric constants to match that of the C++ standard
* Add support for u,ll,l,f suffixes for numeric constants
* Siginificant improvement in error reporting
Changes since 3.1.0
* svenstaro: Unused variables and CMake consistency fixes
* Added support for returning pointers from functions (#13)
* Compile with -pedantic (#9)
* Fix issues with multiple ChaiScript object types having the same attribute name (#15)
* Prevent variable redeclaration in same scope (#22)
* mgee: Boxed_Number improvements (#27)
* Support switch statements (#34)
* Fix uint16 comparions (#26)
* Add ability to add const_var globals in Module objects (#14)
* Add support for ternary operators ?:
* Add headers to CMakeLists so they show up in IDEs
* Add ability to get vector of defined objects and vector of defined functions
* Fix memory leak in cyclical references
* Clean up static analysis issues discovered
* Fix vector construction to be consistent with map construction
* Increased unit tests to 161
* Performance enhancements
Changes since 3.0.0
* Numeric operations performance increased approximately 10x
* Looping operations performance increased up to 2x
* Engine start up time decreased
* Several parsing bugs related to index operators fixed
* Added full support for all C algebraic types: double, long double, float, int, long, char,
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
* Enhanced support for capturing of exceptions thrown from ChaiScript in C++
Changes since 2.3.3
* Code simplifications
* Fully integrate documentation with source code in doxygen style comments
* Unit tests increased from 114 to 137
* Automatic conversion between boost::function objects and ChaiScript functions
* Many bug fixes
* Minor performance improvements
* Namespace reorganization to make end user code more accessible
* clang support
* VisualStudio 2010 Support
* Support for C++ base classes and automatic upcasting
* Remove __ reserved identifiers
* Better code organization to reduce #ifdefs
* clanmills: command line options for chai eval
* clanmills: parser cleanups and code reduction
* Function introspection and reflection
* Correct function dispatch order to account for base classes and provide a defined order of dispatch
* Predictable object lifetime that emulates C++ stack lifetime
* emarcotte: pkgconfig support
* standardize on method/member naming and indentation
* 64bit Visual Studio support
* Better support for const objects
* Drastic reduction of runtime exceptions - making debug builds orders of magnitude faster
* Support for platforms with no loadable module support
* Add helper macro for registering class

View File

@@ -5,21 +5,20 @@
// http://www.chaiscript.com // http://www.chaiscript.com
#include <iostream> #include <iostream>
#include <ctime>
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/dispatchkit/function_call.hpp> #include <chaiscript/dispatchkit/function_call.hpp>
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
void log(const std::string &msg) void log(const std::string &msg)
{ {
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] " << msg << std::endl; std::cout << "[" << time(nullptr) << "] " << msg << '\n';
} }
void log(const std::string &module, const std::string &msg) void log(const std::string &module, const std::string &msg)
{ {
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl; std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
} }
void bound_log(const std::string &msg) void bound_log(const std::string &msg)
@@ -29,30 +28,30 @@ void bound_log(const std::string &msg)
void hello_world(const chaiscript::Boxed_Value & /*o*/) void hello_world(const chaiscript::Boxed_Value & /*o*/)
{ {
std::cout << "Hello World" << std::endl; std::cout << "Hello World\n";
} }
void hello_constructor(const chaiscript::Boxed_Value & /*o*/) void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
{ {
std::cout << "Hello Constructor" << std::endl; std::cout << "Hello Constructor\n";
} }
struct System struct System
{ {
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks; std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
void add_callback(const std::string &t_name, void add_callback(const std::string &t_name,
const chaiscript::Proxy_Function &t_func) const std::function<std::string (const std::string &)> &t_func)
{ {
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func); m_callbacks[t_name] = t_func;
} }
void do_callbacks(const std::string &inp) void do_callbacks(const std::string &inp)
{ {
log("Running Callbacks: " + inp); log("Running Callbacks: " + inp);
for (std::map<std::string, boost::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin(); for (std::map<std::string, std::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
itr != m_callbacks.end(); itr != m_callbacks.end();
++itr) ++itr)
{ {
@@ -61,9 +60,9 @@ struct System
} }
}; };
void take_shared_ptr(const boost::shared_ptr<const std::string> &p) void take_shared_ptr(const std::shared_ptr<const std::string> &p)
{ {
std::cout << *p << std::endl; std::cout << *p << '\n';
} }
int main(int /*argc*/, char * /*argv*/[]) { int main(int /*argc*/, char * /*argv*/[]) {
@@ -71,12 +70,13 @@ int main(int /*argc*/, char * /*argv*/[]) {
ChaiScript chai; ChaiScript chai;
//Create a new system object and share it with the chaiscript engine //Create a new system object and share it with the chaiscript engine
System system; System system;
chai.add(var(&system), "system"); chai.add(var(&system), "system");
//Add a bound callback method //Add a bound callback method
chai.add(fun(&System::add_callback, system), "add_callback_bound"); chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
//Register the two methods of the System structure. //Register the two methods of the System structure.
chai.add(fun(&System::add_callback), "add_callback"); chai.add(fun(&System::add_callback), "add_callback");
@@ -87,7 +87,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
// Let's use chaiscript to add a new lambda callback to our system. // Let's use chaiscript to add a new lambda callback to our system.
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application // The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
// in the "add_callback" function of struct System the chaiscript function is converted into a // in the "add_callback" function of struct System the chaiscript function is converted into a
// boost::function, so it can be handled and called easily and type-safely // std::function, so it can be handled and called easily and type-safely
chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });"); chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");
// Because we are sharing the "system" object with the chaiscript engine we have equal // Because we are sharing the "system" object with the chaiscript engine we have equal
@@ -108,14 +108,14 @@ int main(int /*argc*/, char * /*argv*/[]) {
// A shortcut to using eval is just to use the chai operator() // A shortcut to using eval is just to use the chai operator()
chai("log(\"Test Module\", \"Test Message\");"); chai("log(\"Test Module\", \"Test Message\");");
//Finally, it is possible to register any boost::function as a system function, in this //Finally, it is possible to register any std::function as a system function, in this
//way, we can, for instance add a bound member function to the system //way, we can, for instance add a bound member function to the system
chai.add(fun(&System::do_callbacks, boost::ref(system), std::string("Bound Test")), "do_callbacks"); chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
//Call bound version of do_callbacks //Call bound version of do_callbacks
chai("do_callbacks()"); chai("do_callbacks()");
boost::function<void ()> caller = chai.eval<boost::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }"); std::function<void ()> caller = chai.eval<std::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
caller(); caller();
@@ -123,7 +123,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//the templated version of eval: //the templated version of eval:
int i = chai.eval<int>("5+5"); int i = chai.eval<int>("5+5");
std::cout << "5+5: " << i << std::endl; std::cout << "5+5: " << i << '\n';
//Add a new variable //Add a new variable
chai("var scripti = 15"); chai("var scripti = 15");
@@ -131,21 +131,21 @@ int main(int /*argc*/, char * /*argv*/[]) {
//We can even get a handle to the variables in the system //We can even get a handle to the variables in the system
int &scripti = chai.eval<int &>("scripti"); int &scripti = chai.eval<int &>("scripti");
std::cout << "scripti: " << scripti << std::endl; std::cout << "scripti: " << scripti << '\n';
scripti *= 2; scripti *= 2;
std::cout << "scripti (updated): " << scripti << std::endl; std::cout << "scripti (updated): " << scripti << '\n';
chai("print(\"Scripti from chai: \" + to_string(scripti))"); chai("print(\"Scripti from chai: \" + to_string(scripti))");
//To do: Add examples of handling Boxed_Values directly when needed //To do: Add examples of handling Boxed_Values directly when needed
//Creating a functor on the stack and using it immediatly //Creating a functor on the stack and using it immediately
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6); int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
std::stringstream ss; std::stringstream ss;
ss << x; ss << x;
log("Functor test output", ss.str()); log("Functor test output", ss.str());
chai.add(var(boost::shared_ptr<int>()), "nullvar"); chai.add(var(std::shared_ptr<int>()), "nullvar");
chai("print(\"This should be true.\"); print(nullvar.is_var_null())"); chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
// test the global const action // test the global const action
@@ -167,7 +167,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//Dynamic objects test //Dynamic objects test
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world"); chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType"); chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
// chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr"); // chai.add(fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", std::placeholders::_1))), "attr");
chai.eval("var x = TestType()"); chai.eval("var x = TestType()");
// chai.eval("x.attr = \"hi\""); // chai.eval("x.attr = \"hi\"");

View File

@@ -0,0 +1,4 @@
for (var i = 0; i < 1000; ++i) {
puts(helloWorld("Bob12345"))
}

View File

@@ -0,0 +1,405 @@
// 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)
// http://www.chaiscript.com
#include <iostream>
#include <list>
#include <regex>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
#include <readline/history.h>
#else
char *mystrdup(const char *s) {
size_t len = strlen(s); // Space for length plus nul
char *d = static_cast<char*>(malloc(len + 1));
if (d == nullptr) return nullptr; // No memory
#ifdef CHAISCRIPT_MSVC
strcpy_s(d, len + 1, s); // Copy the characters
#else
strncpy(d, s, len); // Copy the characters
#endif
d[len] = '\0';
return d; // Return the new string
}
char* readline(const char* p)
{
std::string retval;
std::cout << p;
std::getline(std::cin, retval);
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
}
void add_history(const char*){}
void using_history(){}
#endif
void *cast_module_symbol(std::vector<std::string>(*t_path)())
{
union cast_union
{
std::vector<std::string>(*in_ptr)();
void *out_ptr;
};
cast_union c;
c.in_ptr = t_path;
return c.out_ptr;
}
std::vector<std::string> default_search_paths()
{
std::vector<std::string> paths;
#ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
std::string exepath(path, size);
size_t lastslash = exepath.rfind('\\');
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
if (lastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, lastslash));
}
if (secondtolastslash != std::string::npos)
{
return{ exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\" };
}
#else
std::string exepath;
std::vector<char> buf(2048);
ssize_t size = -1;
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
if (exepath.empty())
{
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
}
if (exepath.empty())
{
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
}
if (exepath.empty())
{
Dl_info rInfo;
memset(&rInfo, 0, sizeof(rInfo));
if (!dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname) {
return paths;
}
exepath = std::string(rInfo.dli_fname);
}
size_t lastslash = exepath.rfind('/');
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
if (lastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, lastslash));
}
if (secondtolastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
}
#endif
return paths;
}
void help(int n) {
if (n >= 0) {
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
}
else {
std::cout << "usage : chai [option]+" << std::endl;
std::cout << "option:" << std::endl;
std::cout << " -h | --help" << std::endl;
std::cout << " -i | --interactive" << std::endl;
std::cout << " -c | --command cmd" << std::endl;
std::cout << " -v | --version" << std::endl;
std::cout << " - --stdin" << std::endl;
std::cout << " filepath" << std::endl;
}
}
std::string helloWorld(const std::string &t_name)
{
return "Hello " + t_name + "!";
}
bool throws_exception(const std::function<void()> &f)
{
try {
f();
}
catch (...) {
return true;
}
return false;
}
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f)
{
try {
f();
}
catch (const chaiscript::exception::eval_error &e) {
return e;
}
throw std::runtime_error("no exception throw");
}
std::string get_next_command() {
std::string retval("quit");
if (!std::cin.eof()) {
char *input_raw = readline("eval> ");
if (input_raw) {
add_history(input_raw);
std::string val(input_raw);
size_t pos = val.find_first_not_of("\t \n");
if (pos != std::string::npos)
{
val.erase(0, pos);
}
pos = val.find_last_not_of("\t \n");
if (pos != std::string::npos)
{
val.erase(pos + 1, std::string::npos);
}
retval = val;
::free(input_raw);
}
}
if (retval == "quit"
|| retval == "exit"
|| retval == "help"
|| retval == "version")
{
retval += "(0)";
}
return retval;
}
// We have to wrap exit with our own because Clang has a hard time with
// function pointers to functions with special attributes (system exit being marked NORETURN)
void myexit(int return_val) {
exit(return_val);
}
void interactive(chaiscript::ChaiScript& chai)
{
using_history();
for (;;) {
std::string input = get_next_command();
try {
// evaluate input
chaiscript::Boxed_Value val = chai.eval(input);
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
}
catch (...) {} //If we can't, do nothing
}
}
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what();
if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
}
std::cout << std::endl;
}
catch (const std::exception &e) {
std::cout << e.what();
std::cout << std::endl;
}
}
}
int main(int argc, char *argv[])
{
// Disable deprecation warning for getenv call.
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
const char *usepath = getenv("CHAI_USE_PATH");
const char *modulepath = getenv("CHAI_MODULE_PATH");
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
std::vector<std::string> usepaths;
usepaths.push_back("");
if (usepath)
{
usepaths.push_back(usepath);
}
std::vector<std::string> modulepaths;
std::vector<std::string> searchpaths = default_search_paths();
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
modulepaths.push_back("");
if (modulepath)
{
modulepaths.push_back(modulepath);
}
//chaiscript::ChaiScript chai(modulepaths, usepaths);
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths);
chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
chai.add(chaiscript::fun(&helloWorld), "helloWorld");
clock_t begin = clock();
for (int i = 0; i < 1000; i++)
{
std::string str = helloWorld("Bob12345");
fwrite(str.c_str(), 1, str.size(), stdout);
}
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
//begin = clock();
////for (int i = 0; i < 1000; i++)
////{
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
////}
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
//end = clock();
//elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
//printf("**MyProgram::time= %lf\n", elapsed_secs);
for (int i = 0; i < argc; ++i) {
if (i == 0 && argc > 1) {
++i;
}
std::string arg(i ? argv[i] : "--interactive");
enum {
eInteractive
, eCommand
, eFile
} mode = eCommand;
if (arg == "-c" || arg == "--command") {
if ((i + 1) >= argc) {
std::cout << "insufficient input following " << arg << std::endl;
return EXIT_FAILURE;
}
else {
arg = argv[++i];
}
}
else if (arg == "-" || arg == "--stdin") {
arg = "";
std::string line;
while (std::getline(std::cin, line)) {
arg += line + '\n';
}
}
else if (arg == "-v" || arg == "--version") {
arg = "version()";
}
else if (arg == "-h" || arg == "--help") {
arg = "help(-1)";
}
else if (arg == "-i" || arg == "--interactive") {
mode = eInteractive;
}
else if (arg.find('-') == 0) {
std::cout << "unrecognised argument " << arg << std::endl;
return EXIT_FAILURE;
}
else {
mode = eFile;
}
chaiscript::Boxed_Value val;
try {
switch (mode) {
case eInteractive: interactive(chai); break;
case eCommand: val = chai.eval(arg); break;
case eFile: {
begin = clock();
val = chai.eval_file(arg);
end = clock();
double elapsed_secs1 = double(end - begin) / CLOCKS_PER_SEC;
printf("**C++::time= %.10f\n", elapsed_secs);
printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
break;
}
}
}
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.pretty_print();
std::cout << std::endl;
return EXIT_FAILURE;
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}

136
samples/inheritance.cpp Normal file
View File

@@ -0,0 +1,136 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
class BaseClass
{
public:
BaseClass()
{
}
BaseClass(const BaseClass &) = default;
virtual ~BaseClass() {}
virtual std::string doSomething(float, double) const = 0;
void setValue(const std::string &t_val) {
if (validateValue(t_val))
{
m_value = t_val;
}
}
std::string getValue() const {
return m_value;
}
protected:
virtual bool validateValue(const std::string &t_val) = 0;
private:
std::string m_value;
};
class ChaiScriptDerived : public BaseClass
{
public:
ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &t_funcs)
{
// using the range-checked .at() methods to give us an exception
// instead of a crash if the user passed in too-few params
tie(t_funcs.at(0), m_doSomethingImpl);
tie(t_funcs.at(1), m_validateValueImpl);
}
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
{
assert(m_doSomethingImpl);
return m_doSomethingImpl(*this, f, d);
}
protected:
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
{
assert(m_validateValueImpl);
return m_validateValueImpl(*this, t_val);
}
private:
template<typename Param>
void tie(const chaiscript::Boxed_Value &t_func, Param &t_param)
{
t_param = chaiscript::boxed_cast<Param>(t_func);
}
std::function<std::string (const ChaiScriptDerived&, float, double)> m_doSomethingImpl;
std::function<bool (ChaiScriptDerived&, const std::string &t_val)> m_validateValueImpl;
};
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
chai.add(chaiscript::constructor<ChaiScriptDerived (const std::vector<chaiscript::Boxed_Value> &)>(), "ChaiScriptDerived");
chai.add(chaiscript::base_class<BaseClass, ChaiScriptDerived>());
chai.add(chaiscript::user_type<BaseClass>(), "BaseClass");
chai.add(chaiscript::user_type<ChaiScriptDerived>(), "ChaiScriptDerived");
std::string script = R""(
def MakeDerived() {
return ChaiScriptDerived(
// create a dynamically created array and pass it in to the constructor
[
fun(this, f, d) {
// see here that we are calling back into the 'this' pointer
return "${this.getValue()}${f * d}";
},
fun(this, new_val) {
if (new_val.size() < 5) {
true;
} else {
print("String ${new_val} is too long");
false;
}
}
]
);
}
var myderived := MakeDerived(); // avoid a copy by using reference assignment :=
)"";
chai.eval(script);
BaseClass &myderived = chai.eval<ChaiScriptDerived&>("myderived");
// at this point in the code myderived is both a ChaiScript variable and a C++ variable. In both cases
// it is a derivation of BaseClass, and the implementation is provided via ChaiScript functors
// assigned in the MakeDerived() factory function
//
// Notice that our validateValue() function has a requirement that the new string be < 5 characters long
myderived.setValue("1234");
assert(myderived.getValue() == "1234");
// chaiscript defined function will print out an error message and refuse to allow the setting
myderived.setValue("12345");
assert(myderived.getValue() == "1234");
chai.eval("myderived.setValue(\"new\")"); // set the value via chaiscript
assert(myderived.getValue() == "new");
// call the other derived method via chaiscript and return the value to c++ land:
std::string retval = chai.eval<std::string>("myderived.doSomething(2,4.3)");
assert(retval == "new8.6");
// The whole process is fully orthogonal
}

View File

@@ -1,13 +1,14 @@
#include <iostream> #include <iostream>
#include "chaiscript/chaiscript.hpp" #include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE #ifdef READLINE_AVAILABLE
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#endif #endif
using namespace chaiscript;
std::string get_next_command() { std::string get_next_command() {
#ifdef READLINE_AVAILABLE #ifdef READLINE_AVAILABLE
@@ -23,17 +24,19 @@ std::string get_next_command() {
#endif #endif
} }
void fuction(void) void function(void)
{ {
// do nothing // do nothing
} }
class test class test
{ {
ChaiScript chai; chaiscript::ChaiScript chai;
ChaiScript::State backupState; chaiscript::ChaiScript::State backupState;
public: public:
test() test()
: chai(chaiscript::Std_Lib::library())
{ {
backupState = chai.get_state(); backupState = chai.get_state();
} }
@@ -42,7 +45,7 @@ class test
void ResetState() void ResetState()
{ {
chai.set_state(backupState); chai.set_state(backupState);
chai.add(fun(&fuction),"Whatever()"); chai.add(chaiscript::fun(&function),"Whatever()");
} }
void RunFile(std::string sFile) void RunFile(std::string sFile)
@@ -51,7 +54,7 @@ class test
chaiscript::Boxed_Value val = chai.eval_file(sFile); chaiscript::Boxed_Value val = chai.eval_file(sFile);
} }
catch (std::exception &e) { catch (std::exception &e) {
std::cout << e.what() << std::endl; std::cout << e.what() << '\n';
} }
} }
@@ -67,12 +70,12 @@ int main(int /*argc*/, char * /*argv*/[]) {
std::string command = ""; std::string command = "";
// //
// this loop increases memoryusage, if RunFile is not called (just hittin enter) // this loop increases memory usage, if RunFile is not called (just hitting enter)
// as soon RunFile gets called, memory will be freed. // as soon RunFile gets called, memory will be freed.
// //
// scenario1 - RunFile gets called every Loop: memoryusage does not change // scenario1 - RunFile gets called every Loop: memory usage does not change
// scenario2 - RunFile gets never called (just hitting enter): memoryusage increases every loop // scenario2 - RunFile gets never called (just hitting enter): memory usage increases every loop
// scenario3 - RunFile gets in changing intervals: memoryusage goes up and down, but never as // scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as
// low as in case 1 scenario3 : // low as in case 1 scenario3 :
while(command != "quit") while(command != "quit")

View File

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

30
src/chaiscript_stdlib.cpp Normal file
View File

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

View File

@@ -1,58 +1,161 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <boost/algorithm/string/trim.hpp> #include <regex>
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#endif
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>
#ifdef READLINE_AVAILABLE #ifdef READLINE_AVAILABLE
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#else #else
char *mystrdup (const char *s) {
size_t len = strlen(s); // Space for length plus nul
char *d = static_cast<char*>(malloc (len+1));
if (d == nullptr) return nullptr; // No memory
#ifdef CHAISCRIPT_MSVC
strcpy_s(d, len+1, s); // Copy the characters
#else
strncpy(d,s,len); // Copy the characters
#endif
d[len] = '\0';
return d; // Return the new string
}
char* readline(const char* p) char* readline(const char* p)
{ {
std::string retval; std::string retval;
std::cout << p ; std::cout << p ;
std::getline(std::cin, retval); std::getline(std::cin, retval);
#ifdef BOOST_MSVC return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
return std::cin.eof() ? NULL : _strdup(retval.c_str());
#else
return std::cin.eof() ? NULL : strdup(retval.c_str());
#endif
} }
void add_history(const char*){} void add_history(const char*){}
void using_history(){} void using_history(){}
#endif #endif
void *cast_module_symbol(std::vector<std::string> (*t_path)())
{
union cast_union
{
std::vector<std::string> (*in_ptr)();
void *out_ptr;
};
cast_union c;
c.in_ptr = t_path;
return c.out_ptr;
}
std::vector<std::string> default_search_paths()
{
std::vector<std::string> paths;
#ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
std::string exepath(path, size);
size_t lastslash = exepath.rfind('\\');
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
if (lastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, lastslash));
}
if (secondtolastslash != std::string::npos)
{
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
}
#else
std::string exepath;
std::vector<char> buf(2048);
ssize_t size = -1;
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
if (exepath.empty())
{
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
}
if (exepath.empty())
{
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
{
exepath = std::string(&buf.front(), size);
}
}
if (exepath.empty())
{
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
if ( !dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname ) {
return paths;
}
exepath = std::string(rInfo.dli_fname);
}
size_t lastslash = exepath.rfind('/');
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
if (lastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, lastslash));
}
if (secondtolastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
}
#endif
return paths;
}
void help(int n) { void help(int n) {
if ( n >= 0 ) { if ( n >= 0 ) {
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl; std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl; std::cout << "Additionally, you can inspect the runtime system using:\n";
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl; std::cout << " dump_system() - outputs all functions registered to the system\n";
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl; std::cout << " dump_object(x) - dumps information about the given symbol\n";
} else { } else {
std::cout << "usage : chai [option]+" << std::endl; std::cout << "usage : chai [option]+\n";
std::cout << "option:" << std::endl; std::cout << "option:" << '\n';
std::cout << " -h | --help" << std::endl; std::cout << " -h | --help" << '\n';
std::cout << " -i | --interactive" << std::endl; std::cout << " -i | --interactive" << '\n';
std::cout << " -c | --command cmd" << std::endl; std::cout << " -c | --command cmd" << '\n';
std::cout << " -v | --version" << std::endl; std::cout << " -v | --version" << '\n';
std::cout << " - --stdin" << std::endl; std::cout << " - --stdin" << '\n';
std::cout << " filepath" << std::endl; std::cout << " filepath" << '\n';
} }
} }
void version(int){ bool throws_exception(const std::function<void ()> &f)
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
bool throws_exception(const boost::function<void ()> &f)
{ {
try { try {
f(); f();
@@ -63,7 +166,7 @@ bool throws_exception(const boost::function<void ()> &f)
return false; return false;
} }
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f) chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
{ {
try { try {
f(); f();
@@ -80,6 +183,7 @@ std::string get_next_command() {
char *input_raw = readline("eval> "); char *input_raw = readline("eval> ");
if ( input_raw ) { if ( input_raw ) {
add_history(input_raw); add_history(input_raw);
std::string val(input_raw); std::string val(input_raw);
size_t pos = val.find_first_not_of("\t \n"); size_t pos = val.find_first_not_of("\t \n");
if (pos != std::string::npos) if (pos != std::string::npos)
@@ -91,7 +195,9 @@ std::string get_next_command() {
{ {
val.erase(pos+1, std::string::npos); val.erase(pos+1, std::string::npos);
} }
retval = val; retval = val;
::free(input_raw); ::free(input_raw);
} }
} }
@@ -124,7 +230,7 @@ void interactive(chaiscript::ChaiScript& chai)
//Then, we try to print the result of the evaluation to the user //Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) { if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try { try {
std::cout << chai.eval<boost::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl; std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
} }
catch (...) {} //If we can't, do nothing catch (...) {} //If we can't, do nothing
} }
@@ -132,24 +238,29 @@ void interactive(chaiscript::ChaiScript& chai)
catch (const chaiscript::exception::eval_error &ee) { catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what(); std::cout << ee.what();
if (ee.call_stack.size() > 0) { if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")"; std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
} }
std::cout << std::endl; std::cout << '\n';
} }
catch (const std::exception &e) { catch (const std::exception &e) {
std::cout << e.what(); std::cout << e.what();
std::cout << std::endl; std::cout << '\n';
} }
} }
} }
double now()
{
using namespace std::chrono;
auto now = high_resolution_clock::now();
return duration_cast<duration<double>>(now.time_since_epoch()).count();
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
std::vector<std::string> usepaths;
std::vector<std::string> modulepaths;
// Disable deprecation warning for getenv call. // Disable deprecation warning for getenv call.
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#endif #endif
@@ -157,16 +268,20 @@ int main(int argc, char *argv[])
const char *usepath = getenv("CHAI_USE_PATH"); const char *usepath = getenv("CHAI_USE_PATH");
const char *modulepath = getenv("CHAI_MODULE_PATH"); const char *modulepath = getenv("CHAI_MODULE_PATH");
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif
std::vector<std::string> usepaths;
usepaths.push_back(""); usepaths.push_back("");
if (usepath) if (usepath)
{ {
usepaths.push_back(usepath); usepaths.push_back(usepath);
} }
std::vector<std::string> modulepaths;
std::vector<std::string> searchpaths = default_search_paths();
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
modulepaths.push_back(""); modulepaths.push_back("");
if (modulepath) if (modulepath)
{ {
@@ -178,9 +293,10 @@ int main(int argc, char *argv[])
chai.add(chaiscript::fun(&myexit), "exit"); chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit"); chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help"); chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception"); chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error"); chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
chai.add(chaiscript::fun(&now), "now");
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if ( i == 0 && argc > 1 ) { if ( i == 0 && argc > 1 ) {
@@ -196,7 +312,7 @@ int main(int argc, char *argv[])
if ( arg == "-c" || arg == "--command" ) { if ( arg == "-c" || arg == "--command" ) {
if ( (i+1) >= argc ) { if ( (i+1) >= argc ) {
std::cout << "insufficient input following " << arg << std::endl; std::cout << "insufficient input following " << arg << '\n';
return EXIT_FAILURE; return EXIT_FAILURE;
} else { } else {
arg = argv[++i]; arg = argv[++i];
@@ -208,13 +324,13 @@ int main(int argc, char *argv[])
arg += line + '\n' ; arg += line + '\n' ;
} }
} else if ( arg == "-v" || arg == "--version" ) { } else if ( arg == "-v" || arg == "--version" ) {
arg = "version(0)" ; arg = "version()" ;
} else if ( arg == "-h" || arg == "--help" ) { } else if ( arg == "-h" || arg == "--help" ) {
arg = "help(-1)"; arg = "help(-1)";
} else if ( arg == "-i" || arg == "--interactive" ) { } else if ( arg == "-i" || arg == "--interactive" ) {
mode = eInteractive ; mode = eInteractive ;
} else if ( arg.find('-') == 0 ) { } else if ( arg.find('-') == 0 ) {
std::cout << "unrecognised argument " << arg << std::endl; std::cout << "unrecognised argument " << arg << '\n';
return EXIT_FAILURE; return EXIT_FAILURE;
} else { } else {
mode = eFile; mode = eFile;
@@ -223,19 +339,23 @@ int main(int argc, char *argv[])
chaiscript::Boxed_Value val ; chaiscript::Boxed_Value val ;
try { try {
switch ( mode ) { switch ( mode ) {
case eInteractive : interactive(chai); break; case eInteractive:
case eCommand : val = chai.eval(arg); break; interactive(chai);
case eFile : val = chai.eval_file(arg); break; break;
default : std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE; case eCommand:
val = chai.eval(arg);
break;
case eFile:
val = chai.eval_file(arg);
} }
} }
catch (const chaiscript::exception::eval_error &ee) { catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.pretty_print(); std::cout << ee.pretty_print();
std::cout << std::endl; std::cout << '\n';
return EXIT_FAILURE; return EXIT_FAILURE;
} }
catch (std::exception &e) { catch (std::exception &e) {
std::cout << e.what() << std::endl; std::cout << e.what() << '\n';
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }

View File

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

View File

@@ -1,21 +1,35 @@
// 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)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <list> #include <list>
#include <string> #include <string>
// MSVC doesn't like that we are using C++ return types from our C declared module // MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility // but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4190) #pragma warning(disable : 4190)
#endif #endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra() CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
{ {
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List"); return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
} }
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

@@ -1,16 +1,65 @@
#include <chaiscript/chaiscript.hpp> #include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <string> #include <string>
class TestBaseType class TestBaseType
{ {
public: public:
TestBaseType() {} #ifdef CHAISCRIPT_MSVC_12
TestBaseType(int) {} #pragma warning(push)
TestBaseType(int *) {} #pragma warning(disable : 4351)
#endif
// MSVC 12 warns that we are using new (correct) behavior
TestBaseType() : val(10), const_val(15), mdarray{} { }
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(pop)
#endif
TestBaseType(const TestBaseType &) = default;
virtual ~TestBaseType() {} virtual ~TestBaseType() {}
virtual int func() { return 0; } virtual int func() { return 0; }
int base_only_func() { return -9; }
const TestBaseType &constMe() const { return *this; }
int val;
const int const_val;
int mdarray[2][3][5];
std::function<int (int)> func_member;
private:
TestBaseType &operator=(const TestBaseType &) = delete;
};
class Type2
{
public:
Type2(TestBaseType t_bt)
: m_bt(std::move(t_bt)),
m_str("Hello World")
{
}
int get_val() const
{
return m_bt.val;
}
const char *get_str() const
{
return m_str.c_str();
}
private:
TestBaseType m_bt;
std::string m_str;
}; };
enum TestEnum enum TestEnum
@@ -27,26 +76,61 @@ class TestDerivedType : public TestBaseType
{ {
public: public:
virtual ~TestDerivedType() {} virtual ~TestDerivedType() {}
virtual int func() { return 1; } TestDerivedType(const TestDerivedType &) = default;
TestDerivedType() = default;
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
int derived_only_func() { return 19; }
private:
TestDerivedType &operator=(const TestDerivedType &) = delete;
}; };
class TestMoreDerivedType : public TestDerivedType
{
public:
TestMoreDerivedType(const TestMoreDerivedType &) = default;
TestMoreDerivedType() = default;
virtual ~TestMoreDerivedType() {}
};
std::shared_ptr<TestBaseType> derived_type_factory()
{
return std::make_shared<TestDerivedType>();
}
std::shared_ptr<TestBaseType> more_derived_type_factory()
{
return std::make_shared<TestMoreDerivedType>();
}
std::shared_ptr<TestBaseType> null_factory()
{
return std::shared_ptr<TestBaseType>();
}
std::string hello_world() std::string hello_world()
{ {
return "Hello World"; return "Hello World";
} }
static int global_i = 1;
int *get_new_int() int *get_new_int()
{ {
return new int(1); return &global_i;
} }
// MSVC doesn't like that we are using C++ return types from our C declared module // MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility // but this is the best way to do it for cross platform compatibility
#ifdef BOOST_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4190) #pragma warning(disable : 4190)
#endif #endif
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module() CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
{ {
@@ -56,6 +140,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType"); m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType"); m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
m->add(chaiscript::user_type<Type2>(), "Type2");
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType"); m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType"); // m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
@@ -65,23 +151,65 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType"); m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType"); m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
m->add(chaiscript::constructor<TestMoreDerivedType ()>(), "TestMoreDerivedType");
m->add(chaiscript::constructor<TestMoreDerivedType (const TestMoreDerivedType &)>(), "TestMoreDerivedType");
/// \todo automatic chaining of base classes?
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>()); m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
m->add(chaiscript::base_class<TestBaseType, TestMoreDerivedType>());
m->add(chaiscript::base_class<TestDerivedType, TestMoreDerivedType>());
m->add(chaiscript::fun(&TestDerivedType::derived_only_func), "derived_only_func");
m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory");
m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory");
m->add(chaiscript::fun(&null_factory), "null_factory");
m->add(chaiscript::fun(&TestDerivedType::func), "func");
m->add(chaiscript::fun(&TestBaseType::func), "func"); m->add(chaiscript::fun(&TestBaseType::func), "func");
m->add(chaiscript::fun(&TestBaseType::val), "val");
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
#ifndef CHAISCRIPT_MSVC_12
// we cannot support these in MSVC_12 because of a bug in the implementation of
// std::reference_wrapper
// Array types
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
m->add(chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5"));
m->add(chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5"));
m->add(chaiscript::bootstrap::array<int[5]>("IntArray_5"));
// end array types
#endif
// member that is a function
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
m->add(chaiscript::fun(&get_new_int), "get_new_int"); m->add(chaiscript::fun(&get_new_int), "get_new_int");
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1"); m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
m->add(chaiscript::user_type<TestEnum>(), "TestEnum"); m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
m->add(chaiscript::fun(&to_int), "to_int"); m->add(chaiscript::fun(&to_int), "to_int");
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
m->add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { return Type2(t_bt); }));
m->add(chaiscript::fun(&Type2::get_val), "get_val");
m->add(chaiscript::fun(&Type2::get_str), "get_str");
m->add(chaiscript::type_conversion<const char *, std::string>());
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
return m; return m;
} }
#ifdef BOOST_MSVC #ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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