Compare commits

..

896 Commits

Author SHA1 Message Date
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
deef33640c Update releasenotes and version numbers for 4.1.0 release 2012-11-17 18:31:48 -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
58f3256389 Fix function pointer issue for substr on VS 2010 32bit 2012-11-16 13:58:03 -07:00
Jason Turner
f1a4c4c427 Fix compiler warning found on VS 2008 64bit 2012-11-16 12:57:15 -07:00
Jason Turner
afd27a4b01 Fix errors and warnings found on VisualStudio 2005 2012-11-16 12:27:41 -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
4c65e45598 Correct signing and sizing of integer literals #77 2012-11-10 16:31:05 -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
923369a4f4 Add support for string::substr #75
Also add forgotten missing test for number suffixes
2012-11-07 15:48:25 -07:00
Jason Turner
964342bff3 Prevent leaking macros #76 2012-11-07 14:13:08 -07:00
Jason Turner
c5a86401aa Merge branch 'master' into ChaiScript_5_0_CPP_11
Conflicts:
	include/chaiscript/dispatchkit/bootstrap_stl.hpp
2012-11-07 13:47:09 -07:00
Jason Turner
623c64299a Add ability to specify number prefixes for floating point and integers. 2012-11-07 12:05:34 -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
9832d1ce39 Add insert and insert_ref methods to "map" types 2012-09-26 12:38:32 -06:00
Jason Turner
ed7bdfb172 Add "erase" function to associative sets (maps) 2012-09-26 11:31:19 -06: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
204ab53afc Update readme.txt to readme.md for better formatting. 2012-08-14 12:00:44 -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
8f7226051e Add boost::system to linkage to support boost 1.50. Should not cause any issue for older users of boost 2012-08-14 08:59:48 -06:00
Jason Turner
d84b4c0b37 Merge branch 'master' into ChaiScript_5_0_CPP_11 2012-07-18 07:30:34 -06:00
Jason Turner
46d1c50923 Merge pull request #66 from mgee/master
Make Boxed_Number utility functions const
2012-07-18 06:29:22 -07:00
Markus Groß
9e3c2960aa Make some Boxed_Number functions const. 2012-07-17 18:26:58 +02: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
9fd4a1b9f5 Merge pull request #53 from mgee/master
More Boxed_Number enhancements
2012-07-16 21:18:18 -07: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
441cdf0935 Add test showing c linkage working fine [#16] 2012-07-16 22:10:40 -06:00
Jason Turner
f0016d978a Add test to make sure simultaneous ChaiScript instantiations work 2012-07-16 21:51:06 -06:00
Jason Turner
1155720b14 Add the ability to save and restore the state of local variables #25 2012-07-16 21:27:42 -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
f5b7be3743 Correct building on threadless 2012-07-13 13:14:48 -06:00
Jason Turner
d8f881239f Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-07-13 12:36:37 -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
0a436398dd Use make_shared #64 2012-07-13 12:25:50 -06:00
Jason Turner
9f309fcbe9 Add tests for multithreaded features #55 2012-07-10 15:10:09 -06:00
Jason Turner
4e33e969dc Minor header file include cleanup 2012-07-10 13:27:47 -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
Markus Groß
08d9d9e28e Adapt toString to proper naming scheme. 2012-07-03 18:42:27 +02:00
Markus Groß
935276fccd Adapt getAs function to proper naming scheme. 2012-07-03 18:42:04 +02:00
Markus Groß
f8feaf6ea8 Add toString function to Boxed_Number.
For uint8_t, int8_t and char the value is first
converted to an appropriate int type.
This way the value is converted to a number
rather than a character.
2012-06-29 16:48:53 +02:00
Markus Groß
dfcc415c31 Add getAs<T> function to Boxed_Number to enable casting to a target type. 2012-06-29 08:00:00 +02:00
Markus Groß
927235d871 Add templated constructor to Boxed_Number to allow creating from primitive number types. 2012-06-29 07:42:16 +02: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
bf4f90a4ff Fix build error for building without threads 2012-06-25 16:44:22 -06:00
Jason Turner
45f07f9924 Update method error output to show the expression it is trying to execute. 2012-06-25 16:26:36 -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
39d817469c Optionally allow the user to specify the file name to report to end users when calling "eval" 2012-06-25 08:05:58 -06:00
Jason Turner
7a25625fdd Fix failing error reporting for solitary (non-dispatched) guarded function 2012-06-25 07:53:15 -06:00
Jason Turner
5e6a51ba63 Add failing unit test for remaining error condition to check for. 2012-06-25 07:44:14 -06:00
Jason Turner
a8ea5f151d Extreme error reporting capabilities update and bug fixes 2012-06-25 06:31:34 -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
5a76d98692 Enhance and correct error messages
Backported from C++11 branch.

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:00:10 -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
3bccf4d977 Explicitly link to pthreads, seems some systems need this #47 2012-06-09 18:02:35 -04: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
d2aba2ef56 Eliminate boost::lexical_cast usage completely #39 2012-06-03 09:20:15 -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
832df7f9e8 Remove offending boost code which causes warnings in some cases #39 2012-06-02 17:45:10 -06:00
Jason Turner
6c53e08e9b Fix compiler warning in snow leopard 2012-06-01 15:07:53 -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
254d176266 Set CMakeLists.txt to version 4.0.0 for release 2012-06-01 14:00:20 -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
a5f29e93f5 Eliminate all VC++10 64bit Warnings. 2012-06-01 12:21:14 -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
7f253bd6c1 Catch a few things found with more aggressive g++ warnings 2012-06-01 08:47:40 -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
7cbd494123 It seems boost dropped the BOOST_GCC define? 2012-05-28 11:35:53 -06:00
Jason Turner
ed15cc1730 Clean up a few warnings found in Windows. 2012-05-28 10:48:19 -06:00
Jason Turner
db8863c736 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-05-25 07:10:32 -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
4233d21e5b Correct scope of operator calls
- Enhance reflection module to indicate inheritance
  - Add ability to catch errors thrown from a eval
    inside of a script
2012-05-24 19:25:29 -06:00
Jason Turner
f65e095e4d Update release notes 2012-05-24 15:45:52 -06:00
Jason Turner
f2c6745b8a Merge branch 'master' into 2011-09-09-CxScript 2012-05-21 12:10:15 -06:00
Jason Turner
7ad58c7bcd Apply cpo path from vim mailing list 2012-05-21 12:09:39 -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
Jason Turner
433905b33c Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-05-21 10:17:33 -06:00
Jason Turner
3a7eff1478 Move to a bit smarter stack based object management
- we store all function parameters until the f
    outer function call exits

  - this results in more values being stored longer than
    they need to be, but the results are predictable
    and no leaks
2012-05-21 10:16:16 -06:00
Jason Turner
ef46d1bf60 Remove Boxed_Value dependencies, they are not a solution 2012-05-21 08:18:33 -06:00
Jason Turner
654f7e6b01 Add unit test exposing how scope can leak into operator calls 2012-05-21 07:56:38 -06:00
Jonathan Turner
e853e2e4ac Merge branch 'master' into 2011-09-09-CxScript 2012-05-20 10:48:45 -07:00
Jonathan Turner
4aec12c68f Allow operator exprs to span lines 2012-05-20 10:47:50 -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
Jonathan Turner
a818e7b185 Merge branch 'master' of github.com:ChaiScript/ChaiScript 2012-05-20 10:17:43 -07:00
Jonathan Turner
5aed00dd0b Add ternary condition (?:) operator 2012-05-20 10:17:21 -07:00
Jason Turner
349425fe8a Make vector inplace construction consistent with map
- Clone elements into both vector and map
  - Be sure to drop dependencies after elements are cloned in
2012-05-20 07:04:22 -06:00
Jason Turner
9162b02ce9 Merge branch 'master' into 2011-09-09-CxScript 2012-05-19 21:42:30 -06:00
Jason Turner
6c57729779 Add unit test for pass_by_preference 2012-05-19 21:42:02 -06:00
Jason Turner
ba9d13bf7b Merge branch 'master' into 2011-09-09-CxScript 2012-05-19 18:05:58 -06:00
Jason Turner
56757973b6 Actually reenable function 2012-05-19 18:05:41 -06:00
Jason Turner
f1f4aeb4be Add test and reenable function I accidentally commented out 2012-05-19 18:04:51 -06:00
Jason Turner
16bdfe4571 Merge branch 'master' into 2011-09-09-CxScript 2012-05-19 09:51:19 -06:00
Jason Turner
804de05a0a Fix object_lifetime_test which was broken by last perfomance fix 2012-05-19 09:50:49 -06:00
Jason Turner
0fd4b828f2 Fix some minor issues found by clang's static analyzer 2012-05-19 09:16:21 -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
ae02706c71 Approx 12% speedup for function call heavy profile.chai 2012-05-19 07:09:55 -06:00
Jason Turner
c386af6813 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2012-05-18 16:58:33 -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
Jason Turner
08c153abea Clean up some additional exception handling with new stack handler 2012-05-18 16:37:39 -06:00
Jason Turner
897ad7007f Get system introspection functions fully working 2012-05-18 16:25:13 -06:00
Jason Turner
13fb930676 First part of system introspection for objs and funcs added 2012-05-18 15:31:42 -06:00
Jonathan Turner
7f5fce001b Merge branch 'master' into 2011-09-09-CxScript 2012-05-18 08:45:14 -07:00
Jonathan Turner
8af41b1d3c Add unit test for ignoring hash bang. 2012-05-18 08:43:03 -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
025db4ce3a Oops. Properly handle empty switch statements. 2012-05-17 13:20:15 -07:00
Jonathan Turner
78f02c375e Add syntax support for switch/case/default. 2012-05-17 12:48:57 -07:00
Jonathan Turner
4e14a57016 Add support for switch/case/default statements. 2012-05-17 12:43:25 -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
af1e02b0bb Update copyrights to 2012 #23 2012-05-16 11:55:51 -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
4bcaa75fa4 Throw eval exception if a variable or function is redefined #28 2012-05-16 11:40:43 -06:00
Jason Turner
7deb2311f5 Restore CMakeLists.txt on head to working version
Reverted to revision: 277b4eec9a
2012-05-15 19:48:46 -06:00
Jason Turner
4674594ee7 Make libcxx a default option when using clang 2012-05-15 19:30:17 -06:00
Jonathan Turner
730bad9728 Adding support for building with clang/libcxx. 2012-05-15 14:58:38 -07: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
437f6a03a9 Slight cleanup of the boxed_number cleanups from mgee 2012-05-14 18:09:55 -06:00
Jason Turner
94fefa0690 Fix broken example.cpp 2012-05-14 18:09:36 -06:00
Jason Turner
91dc3604f5 Merge pull request #27 from mgee/master
Improve Boxed_Number
2012-05-14 16:55:03 -07:00
Jason Turner
48ecb3e2b4 Some performance improvements by using perfect argument forwarding 2012-05-14 17:45:30 -06:00
Markus Groß
59dfc847ae Make Boxed_Number assignable from Boxed_Value. 2012-05-14 21:34:28 +02:00
Markus Groß
cdfefed385 Add default constructor for Boxed_Number 2012-05-14 20:13:39 +02: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
b0b1549503 Fix cast for unsigned short #26 2012-05-14 09:33:35 -06:00
Jason Turner
277b4eec9a Add failing test for short comparisons #26 2012-05-14 09:22:03 -06:00
Jason Turner
927619bf47 Switch to using make_sharec 2012-05-14 08:56:33 -06:00
Jonathan Turner
41b0c7768c Adding header files to CMakeLists.txt. Hopefully this will help them
show up in IDEs (works for Qt Creator so far).
2012-03-11 14:06:18 -06:00
Jason Turner
3b95931973 Fixup some documentation 2012-01-30 11:53:12 -07:00
Jason Turner
13f98fa8ce Move "use" function to be public 2012-01-30 11:26:46 -07: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
b0953fb466 Minor cleanup releated to attribute fix 2012-01-30 08:55:12 -07:00
Jason Turner
1186926f30 Fix duplicate object attribute name problem 2012-01-30 08:48:01 -07:00
Jason Turner
70db5d67ff Add failing unit test for dynamic object attributes with the same name 2012-01-30 07:55:54 -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
Jason Turner
d9727973c1 Add files missing from last checkin 2011-09-09 17:08:51 -06:00
Jason Turner
0293762904 Add ability to provide global consts in Module objects. Issue #14 2011-09-09 16:52:32 -06:00
Jason Turner
95c6131ce7 Add missing unit test file 2011-09-09 16:01:29 -06:00
Jason Turner
e326fe6f2d Add test for constructing from a pointer return value and fix test so it works. Task #13 2011-09-09 14:38:55 -06:00
Jason Turner
2b64c90a0e Merge branch 'master' of https://github.com/ChaiScript/ChaiScript
Conflicts:
	CMakeLists.txt

Fixed conflicted CMakeLists.txt
2011-09-09 13:58:19 -06:00
Jason Turner
dd0d91c7e3 Merge pull request #10 from svenstaro/master
Consistency fixes
2011-09-09 12:42:48 -07:00
Jason Turner
a386142fa6 Get chaiscript compiling with -pedantic. Closes issue #9 2011-09-09 13:40:50 -06:00
Sven-Hendrik Haase
cacc744411 More consistency fixes 2011-08-03 19:25:02 +02:00
Sven-Hendrik Haase
2d23578e0b Removing unused variables 2011-08-03 19:22:18 +02:00
Sven-Hendrik Haase
f8880066ea Consistency fix 2011-08-03 16:10:13 +02:00
Jason Turner
a85423869f Edited releasenotes.txt via GitHub 2011-06-18 15:41:27 -07:00
Jason Turner
469c02ad14 Edited releasenotes.txt via GitHub 2011-06-18 15:35:26 -07:00
Jason Turner
1cd9a9098c Update gcc flags for MacOS to ignore sign comparison warnings 2011-06-18 07:34:55 -06:00
Jason Turner
5ff14a54db Commented out code removal 2011-06-16 10:42:26 -06:00
Jason Turner
28e3d442e2 Update version number to 3.1.0 for next release 2011-06-16 10:19:54 -06:00
Jason Turner
bb0edcb62a Add exception_specification and unittests for it. #6 2011-06-16 10:14:52 -06:00
Jonathan Turner
9a015a5c49 Fix typo in unit test and add string literal access 2011-06-13 18:14:41 -07:00
Jonathan Turner
9d20f60903 Update license year 2011-06-13 07:45:11 -07:00
Jonathan Turner
5426496b4f Fix parsing of member access and function calls 2011-06-13 07:43:51 -07:00
Jason Turner
a549e41558 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2011-06-11 17:05:53 -06:00
Jason Turner
a82c892a4e Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2011-06-11 07:15:02 -06:00
Jason Turner
9e9fb3ad7d Fix one more documentation error 2011-06-10 16:42:38 -06:00
Jason Turner
8cc3651c76 Correct copyright date 2011-06-10 16:41:00 -06:00
Jason Turner
4d879afca7 Documentation updates 2011-06-10 16:38:20 -06:00
Jason Turner
afae221cb3 Add tests for more complex uses of the index operator 2011-06-10 11:18:58 -06:00
Jason Turner
b064bb61e9 Finish renaming and cleaning up of Boxed_Number type for dump_system() output 2011-06-10 10:12:09 -06:00
Jason Turner
c839e4bc21 Handle unnecessary MSVC compiler warnings. 2011-06-08 19:19:59 -06:00
Jason Turner
7a9baeb350 Rename of numeric to number 2011-06-08 13:53:55 -06:00
Jason Turner
6d4041b2a1 Added profile for mathy functions.x 2011-06-07 14:59:43 -06:00
Jason Turner
1932cbfbbc Eliminate duplicate code and reduce Boxed_Value copies necessary 2011-06-04 12:31:33 -06:00
Jonathan Turner
8fecf5c145 Merge branch 'master' of github.com:ChaiScript/ChaiScript 2011-06-04 11:02:07 -07:00
Jonathan Turner
6131a9c4c1 Moved common operators into their own AST nodes and removed the operator child. 2011-06-04 11:01:35 -07:00
Jason Turner
881d569d8e Remove unnecessary loop from Binary_Operator 2011-06-04 10:34:15 -06:00
Jonathan Turner
6c18c197c6 Fixed operator parsing to return trees instead of flat representations. Fixed evaluator to not loop over equations. 2011-06-04 09:15:19 -07:00
Jason Turner
f47ec0d522 Merge pull request #7 from lefticus/master
Merge Number Performance Updates
2011-06-03 17:52:04 -07:00
Jason Turner
4053196188 Reduce creation of new Boxed_Value containers when returning the same value that was passed in 2011-06-04 04:26:06 +08:00
Jason Turner
5b40a85024 Add direct access to Boxed_Value data * for high performance operations 2011-06-04 04:26:00 +08:00
Jason Turner
36faba8ed3 Bypass dispatch during numeric operations. 2x speedup 2011-06-04 04:25:54 +08:00
Jason Turner
7d022c4f0d Add is_prime profile script 2011-06-04 04:25:47 +08:00
Jason Turner
b933bb6c50 Begin move of Operators code out a level so that it can be used before dispatch 2011-06-04 04:25:42 +08:00
Jason Turner
92bfcfdcf3 Wrap up new Boxed_Numeric support 2011-06-04 04:25:36 +08:00
Jason Turner
3b754cfec4 Further simplification and refinement of enhanced Algebraic types support 2011-06-04 04:25:30 +08:00
Jason Turner
3689c01e4b Significant reduction in templates instantiated by grouping of operators - smaller code and compile time 2011-06-04 04:25:24 +08:00
Jason Turner
4b90fbd07a wrap up support for all built in C++ Arithmetic types 2011-06-04 04:25:18 +08:00
Jason Turner
1a225dca67 Progress towards eliminating arithmetic operators on a per-type basis 2011-06-04 04:25:12 +08:00
Jason Turner
226666c2bb Rename Boxed_POD_Value to Boxed_Numeric, which is more correct. 2011-06-04 04:24:57 +08:00
Jason Turner
d4ef226911 Reduce creation of new Boxed_Value containers when returning the same value that was passed in 2011-06-03 13:48:32 -06:00
Jason Turner
6491262491 Add direct access to Boxed_Value data * for high performance operations 2011-06-03 12:41:38 -06:00
Jason Turner
2c4d69bfc0 Bypass dispatch during numeric operations. 2x speedup 2011-06-01 22:12:50 -06:00
Jason Turner
f423969a8e Add is_prime profile script 2011-05-31 08:09:30 -06:00
Jason Turner
36cd4c370a Begin move of Operators code out a level so that it can be used before dispatch 2011-05-31 07:42:30 -06:00
Jason Turner
85f69782b2 Wrap up new Boxed_Numeric support 2011-05-30 19:38:04 -06:00
Jason Turner
1f130c0891 Further simplification and refinement of enhanced Algebraic types support 2011-05-29 17:33:45 -06:00
Jason Turner
fdd1b40a9f Significant reduction in templates instantiated by grouping of operators - smaller code and compile time 2011-05-29 09:14:48 -06:00
Jason Turner
6993d58fdc wrap up support for all built in C++ Arithmetic types 2011-05-28 23:48:17 -06:00
Jason Turner
1845114d36 Progress towards eliminating arithmetic operators on a per-type basis 2011-05-26 05:58:19 -06:00
Jason Turner
bba1ffde38 Rename Boxed_POD_Value to Boxed_Numeric, which is more correct. 2011-05-24 12:39:39 -06:00
Jason Turner
18d4984258 Final tweaks to packaging for 3.0.0 2011-05-23 08:16:24 -06:00
Jason Turner
845eb394ac Correct installation of pkgconfig file 2011-05-23 07:58:05 -06:00
Jason Turner
66b2adba5c Final tweaks to release 3.0.0 docs 2011-05-23 07:07:27 -06:00
Jason Turner
02db23e9e2 Minor doc tweaks 2011-05-23 06:55:31 -06:00
Jason Turner
fbef83ecb7 Final documentation for release 3.0.0 completed 2011-05-22 23:29:55 -06:00
Jason Turner
88fbf41091 Getting started document updates 2011-05-22 21:43:58 -06:00
Jason Turner
897385953c More documentation updates and additions to getting started guide 2011-05-22 12:08:24 -06:00
Jason Turner
319f9e4de9 Fix issues with trim() and with unit tests relying on certain line endings. 2011-05-20 16:01:50 -06:00
Jason Turner
2786156086 Finalize documentation for 3.0.0 release and update version number in CMakeLists.txt 2011-05-20 13:44:34 -06:00
Jason Turner
e5f9dbb93b Fix failing unit tests related to recent renaming of function to Function 2011-04-26 10:17:24 -06:00
Jason Turner
61b8481514 Further documentation of the prelude / standard library. 2011-04-25 20:24:31 -06:00
Jason Turner
8a0ef143c9 C++ API documentation is complete. ChaiScript keyword and language documentation about 75% complete (mostly ported from website.) 2011-04-17 09:29:34 -06:00
Jason Turner
f1918f147d More documentation updates. 2011-04-04 07:08:28 -06:00
Jason Turner
0d238b1617 Documentation updates and namespace reorg for docs. 2011-04-02 20:52:49 -06:00
Jason Turner
d22a77503c Fix build errors and warnings for VS2010 2011-04-02 11:21:11 -06:00
Jason Turner
8dec35ba19 Merge branch '2011-03-15-DocumentationUpdates'
Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
2011-03-29 20:24:17 -06:00
Jason Turner
a91c66d286 Couple of include guard cleanups 2011-03-29 09:28:35 -06:00
Jason Turner
8ecd3a084b Add simple efficencies for static ids 2011-03-28 19:50:41 -06:00
Jason Turner
79e8af4f6e Enhance eval error stack reporting
Use OOP to avoid code duplication for eval error tracking. This results
in much more robust stack error reporting and 400 LOC less.
2011-03-27 21:03:24 -06:00
Jason Turner
de5822873b Use RAII for scope management
Possibly fixes a few bugs where scope pops where missed.
2011-03-27 10:03:37 -06:00
Jason Turner
d6b8e32373 Allow for parse time evaluation of const values.
The goal is to allow for more evaluation at parse time, in general, to
increase eval time performance.

 - Make AST_Node non-constructable except by derived classes.
 - Make data in AST_Node const (as much as possible).
 - Replace reflection "text = " with replace_child() (where the
   replacement must be with a new parse tree).
 - Evaluate floats, strings, ints, chars at parse time to avoid repeat
   evaluations (~10% speed up in loops in -O3)
2011-03-27 08:17:04 -06:00
Jason Turner
bbe89e61bc elimination of unused / outdated code and documentation cleanups. 2011-03-26 22:42:11 -06:00
Jason Turner
87c29ebc91 Ensure that non-shared_ptr, non-boxed_value, non-reference return types
are treated as const.
2011-03-26 09:03:36 -06:00
Jason Turner
92c836c58a Simplify mutex code by providing stubs that are do nothing during
CHAISCRIPT_NO_THREADS builds.
2011-03-25 22:49:17 -06:00
Jason Turner
58e5df0a9a Even more reorganization of namespaces to help with documentation and
clarity.
2011-03-25 15:42:18 -06:00
Jason Turner
854737ea25 Fix compile time error for non-posix, non-win32 platforms. 2011-03-25 10:43:17 -06:00
Jason Turner
8bd512a0af Merge branch '2011-03-15-DocumentationUpdates' of https://github.com/ChaiScript/ChaiScript into 2011-03-15-DocumentationUpdates 2011-03-24 09:28:11 -06:00
Jason Turner
deb4cb036f Hide Bare_Type in detail namespace 2011-03-24 09:26:41 -06:00
Jason Turner
cd8bead54a Further namespace reorganization and cleanup to limit to the user the
most important aspect of the API and make documenation easier.
2011-03-24 09:23:05 -06:00
Jason Turner
637164e457 Move around some namespaces for documentation purposes.
Fix problems with building on clang 2.8.
Remove unneeded function for get_engine() and fix functor<> calls that take a Boxed_Value
2011-03-15 17:35:14 -06:00
Jason Turner
9dd9ffec46 Update copyright information for 2011 2011-03-15 09:42:33 -06:00
Jason Turner
ac0688a8d7 Fix warnings in memory_leak_test 2011-03-14 12:07:08 -06:00
Jason Turner
e3feb05e05 Merge branch 'master' of https://github.com/ChaiScript/ChaiScript 2011-03-14 09:12:01 -06:00
Jason Turner
2ce55d81b3 Fix bug in installation of some files 2011-03-13 19:24:42 -06:00
Jason Turner
4e06478fb8 Amp up the warnings used in g++ and fix associated errors 2011-03-12 11:27:53 -07:00
Jason Turner
46a669dab1 Fix problem with method specifiers for bad_dynamic_boxed_cast exception. Add support for operators to Utility.hpp 2011-03-11 17:56:46 -07:00
Jason Turner
d9a92a5148 Add std::exception as a base clase off std::runtime_error and provide unit test for it. 2011-03-09 21:41:32 -07:00
Jason Turner
f6b6936348 Normalize on include guard style, removing __ reserved words 2011-03-08 14:06:09 -07:00
Jason Turner
0b97fcb4df Add better namespaces to make documentation easier to handle 2011-03-05 22:50:38 -07:00
Jason Turner
eee5c19b6e Begin support for Doxygen and building Chaiscript version number into
the code.
2011-03-03 22:43:01 -07:00
Jason Turner
5cc4a758ab Make scoping more explicit during initialization of alphabet 2011-02-21 19:25:22 -07:00
Jason Turner
7c2550ba74 Modify alphabet to m_alphabet to match rest of coding style 2011-02-21 19:17:36 -07:00
Jason Turner
41d7842963 Move from hand rolled trim function to boost::trim function 2011-02-21 19:02:30 -07:00
Jason Turner
13b35f2f47 Better localize MSVC specific code. Remove deprecated / gratuitous use
of "static". Clean up code for readability and effeciencies in C++.
2011-02-21 18:56:04 -07:00
clanmills
18c6ed71f0 Add code to compile _strdup on non-Microsoft platforms (builds on Windows with DevStudio and Cygwin). 2011-02-16 23:24:51 -08:00
clanmills
7ac22c7072 Tweaking the --help output 2011-02-16 11:00:18 -08:00
Robin Mills
c9c4f1add7 Tweak to --stdin line end handling. 2011-02-16 10:13:12 -08:00
clanmills
65d054b36e Three lots of changes:
1) Changes post code review by Jason
2) Fixing bug in end of line processing on Windows with cr-lf
3) Adding command-line options to chai
2011-02-16 08:21:19 -08:00
clanmills
894063261e Changes to parser. 2011-02-14 10:33:40 -08:00
Jason Turner
80f576a2f3 Reflection and introspection updates for task #85 2010-12-29 17:58:56 +00:00
Jason Turner
0a2b5d7a40 Find, test and fix an issue related to function argument type reporting when discussing dynamic object functions (ie, def int::somefunc() {} ) 2010-12-24 22:26:14 +00:00
Jason Turner
660e978da3 Implement test for function ordering for dispatch. Catch bug for "const" characterization of function parameters. Add test for type characterizations. 2010-12-13 03:32:47 +00:00
Jason Turner
e90d49bb9d Function ordering is working properly now, just need to add a unit test for it. 2010-12-11 22:38:08 +00:00
Jason Turner
13f53839c9 Check in of function ordering. Breaks function assignment test - need to understand why still. 2010-12-11 21:01:18 +00:00
Jason Turner
65edf30ef0 Fix regression in parsing of empty file. Visible in windows debug mode, but probably affects all platforms. 2010-11-15 22:45:57 +00:00
Jason Turner
7ef1b81504 Simplify how functions are stored and passed. This is the first step in allowing us to sort functions so that dispatches are attempted in an organized order (as opposed to just the order they were added in).
Should have resulted in a speed imrovement too - fewer string copies during dispatch.
2010-11-15 05:52:48 +00:00
Jason Turner
3aee589274 Remove unused variable 2010-11-15 00:01:33 +00:00
Jason Turner
97081b1f33 Remove vestiges of object caching from dispatch kit 2010-11-14 22:28:05 +00:00
Jason Turner
a758c86ba5 Add automatic unwrapping of Proxy_Function_Impl contained boost::function during functor() construction if possible.
Task #110
2010-11-14 01:17:56 +00:00
Jason Turner
5f661fad20 Get rid of a C++ conversion and make it a static_cast 2010-11-12 23:19:30 +00:00
Jason Turner
811764e048 Object lifetime specificity test added. 2010-11-11 15:58:51 +00:00
Jason Turner
0f9b1aaf92 Make extra modules (stl, reflection) into compile time options. Task #118 2010-11-11 04:36:43 +00:00
Jason Turner
912379d58c Fix some compile warnings 2010-11-09 21:06:50 +00:00
Jason Turner
91c05f0e73 Apply patch (and rearrange a directory) from emarcotte for pkgconfig support 2010-11-08 13:47:41 +00:00
Jason Turner
906140ec78 Find and fix bug in handling of bound function types_infos and arity.
Remote outdated samples. Move working samples into samples folder and make part of build process. Make building of samples optional.
Closing #107
2010-11-08 05:22:15 +00:00
Jason Turner
e75a354a04 Apply some module and parameter variable naming standards. Remove ChaiScript template where it was no longer necessary. 2010-11-06 05:20:41 +00:00
Jason Turner
36173d277d Closing issue #99 : shared const char * memory issues. Also, clean up some file loading overhead (did not seem to have an performance impact). 2010-11-05 22:01:39 +00:00
Jason Turner
e1e48d732f Wrap up of clean up of warnings in 64bit visual studio 2010-11-05 04:05:02 +00:00
Jason Turner
6e18aa3dcd Further VS 64bit warning fixes. 2010-11-05 02:43:52 +00:00
Jason Turner
6a18862c79 Fix some of the 64bit VS warnings. 2010-11-05 02:22:38 +00:00
Jason Turner
b3dafa385e Add bigobj compile flag for 64bit windows builds. 2010-11-05 01:58:48 +00:00
Jason Turner
70cc1111f3 Regression - fix VisualStudio builds 2010-10-23 16:25:16 +00:00
Jason Turner
2d353cb189 Fix oddity found while testing on msys with G++ 4.5.0 2010-10-23 15:59:39 +00:00
Jason Turner
67bad374a9 Get mutlifile compilation working again and add a test for it 2010-10-22 21:30:58 +00:00
Jason Turner
bff5b8bce0 Add some quick comments 2010-10-14 14:36:32 +00:00
Jason Turner
2cdfac4e47 Add function meta data functions, plus related tests, and some various cleanups for how functions are constructed internally 2010-10-14 14:33:17 +00:00
Jason Turner
0caa782437 Basic unit tests for casting to **. Storing of (double) pointer types is probably not something we will make an effort to support 100%.
Also, tests of all types that are supported.
2010-10-11 03:45:45 +00:00
Jason Turner
caa67e811c Add boost::ref and boost::cref tests for inputs 2010-10-08 18:48:10 +00:00
Jason Turner
c1318eb8b4 Fix llvm (probably affecting gcc too, MSVC is too lax onthe use of "typename") 2010-10-08 18:42:59 +00:00
Jason Turner
3f87210dc5 Several tests and fixes related to type conversions added. Still more to go. 2010-10-08 15:18:58 +00:00
Jason Turner
c3da778103 Preliminary boxed_cast_test added. This test is meant to test all possible boxed_cast conversions that are available. Currently... some basic ones are failing. 2010-10-08 03:07:26 +00:00
Jonathan Turner
5a92146d28 Fix to disallow mixing inline map and array elements 2010-10-02 23:39:17 +00:00
Jason Turner
3ab91356e5 Make inline maps const. Add test for malformed inline map that causes crash 2010-10-02 22:50:09 +00:00
Jason Turner
fa2a7045a7 Make inplace vector construction result in const temp return. Also clean up construction of vectors in code 2010-10-02 22:19:51 +00:00
Jason Turner
512d6b342d Support for const ranges working 2010-10-02 21:56:33 +00:00
Jason Turner
4ab29013ec Add currently failing test for const range support 2010-10-02 21:31:18 +00:00
Jason Turner
3ae748c026 Add "Pair" unit test. It was the basis for failures with Dynamic_Object on MSVC2010 2010-10-02 21:28:13 +00:00
Jason Turner
d8c979b204 Fix for unexpected new base class to std::pair in VS2010. All tests now pass in VS2010 2010-10-02 20:38:46 +00:00
Jason Turner
74e719c053 Add object dependency tracking to make sure that during nested function calls all returned values are not prematurely destructed.
All tests pass on vc2008 now.
2010-10-02 13:26:06 +00:00
Jason Turner
43dbd8ac78 Rip out object caching. With this removed it becomes that much more critical that we fix the scoping issue with references returned from temporaries. 2010-10-01 02:25:29 +00:00
Jason Turner
7b77af3736 Remove commented out code and make variable declarations/scopes consistent with the rest of the C++ codebase 2010-09-30 19:16:03 +00:00
Jason Turner
8b35434e6f rip out a couple hundred lines of code with inheritance 2010-09-30 18:17:32 +00:00
Jason Turner
1e867f5760 Fix broken gcc build introduced during vc2010 fixes 2010-09-30 16:34:27 +00:00
Jason Turner
670eb0692b Visual studio warning reduction and compile fixes for vs2010. Warning suppression on vs2005. Fixes to get cmake working with boost autolinking. Update to support boost 1.44 2010-09-30 14:33:12 +00:00
Jason Turner
4b9d2d130f Add comment about clang work around 2010-09-20 12:57:33 +00:00
Jason Turner
30affb8855 Correct assertion that was causing clang (and any other debug build) to fail tests 2010-09-20 12:47:25 +00:00
Jason Turner
22c2be835a Get chaiscript compiling with LLVM/clang. Resulting code crashes, however. 2010-09-20 03:24:48 +00:00
Jason Turner
a39d70dbca Rip out caching in dispatch kit to get a more clean view of the performance world 2010-09-19 23:24:52 +00:00
Jason Turner
10986c159f Add support for automatic conversion between chaiscript functions and boost::function. Might merit some look to see how much overhead this adds. 2010-09-13 14:24:12 +00:00
Jonathan Turner
cfa42158af Clean up reflection a bit, and how we do pretty printing of ast nodes. Registered new internal_to_string in reflection module so that we
can have automatic pretty printing of ast nodes during repl eval.
2010-08-30 13:37:50 +00:00
Jonathan Turner
054179ead3 Commenting out of previous node value caching scheme. This allows us to profile later, without having these smaller optimizations
clutter up the flow.  This also allows us to pass the reflection test.
2010-08-29 21:33:11 +00:00
Jonathan Turner
8a6a46d0d3 Fix to the method/array dispatch issue 2010-08-29 19:49:57 +00:00
Jason Turner
efae821996 Add some unit tests for reflection and recently discovered array lookup returned from a method problem 2010-08-28 22:55:43 +00:00
Jason Turner
31feab6053 Fix to parsing of single-line comments where the comment at the end of a line was merging statements separated by a single line comment 2010-08-28 22:14:09 +00:00
Jason Turner
7ef12f634d Register AST_Node and Parser, overloaded eval for AST_Node and some const correctness fixes 2010-08-28 21:48:30 +00:00
Jonathan Turner
c6452c4bd6 Rename of Token to AST_Node to be more correct 2010-08-28 18:38:01 +00:00
Jason Turner
71de169e09 Stub out the reflection module 2010-08-28 18:29:38 +00:00
Jason Turner
329244759f Fix warnings discovered on macos 2010-08-28 17:58:02 +00:00
Jonathan Turner
c5f20ea158 A little cleanup of logical and/or since those are now separate evals. 2010-08-19 14:42:18 +00:00
Jonathan Turner
58c62f6333 More refactoring of parser to use the token children types directly instead of using a giant switch statement during build_match. 2010-08-15 02:04:35 +00:00
Jonathan Turner
7f037b26d4 Updated email addresses in copyright information. 2010-08-10 05:24:07 +00:00
Jonathan Turner
b1e357423f Move structure to being inheritance-based in preparation for reflection infrastructure. This technique relies on the vtable's dynamic dispatch for correct evaluation, and removes the giant switch eval style of previous revisions. 2010-08-08 17:18:32 +00:00
Jason Turner
3a904d9f74 Drastically reduce the number of exceptions thrown at runtime (cannot completely eliminate them all, it's the nature of doing what we are doing with making a runtime interface to a compiled system like we are).
profile.chai should see something like a reduction from 35,000 exceptions to about 100.
2010-08-07 19:27:15 +00:00
Jonathan Turner
d838f7a6d4 Renaming of helper function char_between. Adding help to check for hitting the end of input. 2010-08-07 02:18:51 +00:00
Jonathan Turner
556e7ad916 Cleaned up the formatting a bit. Switched parser over to using charBetween, which significantly improves
readability of the early parsing rules.
2010-08-06 11:17:53 +00:00
Jason Turner
21253043d1 Add option for "light" testing, which greatly reduces compile times 2010-08-05 13:44:23 +00:00
Jason Turner
f215cae866 Add string.c_str() and string.data() methods. 2010-08-05 13:38:11 +00:00
Jason Turner
ea93903884 Fix build problem that was causing chaiscript_no_threads to still link with boost_thread 2010-08-04 19:17:33 +00:00
Jason Turner
f03189c168 Quiet down some irrelevant warnings in MSVC2008, make dynamic_cast conversions work in msvc across modules by applying a kludge that will probably not work long term, but does work now. This may mean that chaiscript needs to move to being a library? 2010-08-03 17:21:51 +00:00
Jason Turner
a122403c20 Fix problem with functor<>() not casting to the proper type and add unit test for this case 2010-08-03 15:19:20 +00:00
Jason Turner
e1fbf54e40 Make disabling of thread support a configuration time option. This mainly exists for testing purposes. 2010-08-03 03:09:49 +00:00
Jason Turner
2b80ca8cc5 Add missing inheritance unit test 2010-08-03 01:18:15 +00:00
Jason Turner
f4e4f92dae Move type registration into module code, and fix problems with unloading of modules and type conversions registered inside of a module.
We have to allow the same type registration more than once now, just in case several different modules register the same conversion.
2010-08-03 01:17:38 +00:00
Jason Turner
4358564065 Make sure the same base/derived relationship is never registered more than once 2010-08-02 18:18:39 +00:00
Jason Turner
a463ee5ff2 Clean up key used in the thread global object cache, to make sure proper type comparisons are done in the corner cases found in the main boxed_cast<> code a while back 2010-08-02 17:51:30 +00:00
Jason Turner
cd015a8437 Thread safety for dynamic conversions / registration of new inheritance relationship 2010-08-02 17:01:38 +00:00
Jason Turner
8be4aa08db Reduce runtime calls into the new dynamic cast system by first making sure the type is polymorphic.
Cleanup some std::cout calls
2010-08-02 02:30:41 +00:00
Jason Turner
edee892cad Initial check in of support for upcasting during function invocation. No examples or tests are checked in yet. Some reorg was necessary to get things compiling in the right order. Is not currently thread safe and probably does not work properly across module boundaries 2010-08-02 01:38:25 +00:00
Jason Turner
b971ee44ad Make warnings stricter on windows and clean up all legit warnings in our code. 2010-07-30 18:06:17 +00:00
Jason Turner
b9ae4cd528 Make warnings more strict and fix one warning caught by gcc 2010-07-30 16:25:58 +00:00
Jason Turner
4ec21ff552 Add test of dynamic object attribute access shared between c++ and chaiscript 2010-07-25 19:56:19 +00:00
Jason Turner
f5f99961c1 Make sure that stack is properly initialized on a per-thread basis. Fixes #95wq 2010-07-23 20:00:17 +00:00
Jason Turner
f7086c10ec Roll back changes from last 2 checkins - user defined type conversions are going to be too slow and too hard to keep track of. Need more portable / generic approach to solving the actual problem - the ability to deal with inhertance properly 2010-07-23 14:55:32 +00:00
Jason Turner
3d19138c95 Minor reorg of type conversion code to support move to using it in dispatch 2010-07-18 01:52:07 +00:00
Jason Turner
35ac7342b6 Stub in of support for type conversions. Not yet fully implemented. 2010-07-17 21:49:27 +00:00
Jason Turner
3f9b5081c6 Add macro for helping with registering classes with ChaiScript, plus unit test for it 2010-07-17 01:01:21 +00:00
Jason Turner
799b3ef388 Update copyright for 2010 2010-05-15 22:48:54 +00:00
Jason Turner
fe6694297f Set version number to 2.3.3 2010-05-15 22:39:28 +00:00
Jason Turner
e77ec4b16a Clean up the vim syntax a bit, add escape characters and incorporate changes from bram 2010-04-01 19:01:18 +00:00
Jason Turner
f070575205 Cleanups of vim files to get them ready for submission 2010-03-31 20:11:19 +00:00
Jason Turner
43d0d6199a Clean up use recognition of backtick operator functions, add support for .. range operator 2010-03-31 01:01:45 +00:00
Jason Turner
65c5178549 Update copyright/version info for geshi filter 2010-03-31 00:23:02 +00:00
Jason Turner
c928e2992b Fix readline support for the eval 2010-03-30 18:40:55 +00:00
Jason Turner
7fef086cab Add geshi syntax highlighting (updated and cleaned up from the version that was hosted at chaiscript.com) 2010-03-30 16:50:18 +00:00
Jason Turner
791fd242e7 Add "throw" built in function to vim syntax highlighting 2010-03-30 16:38:20 +00:00
Jason Turner
e81b71ccc7 Add missing README for vim highlighting 2010-03-30 16:21:35 +00:00
Jason Turner
ef7a785214 Initial check-in of vim syntax highlighting 2010-03-30 16:21:06 +00:00
Jason Turner
f431d479fc Add support for using cmake to build RPMs 2010-03-30 02:01:59 +00:00
Jason Turner
e11eca406d Get cpack working for source and deb distribtions. Still need to check nsis and rpm 2010-03-29 15:32:20 +00:00
Jason Turner
7efb65a5c2 Move to using cmake for VisualStudio 2010-03-28 13:31:19 +00:00
Jason Turner
39339d769a Get the rest of the unit tests passing. Note: ChaiScript now requires CMake 2.8, which is almost a year old, so this is fair, but for the meantime we will have to either get it from backports in ubuntu or from cmake.org 2010-03-19 00:50:36 +00:00
Jason Turner
7ac9ea7249 Add the ability to specify "load_module" and "use" search paths. The capability is primitive and it is currently used by chaiscript_eval to set a single path from environment variables 2010-03-18 22:53:52 +00:00
Jason Turner
7080f5d681 Use ctest to run unit tests. run "make test" to run them. Note, anything "use"ing another file or loading a module will fail. Need to come up with some cross platform mechanism for specifying include dirs to solve this. Current thought: using environment variables "CHAI_USE_PATH" and "CHAI_MODULE_PATH" 2010-03-16 04:07:38 +00:00
Jason Turner
22d994009e Add missing unit_test.inc file 2010-03-14 14:54:00 +00:00
Jason Turner
567f911093 Move to a more standardized unit testing design which relies less on OS support and can soon be moved to a ctest implementation 2010-03-14 05:19:24 +00:00
Jason Turner
5c98a5d6e7 Add sync_cache to set_state code to fix logic flaw in resetting of state and memory leak. #92 2010-03-09 02:09:05 +00:00
Jason Turner
856b682e72 Testing of memberscope so we can close #91 2010-03-09 01:39:54 +00:00
Jason Turner
faaa964565 No longer allow a local variable to be used as a function during dot notation sugar lookup. It's far less confusing this way 2010-01-27 03:54:42 +00:00
Jason Turner
d8213a4206 Convert from #warning to #pragma message for notification of thread safety being disabled, so support more compilers portably 2010-01-19 01:54:00 +00:00
Jason Turner
3a4421a57c Fix empty array unit test by reimplementing the node->children.size() test erroneously removed in r466 2010-01-07 01:47:04 +00:00
Jonathan Turner
31fec2202c Add the answer to the unittest I added earlier 2010-01-06 19:42:09 +00:00
Jonathan Turner
13178e55e1 Add unit test that dies after r465 2010-01-06 19:39:04 +00:00
Jason Turner
968da650b2 Clean up leaking #define's for iterations (n, m) that could mess up subsequently included files such as boost/signals2.hpp 2010-01-03 15:48:17 +00:00
Jason Turner
fb5ba0be26 Remove std::swap implementation that was not supported for multiple file compilation. 2010-01-03 15:03:26 +00:00
Jason Turner
39a2c39d90 Minor fixes to example.cpp to avoid exceptions 2009-12-30 15:29:36 +00:00
Jason Turner
70047424f9 Get compiling with Visual Studio 10 beta 2. Had to work around issues with conflicts between boost::function and VisualStudio's std::tr1::mem_fn (http://social.msdn.microsoft.com/Forums/en/vcprerelease/thread/e04d93ed-d686-4ef6-9939-26e34c0955eb). Also had to work around non-standard overloaded std member functions in std::map (http://msdn.microsoft.com/en-us/library/fe72hft9(VS.100).aspx)
Strongly consider rolling this back when the issues are resolved between microsoft and boost. Also, needs to be tested across all platforms.
2009-12-28 17:16:03 +00:00
Jason Turner
2805af1ed2 move from std::numeric_limits::min() to boost::integer_traits::const_min - avoids runtime overhead of the function call. 2009-12-11 15:35:59 +00:00
Jonathan Turner
e5a29ede5f Added 0b1010 binary format. Fixed hex and octal to allow negative ints 2009-12-11 14:46:12 +00:00
Jason Turner
0c0df2c982 VS 2008 related corrections. 2009-12-08 15:57:31 +00:00
Jason Turner
4457df9ff5 Fix NO_THREADS related issues 2009-12-06 05:12:02 +00:00
Jason Turner
e601de9d18 Reduce use of Param_List_Builder by providing call_function implementations for 0,1,2 arity 2009-12-06 01:31:58 +00:00
Jason Turner
37b2ac2056 Implement proper swap for Boxed_Value 2009-12-05 19:30:09 +00:00
Jason Turner
645cdddd70 Small but measurable eval performance increase (in optimized builds) by managing the number of Boxed_Values copies and assignments 2009-12-05 18:54:55 +00:00
Jonathan Turner
ac8462fb67 Fix up some broken sample files 2009-12-02 14:29:42 +00:00
Jason Turner
636c55493c Smartly size the integer returned from a Boxed_POD_Value operation to return an "int" if the resulting value is small enough 2009-12-01 03:52:57 +00:00
Jason Turner
e2a2c14c0d Eliminate use of size_t in stl related wrappings 2009-12-01 02:56:02 +00:00
Jonathan Turner
c418644a5b Fix for single-line comments stopping at semicolon. 2009-11-27 22:52:55 +00:00
Jason Turner
fbf8f53e04 Add Type_Info type and add *_type objects at time of type registration. 2009-11-21 22:47:44 +00:00
Jason Turner
a0c6366479 Added introspecition/classification of types 2009-11-21 06:39:35 +00:00
Jason Turner
15ffbd200a Fixed unittests broken by last checkin 2009-11-21 06:39:11 +00:00
Jason Turner
1c6b2725b3 Provide some hints for dispatches with lhs (first param) that is const 2009-11-21 06:02:17 +00:00
Jason Turner
95c124ca35 Support better tracking of loaded modules for saving and setting of state 2009-11-21 05:28:00 +00:00
Jason Turner
1bd73884b2 Add documentation to the set_state get_state functions 2009-11-18 05:05:40 +00:00
Jason Turner
d3e4af433e Add support for saving/restoring of chaiscript engine state. 2009-11-18 04:43:08 +00:00
Jason Turner
9f65303370 Handle case of const & return values (should probably be investigated a bit more) 2009-11-18 04:42:43 +00:00
Jason Turner
391eaa9e11 VC++ 2008 warnings cleanups 2009-11-15 03:26:47 +00:00
Jason Turner
ed11f48847 More robust handling of potential class object member types 2009-11-15 00:37:01 +00:00
Jason Turner
9dddb49850 Added support for const attribute access 2009-11-14 19:02:00 +00:00
Jason Turner
cca477dae6 Only share const globals between threads. Require all globals to be const. 2009-11-11 05:47:54 +00:00
Jason Turner
07352a16a3 Operators unittests 2009-11-11 03:03:24 +00:00
Jonathan Turner
e14931f389 Move completely over to new operators 2009-11-10 14:07:51 +00:00
Jason Turner
f4a680a582 Add missing operators.hpp file 2009-11-10 13:27:44 +00:00
Jason Turner
e6c6223c5b Operator handling rewrite and fleshing out of operators to include all standard C++ operators 2009-11-10 05:55:58 +00:00
Jason Turner
cbc61d898c Add "is_null" for boxed_values to see if they contain a null shared_ptr value 2009-11-08 16:30:12 +00:00
Jason Turner
3a37ceedb7 Rollback to r437 for bind_first implementation. The "cleaned up" version was a no-go in some cases 2009-11-08 16:28:35 +00:00
Jonathan Turner
1bc968e788 Add initial unaries 2009-11-08 16:27:39 +00:00
Jason Turner
fe5a935abd add is_undef functionality to boxed_value 2009-11-08 15:16:15 +00:00
Jason Turner
4e5c972e66 Simplify implementation of bind_first and add some detail namespacing 2009-11-08 14:46:44 +00:00
Jonathan Turner
d946cb7e9d Small fix to the casting of values in boolean logical statements 2009-11-07 14:50:41 +00:00
Jonathan Turner
18bfead387 Move to a better operator parser, add support for most of the C++ binary operators 2009-11-07 14:43:12 +00:00
Jason Turner
4c015d7e44 Simplification of bootstrap_stl code resulting in slightly better engine start up performance and compile time performance 2009-10-21 01:48:21 +00:00
Jason Turner
1122f2c818 Clean up reference counting implementation while improving compile time and compromising runtime slightly 2009-10-20 00:34:15 +00:00
Jason Turner
d2d752ecd4 Fix registration of module loading functions 2009-10-19 14:00:48 +00:00
Jason Turner
a18c701866 Fix type-shifting of bind_first for free function pointer types 2009-10-16 15:49:46 +00:00
Jason Turner
9871604a48 Make sure example.cpp compilable with new setup 2009-10-15 15:55:16 +00:00
Jason Turner
b1d12fdc91 Further updates to the new bound function support, plus general cleanup of how it is used 2009-10-15 15:27:16 +00:00
Jason Turner
24e717d532 Fix "bind_first" for non member functions 2009-10-14 22:42:45 +00:00
Jason Turner
1568fedebd Reduce # of required versions for bound_fun and enhance it to work with non-member functions 2009-10-14 17:19:42 +00:00
Jonathan Turner
c88578d537 Add another unit test for operator overloading 2009-10-14 14:00:22 +00:00
Jonathan Turner
9827345213 Fix Id Literals so that they are keyed off an Id search. This allows us to add operator overloading on the parse side. 2009-10-14 13:51:35 +00:00
Jonathan Turner
c51d14fb13 Add some missing unit tests for number formats and block starting 2009-10-14 12:25:21 +00:00
Jason Turner
480761c1f7 Add bound_fun helper and put it to use cleaning up the engine bootstrapping 2009-10-14 02:34:09 +00:00
Jonathan Turner
12e909d9aa Add bit shifting operators 2009-10-13 03:35:01 +00:00
Jason Turner
b1e892487f Enhance "is_type" to be more accurate and to work with Dynamic_Object types 2009-10-13 03:31:56 +00:00
Jason Turner
720eabcb16 Impliment range find functions and add unit test for contains and find. 2009-10-13 02:05:18 +00:00
Jason Turner
1fde71f3f4 Add type generic comparison operations "eq", "gt", and "lt" and port the "contains" operation to use it 2009-10-13 00:18:59 +00:00
Jonathan Turner
90f8b77171 Added .contains() to ranges 2009-10-11 20:02:21 +00:00
Jonathan Turner
315d7521a7 Clean up warnings. Add simple blocks. 2009-10-08 03:01:19 +00:00
Jonathan Turner
ff177b5eaf Add octal support 2009-10-06 21:17:23 +00:00
Jonathan Turner
46fd7e9a58 Add hex value parsing support 2009-10-06 16:04:05 +00:00
Jason Turner
edd274ccce Fix some more obscure warnings 2009-10-06 02:26:47 +00:00
Jonathan Turner
a5b2ec3006 Start code cleanups by moving chaiscript common structures into their own file. 2009-09-23 05:00:14 +00:00
Jason Turner
cd3c0d4fd7 Update property page to something more in line with normal boost installs. 2009-09-23 00:42:08 +00:00
Jason Turner
3bdd79a3fd Correct Windows unicode build issues. 2009-09-22 23:03:16 +00:00
Jason Turner
b04e01cda7 Ensure that __EVAL__ is in the list of loaded files and be smarter about accessing it 2009-09-22 21:06:02 +00:00
Jason Turner
bad5384c96 Fix multi-file compilation issues 2009-09-22 20:59:10 +00:00
Jason Turner
443902f787 Reduce overhead necessary for internal_eval. Desirable due to the use of "eval" during cloning operations 2009-09-22 01:58:16 +00:00
Jason Turner
d3cdd6959d Add unit tests for range lookups 2009-09-22 01:36:13 +00:00
Jason Turner
9762e15460 Fix some range/retro issues and update the visual studio files 2009-09-22 01:23:02 +00:00
Jonathan Turner
33897e2c0f Add unit tests for multiline and inner outer loops 2009-09-21 17:31:10 +00:00
Jonathan Turner
9528e44b88 Add unit tests for multiline and inner outer loops 2009-09-21 17:30:55 +00:00
Jonathan Turner
03746e7606 Add keywords for NaN and Infinity 2009-09-21 16:50:30 +00:00
Jason Turner
50eace16da Allow "Module" to contain chaiscript snippets to be executed when a module is initialized. Update dynamic_object to use the new feature to clean up some of the _prelude.hpp 2009-09-21 03:07:01 +00:00
Jason Turner
8241e46680 Further refine how clone calls are dynamically generated, to avoid accidentally matching when we should not 2009-09-20 21:49:53 +00:00
Jason Turner
160f64e9c2 Enabled short hand for adding new methods to existing C++ types 2009-09-20 21:32:39 +00:00
Jason Turner
593c6c68ee Port "retro" to use the new built in object typing, add unit test for retro'ing a retro 2009-09-20 03:50:25 +00:00
Jason Turner
991753a492 Add support for cloning of dynamic objects 2009-09-19 23:12:56 +00:00
Jason Turner
7cdd772f2b Add const correctness for proxy functions. Add unit tests for function variable assignment scenarios 2009-09-19 21:13:12 +00:00
Jonathan Turner
c5f837fd19 Added 'finally' to try/catch block 2009-09-19 18:12:22 +00:00
Jonathan Turner
7c244d25b5 Add support for chai objects by adding methods and attrs 2009-09-19 15:32:12 +00:00
Jonathan Turner
18fc4d419f Fix to catch block handling that would have lost the scope of the boost::ref of the exception 2009-09-19 13:40:48 +00:00
Jonathan Turner
813fa055a3 Added guarded exception catches 2009-09-19 13:30:11 +00:00
Jason Turner
6a47846b84 Add runtime_error support, for throwing a normal std::exception. Also, move bootstrap for Dynamic_Object into its proper place. 2009-09-19 12:15:17 +00:00
Jason Turner
b0041217b0 initial checkin of dynamic object support with example usage in example.cpp 2009-09-19 02:36:27 +00:00
Jonathan Turner
fedcd28ecc Add exception unit test 2009-09-19 02:21:36 +00:00
Jonathan Turner
b17c6b9748 Add support for std::exception and what() 2009-09-18 22:26:07 +00:00
Jonathan Turner
204d379176 Fix default cmake build to use readline and gdb. Add simple try/catch/throw exceptions 2009-09-18 22:04:07 +00:00
Jason Turner
a754ce9eb6 Initial check in of code analysis tool 2009-09-16 01:46:04 +00:00
Jonathan Turner
99b5f46a9e Fix type in help. 2009-09-15 20:32:16 +00:00
Jason Turner
394d8c3bf6 Allow the user to choose the build type using CMAKE_BUILD_TYPE by eliminating the overrides in the CMakeLists.txt file 2009-09-15 02:53:23 +00:00
Jason Turner
4bdbcf30ff Move std::list<> support from main.cpp into a module, stl_extra.cpp, to better allow for measuring of core compile times / performance. 2009-09-15 01:30:51 +00:00
Jonathan Turner
63de0fd33c Add a couple more in-string eval unit tests to check for proper escaping 2009-09-13 12:53:12 +00:00
Jonathan Turner
0fbb7c44bd Add some unit tests for in-string eval 2009-09-12 14:55:14 +00:00
Jonathan Turner
5092713876 Add in-string eval 2009-09-12 14:52:46 +00:00
Jason Turner
f369afed77 Decrease compile times by 30% and runtimes by 10% by eliminating use of boost::bind during function dispatch 2009-09-10 03:44:42 +00:00
Jonathan Turner
f23f0edc70 Fix parser to handle shortform equations (fix bad operator parsing). Add back lines to prelude for line numbers 2009-09-09 14:11:03 +00:00
Jason Turner
daee00da95 Minor performance enhancement for caching function and cleanup of minor windows warning in same function. 2009-09-09 13:17:20 +00:00
Jason Turner
e2cdac0406 Decrease compilation time by removing "Retro" from c++ compiled and making a chaiscript version instead 2009-09-09 03:11:47 +00:00
Jason Turner
cc44ec99ba Fix reversed logic in printing output during eval 2009-09-08 23:39:34 +00:00
Jonathan Turner
1bf3b1ed37 Couple changes for module loading in mingw 2009-09-08 21:22:37 +00:00
Jason Turner
f7b530ebae Quick fix to (hopefully) module support on mingw 2009-09-08 19:21:11 +00:00
Jason Turner
b185e2e792 Make Type_Info internal data private and provide more rigorous definitions for comparisions of objects 2009-09-08 13:31:14 +00:00
Jonathan Turner
73ec2abd43 Add unit test script for windows 2009-09-08 02:22:49 +00:00
Jonathan Turner
cfee4c6bc1 Bugfix: cached the wrong boolean value. Fixed. 2009-09-08 02:15:41 +00:00
Jonathan Turner
2d4b9c0d93 Another Touchup fix to CMakeLists.txt for cleanliness 2009-09-07 21:25:10 +00:00
Jonathan Turner
f522d3697c Touchup fix to CMakeLists.txt for cleanliness 2009-09-07 21:09:18 +00:00
Jonathan Turner
48e96b2f3b Add readline support to eval. 2009-09-07 20:52:31 +00:00
Jason Turner
798908f127 Add loadable module support for ms Visual C++ and fix visual studio specific type identification problems, (while making the C++ more correct) 2009-09-07 17:05:57 +00:00
Jonathan Turner
7e3127549f Added simple const value caching. Fix CMake to default back to debug mode 2009-09-07 15:48:32 +00:00
Jonathan Turner
4713325877 Touchup to cmake project file to prevent error msg in OS X 2009-09-07 14:13:28 +00:00
Jason Turner
7cc6a3cab9 Add support for loadable modules on POSIX systems 2009-09-06 23:33:03 +00:00
Jonathan Turner
cba5731576 Fixing the last of the const change issues 2009-09-06 02:55:39 +00:00
Jonathan Turner
b3656c95f5 Correcting unit tests that are inc/dec temporaries. This is no longer allowed 2009-09-06 02:50:36 +00:00
Jonathan Turner
e9539dfee2 BROKEN./run_unit_tests.sh ! This is to help repair unit tests broken in move to consts. Should be fixed shortly. 2009-09-06 02:24:46 +00:00
Jason Turner
4b40812e26 Add const_var helper function for making const values. 2009-09-06 02:09:19 +00:00
Jason Turner
ef8cd1f591 Add more robust support for handling of const ptr values 2009-09-05 23:46:21 +00:00
Jason Turner
46cdb89921 Add missing chaiscript_threading.hpp 2009-09-05 13:10:27 +00:00
Jason Turner
3094ff6e3b Made thread saftey a compilation option for performance and dependencies reasons 2009-09-05 00:16:46 +00:00
Jason Turner
4d42d6ff33 Add shared objects that can be used by all threads at their root scope only 2009-09-03 11:42:23 +00:00
Jason Turner
a427d2c1a9 Correct function pointer casts to more correct static_cast<>() 2009-09-03 00:15:56 +00:00
Jason Turner
efb7a8d453 Create local thread caches of registered function objects to reduce thread contention 2009-09-02 02:28:38 +00:00
Jason Turner
6c4872eae9 Initial check in of multithreaded support for chaiscript 2009-08-31 19:50:41 +00:00
Jason Turner
ff639a267d Shave a few cycles off by reducing copies and assignments of objects in eval 2009-08-30 02:24:11 +00:00
Jason Turner
94e4b671f3 Make sure to invalidate the cache when a new function name is added 2009-08-30 01:06:21 +00:00
Jason Turner
096c8aab50 Provide for caching of objects in the dispatch get get_object side. Also, update chaiscript_eval to not explicitly add a new stack object to each scope as it is created 2009-08-30 00:48:17 +00:00
Jason Turner
89186a86c8 speed up operator calls by about 10% by reducing Proxy_Function copies and such 2009-08-29 19:19:31 +00:00
Jason Turner
c8c1c65e8c Add std::list support 2009-08-29 14:00:07 +00:00
Jonathan Turner
c5e1d5fa20 Add ref equal unit test 2009-08-27 15:03:49 +00:00
Jonathan Turner
91011695f0 Allow simple multiline commands in arg list and container arg list 2009-08-26 20:34:32 +00:00
Jason Turner
3a951cea99 Extend the reserved object name registration to include some missing values such as break and return and such 2009-08-26 02:21:41 +00:00
Jonathan Turner
8620f4eaf9 Fix for issue 23, makes for and while loops live in their own deeper scope 2009-08-26 02:02:41 +00:00
Jonathan Turner
59ecf32f9b Add Eval_Error end extents and reserved word errors 2009-08-25 01:10:28 +00:00
Jason Turner
541e453098 check in of reserved word handling 2009-08-25 00:36:02 +00:00
Jason Turner
0b780593a6 Make for better error messages when a clone fails 2009-08-22 13:55:06 +00:00
Jason Turner
2e7c5f413e Cleanup get_function implementation 2009-08-21 22:51:12 +00:00
Jonathan Turner
7e5b7cbd7a Switch get_function to default to not doing object lookup. Correct method eval to maintain method lambda syntax. Add unit test for method lambda 2009-08-21 20:05:05 +00:00
Jonathan Turner
c539e0b458 Add unittest for 'use' feature 2009-08-21 18:26:34 +00:00
Jason Turner
1f011f3d5b Add "use" function for loading chai files from inside of ChaiScript and fix potential memory bug with filename const char * pointers being passed around 2009-08-21 03:33:57 +00:00
Jason Turner
a136236179 Fix dispatch for const boost::shared_ptr<> & parameters for functions, add a test to example.cpp and fix some issues with building example.cpp 2009-08-20 21:35:56 +00:00
Jonathan Turner
8840f06053 Allow floating point numbers without a zero before the decimal point 2009-08-20 14:50:13 +00:00
Jason Turner
00e4de774f Move "fun_helper" into detail namespace 2009-08-09 19:12:01 +00:00
Jason Turner
bc3a17b3b7 Port VC++ fix from last rev back to Linux 2009-08-09 18:42:32 +00:00
Jason Turner
4a57efde25 Correct bug with bootstrapping of Map type on windows. Also, make it easier to specify the type of a function being added at the time it is being added. 2009-08-09 16:49:14 +00:00
524 changed files with 23386 additions and 7103 deletions

25
.decent_ci-Linux.yaml Normal file
View File

@@ -0,0 +1,25 @@
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: 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*"

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

22
.decent_ci-Windows.yaml Normal file
View File

@@ -0,0 +1,22 @@
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%
compiler_extra_flags: /analyze
- 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%
compiler_extra_flags: /analyze

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

31
.travis.yml Normal file
View File

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

View File

@@ -1,25 +1,411 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.8)
project(chaiscript) project(chaiscript)
SET (CMAKE_BUILD_TYPE gdb) # MINGW does not yet support C++11's concurrency features
SET (CMAKE_C_FLAGS_GDB " -Wall -ggdb") if(MINGW)
SET (CMAKE_CXX_FLAGS_GDB " -Wall -ggdb") option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" FALSE)
else()
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
endif()
#SET (CMAKE_BUILD_TYPE rel)
#SET (CMAKE_C_FLAGS_REL " -Wall -O3") option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
#SET (CMAKE_CXX_FLAGS_REL " -Wall -O3") option(BUILD_SAMPLES "Build Samples Folder" FALSE)
if(CMAKE_COMPILER_IS_GNUCC)
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
if(ENABLE_COVERAGE)
add_definitions(--coverage -O0)
set(LINKER_FLAGS "${LINKER_FLAGS} --coverage")
endif()
endif()
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
option(ENABLE_THREAD_SANITIZER "Enable thread sanitizer testing in gcc/clang" FALSE)
if(ENABLE_THREAD_SANITIZER)
add_definitions(-fsanitize=thread -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=thread")
endif()
option(ENABLE_ADDRESS_SANITIZER "Enable address sanitizer testing in gcc/clang" FALSE)
if(ENABLE_ADDRESS_SANITIZER)
add_definitions(-fsanitize=address -g)
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
endif()
option(ENABLE_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 "\\\\.svn")
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.git")
list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp")
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 6)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An embedded scripting language for C++")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_RPM_PACKAGE_LICENSE "BSD")
set(CPACK_RPM_PACKAGE_GROUP "Programming")
set(CHAI_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest)
include(CPack)
include(cmake/CheckCXX11Features.cmake)
if(NOT MINGW)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
endif()
if(HAS_CXX11_VARIADIC_TEMPLATES)
message(STATUS "Variadic Template support detected")
else()
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
endif()
enable_testing()
message(STATUS "Detecting readline support")
if(READLINE_LIBRARY)
message(STATUS "Found: ${READLINE_LIBRARY}")
set(READLINE_LIB readline)
add_definitions(/DREADLINE_AVAILABLE)
else()
message(STATUS "Not Found")
set(READLINE_LIB)
set(READLINE_FLAG)
endif()
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)
add_definitions(/W4 /w44640)
add_definitions(/bigobj)
# Note on MSVC compiler flags.
# The code base selective disables warnings as necessary when the compiler is complaining too much
# about something that is perfectly valid, or there is simply no technical way around it
# This particular warning, C4503 is in regards to the decorated names that MSVC generates internally.
# The error did not come up until the move to C++11, but the compiler doesn't give enough information
# to determine where the error is coming from, and the internet provides no real information for
# how to workaround or fix the error. So I'm disabling it globally.
add_definitions(/wd4503)
else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -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)
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()
include_directories(include) include_directories(include)
find_package(Boost 1.36.0)
if (Boost_FOUND) set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(chaiscript_eval src/main.cpp) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
#add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp)
target_link_libraries(chaiscript_eval ${Boost_LIBRARIES}) if(NOT MULTITHREAD_SUPPORT_ENABLED)
install(TARGETS chaiscript_eval DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/bin) add_definitions(-DCHAISCRIPT_NO_THREADS)
else(Boost_FOUND) endif()
message(FATAL_ERROR "Can not find Boost")
endif(Boost_FOUND) if(CMAKE_HOST_UNIX)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
list(APPEND LIBS "dl")
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})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib.cpp)
target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
add_executable(chai src/main.cpp ${Chai_INCLUDES})
target_link_libraries(chai ${LIBS})
add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
if(BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS})
add_executable(inheritance samples/inheritance.cpp)
target_link_libraries(inheritance ${LIBS})
add_executable(fun_call_performance samples/fun_call_performance.cpp)
target_link_libraries(fun_call_performance ${LIBS})
endif()
if(BUILD_MODULES)
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS})
set(MODULES stl_extra)
endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
list(SORT UNIT_TESTS)
if(BUILD_TESTING)
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
add_test(version_check chai -c "if(\"\\\${ version() };\\\${version_major()};\\\${version_minor()};\\\${version_patch()}\" != \"${CHAI_VERSION};${CPACK_PACKAGE_VERSION_MAJOR};${CPACK_PACKAGE_VERSION_MINOR};${CPACK_PACKAGE_VERSION_PATCH}\") { exit(-1) }")
set_property(TEST version_check
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
endforeach()
set_property(TEST ${UNIT_TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
if(NOT UNIT_TEST_LIGHT)
# commented out because uniform initializer syntax is not working properly in MSVC 2013
add_executable(utility_test unittests/utility_test.cpp)
target_link_libraries(utility_test ${LIBS})
add_test(NAME Utility_Test COMMAND utility_test)
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
target_link_libraries(dynamic_object_test ${LIBS})
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)
target_link_libraries(boxed_cast_test ${LIBS})
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
target_link_libraries(object_lifetime_test ${LIBS})
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
add_executable(object_lifetime_test2 unittests/object_lifetime_test2.cpp)
target_link_libraries(object_lifetime_test2 ${LIBS})
add_test(NAME Object_Lifetime_Test2 COMMAND object_lifetime_test2)
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)
target_link_libraries(type_info_test ${LIBS})
add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(type_name_test unittests/type_name_test.cpp)
target_link_libraries(type_name_test ${LIBS})
add_test(NAME Type_Name_Test COMMAND type_name_test)
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
target_link_libraries(eval_catch_exception_test ${LIBS})
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(cpp_lambda_test unittests/cpp_lambda_test.cpp)
target_link_libraries(cpp_lambda_test ${LIBS})
add_test(NAME cpp_lambda_test COMMAND cpp_lambda_test)
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
target_link_libraries(expected_eval_errors_test ${LIBS})
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
add_executable(set_state_test unittests/set_state_test.cpp)
target_link_libraries(set_state_test ${LIBS})
add_test(NAME Set_State_Test COMMAND set_state_test)
add_executable(simultaneous_chaiscript_test unittests/simultaneous_chaiscript_test.cpp)
target_link_libraries(simultaneous_chaiscript_test ${LIBS})
add_test(NAME Simultaneous_ChaiScript_Test COMMAND simultaneous_chaiscript_test)
add_executable(heap_allocated_chaiscript_test unittests/heap_allocated_chaiscript_test.cpp)
target_link_libraries(heap_allocated_chaiscript_test ${LIBS})
add_test(NAME Heap_Allocated_ChaiScript_Test COMMAND heap_allocated_chaiscript_test)
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
target_link_libraries(c_linkage_test ${LIBS})
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
target_link_libraries(integer_literal_test ${LIBS})
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp)
target_link_libraries(arithmetic_conversions_test ${LIBS})
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test)
if(MULTITHREAD_SUPPORT_ENABLED)
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
target_link_libraries(multithreaded_test ${LIBS})
add_test(NAME Multithreaded_Test COMMAND multithreaded_test)
set_property(TEST Multithreaded_Test
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
endif()
add_executable(multifile_test
unittests/multifile_test_main.cpp
unittests/multifile_test_chai.cpp
unittests/multifile_test_module.cpp
)
target_link_libraries(multifile_test ${LIBS})
add_test(NAME MultiFile_Test COMMAND multifile_test)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
endif()
endif()
install(TARGETS chai chaiscript_stdlib-${CHAI_VERSION} ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
install(DIRECTORY include/chaiscript DESTINATION include
PATTERN "*.hpp"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
install(DIRECTORY unittests DESTINATION share/chaiscript
PATTERN "*.chai"
PATTERN "*.inc"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
install(DIRECTORY samples DESTINATION share/chaiscript
PATTERN "*.chai"
PATTERN "*/.svn*" EXCLUDE
PATTERN "*/.git*" EXCLUDE
PATTERN "*~" EXCLUDE)
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
DESTINATION lib/pkgconfig)

1890
Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
This is a placeholder

View File

@@ -1,8 +0,0 @@
#!/bin/bash
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .
make install
INCLUDED_FILES="include/chaiscript/*.hpp include/chaiscript/dispatchkit/*.hpp include/chaiscript/language/*.hpp bin/chaiscript_eval"
zip -r chaiscript-1.0.zip $INCLUDED_FILES

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

@@ -0,0 +1,43 @@
function analyze_data
{
echo -n "$1," >> $2
awk 'END {printf "%s,", $1}' r$1-codesize.out >> $2
awk '{printf "%s,", $1}' r$1-numunittests.out >> $2
awk 'END {printf "%s,", $1}' r$1-unittestsoutput.out >> $2
awk '{printf "%s,", $1}' r$1-debugbinarysize.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-debugbuildtime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-debugprofiletime.out >> $2
awk '{printf "%s,", $1}' r$1-releasebinarysize.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releasebuildtime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releasemodulesbuildtime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releaseprofiletime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-releaseunittestruntime.out >> $2
if [ -x r$1-threadfreebinarysize.out ]
then
awk '{printf "%s,", $1}' r$1-threadfreebinarysize.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-threadfreeprofiletime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-1threadruntime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-2threadruntime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-4threadruntime.out >> $2
awk 'NR>1{exit} 1 {printf "%s,", $2}' r$1-8threadruntime.out >> $2
else
echo -n ",,,,,," >> $2
fi
awk -F "\n" 'NR>1{exit} 1 {printf "\"%s\"\n", $1}' r$1-revisionlog.out >> $2
}
filename=output-$1-$2.csv
echo "Revision, LOC, Num Unit Tests, Successful Unit Tests, Debug Binary Size, Debug Build Time, Debug Profile Time, Release Binary Size, Release Core Build Time, Release Modules Build Time, Release Profile Time, Release Unit Tests Time, Threadless Binary Size, Threadless Profile Time, 1 Thread Profile Time, 2 Threads Profile Time, 4 Threads Profile Time, 8 Threads Profile Time, Revision Log" > $filename
for i in `seq $1 $2`
do
analyze_data $i $filename
done

View File

@@ -0,0 +1,81 @@
function run_test
{
echo "****Getting r$1 from SVN"
svn export --quiet -r$1 http://chaiscript.googlecode.com/svn/trunk chaiscript-r$1
pushd chaiscript-r$1
echo "****Getting svn revision log"
svn propget svn:log --revprop -r$1 http://chaiscript.googlecode.com/svn/trunk > ../r$1-revisionlog.out
echo "****Editing CMakeLists.txt to allow for build type switching"
# Clean up CMakeLists.txt so that we can set the build type at configure time
sed -i -e "s/SET (CMAKE_BUILD_TYPE.*//" CMakeLists.txt
echo "****Compiling Debug Build"
cmake -D CMAKE_BUILD_TYPE=Debug CMakeLists.txt
/usr/bin/time -p make chaiscript_eval 2> ../r$1-debugbuildtime.out
echo "****Analyzing Debug Build"
/usr/bin/time -p ./chaiscript_eval ../profile.chai 2>../r$1-debugprofiletime.out
ls -s --block-size=1 ./chaiscript_eval > ../r$1-debugbinarysize.out
make clean
echo "****Compiling Release Build"
cmake -D CMAKE_BUILD_TYPE=Release CMakeLists.txt
/usr/bin/time -p make chaiscript_eval 2> ../r$1-releasebuildtime.out
echo "****Analyzing Release Build"
/usr/bin/time -p ./chaiscript_eval ../profile.chai 2>../r$1-releaseprofiletime.out
ls -s --block-size=1 ./chaiscript_eval > ../r$1-releasebinarysize.out
echo "****Analyzing Code Size"
find ./include -name "*.hpp" | xargs wc > ../r$1-codesize.out
echo "****Building Remaining Modules"
/usr/bin/time -p make 2> ../r$1-releasemodulesbuildtime.out
echo "****Running unit tests"
/usr/bin/time -p ./run_unit_tests.sh 2> ../r$1-releaseunittestruntime.out > ../r$1-unittestsoutput.out
echo "****Counting number of unit tests"
find unittests/ -name "*.chai" | wc | awk '{print $1}' > ../r$1-numunittests.out
echo "****Running multithreaded tests"
if [ -e src/multithreaded.cpp ]
then
# Run multithreaded tests
echo "****Building multithreaded test"
pushd src
g++ multithreaded.cpp -ldl -omultithreaded -I../include -O3
echo "****Testing 1 thread runtime"
/usr/bin/time -p ./multithreaded 1 2> ../../r$1-1threadruntime.out
echo "****Testing 2 thread runtime"
/usr/bin/time -p ./multithreaded 1 1 2> ../../r$1-2threadruntime.out
echo "****Testing 4 thread runtime"
/usr/bin/time -p ./multithreaded 1 1 1 1 2> ../../r$1-4threadruntime.out
echo "****Testing 8 thread runtime"
/usr/bin/time -p ./multithreaded 1 1 1 1 1 1 1 1 2> ../../r$1-8threadruntime.out
echo "****Compiling thread-free version"
g++ main.cpp -ldl -othreadfree -I../include -O3 -DCHAISCRIPT_NO_THREADS
echo "****Analyzing thread-free version"
/usr/bin/time -p ./threadfree ../../profile.chai 2>../../r$1-threadfreeprofiletime.out
ls -s --block-size=1 ./threadfree > ../../r$1-threadfreebinarysize.out
popd
else
echo "Multithreaded test non-existent"
fi
popd
}
for i in `seq $1 $2`
do
run_test $i
done

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
var total = 0
for (var i = 0.0; i < 10000.0; i += 0.1) {
total += int(double(i) + int(10));
if (i < 9000.0)
{
total += double(11);
if (i > double(4000.0))
{
total += double(10);
}
}
}
print(total)

View File

@@ -0,0 +1,9 @@
var something = 0;
for (var i = 1; i < 10000; ++i)
{
something += int(3 % 2 * 4 + 2 / 16.0 - 100 + (10 ^ 19) / 64 + (3 & 12) - (4 | 14)) % i;
}
print(something);

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,136 @@
<?php
/*************************************************************************************
* chaiscript.php
* --------------
* Author: Jason Turner & Jonathan Turner (based on JavaScript by Ben Keen (ben.keen@gmail.com))
* Copyright: (c) 2010 Jason Turner (jason@emptycrate.com) (c) 2009 Jonathan Turner
* (c) 2004 Ben Keen (ben.keen@gmail.com), Nigel McNie (http://qbnz.com/highlighter)
* Release Version: 1.0
* Date Started: 2009/07/03
*
* ChaiScript language file for GeSHi.
*
* CHANGES
* -------
* 2009/07/03 (1.0.0)
* - First Release
* 2010/03/30 (1.1.0)
* - Updated to include more language features and remove left over pieces from JavaScript
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'ChaiScript',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
//Regular Expressions
'COMMENT_REGEXP' => array(2 => "/(?<=[\\s^])s\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])m?\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\,\\;\\)])/iU"),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally', 'case', 'switch', 'default',
),
2 => array(
'def', 'false', 'fun', 'true', 'var', 'auto', 'attr',
),
3 => array(
// built in functions
'throw',
)
),
'SYMBOLS' => array(
'(', ')', '[', ']', '{', '}',
'+', '-', '*', '/', '%',
'!', '@', '&', '|', '^',
'<', '>', '=',
',', ';', '?', ':'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #000066; font-weight: bold;',
2 => 'color: #003366; font-weight: bold;',
3 => 'color: #000066;'
),
'COMMENTS' => array(
1 => 'color: #006600; font-style: italic;',
2 => 'color: #009966; font-style: italic;',
'MULTI' => 'color: #006600; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #009900;'
),
'STRINGS' => array(
0 => 'color: #3366CC;'
),
'NUMBERS' => array(
0 => 'color: #CC0000;'
),
'METHODS' => array(
1 => 'color: #660066;'
),
'SYMBOLS' => array(
0 => 'color: #339933;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
0 => '',
1 => '',
2 => '',
3 => ''
)
),
'URLS' => array(
1 => '',
2 => '',
3 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_MAYBE,
'SCRIPT_DELIMITERS' => array(
0 => array(
),
1 => array(
)
),
'HIGHLIGHT_STRICT_BLOCK' => array(
0 => true,
1 => true
)
);
?>

View File

@@ -0,0 +1,12 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: chaiscript
Description: ChaiScript is a scripting language that easily embeds into your existing C++ applications. It's built to be flexible and dynamic, yet still maintain the type-safety you expect as a C++ user. It can natively use classes, methods, and attributes, even if the class inherits functionality from a parent class.
Version: @CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@
Requires:
Conflicts:
Libs:
Cflags: -I${includedir}

View File

@@ -1,69 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include <iostream>
#include "function_call.hpp"
#include "chaiscript.hpp"
#include <boost/function.hpp>
struct Callback_Handler
{
typedef std::vector<std::pair<boost::function<std::string ()>,
boost::function<double (int)> > > Callbacks;
Callbacks m_callbacks;
void add_callbacks(boost::shared_ptr<dispatchkit::Proxy_Function> t_name,
boost::shared_ptr<dispatchkit::Proxy_Function> t_value)
{
m_callbacks.push_back(
std::make_pair(dispatchkit::build_function_caller<std::string ()>(t_name),
dispatchkit::build_function_caller<double (int)>(t_value)
)
);
}
void do_callbacks()
{
int i=1;
for (Callbacks::iterator itr = m_callbacks.begin();
itr != m_callbacks.end();
++itr)
{
std::cout << "Name: " << itr->first() << " = " << itr->second(i) << std::endl;
++i;
}
}
};
int main(int argc, char *argv[]) {
chaiscript::ChaiScript_Engine chai;
Callback_Handler cb_handler;
chai.get_eval_engine().add_object("cb_handler", boost::ref(cb_handler));
dispatchkit::register_function(chai.get_eval_engine(), &Callback_Handler::add_callbacks, "add_callbacks");
for (int i = 1; i < argc; ++i) {
try {
dispatchkit::Boxed_Value val = chai.evaluate_file(argv[i]);
}
catch (std::exception &e) {
std::cerr << "Could not open: " << argv[i] << std::endl;
exit(1);
}
}
cb_handler.do_callbacks();
boost::function<std::string (const std::string&, const std::string &)> f =
dispatchkit::build_functor<std::string (const std::string &, const std::string &)>
(chai, "function(x, y) { return x + y }");
std::cout << "Functor call: " << f("Hello", " World") << std::endl;
}

View File

@@ -1,212 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/dispatchkit/function_call.hpp>
using namespace dispatchkit;
struct Test
{
Test(const std::string &s)
: number(-25), message(s)
{
std::cout << "Test class constructed with value: " << s << std::endl;
}
void show_message()
{
std::cout << "Constructed Message: " << message << std::endl;
}
std::string &get_message()
{
return message;
}
int number;
std::string message;
};
Boxed_Value named_func_call(Dispatch_Engine &ss,
const std::string &nametocall, const std::vector<Boxed_Value> &params)
{
if (params.size() == 2)
{
return dispatch(ss.get_function(nametocall), params);
} else {
throw std::runtime_error("Invalid num params");
}
}
// A function that takes a dynamic list of params
// and calls a bunch of conversion functions on them and
// returns the result as a boxed_value
Boxed_Value dynamic_function(Dispatch_Engine &ss, const std::string &name,
const std::vector<Boxed_Value> &params)
{
if (name == "concat_string")
{
Boxed_Value result;
//Return a void if there is nothing in the array
if (params.size() == 0)
{
return result;
} else {
//else, prepopulate the result with a string conversion of the first
//param
result =
dispatch(ss.get_function("to_string"), Param_List_Builder() << params[0]);
}
//Then, loop over all remaining params, converting them to strings and adding
//them to the result. This example maybe bette served with a string += operator
//implementation, but it works.
for (size_t i = 1; i < params.size(); ++i)
{
result =
dispatch(ss.get_function("+"), Param_List_Builder() << result <<
dispatch(ss.get_function("to_string"), Param_List_Builder() << params[i]));
}
return result;
} else {
throw std::runtime_error("Unknown function call");
}
}
void test(const std::string &p)
{
std::cout << "Test: " << p << std::endl;
}
//Test main
int main()
{
Dispatch_Engine ss;
Bootstrap::bootstrap(ss);
bootstrap_vector<std::vector<int> >(ss, "VectorInt");
dump_system(ss);
//Calling a function by name and allowing the built in dispatch mechanism to
//choose the most appropriate version of the function
Boxed_Value addresult = dispatch(ss.get_function("+"), Param_List_Builder() << double(5.1) << double(10.3));
//Using the cast to unbox the resultant value and output it
std::cout << boxed_cast<double>(addresult) << std::endl;
//Using the Boxed_Value as input to another function, again with automatic dispatch.
//This time we will not bother saving the result and will instead send it straight out
std::cout << boxed_cast<double>(
dispatch(ss.get_function("*"), Param_List_Builder() << 2 << addresult)
) << std::endl;
//Register a new function, this one with typing for us, so we don't have to ubox anything
//right here
//Now we have a print method, let's try to print out the earlier example:
//so, we dispatch the to_string and pass its result as a param to "print"
//In this example we don't bother with temporaries and we don't have to know
//anything about types
dispatch(ss.get_function("print_string"),
Param_List_Builder() << dispatch(ss.get_function("to_string"), Param_List_Builder() << addresult));
// Now we are going to register a new dynamic function,
// when this function is called the objects are not unboxed, but passed
// in in their boxed state
ss.register_function(boost::shared_ptr<Proxy_Function>(new Dynamic_Proxy_Function(boost::bind(&dynamic_function, boost::ref(ss), "concat_string", _1))), "concat_string");
// Call our newly defined dynamic function with 10 parameters, then send
// its output to the "print" function
dispatch(ss.get_function("print_string"),
Param_List_Builder() << dispatch(ss.get_function("concat_string"),
Param_List_Builder() << std::string("\n\t") << std::string("The Value Was: ")
<< double(42.5) << std::string(".")
<< '\n'
<< '\t' << std::string("The old value was: ")
<< addresult << '.' << '\n' ));
//Register some local methods of the "Test" class
ss.register_function(build_constructor<Test, const std::string &>(), "Test");
register_function(ss, &Test::get_message, "get_message");
register_function(ss, &Test::show_message, "show_message");
register_member(ss, &Test::number, "number");
//Create a new object using the "Test" constructor, passing the param "Yo".
//Then, add the new object to the system with the name "testobj2"
ss.add_object("testobj2",
dispatch(ss.get_function("Test"), Param_List_Builder() << std::string("Yo")));
// Look up and store a reference to our new object
std::vector<Boxed_Value> sos;
sos.push_back(ss.get_object("testobj2"));
//Build a bound function proxy for calling the script handled function
boost::function<void (Test &)> show_message =
build_function_caller<void (Test &)>(ss.get_function("show_message"));
Test &t = boxed_cast<Test &>(ss.get_object("testobj2"));
//Print the message the object was created with
show_message(t);
//Now, get a reference to the object's stored message
Boxed_Value stringref = dispatch(ss.get_function("get_message"), sos);
//Unbox it using boxed_cast
std::string &sr = boxed_cast<std::string &>(stringref);
//Update the value of the reference
sr = "Bob Updated The message";
//Now, get a reference to the object's stored number
Boxed_Value numberref= dispatch(ss.get_function("number"), sos);
//Unbox it using boxed_cast
int &ir = boxed_cast<int &>(numberref);
std::cout << "Number: " << ir << std::endl;
//Now, prove that the reference was successfully acquired
//and we are able to peek into the boxed types
show_message(t);
// Finally, we are going to register some named function aliases, for
// the fun of it
ss.register_function(boost::shared_ptr<Proxy_Function>(
new Dynamic_Proxy_Function(boost::bind(&named_func_call, boost::ref(ss), "+", _1))), "add");
//Call our newly named "add" function (which in turn dispatches +)
std::cout << "Result of add function: " <<
boxed_cast<int>(dispatch(ss.get_function("add"), Param_List_Builder() << 5 << 2))
<< std::endl;
ss.set_object("myfunc", boost::shared_ptr<Proxy_Function>(new Proxy_Function_Impl<boost::function<void (const std::string &)> >(&test)));
dispatch(ss.get_function("myfunc"), Param_List_Builder() << std::string("hello function variable"));
}

View File

@@ -1,23 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include "dispatchkit.hpp"
#include "bootstrap.hpp"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE boxedcpp_unittests
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE( add_operators )
{
using namespace dispatchkit;
Dispatch_Engine ss;
Bootstrap::bootstrap(ss);
dump_system(ss);
BOOST_CHECK_EQUAL(boxed_cast<int>(dispatch(ss.get_function("+"), Param_List_Builder() << double(5.1) << double(10.3))), 15.4);
}

View File

@@ -1,148 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#include <iostream>
#include "chaiscript.hpp"
#include "function_call.hpp"
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
std::string load_text_file(const std::string &filename)
{
std::ifstream infile(filename.c_str());
std::string str;
std::string result;
while (std::getline(infile, str))
{
result += str + "\n";
}
return result;
}
std::vector<dispatchkit::Boxed_Value> regex_search(const std::string &str, const std::string &regex)
{
boost::smatch matches;
boost::regex_search(str, matches, boost::regex(regex));
std::vector<dispatchkit::Boxed_Value> results;
for (unsigned int i = 0; i < matches.size(); ++i)
{
results.push_back(dispatchkit::Boxed_Value(std::string(matches.str(i))));
}
return results;
}
struct Sensor_Manager
{
struct Sensor
{
int milliseconds;
dispatchkit::Boxed_Value state_object;
boost::function<double (dispatchkit::Boxed_Value)> sensor;
boost::posix_time::ptime next_run;
Sensor(int t_milliseconds, dispatchkit::Boxed_Value t_state_object,
boost::function<double (dispatchkit::Boxed_Value)> t_sensor)
: milliseconds(t_milliseconds), state_object(t_state_object), sensor(t_sensor),
next_run(boost::posix_time::microsec_clock::universal_time()
+ boost::posix_time::milliseconds(milliseconds))
{
}
std::pair<boost::posix_time::ptime, double> get_value()
{
next_run = boost::posix_time::microsec_clock::universal_time()
+ boost::posix_time::milliseconds(milliseconds);
return std::make_pair(boost::posix_time::microsec_clock::universal_time(),
sensor(state_object));
}
};
std::map<std::string, Sensor> m_sensors;
//sensor_manager.add_sensor("CPU", 1000, global_state, function(state) { update_state(state); state["CPU"]; } )
void add_sensor(const std::string &t_name, int t_milliseconds, dispatchkit::Boxed_Value t_state_object,
boost::shared_ptr<dispatchkit::Proxy_Function> t_func)
{
m_sensors.insert(
std::make_pair(t_name,
Sensor(t_milliseconds, t_state_object,
dispatchkit::build_function_caller<double (dispatchkit::Boxed_Value)>(t_func)
)
)
);
}
std::vector<std::pair<std::string, double> > run_sensors()
{
std::vector<std::pair<std::string, double> > results;
boost::posix_time::ptime t(boost::posix_time::microsec_clock::universal_time());
for (std::map<std::string, Sensor>::iterator itr = m_sensors.begin();
itr != m_sensors.end();
++itr)
{
if (itr->second.next_run <= t)
{
results.push_back(std::make_pair(itr->first, itr->second.get_value().second));
}
}
return results;
}
};
int main(int argc, char *argv[]) {
chaiscript::ChaiScript_Engine chai;
Sensor_Manager sensor_manager;
chai.get_eval_engine().add_object("sensor_manager", boost::ref(sensor_manager));
dispatchkit::register_function(chai.get_eval_engine(), &Sensor_Manager::add_sensor, "add_sensor");
dispatchkit::register_function(chai.get_eval_engine(), &regex_search, "regex_search");
dispatchkit::register_function(chai.get_eval_engine(), &load_text_file, "load_text_file");
for (int i = 1; i < argc; ++i) {
try {
chai.evaluate_file(argv[i]);
}
catch (std::exception &e) {
std::cerr << "Could not open: " << argv[i] << std::endl;
exit(1);
}
}
while (true)
{
usleep(1000);
std::vector<std::pair<std::string, double> > sensor_data = sensor_manager.run_sensors();
for (std::vector<std::pair<std::string, double> >::iterator itr = sensor_data.begin();
itr != sensor_data.end();
++itr)
{
std::cout << "Sensor: " << itr->first << " value: " << itr->second << std::endl;
}
}
}

7
contrib/vim/README.txt Normal file
View File

@@ -0,0 +1,7 @@
Install ftdetect, indent and syntax subdirectories to:
~/.vim/
See the vim documentation on this:
http://vimdoc.sourceforge.net/htmldoc/syntax.html#mysyntaxfile

View File

@@ -0,0 +1,2 @@
au BufRead,BufNewFile *.chai set filetype=chaiscript

View File

@@ -0,0 +1,50 @@
" Vim indent file
" Language: ChaiScript
" Maintainer: Jason Turner <lefticus 'at' gmail com>
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal indentexpr=GetChaiScriptIndent()
setlocal autoindent
" Only define the function once.
if exists("*GetChaiScriptIndent")
finish
endif
function! GetChaiScriptIndent()
" Find a non-blank line above the current line.
let lnum = prevnonblank(v:lnum - 1)
" Hit the start of the file, use zero indent.
if lnum == 0
return 0
endif
" Add a 'shiftwidth' after lines that start a block:
" lines containing a {
let ind = indent(lnum)
let flag = 0
let prevline = getline(lnum)
if prevline =~ '^.*{.*'
let ind = ind + &shiftwidth
let flag = 1
endif
" Subtract a 'shiftwidth' after lines containing a { followed by a }
" to keep it balanced
if flag == 1 && prevline =~ '.*{.*}.*'
let ind = ind - &shiftwidth
endif
" Subtract a 'shiftwidth' on lines ending with }
if getline(v:lnum) =~ '^\s*\%(}\)'
let ind = ind - &shiftwidth
endif
return ind
endfunction

View File

@@ -0,0 +1,99 @@
" Vim syntax file
" Language: ChaiScript
" Maintainer: Jason Turner <lefticus 'at' gmail com>
" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
finish
end
let s:cpo_save = &cpo
set cpo&vim
syn case match
" syncing method
syn sync fromstart
" Strings
syn region chaiscriptString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=chaiscriptSpecial,chaiscriptEval,@Spell
" Escape characters
syn match chaiscriptSpecial contained "\\[\\abfnrtv\'\"]\|\\\d\{,3}"
" String evals
syn region chaiscriptEval contained start="${" end="}"
" integer number
syn match chaiscriptNumber "\<\d\+\>"
" floating point number, with dot, optional exponent
syn match chaiscriptFloat "\<\d\+\.\d*\%(e[-+]\=\d\+\)\=\>"
" floating point number, starting with a dot, optional exponent
syn match chaiscriptFloat "\.\d\+\%(e[-+]\=\d\+\)\=\>"
" floating point number, without dot, with exponent
syn match chaiscriptFloat "\<\d\+e[-+]\=\d\+\>"
" Hex strings
syn match chaiscriptNumber "\<0x\x\+\>"
" Binary strings
syn match chaiscriptNumber "\<0b[01]\+\>"
" Various language features
syn keyword chaiscriptCond if else
syn keyword chaiscriptRepeat while for do
syn keyword chaiscriptStatement break continue return switch case default
syn keyword chaiscriptExceptions try catch throw
"Keyword
syn keyword chaiscriptKeyword def true false attr
"Built in types
syn keyword chaiscriptType fun var auto
"Built in funcs, keep it simple
syn keyword chaiscriptFunc eval throw
"Let's treat all backtick operator function lookups as built in too
syn region chaiscriptFunc matchgroup=chaiscriptFunc start="`" end="`"
" Account for the "[1..10]" syntax, treating it as an operator
" Intentionally leaving out all of the normal, well known operators
syn match chaiscriptOperator "\.\."
" Guard seperator as an operator
syn match chaiscriptOperator ":"
" Comments
syn match chaiscriptComment "//.*$" contains=@Spell
syn region chaiscriptComment matchgroup=chaiscriptComment start="/\*" end="\*/" contains=@Spell
hi def link chaiscriptExceptions Exception
hi def link chaiscriptKeyword Keyword
hi def link chaiscriptStatement Statement
hi def link chaiscriptRepeat Repeat
hi def link chaiscriptString String
hi def link chaiscriptNumber Number
hi def link chaiscriptFloat Float
hi def link chaiscriptOperator Operator
hi def link chaiscriptConstant Constant
hi def link chaiscriptCond Conditional
hi def link chaiscriptFunction Function
hi def link chaiscriptComment Comment
hi def link chaiscriptTodo Todo
hi def link chaiscriptError Error
hi def link chaiscriptSpecial SpecialChar
hi def link chaiscriptFunc Identifier
hi def link chaiscriptType Type
hi def link chaiscriptEval Special
let b:current_syntax = "chaiscript"
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: nowrap sw=2 sts=2 ts=8 noet

1
description.txt Normal file
View File

@@ -0,0 +1 @@
ChaiScript is a header-only C++ embedded scripting language loosely based on ECMA script. It is designed for ease of use and tight integration with C++. See http://www.chaiscript.com for more details.

View File

@@ -1,135 +1,805 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_ #ifndef CHAISCRIPT_HPP_
#define CHAISCRIPT_HPP_ #define CHAISCRIPT_HPP_
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <stdexcept>
#include <iostream> /// @mainpage
#include <map> /// [ChaiScript](http://www.chaiscript.com") is a scripting language designed specifically for integration with C++. It provides
#include <fstream> /// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
#include <boost/shared_ptr.hpp> ///
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
/// chaiscript namespace and the chaiscript::ChaiScript class.
///
/// The end user parts of the API are extremely simple both in size and ease of use.
///
/// Currently, all source control and project management aspects of ChaiScript occur on [github](http://www.github.com/ChaiScript/ChaiScript").
///
/// ------------------------------------------------------------
///
/// @sa chaiscript
/// @sa chaiscript::ChaiScript
/// @sa ChaiScript_Language for Built in Functions
/// @sa @ref LangGettingStarted
/// @sa @ref LangKeywordRef
/// @sa @ref LangInPlaceRef
/// @sa @ref LangObjectSystemRef
/// @sa http://www.chaiscript.com
/// @sa http://www.github.com/ChaiScript/ChaiScript
///
/// -----------------------------------------------------------
///
/// @section gettingstarted API Getting Started
///
/// - @ref basics
/// - @ref compiling
/// - @ref eval
/// - @ref adding_items
/// - @ref operatoroverloading
/// - @ref add_class
/// - @ref pointer_conversions
/// - @ref baseclasses
/// - @ref functionobjects
/// - @ref threading
/// - @ref exceptions
///
///
/// @subsection basics Basics
///
/// Basic simple example:
///
/// ~~~~~~~{.cpp}
/// //main.cpp
/// #include <chaiscript/chaiscript.hpp>
///
/// double function(int i, double j)
/// {
/// return i * j;
/// }
///
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(&function, "function");
///
/// double d = chai.eval<double>("function(3, 4.75);");
/// }
/// ~~~~~~~
///
/// ------------------------------------------------------
///
/// @subsection compiling Compiling ChaiScript Applications
///
/// ChaiScript is a header only library with only one dependency: The
/// operating system provided dynamic library loader, which has to be specified on some platforms.
///
/// @subsubsection compilinggcc Compiling with GCC
///
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
/// the dynamic loader. For example:
///
/// ~~~~~~~~
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
/// ~~~~~~~~
///
/// Alternatively, you may compile without threading support.
///
/// ~~~~~~~~
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -DCHAISCRIPT_NO_THREADS
/// ~~~~~~~~
///
/// ------------------------------------------
///
/// @subsection eval Evaluating Scripts
///
/// Scripts can be evaluated with the () operator, eval method or eval_file method.
///
/// @subsubsection parenoperator () Operator
///
/// operator() can be used as a handy shortcut for evaluating ChaiScript snippets.
///
/// ~~~~~~~~{.cpp}
/// chaiscript::ChaiScript chai;
/// chai("print(@"hello world@")");
/// ~~~~~~~~
///
/// @sa chaiscript::ChaiScript::operator()(const std::string &)
///
/// @subsubsection evalmethod Method 'eval'
///
/// The eval method is somewhat more verbose and can be used to get type safely return values
/// from the script.
///
/// ~~~~~~~~{.cpp}
/// chaiscript::ChaiScript chai;
/// chai.eval("callsomefunc()");
/// int result = chai.eval<int>("1 + 3");
/// // result now equals 4
/// ~~~~~~~~
///
/// @sa chaiscript::ChaiScript::eval
///
/// @subsubsection evalfilemethod Method 'eval_file'
///
/// The 'eval_file' method loads a file from disk and executes the script in it
///
/// ~~~~~~~~{.cpp}
/// chaiscript::ChaiScript chai;
/// chai.eval_file("myfile.chai");
/// std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
/// ~~~~~~~~
///
/// @sa chaiscript::ChaiScript::eval_file
///
/// --------------------------------------------------
///
/// @subsection adding_items Adding Items to ChaiScript
///
/// ChaiScript supports 4 basic things that can be added: objects, functions, type infos and Modules
///
/// @subsubsection adding_objects Adding Objects
///
/// Named objects can be created with the chaiscript::var function. Note: adding a object
/// adds it to the current thread scope, not to a global scope. If you have multiple
/// threads that need to access the same variables you will need to add them
/// separately for each thread, from the thread itself.
///
/// ~~~~~~~~~{.cpp}
/// using namespace chaiscript;
/// ChaiScript chai;
/// int i = 5;
/// chai.add(var(i), "i");
/// chai("print(i)");
/// ~~~~~~~~~
///
/// Immutable objects can be created with the chaiscript::const_var function.
///
/// ~~~~~~~~~{.cpp}
/// chai.add(const_var(i), "i");
/// chai("i = 5"); // exception throw, cannot assign const var
/// ~~~~~~~~~
///
/// Named variables can only be accessed from the context they are created in.
/// If you want a global variable, it must be const, and created with the
/// chaiscript::ChaiScript::add_global_const function.
///
/// ~~~~~~~~~{.cpp}
/// chai.add_global_const(const_var(i), "i");
/// chai("def somefun() { print(i); }; sumfun();");
/// ~~~~~~~~~
///
/// @subsubsection adding_functions Adding Functions
///
/// Functions, methods and members are all added using the same function: chaiscript::fun.
///
/// ~~~~~~~~~{.cpp}
/// using namespace chaiscript;
///
/// class MyClass {
/// public:
/// int memberdata;
/// void method();
/// void method2(int);
/// static void staticmethod();
/// void overloadedmethod();
/// void overloadedmethod(const std::string &);
/// };
///
/// ChaiScript chai;
/// chai.add(fun(&MyClass::memberdata), "memberdata");
/// chai.add(fun(&MyClass::method), "method");
/// chai.add(fun(&MyClass::staticmethod), "staticmethod");
/// ~~~~~~~~~
///
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
///
/// ~~~~~~~~~{.cpp}
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod");
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod), "overloadedmethod");
/// ~~~~~~~~~
///
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
///
/// ~~~~~~~~~{.cpp}
/// MyClass obj;
/// chai.add(fun(&MyClass::method, &obj), "method");
/// chai("method()"); // equiv to obj.method()
/// chai.add(fun(&MyClass::method2, &obj, 3), "method2");
/// chai("method2()"); // equiv to obj.method2(3)
/// ~~~~~~~~~
///
/// @subsubsection addingtypeinfo Adding Type Info
///
/// ChaiScript will automatically support any type implicitly provided to it in the form
/// of objects and function parameters / return types. However, it can be nice to let ChaiScript
/// know more details about the types you are giving it. For instance, the "clone" functionality
/// cannot work unless there is a copy constructor registered and the name of the type is known
/// (so that ChaiScript can look up the copy constructor).
///
/// Continuing with the example "MyClass" from above:
///
/// ~~~~~~~~{.cpp}
/// chai.add(user_type<MyClass>(), "MyClass");
/// ~~~~~~~~
///
/// @subsubsection adding_modules Adding Modules
///
/// Modules are holders for collections of ChaiScript registrations.
///
/// ~~~~~~~~{.cpp}
/// ModulePtr module = get_sum_module();
/// chai.add(module);
/// ~~~~~~~~
///
/// @sa chaiscript::Module
///
/// -----------------------------------------------------------------------
///
/// @subsection operatoroverloading Operator Overloading
///
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
///
/// ~~~~~~~~{.cpp}
/// class MyClass {
/// MyClass operator+(const MyClass &) const;
/// };
///
/// chai.add(fun(&MyClass::operator+), "+");
///
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
/// {
/// std::stringstream ss;
/// ss << t_lhs << t_rhs;
/// return ss.str();
/// }
///
/// chai.add(fun(append_string_int), "+");
/// ~~~~~~~~
///
/// @sa @ref adding_functions
///
/// -----------------------------------------------------------------------
///
/// @subsection add_class Class Helper Utility
///
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
/// of the add_class helper utility.
///
/// ~~~~~~~~{.cpp}
/// class Test
/// {
/// public:
/// void function() {}
/// std::string function2() { return "Function2"; }
/// void function3() {}
/// std::string functionOverload(double) { return "double"; }
/// std::string functionOverload(int) { return "int"; }
/// };
///
/// int main()
/// {
/// chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
///
/// chaiscript::utility::add_class<chaiscript::Test>(*m,
/// "Test",
/// { constructor<Test()>(),
/// constructor<Test(const Test &)>() },
/// { {fun(&Test::function), "function"},
/// {fun(&Test::function2), "function2"},
/// {fun(&Test::function2), "function3"}
/// {fun(static_cast<std::string Test::*(double)>(&Test::functionOverload)), "functionOverload"}
/// {fun(static_cast<std::string Test::*(int)>(&Test::functionOverload)), "functionOverload"} }
/// );
///
///
/// chaiscript::ChaiScript chai;
/// chai.add(m);
/// }
/// ~~~~~~~~
///
/// @sa @ref adding_modules
///
/// -----------------------------------------------------------------------
///
/// @subsection pointer_conversions Pointer / Object Conversions
///
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
///
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted to a shared_ptr (this would add invalid reference counting).
/// Const may be added, but never removed.
///
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
///
/// ~~~~~~~~{.cpp}
/// void fun1(const int *);
/// void fun2(int *);
/// void fun3(int);
/// void fun4(int &);
/// void fun5(const int &);
/// void fun5(std::shared_ptr<int>);
/// void fun6(std::shared_ptr<const int>);
/// void fun7(const std::shared_ptr<int> &);
/// void fun8(const std::shared_ptr<const int> &);
/// void fun9(std::reference_wrapper<int>);
/// void fun10(std::reference_wrapper<const int>);
///
/// int main()
/// {
/// using namespace chaiscript
/// chaiscript::ChaiScript chai;
/// chai.add(fun(fun1), "fun1");
/// chai.add(fun(fun2), "fun2");
/// chai.add(fun(fun3), "fun3");
/// chai.add(fun(fun4), "fun4");
/// chai.add(fun(fun5), "fun5");
/// chai.add(fun(fun6), "fun6");
/// chai.add(fun(fun7), "fun7");
/// chai.add(fun(fun8), "fun8");
/// chai.add(fun(fun9), "fun9");
/// chai.add(fun(fun10), "fun10");
///
/// chai("var i = 10;");
/// chai("fun1(i)");
/// chai("fun2(i)");
/// chai("fun3(i)");
/// chai("fun4(i)");
/// chai("fun5(i)");
/// chai("fun6(i)");
/// chai("fun7(i)");
/// chai("fun8(i)");
/// chai("fun9(i)");
/// chai("fun10(i)");
/// }
/// ~~~~~~~~
///
/// See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that
/// available and tested.
///
/// -----------------------------------------------------------------------
///
/// @subsection baseclasses Base Classes
///
/// ChaiScript supports handling of passing a derived class object to a function expecting a base class object.
/// For the process to work, the base/derived relationship must be registered with the engine.
///
/// ~~~~~~~~{.cpp}
/// class Base {};
/// class Derived : public Base {};
/// void myfunction(Base *b);
///
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<Base, Derived>());
/// Derived d;
/// chai.add(chaiscript::var(&d), "d");
/// chai.add(chaiscript::fun(&myfunction), "myfunction");
/// chai("myfunction(d)");
/// }
/// ~~~~~~~~
///
/// -----------------------------------------------------------------------
///
///
/// @subsection functionobjects Function Objects
///
/// Functions are first class objects in ChaiScript and ChaiScript supports automatic conversion
/// between ChaiScript functions and std::function objects.
///
/// ~~~~~~~~{.cpp}
/// void callafunc(const std::function<void (const std::string &)> &t_func)
/// {
/// t_func("bob");
/// }
///
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::fun(&callafunc), "callafunc");
/// chai("callafunc(fun(x) { print(x); })"); // pass a lambda function to the registered function
/// // which expects a typed std::function
///
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
/// f(); // call the ChaiScript function dump_system, from C++
/// }
/// ~~~~~~~~
///
/// -----------------------------------------------------------------------
///
///
/// @subsection threading Threading
///
/// Thread safety is automatically handled within the ChaiScript system. Objects can be added
/// and scripts executed from multiple threads. For each thread that executes scripts, a new
/// context is created and managed by the engine.
///
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
///
/// Disabling thread safety increases performance in many cases.
///
/// -----------------------------------------------------------------------
///
///
/// @subsection exceptions Exception Handling
///
/// @subsubsection exceptionsbasics Exception Handling Basics
///
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
/// ChaiScript.
///
/// ~~~~~~~~{.cpp}
/// void throwexception()
/// {
/// throw std::runtime_error("err");
/// }
///
/// int main()
/// {
/// // Throw in C++, catch in ChaiScript
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
///
/// // Throw in ChaiScript, catch in C++
/// try {
/// chai("throw(1)");
/// } catch (chaiscript::Boxed_Value bv) {
/// int i = chaiscript::boxed_cast<int>(bv);
/// // i == 1
/// }
/// }
/// ~~~~~~~~
///
/// @subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
///
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
/// ChaiScript what possible exceptions are expected from the script being executed.
///
/// Example:
/// ~~~~~~~~{.cpp}
/// chaiscript::ChaiScript chai;
///
/// 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
/// }
/// ~~~~~~~~
///
/// @sa chaiscript::Exception_Handler for details on automatic exception unboxing
/// @sa chaiscript::exception_specification
/// @page LangObjectSystemRef ChaiScript Language Object Model Reference
///
///
/// ChaiScript has an object system built in, for types defined within the ChaiScript system.
///
/// ~~~~~~~~~
/// attr Rectangle::height
/// attr Rectangle::width
/// def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
/// def Rectangle::area() { this.height * this.width }
///
/// var rect = Rectangle()
/// rect.height = 30
/// print(rect.area())
/// ~~~~~~~~~
///
/// Since ChaiScript 5.4.0 it has been possible to use the "class" keyword to simplify this code.
///
/// ~~~~~~~~~
/// class Rectangle {
/// attr height
/// attr width
/// def Rectangle() { this.height = 10; this.width = 20 }
/// def area() { this.height * this.width }
/// }
///
/// var rect = Rectangle()
/// rect.height = 30
/// print(rect.area())
/// ~~~~~~~~~
///
/// @sa @ref keywordattr
/// @sa @ref keyworddef
/// @page LangInPlaceRef ChaiScript Language In-Place Creation Reference
/// @section inplacevector Vector
///
/// ~~~~~~~~~
/// In-place Vector ::= "[" [expression ("," expression)*] "]"
/// ~~~~~~~~~
///
/// @section inplacerangedvector Ranged Vector
///
/// ~~~~~~~~~
/// In-place Ranged Vector ::= "[" value ".." value "]"
/// ~~~~~~~~~
///
/// Creates a vector over a range (eg. 1..10)
///
/// @section inplacemap Map
///
/// ~~~~~~~~
/// In-place Map ::= "[" (string ":" expression)+ "]"
/// ~~~~~~~~
/// @page LangGettingStarted ChaiScript Language Getting Started
///
/// ChaiScript is a simple language that should feel familiar to anyone who knows
/// C++ or ECMAScript (JavaScript).
///
/// -----------------------------------------------------------------------
///
/// @section chaiscriptloops Loops
///
/// Common looping constructs exist in ChaiScript
///
/// ~~~~~~~~
/// var i = 0;
/// while (i < 10)
/// {
/// // do something
/// ++i;
/// }
/// ~~~~~~~~
///
/// ~~~~~~~~
/// for (var i = 0; i < 10; ++i)
/// {
/// // do something
/// }
/// ~~~~~~~~
///
/// @sa @ref keywordfor
/// @sa @ref keywordwhile
///
/// -----------------------------------------------------------------------
///
/// @section chaiscriptifs Conditionals
///
/// If statements work as expected
///
/// ~~~~~~~~
/// var b = true;
///
/// if (b) {
/// // do something
/// } else if (c < 10) {
/// // do something else
/// } else {
/// // or do this
/// }
/// ~~~~~~~~
///
/// @sa @ref keywordif
///
/// -----------------------------------------------------------------------
///
/// @section chaiscriptfunctions Functions
///
/// Functions are defined with the def keyword
///
/// ~~~~~~~~
/// def myfun(x) { print(x); }
///
/// myfun(10);
/// ~~~~~~~~
///
/// Functions may have "guards" which determine if which is called.
///
/// ~~~~~~~~
/// eval> def myfun2(x) : x < 10 { print("less than 10"); }
/// eval> def myfun2(x) : x >= 10 { print("10 or greater"); }
/// eval> myfun2(5)
/// less than 10
/// eval> myfun2(12)
/// 10 or greater
/// ~~~~~~~~
///
/// @sa @ref keyworddef
/// @sa @ref keywordattr
/// @sa @ref LangObjectSystemRef
///
/// -----------------------------------------------------------------------
///
/// @section chaiscriptfunctionobjects Function Objects
///
/// Functions are first class types in ChaiScript and can be used as variables.
///
/// ~~~~~~~~
/// eval> var p = print;
/// eval> p(1);
/// 1
/// ~~~~~~~~
///
/// They can also be passed to functions.
///
/// ~~~~~~~~
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
/// eval> def do_something(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
/// eval> callfunc(do_something, 1, 2);
/// lhs: 1, rhs: 2
/// ~~~~~~~~
///
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
///
/// ~~~~~~~~
/// eval> callfunc(`+`, 1, 4);
/// 5
/// eval> callfunc(`*`, 3, 2);
/// 6
/// ~~~~~~~~
///
/// -----------------------------------------------------------------------
///
/// @sa @ref LangKeywordRef
/// @sa ChaiScript_Language for Built in Functions
/// @page LangKeywordRef ChaiScript Language Keyword Reference
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordattr attr
/// Defines a ChaiScript object attribute
///
/// ~~~~~~~~
/// Attribute Definition ::= "attr" class_name "::" attribute_name
/// ~~~~~~~~
///
/// @sa @ref LangObjectSystemRef
///
/// -----------------------------------------------------------------------
///
/// @section keywordbreak break
/// Stops execution of a looping block.
///
/// ~~~~~~~~
/// Break Statement ::= "break"
/// ~~~~~~~~
///
/// @sa @ref keywordfor
/// @sa @ref keywordwhile
///
///
/// -----------------------------------------------------------------------
///
/// @section keyworddef def
/// Begins a function or method definition
///
/// ~~~~~~~~
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [arg ("," arg)*] ")" [":" guard] block
/// ~~~~~~~~
///
/// annotation: meta-annotation on function, currently used as documentation. Optional.
/// identifier: name of function. Required.
/// args: comma-delimited list of parameter names. Optional.
/// guards: guarding statement that act as a prerequisite for the function. Optional.
/// { }: scoped block as function body. Required.
///
/// Functions return values in one of two ways:
///
/// By using an explicit return call, optionally passing the value to be returned.
/// By implicitly returning the value of the last expression (if it is not a while or for loop).
///
/// Method definitions for known types extend those types with new methods. This includes C++ and ChaiScript defined types.
/// Method definitions for unknown types implicitly define the named type.
///
/// @sa @ref LangObjectSystemRef
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordelse else
/// @sa @ref keywordif
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordfor for
/// ~~~~~~~~
/// For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block
/// ~~~~~~~~
/// This loop can be broken using the @ref keywordbreak command.
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordfun fun
/// Begins an anonymous function declaration (sometimes called a lambda).
///
/// ~~~~~~~~
/// Lambda ::= "fun" "(" [variable] ("," variable)* ")" block
/// ~~~~~~~~
///
/// _Example_
///
/// ~~~~~~~~
/// // Generate an anonymous function object that adds 2 to its parameter
/// var f = fun(x) { x + 2; }
/// ~~~~~~~~
///
/// @sa @ref keyworddef for more details on ChaiScript functions
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordif if
/// Begins a conditional block of code that only executes if the condition evaluates as true.
/// ~~~~~~~~
/// If Block ::= "if" "(" condition ")" block
/// Else If Block ::= "else if" "(" condition ")" block
/// Else Block ::= "else" block
/// ~~~~~~~~
///
/// _Example_
///
/// ~~~~~~~~
/// if (true) {
/// // do something
/// } else if (false) {
/// // do something else
/// } else {
/// // otherwise do this
/// }
/// ~~~~~~~~
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordtry try
/// ~~~~~~~~
/// Try Block ::= "try" block
/// ("catch" ["(" variable ")"] [":" guards] block)+
/// ["finally" block]
/// ~~~~~~~~
///
/// @sa ChaiScript_Language::throw
///
/// -----------------------------------------------------------------------
///
/// @section keywordwhile while
///
/// Begins a conditional block of code that loops 0 or more times, as long as the condition is true
///
/// ~~~~~~~~
/// While Block ::= "while" "(" condition ")" block
/// ~~~~~~~~
///
/// This loop can be broken using the @ref keywordbreak command.
/// @namespace chaiscript
/// @brief Namespace chaiscript contains every API call that the average user will be concerned with.
/// @namespace chaiscript::detail
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
#include "chaiscript_defines.hpp"
#include "dispatchkit/dispatchkit.hpp" #include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/function_call.hpp" #include "dispatchkit/function_call.hpp"
namespace chaiscript #include "dispatchkit/dynamic_object.hpp"
{ #include "dispatchkit/boxed_number.hpp"
/**
* Types of AST nodes available to the parser and eval
*/
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Expression, Comparison, Additive, Multiplicative, Negate, Not, 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,
Inline_Range, Annotation }; };
/**
* Helper lookup to get the name of each node type
*/
const char *token_type_to_string(int tokentype) {
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "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",
"Inline_Range", "Annotation"};
return token_types[tokentype];
}
/**
* Convenience type for file positions
*/
struct File_Position {
int line;
int column;
File_Position(int file_line, int file_column)
: line(file_line), column(file_column) { }
File_Position() : line(0), column(0) { }
};
typedef boost::shared_ptr<struct Token> TokenPtr;
/**
* The struct that doubles as both a parser token and an AST node
*/
struct Token {
std::string text;
int identifier;
const char *filename;
File_Position start, end;
std::vector<TokenPtr> children;
TokenPtr annotation;
Token(const std::string &token_text, int id, const char *fname) : text(token_text), identifier(id), filename(fname) { }
Token(const std::string &token_text, int id, const char *fname, int start_line, int start_col, int end_line, int end_col) :
text(token_text), identifier(id), filename(fname) {
start.line = start_line;
start.column = start_col;
end.line = end_line;
end.column = end_col;
}
};
/**
* Errors generated during parsing or evaluation
*/
struct Eval_Error : public std::runtime_error {
std::string reason;
File_Position position;
const char *filename;
Eval_Error(const std::string &why, const File_Position &where, const char *fname) :
std::runtime_error("Error: \"" + why + "\" " +
(std::string(fname) != "__EVAL__" ? ("in '" + std::string(fname) + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(where.line) + ", " +
boost::lexical_cast<std::string>(where.column) + ")"),
reason(why), position(where), filename(fname)
{ }
Eval_Error(const std::string &why, const TokenPtr &where)
: std::runtime_error("Error: \"" + why + "\" " +
(std::string(where->filename) != "__EVAL__" ? ("in '" + std::string(where->filename) + "' ") : "during evaluation ") +
"at (" + boost::lexical_cast<std::string>(where->start.line) + ", " +
boost::lexical_cast<std::string>(where->start.column) + ")"),
reason(why), position(where->start), filename(where->filename) {
}
virtual ~Eval_Error() throw() {}
};
/**
* Special type for returned values
*/
struct Return_Value {
Boxed_Value retval;
TokenPtr location;
Return_Value(const Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
};
/**
* Special type indicating a call to 'break'
*/
struct Break_Loop {
TokenPtr location;
Break_Loop(const TokenPtr where) : location(where) { }
};
}
#include "language/chaiscript_eval.hpp" #include "language/chaiscript_eval.hpp"
#include "language/chaiscript_engine.hpp" #include "language/chaiscript_engine.hpp"
#endif /* CHAISCRIPT_HPP_ */ #endif /* CHAISCRIPT_HPP_ */

View File

@@ -0,0 +1,53 @@
// 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
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
#define CHAISCRIPT_WINDOWS
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
/// 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
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 6;
static const int version_patch = 0;
}
#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

@@ -0,0 +1,235 @@
// 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_THREADING_HPP_
#define CHAISCRIPT_THREADING_HPP_
#include <unordered_map>
#ifndef CHAISCRIPT_NO_THREADS
#include <thread>
#include <mutex>
#else
#pragma message ("ChaiScript is compiling without thread safety.")
#endif
/// \file
///
/// This file contains code necessary for thread support in ChaiScript.
/// If the compiler definition CHAISCRIPT_NO_THREADS is defined then thread safety
/// is disabled in ChaiScript. This has the result that some code is faster, because mutex locks are not required.
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
/// one thread simultaneously.
namespace chaiscript
{
namespace detail
{
/// If threading is enabled, then this namespace contains std thread classes.
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
/// This allows us to avoid \#ifdef code in the sections that need thread safety.
namespace threading
{
#ifndef CHAISCRIPT_NO_THREADS
template<typename T>
class unique_lock : public std::unique_lock<T>
{
public:
unique_lock(T &t) : std::unique_lock<T>(t) {}
};
template<typename T>
class shared_lock : public std::unique_lock<T>
{
public:
shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
template<typename T>
class lock_guard : public std::lock_guard<T>
{
public:
lock_guard(T &t) : std::lock_guard<T>(t) {}
};
class shared_mutex : public std::mutex { };
using std::mutex;
using std::recursive_mutex;
#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.
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *t_key)
: m_key(t_key)
{
}
~Thread_Storage()
{
t().erase(m_key);
}
inline const T *operator->() const
{
return &(t()[m_key]);
}
inline const T &operator*() const
{
return t()[m_key];
}
inline T *operator->()
{
return &(t()[m_key]);
}
inline T &operator*()
{
return t()[m_key];
}
void *m_key;
private:
static std::unordered_map<void*, T> &t()
{
thread_local static std::unordered_map<void *, T> my_t;
return my_t;
}
};
#else
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// This version is used if the compiler does not support thread_local
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *)
{
}
inline 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(new 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>
class unique_lock
{
public:
unique_lock(T &) {}
void lock() {}
void unlock() {}
};
template<typename T>
class shared_lock
{
public:
shared_lock(T &) {}
void lock() {}
void unlock() {}
};
template<typename T>
class lock_guard
{
public:
lock_guard(T &) {}
};
class shared_mutex { };
class recursive_mutex {};
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *)
{
}
inline T *operator->() const
{
return &obj;
}
inline T &operator*() const
{
return obj;
}
private:
mutable T obj;
};
#endif
}
}
}
#endif

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

@@ -0,0 +1,69 @@
// 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_BAD_BOXED_CAST_HPP_
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
#include <string>
#include <typeinfo>
#include "../chaiscript_defines.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Type_Info;
} // namespace chaiscript
namespace chaiscript
{
namespace exception
{
/// \brief Thrown in the event that a Boxed_Value cannot be cast to the desired type
///
/// It is used internally during function dispatch and may be used by the end user.
///
/// \sa chaiscript::boxed_cast
class bad_boxed_cast : public std::bad_cast
{
public:
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
std::string t_what) CHAISCRIPT_NOEXCEPT
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
{
}
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast")
{
}
bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(nullptr), m_what(std::move(t_what))
{
}
bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occurred
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();
}
Type_Info from; ///< Type_Info contained in the Boxed_Value
const std::type_info *to; ///< std::type_info of the desired (but failed) result type
private:
std::string m_what;
};
}
}
#endif

View File

@@ -0,0 +1,79 @@
// 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_BIND_FIRST_HPP_
#define CHAISCRIPT_BIND_FIRST_HPP_
#include <functional>
namespace chaiscript
{
namespace detail
{
struct Placeholder
{
static std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)> placeholder() {
return std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)>(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10);
}
};
template<int count, int maxcount, typename Sig>
struct Bind_First
{
template<typename F, typename ... InnerParams>
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
{
return Bind_First<count - 1, maxcount, Sig>::bind(std::forward<F>(f), innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
}
};
template<int maxcount, typename Sig>
struct Bind_First<0, maxcount, Sig>
{
template<typename F, typename ... InnerParams>
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
{
return std::bind(std::forward<F>(f), innerparams...);
}
};
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(std::function<Ret (P1, Param...)> &&f, O&& o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(std::move(f), std::forward<O>(o));
}
}
}
#endif

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,124 @@
// 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_BOXED_CAST_HPP_
#define CHAISCRIPT_BOXED_CAST_HPP_
#include <type_traits>
#include "../chaiscript_defines.hpp"
#include "../chaiscript_threading.hpp"
#include "bad_boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_conversions.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Type_Conversions;
namespace detail {
namespace exception {
class bad_any_cast;
} // namespace exception
} // namespace detail
} // namespace chaiscript
namespace chaiscript
{
/// \brief Function for extracting a value stored in a Boxed_Value object
/// \tparam Type The type to extract from the Boxed_Value
/// \param[in] bv The Boxed_Value to extract a typed value from
/// \returns Type equivalent to the requested type
/// \throws exception::bad_boxed_cast If the requested conversion is not possible
///
/// boxed_cast will attempt to make conversions between value, &, *, std::shared_ptr, std::reference_wrapper,
/// and std::function (const and non-const) where possible. boxed_cast is used internally during function
/// dispatch. This means that all of these conversions will be attempted automatically for you during
/// ChaiScript function calls.
///
/// \li non-const values can be extracted as const or non-const
/// \li const values can be extracted only as const
/// \li Boxed_Value constructed from pointer or std::reference_wrapper can be extracted as reference,
/// pointer or value types
/// \li Boxed_Value constructed from std::shared_ptr or value types can be extracted as reference,
/// pointer, value, or std::shared_ptr types
///
/// Conversions to std::function objects are attempted as well
///
/// Example:
/// \code
/// // All of the following should succeed
/// chaiscript::Boxed_Value bv(1);
/// std::shared_ptr<int> spi = chaiscript::boxed_cast<std::shared_ptr<int> >(bv);
/// int i = chaiscript::boxed_cast<int>(bv);
/// int *ip = chaiscript::boxed_cast<int *>(bv);
/// int &ir = chaiscript::boxed_cast<int &>(bv);
/// std::shared_ptr<const int> cspi = chaiscript::boxed_cast<std::shared_ptr<const int> >(bv);
/// const int ci = chaiscript::boxed_cast<const int>(bv);
/// const int *cip = chaiscript::boxed_cast<const int *>(bv);
/// const int &cir = chaiscript::boxed_cast<const int &>(bv);
/// \endcode
///
/// std::function conversion example
/// \code
/// chaiscript::ChaiScript chai;
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
/// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
/// int i = f(2,3);
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
{
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
#ifdef CHAISCRIPT_MSVC
//Thank you MSVC, yes we know that a constant value is being used in the if
// statment in THIS VERSION of the template instantiation
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
if (t_conversions && t_conversions->convertable_type<Type>())
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
} 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));
}
}
} else {
// If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
}
}
#endif

View File

@@ -0,0 +1,258 @@
// 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_BOXED_CAST_HELPER_HPP_
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
#include <functional>
#include <memory>
#include <type_traits>
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript
{
class Type_Conversions;
namespace detail
{
// Cast_Helper_Inner helper classes
template<typename T>
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>
struct Cast_Helper_Inner
{
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return *(static_cast<const Result *>(throw_if_null(ob.get_const_ptr())));
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
template<typename Result>
struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
{
};
/// Cast_Helper_Inner for casting to a const & type
template<typename Result>
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
{
};
/// Cast_Helper_Inner for casting to a const * type
template<typename Result>
struct Cast_Helper_Inner<const Result *>
{
typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
if (ob.is_ref())
{
if (!ob.get_type_info().is_const())
{
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else {
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
}
} else {
if (!ob.get_type_info().is_const())
{
return (ob.get().cast<std::shared_ptr<Result> >()).get();
} else {
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
}
}
}
};
/// Cast_Helper_Inner for casting to a * type
template<typename Result>
struct Cast_Helper_Inner<Result *>
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
if (ob.is_ref())
{
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
} else {
return (ob.get().cast<std::shared_ptr<Result> >()).get();
}
}
};
/// Cast_Helper_Inner for casting to a & type
template<typename Result>
struct Cast_Helper_Inner<Result &>
{
typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
template<typename Result>
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
{
typedef typename std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
return ob.get().cast<std::shared_ptr<Result> >();
}
};
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
template<typename Result>
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
{
typedef typename std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
if (!ob.get_type_info().is_const())
{
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
} else {
return ob.get().cast<std::shared_ptr<const Result> >();
}
}
};
/// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
template<typename Result>
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
{
};
template<typename Result>
struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
{
};
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
template<typename Result>
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
{
};
template<typename Result>
struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
{
};
/// Cast_Helper_Inner for casting to a Boxed_Value type
template<>
struct Cast_Helper_Inner<Boxed_Value>
{
typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
return ob;
}
};
/// Cast_Helper_Inner for casting to a Boxed_Value & type
template<>
struct Cast_Helper_Inner<Boxed_Value &>
{
typedef Boxed_Value& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
return const_cast<Boxed_Value &>(ob);
}
};
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
template<>
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
{
};
template<>
struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
{
};
/// Cast_Helper_Inner for casting to a std::reference_wrapper type
template<typename Result>
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{
};
template<typename Result>
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
{
};
template<typename 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
template<typename T>
struct Cast_Helper
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
{
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
}
};
}
}
#endif

View File

@@ -0,0 +1,913 @@
// 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_BOXED_NUMERIC_HPP_
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
#include <cstdint>
#include <sstream>
#include <string>
#include "../language/chaiscript_algebraic.hpp"
#include "any.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Type_Conversions;
} // namespace chaiscript
namespace chaiscript
{
namespace exception
{
struct arithmetic_error : public 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
{
// Due to the nature of generating every possible arithmetic operation, there
// are going to be warnings generated on every platform regarding size and sign,
// this is OK, so we're disabling size/and sign type warnings
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4244 4018 4389 4146 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
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_Number
{
private:
template<typename T>
static void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
{
#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* = 0)
{
}
struct boolean
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::equals:
return const_var(t == u);
case Operators::less_than:
return const_var(t < u);
case Operators::greater_than:
return const_var(t > u);
case Operators::less_than_equal:
return const_var(t <= u);
case Operators::greater_than_equal:
return const_var(t >= u);
case Operators::not_equal:
return const_var(t != u);
default:
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
struct binary
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
{
switch (t_oper)
{
case Operators::assign:
t = u;
break;
case Operators::pre_increment:
++t;
break;
case Operators::pre_decrement:
--t;
break;
case Operators::assign_product:
t *= u;
break;
case Operators::assign_sum:
t += u;
break;
case Operators::assign_quotient:
check_divide_by_zero(u);
t /= u;
break;
case Operators::assign_difference:
t -= u;
break;
default:
throw chaiscript::detail::exception::bad_any_cast();
}
return t_lhs;
}
};
struct binary_int
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
{
switch (t_oper)
{
case Operators::assign_bitwise_and:
t &= u;
break;
case Operators::assign_bitwise_or:
t |= u;
break;
case Operators::assign_shift_left:
t <<= u;
break;
case Operators::assign_shift_right:
t >>= u;
break;
case Operators::assign_remainder:
check_divide_by_zero(u);
t %= u;
break;
case Operators::assign_bitwise_xor:
t ^= u;
break;
default:
throw chaiscript::detail::exception::bad_any_cast();
}
return t_lhs;
}
};
struct const_binary_int
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::shift_left:
return const_var(t << u);
case Operators::shift_right:
return const_var(t >> u);
case Operators::remainder:
check_divide_by_zero(u);
return const_var(t % u);
case Operators::bitwise_and:
return const_var(t & u);
case Operators::bitwise_or:
return const_var(t | u);
case Operators::bitwise_xor:
return const_var(t ^ u);
case Operators::bitwise_complement:
return const_var(~t);
default:
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
struct const_binary
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::sum:
return const_var(t + u);
case Operators::quotient:
check_divide_by_zero(u);
return const_var(t / u);
case Operators::product:
return const_var(t * u);
case Operators::difference:
return const_var(t - u);
case Operators::unary_minus:
return const_var(-t);
case Operators::unary_plus:
return const_var(+t);
default:
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
template<typename LHS, typename RHS, bool Float>
struct Go
{
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
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);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const()) {
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) {
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) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
template<typename LHS, typename RHS>
struct Go<LHS, RHS, true>
{
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
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);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
throw chaiscript::detail::exception::bad_any_cast();
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
throw chaiscript::detail::exception::bad_any_cast();
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
template<typename LHS, bool Float>
static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
const auto &inp_ = t_rhs.get_type_info();
if (inp_ == typeid(int)) {
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(double)) {
return Go<LHS, double, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(float)) {
return Go<LHS, float, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long double)) {
return Go<LHS, long double, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(char)) {
return Go<LHS, char, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {
return Go<LHS, unsigned int, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long)) {
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int8_t)) {
return Go<LHS, std::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int16_t)) {
return Go<LHS, std::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int32_t)) {
return Go<LHS, std::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int64_t)) {
return Go<LHS, std::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint8_t)) {
return Go<LHS, std::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint16_t)) {
return Go<LHS, std::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint32_t)) {
return Go<LHS, std::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint64_t)) {
return Go<LHS, std::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
const Type_Info &inp_ = t_lhs.get_type_info();
if (inp_ == typeid(int)) {
return oper_rhs<int, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(double)) {
return oper_rhs<double, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long double)) {
return oper_rhs<long double, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(float)) {
return oper_rhs<float, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(char)) {
return oper_rhs<char, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {
return oper_rhs<unsigned int, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long)) {
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int8_t)) {
return oper_rhs<std::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int16_t)) {
return oper_rhs<std::int16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int32_t)) {
return oper_rhs<std::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::int64_t)) {
return oper_rhs<std::int64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint8_t)) {
return oper_rhs<std::uint8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint16_t)) {
return oper_rhs<std::uint16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint32_t)) {
return oper_rhs<std::uint32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(std::uint64_t)) {
return oper_rhs<std::uint64_t, false>(t_oper, t_lhs, t_rhs);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename Target, typename Source>
Target get_as_aux() const
{
return static_cast<Target>(*static_cast<const Source *>(bv.get_const_ptr()));
}
template<typename Source>
static std::string to_string_aux(const Boxed_Value &v)
{
std::ostringstream oss;
oss << *static_cast<const Source *>(v.get_const_ptr());
return oss.str();
}
public:
Boxed_Number()
: bv(Boxed_Value(0))
{
}
Boxed_Number(Boxed_Value v)
: bv(std::move(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)
: bv(Boxed_Value(t))
{
validate_boxed_number(bv);
}
Boxed_Number get_as(const Type_Info &inp_) const
{
if (inp_.bare_equal_type_info(typeid(int))) {
return Boxed_Number(get_as<int>());
} else if (inp_.bare_equal_type_info(typeid(double))) {
return Boxed_Number(get_as<double>());
} else if (inp_.bare_equal_type_info(typeid(float))) {
return Boxed_Number(get_as<float>());
} else if (inp_.bare_equal_type_info(typeid(long double))) {
return Boxed_Number(get_as<long double>());
} else if (inp_.bare_equal_type_info(typeid(char))) {
return Boxed_Number(get_as<char>());
} else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
return Boxed_Number(get_as<unsigned int>());
} else if (inp_.bare_equal_type_info(typeid(long))) {
return Boxed_Number(get_as<long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
return Boxed_Number(get_as<unsigned long>());
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
return Boxed_Number(get_as<int8_t>());
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {
return Boxed_Number(get_as<int16_t>());
} else if (inp_.bare_equal_type_info(typeid(int32_t))) {
return Boxed_Number(get_as<int32_t>());
} else if (inp_.bare_equal_type_info(typeid(int64_t))) {
return Boxed_Number(get_as<int64_t>());
} else if (inp_.bare_equal_type_info(typeid(uint8_t))) {
return Boxed_Number(get_as<uint8_t>());
} else if (inp_.bare_equal_type_info(typeid(uint16_t))) {
return Boxed_Number(get_as<uint16_t>());
} else if (inp_.bare_equal_type_info(typeid(uint32_t))) {
return Boxed_Number(get_as<uint32_t>());
} else if (inp_.bare_equal_type_info(typeid(uint64_t))) {
return Boxed_Number(get_as<uint64_t>());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename Target> Target get_as() const
{
const Type_Info &inp_ = bv.get_type_info();
if (inp_ == typeid(int)) {
return get_as_aux<Target, int>();
} else if (inp_ == typeid(double)) {
return get_as_aux<Target, double>();
} else if (inp_ == typeid(float)) {
return get_as_aux<Target, float>();
} else if (inp_ == typeid(long double)) {
return get_as_aux<Target, long double>();
} else if (inp_ == typeid(char)) {
return get_as_aux<Target, char>();
} else if (inp_ == typeid(unsigned int)) {
return get_as_aux<Target, unsigned int>();
} else if (inp_ == typeid(long)) {
return get_as_aux<Target, long>();
} else if (inp_ == typeid(unsigned long)) {
return get_as_aux<Target, unsigned long>();
} else if (inp_ == typeid(std::int8_t)) {
return get_as_aux<Target, std::int8_t>();
} else if (inp_ == typeid(std::int16_t)) {
return get_as_aux<Target, std::int16_t>();
} else if (inp_ == typeid(std::int32_t)) {
return get_as_aux<Target, std::int32_t>();
} else if (inp_ == typeid(std::int64_t)) {
return get_as_aux<Target, std::int64_t>();
} else if (inp_ == typeid(std::uint8_t)) {
return get_as_aux<Target, std::uint8_t>();
} else if (inp_ == typeid(std::uint16_t)) {
return get_as_aux<Target, std::uint16_t>();
} else if (inp_ == typeid(std::uint32_t)) {
return get_as_aux<Target, std::uint32_t>();
} else if (inp_ == typeid(std::uint64_t)) {
return get_as_aux<Target, std::uint64_t>();
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
std::string to_string() const
{
const Type_Info &inp_ = bv.get_type_info();
if (inp_ == typeid(int)) {
return to_string_aux<int>(bv);
} else if (inp_ == typeid(double)) {
return to_string_aux<double>(bv);
} else if (inp_ == typeid(float)) {
return to_string_aux<float>(bv);
} else if (inp_ == typeid(long double)) {
return to_string_aux<long double>(bv);
} else if (inp_ == typeid(char)) {
return to_string_aux<int>(Boxed_Value(get_as_aux<int, char>()));
} else if (inp_ == typeid(unsigned int)) {
return to_string_aux<unsigned int>(bv);
} else if (inp_ == typeid(long)) {
return to_string_aux<long>(bv);
} else if (inp_ == typeid(unsigned long)) {
return to_string_aux<unsigned long>(bv);
} else if (inp_ == typeid(std::int8_t)) {
return to_string_aux<int>(Boxed_Value(get_as_aux<int, std::int8_t>()));
} else if (inp_ == typeid(std::int16_t)) {
return to_string_aux<std::int16_t>(bv);
} else if (inp_ == typeid(std::int32_t)) {
return to_string_aux<std::int32_t>(bv);
} else if (inp_ == typeid(std::int64_t)) {
return to_string_aux<std::int64_t>(bv);
} else if (inp_ == typeid(std::uint8_t)) {
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, std::uint8_t>()));
} else if (inp_ == typeid(std::uint16_t)) {
return to_string_aux<std::uint16_t>(bv);
} else if (inp_ == typeid(std::uint32_t)) {
return to_string_aux<std::uint32_t>(bv);
} else if (inp_ == typeid(std::uint64_t)) {
return to_string_aux<std::uint64_t>(bv);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
bool operator==(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
}
bool operator<(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
}
bool operator>(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
}
bool operator>=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
}
bool operator<=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
}
bool operator!=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
}
Boxed_Number operator--()
{
return oper(Operators::pre_decrement, this->bv, var(0));
}
Boxed_Number operator++()
{
return oper(Operators::pre_increment, this->bv, var(0));
}
Boxed_Number operator+(const Boxed_Number &t_rhs) const
{
return oper(Operators::sum, this->bv, t_rhs.bv);
}
Boxed_Number operator+() const
{
return oper(Operators::unary_plus, this->bv, Boxed_Value(0));
}
Boxed_Number operator-() const
{
return oper(Operators::unary_minus, this->bv, Boxed_Value(0));
}
Boxed_Number operator-(const Boxed_Number &t_rhs) const
{
return oper(Operators::difference, this->bv, t_rhs.bv);
}
Boxed_Number operator&=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
}
static void validate_boxed_number(const Boxed_Value &v)
{
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool))
{
throw chaiscript::detail::exception::bad_any_cast();
}
if (!inp_.is_arithmetic())
{
throw chaiscript::detail::exception::bad_any_cast();
}
}
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Value &v)
{
validate_boxed_number(v);
bv = v;
return *this;
}
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Number &t_rhs) const
{
return oper(Operators::assign, this->bv, t_rhs.bv);
}
Boxed_Number operator|=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator^=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator%=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
}
Boxed_Number operator&(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator~() const
{
return oper(Operators::bitwise_complement, this->bv, Boxed_Value(0));
}
Boxed_Number operator^(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator|(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator*=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, this->bv, t_rhs.bv);
}
Boxed_Number operator/=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator+=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
}
Boxed_Number operator-=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
}
Boxed_Number operator/(const Boxed_Number &t_rhs) const
{
return oper(Operators::quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator*(const Boxed_Number &t_rhs) const
{
return oper(Operators::product, this->bv, t_rhs.bv);
}
Boxed_Number operator%(const Boxed_Number &t_rhs) const
{
return oper(Operators::remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_right, this->bv, t_rhs.bv);
}
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
}
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
{
return oper(Operators::pre_decrement, t_lhs.bv, var(0));
}
static Boxed_Number pre_increment(Boxed_Number t_lhs)
{
return oper(Operators::pre_increment, t_lhs.bv, var(0));
}
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_plus, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_minus, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
{
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
}
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
return oper(t_oper, t_lhs, t_rhs);
}
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
{
return oper(t_oper, t_lhs, const_var(0));
}
Boxed_Value bv;
};
namespace detail
{
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
template<>
struct Cast_Helper<Boxed_Number>
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
{
return Boxed_Number(ob);
}
};
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
template<>
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
{
};
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
template<>
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
{
};
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
#endif

View File

@@ -1,89 +1,46 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef __boxed_value_hpp__ #ifndef CHAISCRIPT_BOXED_VALUE_HPP_
#define __boxed_value_hpp__ #define CHAISCRIPT_BOXED_VALUE_HPP_
#include "type_info.hpp" #include <functional>
#include <map> #include <map>
#include <boost/shared_ptr.hpp> #include <memory>
#include <boost/any.hpp> #include <type_traits>
#include <boost/function.hpp>
#include <boost/ref.hpp> #include "../chaiscript_threading.hpp"
#include <boost/bind.hpp> #include "../chaiscript_defines.hpp"
#include <boost/cstdint.hpp> #include "any.hpp"
#include <boost/type_traits/add_const.hpp> #include "type_info.hpp"
namespace chaiscript namespace chaiscript
{ {
/**
* Boxed_Value is the main tool of the dispatchkit. It allows /// \brief A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects
* for boxed / untyped containment of any C++ object. It uses /// \sa chaiscript::boxed_cast
* boost::any internally but also provides user access the underlying
* stored type information
*/
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
{ {
/**
* used to provide type-erased access to the internal boost::shared_ptr
* reference count information
*/
struct Shared_Ptr_Proxy
{
virtual ~Shared_Ptr_Proxy()
{
}
virtual bool unique(boost::any *) = 0;
virtual long use_count(boost::any *) = 0;
};
/**
* Typed implementation of the Shared_Ptr_Proxy
*/
template<typename T>
struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
{
virtual ~Shared_Ptr_Proxy_Impl()
{
}
virtual bool unique(boost::any *a)
{
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
return ptr->unique();
}
virtual long use_count(boost::any *a)
{
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
return ptr->use_count();
}
};
Data(const Type_Info &ti, Data(const Type_Info &ti,
const boost::any &to, chaiscript::detail::Any to,
bool tr, bool tr,
const boost::shared_ptr<Shared_Ptr_Proxy> &t_proxy = boost::shared_ptr<Shared_Ptr_Proxy>()) const void *t_void_ptr)
: m_type_info(ti), m_obj(to), : 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_ptr_proxy(t_proxy) m_is_ref(tr)
{ {
} }
@@ -92,624 +49,337 @@ namespace chaiscript
m_type_info = rhs.m_type_info; m_type_info = rhs.m_type_info;
m_obj = rhs.m_obj; m_obj = rhs.m_obj;
m_is_ref = rhs.m_is_ref; m_is_ref = rhs.m_is_ref;
m_ptr_proxy = rhs.m_ptr_proxy; m_data_ptr = rhs.m_data_ptr;
m_const_data_ptr = rhs.m_const_data_ptr;
if (rhs.m_attrs)
{
m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*rhs.m_attrs));
}
return *this; return *this;
} }
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;
const void *m_const_data_ptr;
std::unique_ptr<std::map<std::string, Boxed_Value>> m_attrs;
bool m_is_ref; bool m_is_ref;
boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy;
}; };
/** struct Object_Data
* Cache of all created objects in the dispatch kit. Used to return the
* same shared_ptr if the same object is created more than once.
* Also used for acquiring a shared_ptr of a reference object, if the
* value of the shared_ptr is known
*/
struct Object_Cache
{ {
Object_Cache() static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
: m_cullcount(0)
{ {
} return std::make_shared<Data>(
boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
{
return boost::shared_ptr<Data> (new Data(
detail::Get_Type_Info<void>::get(), detail::Get_Type_Info<void>::get(),
boost::any(), chaiscript::detail::Any(),
false) false,
); nullptr)
;
} }
template<typename T> template<typename T>
boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj) static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
{ {
return get(*obj); return get(*obj);
} }
template<typename T> template<typename T>
boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj) static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
{ {
boost::shared_ptr<Data> data(new 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,
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>())) obj.get()
); );
std::map<const void *, Data>::iterator itr
= m_ptrs.find(obj.get());
if (itr != m_ptrs.end())
{
(*data) = (itr->second);
} else {
m_ptrs.insert(std::make_pair(obj.get(), *data));
}
return data;
} }
template<typename T> template<typename T>
boost::shared_ptr<Data> get(T *t) static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj)
{ {
return get(boost::ref(*t)); auto ptr = obj.get();
} return std::make_shared<Data>(
template<typename T>
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
{
boost::shared_ptr<Data> data(new Data(
detail::Get_Type_Info<T>::get(), detail::Get_Type_Info<T>::get(),
boost::any(obj), chaiscript::detail::Any(std::move(obj)),
true)
);
std::map<const void *, Data >::iterator itr
= m_ptrs.find(obj.get_pointer());
// If the ptr is found in the cache and it is the correct type,
// return it. It may be the incorrect type when two variables share the
// same memory location. Example:
// struct test { int x; };
// test t;
// Both t and t.x share the same memory location, but do not represent
// objects of the same type.
if (itr != m_ptrs.end()
&& itr->second.m_type_info.m_bare_type_info == data->m_type_info.m_bare_type_info)
{
(*data) = (itr->second);
}
return data;
}
template<typename T>
boost::shared_ptr<Data> get(const T& t)
{
boost::shared_ptr<Data> data(new Data(
detail::Get_Type_Info<T>::get(),
boost::any(boost::shared_ptr<T>(new T(t))),
false, false,
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>())) ptr
); );
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj);
m_ptrs.insert(std::make_pair(ptr->get(), *data));
return data;
} }
boost::shared_ptr<Data> get() template<typename T>
static std::shared_ptr<Data> get(T *t)
{
return get(std::ref(*t));
}
template<typename T>
static std::shared_ptr<Data> get(const T *t)
{
return get(std::cref(*t));
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
{
auto p = &obj.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
true,
p
);
}
template<typename T>
static std::shared_ptr<Data> get(T t)
{
auto p = std::make_shared<T>(std::move(t));
auto ptr = p.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(p)),
false,
ptr
);
}
static std::shared_ptr<Data> get()
{ {
return boost::shared_ptr<Data> (new Data( return std::make_shared<Data>(
Type_Info(), Type_Info(),
boost::any(), chaiscript::detail::Any(),
false) false,
nullptr
); );
} }
/**
* Drop objects from the cache where there is only one (ie, our)
* reference to it, so it may be destructed
*/
void cull()
{
++m_cullcount;
if (m_cullcount % 10 != 0)
{
return;
}
std::map<const void *, Data >::iterator itr = m_ptrs.begin();
while (itr != m_ptrs.end())
{
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
{
std::map<const void *, Data >::iterator todel = itr;
++itr;
m_ptrs.erase(todel);
} else {
++itr;
}
}
}
std::map<const void *, Data > m_ptrs;
int m_cullcount;
}; };
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)
explicit Boxed_Value(T t) : m_data(Object_Data::get(std::forward<T>(t)))
: m_data(get_object_cache().get(t))
{ {
get_object_cache().cull();
} }
/** /// 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(get_object_cache().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)
{ {
std::swap(m_data, rhs.m_data);
} }
/** /// Copy the values stored in rhs.m_data to m_data.
* Return a reference to the static global Object_Cache /// m_data pointers are not shared in this case
*/
Object_Cache &get_object_cache()
{
static Object_Cache oc;
return oc;
}
/**
* copy the values stored in rhs.m_data to m_data
* m_data pointers are not shared in this case
*/
Boxed_Value assign(const Boxed_Value &rhs) 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)
{
m_data = rhs.m_data;
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_unknown() const
{ {
return m_data->m_type_info.m_is_unknown; return m_data->m_type_info.is_undef();
} }
boost::any get() const bool is_const() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.is_const();
}
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.bare_equal(ti);
}
bool is_null() const CHAISCRIPT_NOEXCEPT
{
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
}
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;
} }
private: bool is_pointer() const CHAISCRIPT_NOEXCEPT
boost::shared_ptr<Data> m_data;
};
namespace detail
{
// Cast_Helper helper classes
/**
* Generic Cast_Helper, for casting to any type
*/
template<typename Result>
struct Cast_Helper
{
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().m_is_const)
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
} else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
}
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
}
}
};
/**
* Cast_Helper for casting to a const & type
*/
template<typename Result>
struct Cast_Helper<const Result &>
{
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().m_is_const)
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
} else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
}
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
}
}
};
/**
* Cast_Helper for casting to a const * type
*/
template<typename Result>
struct Cast_Helper<const Result *>
{
typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
if (!ob.get_type_info().m_is_const)
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
} else {
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
}
} else {
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
}
}
};
/**
* Cast_Helper for casting to a * type
*/
template<typename Result>
struct Cast_Helper<Result *>
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
} else {
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
}
}
};
/**
* Cast_Helper for casting to a & type
*/
template<typename Result>
struct Cast_Helper<Result &>
{
typedef typename boost::reference_wrapper<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.is_ref())
{
return boost::any_cast<boost::reference_wrapper<Result> >(ob.get());
} else {
return boost::ref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
}
}
};
/**
* Cast_Helper for casting to a boost::shared_ptr<> type
*/
template<typename Result>
struct Cast_Helper<typename boost::shared_ptr<Result> >
{
typedef typename boost::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
}
};
/**
* Cast_Helper for casting to a boost::shared_ptr<> type
*/
template<typename Result>
struct Cast_Helper<const boost::shared_ptr<Result> &>
{
typedef typename boost::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
}
};
/**
* Cast_Helper for casting to a Boxed_Value type
*/
template<>
struct Cast_Helper<Boxed_Value>
{
typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return ob;
}
};
/**
* Cast_Helper for casting to a const Boxed_Value & type
*/
template<>
struct Cast_Helper<const Boxed_Value &>
{
typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return ob;
}
};
}
/**
* class that is thrown in the event of a bad_boxed_cast. That is,
* in the case that a Boxed_Value cannot be cast to the desired type
*/
class bad_boxed_cast : public std::bad_cast
{
public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
: from(t_from.m_type_info), to(&t_to), m_what("Cannot perform boxed_cast")
{ {
return !is_ref();
} }
bad_boxed_cast(const std::string &w) throw() void *get_ptr() const CHAISCRIPT_NOEXCEPT
: m_what(w)
{ {
return m_data->m_data_ptr;
} }
virtual ~bad_boxed_cast() throw() {} const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
virtual const char * what () throw()
{ {
return m_what.c_str(); return m_data->m_const_data_ptr;
}
Boxed_Value get_attr(const std::string &t_name)
{
if (!m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>());
}
return (*m_data->m_attrs)[t_name];
}
Boxed_Value &copy_attrs(const Boxed_Value &t_obj)
{
if (t_obj.m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*t_obj.m_data->m_attrs));
}
return *this;
}
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
{
return l.get_type_info() == r.get_type_info();
} }
const std::type_info *from;
const std::type_info *to;
private: private:
std::string m_what; std::shared_ptr<Data> m_data;
}; };
/** /// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
* boxed_cast function for casting a Boxed_Value into a given type /// a copy is not made.
* example: /// @param t The value to box
* int &i = boxed_cast<int &>(boxedvalue); ///
*/ /// Example:
template<typename Type> ///
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) /// ~~~{.cpp}
{ /// int i;
try { /// chaiscript::ChaiScript chai;
return detail::Cast_Helper<Type>::cast(bv); /// chai.add(chaiscript::var(i), "i");
} catch (const boost::bad_any_cast &) { /// chai.add(chaiscript::var(&i), "ip");
throw bad_boxed_cast(bv.get_type_info(), typeid(Type)); /// ~~~
} ///
} /// @sa @ref adding_objects
/**
* Object which attempts to convert a Boxed_Value into a generic
* POD type and provide generic POD type operations
*/
struct Boxed_POD_Value
{
Boxed_POD_Value(const Boxed_Value &v)
: d(0), i(0), m_isfloat(false)
{
if (!v.get_type_info().m_type_info)
{
throw boost::bad_any_cast();
}
const std::type_info &inp_ = *v.get_type_info().m_type_info;
if (inp_ == typeid(double))
{
d = boxed_cast<double>(v);
m_isfloat = true;
} else if (inp_ == typeid(float)) {
d = boxed_cast<float>(v);
m_isfloat = true;
} else if (inp_ == typeid(bool)) {
i = boxed_cast<bool>(v);
} else if (inp_ == typeid(char)) {
i = boxed_cast<char>(v);
} else if (inp_ == typeid(int)) {
i = boxed_cast<int>(v);
} else if (inp_ == typeid(unsigned int)) {
i = boxed_cast<unsigned int>(v);
} else if (inp_ == typeid(long)) {
i = boxed_cast<long>(v);
} else if (inp_ == typeid(unsigned long)) {
i = boxed_cast<unsigned long>(v);
} else if (inp_ == typeid(boost::int8_t)) {
i = boxed_cast<boost::int8_t>(v);
} else if (inp_ == typeid(boost::int16_t)) {
i = boxed_cast<boost::int16_t>(v);
} else if (inp_ == typeid(boost::int32_t)) {
i = boxed_cast<boost::int32_t>(v);
} else if (inp_ == typeid(boost::int64_t)) {
i = boxed_cast<boost::int64_t>(v);
} else if (inp_ == typeid(boost::uint8_t)) {
i = boxed_cast<boost::uint8_t>(v);
} else if (inp_ == typeid(boost::uint16_t)) {
i = boxed_cast<boost::uint16_t>(v);
} else if (inp_ == typeid(boost::uint32_t)) {
i = boxed_cast<boost::uint32_t>(v);
} else {
throw boost::bad_any_cast();
}
}
bool operator==(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i);
}
bool operator<(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) < ((r.m_isfloat)?r.d:r.i);
}
bool operator>(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) > ((r.m_isfloat)?r.d:r.i);
}
bool operator>=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) >= ((r.m_isfloat)?r.d:r.i);
}
bool operator<=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) <= ((r.m_isfloat)?r.d:r.i);
}
bool operator!=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) != ((r.m_isfloat)?r.d:r.i);
}
Boxed_Value operator+(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i + r.i);
}
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator*(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i * r.i);
}
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator/(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i / r.i);
}
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator-(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i - r.i);
}
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
}
double d;
boost::int64_t i;
bool m_isfloat;
};
namespace detail
{
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<>
struct Cast_Helper<Boxed_POD_Value>
{
typedef Boxed_POD_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_POD_Value(ob);
}
};
}
template<typename T> template<typename T>
Boxed_Value var(T t) Boxed_Value var(T t)
{ {
return Boxed_Value(t); return Boxed_Value(t);
} }
/** namespace detail {
* Return true if the two Boxed_Values share the same internal type /// \brief Takes a value, copies it and returns a Boxed_Value object that is immutable
*/ /// \param[in] t Value to copy and make const
static bool type_match(Boxed_Value l, Boxed_Value r) /// \returns Immutable Boxed_Value
{ /// \sa Boxed_Value::is_const
return l.get_type_info() == r.get_type_info(); template<typename T>
Boxed_Value const_var_impl(const 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.
/// Does not copy the pointed to value.
/// \param[in] t Pointer to make immutable
/// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const
template<typename T>
Boxed_Value const_var_impl(T *t)
{
return Boxed_Value( const_cast<typename std::add_const<T>::type *>(t) );
}
/// \brief Takes a std::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
/// Does not copy the pointed to value.
/// \param[in] t Pointer to make immutable
/// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const
template<typename T>
Boxed_Value const_var_impl(const std::shared_ptr<T> &t)
{
return Boxed_Value( std::const_pointer_cast<typename std::add_const<T>::type>(t) );
}
/// \brief Takes a std::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
/// Does not copy the referenced value.
/// \param[in] t Reference object to make immutable
/// \returns Immutable Boxed_Value
/// \sa Boxed_Value::is_const
template<typename T>
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
{
return Boxed_Value( std::cref(t.get()) );
}
} }
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer type
/// the value is not copied. If it is an object type, it is copied.
/// \param[in] t Object to make immutable
/// \returns Immutable Boxed_Value
/// \sa chaiscript::Boxed_Value::is_const
/// \sa chaiscript::var
///
/// Example:
/// \code
/// enum Colors
/// {
/// Blue,
/// Green,
/// Red
/// };
/// chaiscript::ChaiScript chai
/// chai.add(chaiscript::const_var(Blue), "Blue"); // add immutable constant
/// chai.add(chaiscript::const_var(Red), "Red");
/// chai.add(chaiscript::const_var(Green), "Green");
/// \endcode
///
/// \todo support C++11 strongly typed enums
/// \sa \ref adding_objects
template<typename T>
Boxed_Value const_var(const T &t)
{
return detail::const_var_impl(t);
}
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
// 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_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#include <cassert>
#include <map>
#include <memory>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Type_Conversions;
namespace dispatch {
class Proxy_Function_Base;
} // namespace dispatch
} // namespace chaiscript
namespace chaiscript
{
namespace dispatch
{
class Dynamic_Object
{
public:
Dynamic_Object(std::string t_type_name)
: m_type_name(std::move(t_type_name))
{
}
std::string get_type_name() const
{
return m_type_name;
}
Boxed_Value get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
}
std::map<std::string, Boxed_Value> get_attrs() const
{
return m_attrs;
}
private:
std::string m_type_name;
std::map<std::string, Boxed_Value> m_attrs;
};
}
}
#endif

View File

@@ -0,0 +1,251 @@
// 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)
: 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>())
{
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)
: 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(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
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 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;
};
/**
* 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);
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 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

@@ -0,0 +1,199 @@
// 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_EXCEPTION_SPECIFICATION_HPP_
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#include <memory>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
namespace chaiscript {
class Boxed_Value;
namespace exception {
class bad_boxed_cast;
} // namespace exception
} // namespace chaiscript
namespace chaiscript
{
namespace detail
{
/// \todo make this a variadic template
struct Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
virtual ~Exception_Handler_Base() {}
protected:
template<typename T>
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
}
};
template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl1() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
}
};
template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl2() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl3() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl4() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl5() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
throw_type<T5>(bv, t_engine);
}
};
}
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
///
/// Exception specifications allow the user to tell ChaiScript what possible exceptions are expected from the script
/// being executed. Exception_Handler objects are created with the chaiscript::exception_specification() function.
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
///
/// 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
/// }
/// \endcode
///
/// It is recommended that if catching the generic \c std::exception& type that you specifically catch
/// the chaiscript::exception::eval_error type, so that there is no confusion.
///
/// \code
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<const std::exception &>());
/// } catch (const chaiscript::exception::eval_error &) {
/// // Error in script parsing / execution
/// } catch (const std::exception &e) {
/// // Error explicitly thrown from script
/// }
/// \endcode
///
/// Similarly, if you are using the ChaiScript::eval form that unboxes the return value, then chaiscript::exception::bad_boxed_cast
/// should be handled as well.
///
/// \code
/// try {
/// chai.eval<int>("1.0", chaiscript::exception_specification<const std::exception &>());
/// } catch (const chaiscript::exception::eval_error &) {
/// // Error in script parsing / execution
/// } catch (const chaiscript::exception::bad_boxed_cast &) {
/// // Error unboxing return value
/// } catch (const std::exception &e) {
/// // Error explicitly thrown from script
/// }
/// \endcode
///
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
/// \sa \ref exceptions
typedef std::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions
template<typename T1>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
}
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
}
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
}
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
}
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
}
}
#endif

View File

@@ -1,71 +1,127 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef __function_call_hpp__ #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define __function_call_hpp__ #define CHAISCRIPT_FUNCTION_CALL_HPP_
#include <boost/shared_ptr.hpp> #include <functional>
#include <boost/bind.hpp> #include <iostream>
#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 {
class Boxed_Value;
class Type_Conversions;
namespace detail {
template <typename T> struct Cast_Helper;
} // namespace detail
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
/** namespace dispatch
* Build a function caller that knows how to dispatch on a set of functions {
* example: /// Build a function caller that knows how to dispatch on a set of functions
* boost::function<void (int)> f = /// example:
* build_function_caller(dispatchkit.get_function("print")); /// std::function<void (int)> f =
* \returns A boost::function object for dispatching /// build_function_caller(dispatchkit.get_function("print"));
* \param[in] funcs the set of functions to dispatch on. /// \returns A std::function object for dispatching
*/ /// \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<std::pair<std::string, Proxy_Function > > &funcs) functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
{ {
FunctionType *p=0; FunctionType *p=nullptr;
return 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>
*/ std::function<FunctionType>
template<typename FunctionType> functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
boost::function<FunctionType>
functor(Proxy_Function func)
{ {
std::vector<std::pair<std::string, Proxy_Function > > funcs; return functor<FunctionType>(std::vector<Const_Proxy_Function>({func}), t_conversions);
funcs.push_back(std::make_pair(std::string(), 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>
*/ std::function<FunctionType>
template<typename FunctionType> functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
boost::function<FunctionType>
functor(const Boxed_Value &bv)
{ {
return functor<FunctionType>(boxed_cast<Proxy_Function >(bv)); return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
} }
}
namespace detail{
/// Cast helper to handle automatic casting to const std::function &
template<typename Signature>
struct Cast_Helper<const std::function<Signature> &>
{
typedef std::function<Signature> Result_Type;
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>()))
{
return dispatch::functor<Signature>(ob, t_conversions);
} else {
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
}
}
};
/// Cast helper to handle automatic casting to std::function
template<typename Signature>
struct Cast_Helper<std::function<Signature> >
{
typedef std::function<Signature> Result_Type;
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>()))
{
return dispatch::functor<Signature>(ob, t_conversions);
} else {
return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
}
}
};
/// Cast helper to handle automatic casting to const std::function
template<typename Signature>
struct Cast_Helper<const std::function<Signature> >
{
typedef std::function<Signature> Result_Type;
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>()))
{
return dispatch::functor<Signature>(ob, t_conversions);
} else {
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
}
}
};
}
} }
#endif #endif

View File

@@ -1,96 +1,118 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp> #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define addparam(z,n,text) params.push_back(boost::is_reference<Param ## n>::value?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) )); #include <algorithm>
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n)) #include <functional>
#include <memory>
#ifndef BOOST_PP_IS_ITERATING
#ifndef __function_call_detail_hpp__
#define __function_call_detail_hpp__
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#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
{ {
namespace detail namespace dispatch
{ {
/** namespace detail
* Internal helper class for handling the return {
* value of a build_function_caller /// Internal helper class for handling the return
*/ /// value of a build_function_caller
template<typename Ret> template<typename Ret, bool is_arithmetic>
class Function_Caller_Ret struct Function_Caller_Ret
{
static Ret call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params)
{ {
return boxed_cast<Ret>(dispatch(t_funcs, params)); static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
} const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
}; {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
}
};
/** /**
* Specialization for void return types * Specialization for arithmetic return types
*/ */
template<> template<typename Ret>
struct Function_Caller_Ret<void> struct Function_Caller_Ret<Ret, true>
{
static void call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params)
{ {
dispatch(t_funcs, params); 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
*/
template<>
struct Function_Caller_Ret<void, false>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
dispatch::dispatch(t_funcs, params, t_conversions);
}
};
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper
{
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)
{
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
(funcs[0]);
if (pfi)
{
return pfi->internal_function();
}
// looks like this either wasn't a Proxy_Function_Impl or the types didn't match
// we cannot make any other guesses or assumptions really, so continuing
}
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_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 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<std::pair<std::string, 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
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, Proxy_Function> > &funcs)
{
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
BOOST_PP_ENUM_TRAILING(n, curry, ~));
}
} }
} }

View File

@@ -1,100 +1,207 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef __handle_return_hpp__ #ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
#define __handle_return_hpp__ #define CHAISCRIPT_HANDLE_RETURN_HPP_
#include <functional>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
#include "boxed_number.hpp"
#include "boxed_value.hpp" #include "boxed_value.hpp"
#include "type_info.hpp" #include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
#include <stdexcept> namespace chaiscript {
#include <vector> class Boxed_Number;
} // namespace chaiscript
namespace chaiscript namespace chaiscript
{ {
/** namespace dispatch
* Used internally for handling a return value from a Proxy_Function call {
*/ namespace detail
template<typename Ret>
struct Handle_Return
{ {
static Boxed_Value call(const boost::function<Ret ()> &f) /**
{ * Used internally for handling a return value from a Proxy_Function call
return Boxed_Value(f()); */
} template<typename Ret>
}; struct Handle_Return
{
static Boxed_Value handle(const Ret &r)
{
return const_var(r);
}
template<typename Ret> static Boxed_Value handle(Ret &&r)
struct Handle_Return<boost::shared_ptr<Ret> &> {
{ return Boxed_Value(std::move(r));
static Boxed_Value call(const boost::function<boost::shared_ptr<Ret> & ()> &f) }
{ };
return Boxed_Value(f());
}
};
template<typename Ret> template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &> struct Handle_Return<Ret *>
{ {
static Boxed_Value call(const boost::function<const boost::shared_ptr<Ret> & ()> &f) static Boxed_Value handle(Ret *p)
{ {
return Boxed_Value(f()); return Boxed_Value(p);
} }
}; };
/** template<typename Ret>
* Used internally for handling a return value from a Proxy_Function call struct Handle_Return<const Ret *>
*/ {
template<typename Ret> static Boxed_Value handle(const Ret *p)
struct Handle_Return<Ret &> {
{ return Boxed_Value(p);
static Boxed_Value call(const boost::function<Ret &()> &f) }
{ };
return Boxed_Value(boost::ref(f()));
}
};
/** template<typename Ret>
* Used internally for handling a return value from a Proxy_Function call struct Handle_Return<std::shared_ptr<Ret> &>
*/ {
template<> static Boxed_Value handle(const std::shared_ptr<Ret> &r)
struct Handle_Return<Boxed_Value> {
{ return Boxed_Value(r);
static Boxed_Value call(const boost::function<Boxed_Value ()> &f) }
{ };
return f();
}
};
/** template<typename Ret>
* Used internally for handling a return value from a Proxy_Function call struct Handle_Return<std::shared_ptr<Ret> >
*/ {
template<> static Boxed_Value handle(const std::shared_ptr<Ret> &r)
struct Handle_Return<Boxed_Value &> {
{ return Boxed_Value(r);
static Boxed_Value call(const boost::function<Boxed_Value &()> &f) }
{ };
return f();
}
};
/** template<typename Ret>
* Used internally for handling a return value from a Proxy_Function call struct Handle_Return<const std::shared_ptr<Ret> &>
*/ {
template<> static Boxed_Value handle(const std::shared_ptr<Ret> &r)
struct Handle_Return<void> {
{ return Boxed_Value(r);
static Boxed_Value call(const boost::function<void ()> &f) }
{ };
f();
return Boxed_Value(Boxed_Value::Void_Type()); template<typename Ret>
} struct Handle_Return<const Ret &>
}; {
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return<Ret &>
{
static Boxed_Value handle(Ret &r)
{
return Boxed_Value(std::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<void>
{
static Boxed_Value handle()
{
return Boxed_Value(Boxed_Value::Void_Type());
}
};
}
}
} }
#endif #endif

View File

@@ -0,0 +1,465 @@
// 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_OPERATORS_HPP_
#define CHAISCRIPT_OPERATORS_HPP_
#include "../chaiscript_defines.hpp"
#include "register_function.hpp"
namespace chaiscript
{
namespace bootstrap
{
namespace operators
{
namespace detail
{
/// \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);
}
template<typename L, typename R>
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
{
return (l &= r);
}
template<typename L, typename R>
auto assign_xor(L l, R r) -> decltype((l^=r))
{
return (l ^= r);
}
template<typename L, typename R>
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
{
return (l |= r);
}
template<typename L, typename R>
auto assign_difference(L l, R r) -> decltype(( l -= r))
{
return (l -= r);
}
template<typename L, typename R>
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
{
return (l <<= r);
}
template<typename L, typename R>
auto assign_product(L l, R r) -> decltype(( l *= r ))
{
return (l *= r);
}
template<typename L, typename R>
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
{
return (l /= r);
}
template<typename L, typename R>
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
{
return (l %= r);
}
template<typename L, typename R>
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
{
return (l >>= r);
}
/// \todo make this return a decltype once we drop gcc 4.6
template<typename L, typename R>
auto assign_sum(L l, R r) -> L&
{
return (l += r);
}
template<typename L>
auto prefix_decrement(L l) -> decltype(( --l ))
{
return (--l);
}
template<typename L>
auto prefix_increment(L l) -> decltype(( ++l ))
{
return (++l);
}
template<typename L, typename R>
auto equal(L l, R r) -> decltype(( l == r ))
{
return (l == r);
}
template<typename L, typename R>
auto greater_than(L l, R r) -> decltype(( l > r ))
{
return (l > r);
}
template<typename L, typename R>
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
{
return (l >= r);
}
template<typename L, typename R>
auto less_than(L l, R r) -> decltype(( l < r ))
{
return (l < r);
}
template<typename L, typename R>
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
{
return (l <= r);
}
template<typename L>
auto logical_compliment(L l) -> decltype(( !l ))
{
return (!l);
}
template<typename L, typename R>
auto not_equal(L l, R r) -> decltype(( l != r ))
{
return (l != r);
}
template<typename L, typename R>
auto addition(L l, R r) -> decltype(( l + r ))
{
return (l + r);
}
template<typename L>
auto unary_plus(L l) -> decltype(( +l ))
{
return (+l);
}
template<typename L, typename R>
auto subtraction(L l, R r) -> decltype(( l - r ))
{
return (l - r);
}
template<typename L>
auto unary_minus(L l) -> decltype(( -l ))
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4146)
return (-l);
#pragma warning(pop)
#else
return (-l);
#endif
}
template<typename L, typename R>
auto bitwise_and(L l, R r) -> decltype(( l & r ))
{
return (l & r);
}
template<typename L>
auto bitwise_compliment(L l) -> decltype(( ~l ))
{
return (~l);
}
template<typename L, typename R>
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
{
return (l ^ r);
}
template<typename L, typename R>
auto bitwise_or(L l, R r) -> decltype(( l | r ))
{
return (l | r);
}
template<typename L, typename R>
auto division(L l, R r) -> decltype(( l / r ))
{
return (l / r);
}
template<typename L, typename R>
auto left_shift(L l, R r) -> decltype(( l << r ))
{
return l << r;
}
template<typename L, typename R>
auto multiplication(L l, R r) -> decltype(( l * r ))
{
return l * r;
}
template<typename L, typename R>
auto remainder(L l, R r) -> decltype(( l % r ))
{
return (l % r);
}
template<typename L, typename R>
auto right_shift(L l, R r) -> decltype(( l >> r ))
{
return (l >> r);
}
}
template<typename T>
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
return m;
}
template<typename T>
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
return m;
}
template<typename T>
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
return m;
}
template<typename T>
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
return m;
}
template<typename T>
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
return m;
}
template<typename T>
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
return m;
}
template<typename T>
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
return m;
}
template<typename T>
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
return m;
}
template<typename T>
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
return m;
}
template<typename T>
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
return m;
}
template<typename T>
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
return m;
}
template<typename T>
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
return m;
}
template<typename T>
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
return m;
}
template<typename T>
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
return m;
}
template<typename T>
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
return m;
}
template<typename T>
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
return m;
}
template<typename T>
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
return m;
}
template<typename T>
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
return m;
}
template<typename T>
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
return m;
}
template<typename T>
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
return m;
}
template<typename T>
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
return m;
}
template<typename T>
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
return m;
}
template<typename T>
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
return m;
}
template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
return m;
}
template<typename T>
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
return m;
}
template<typename T>
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
return m;
}
template<typename T>
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
return m;
}
template<typename T>
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
return m;
}
template<typename T>
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
return m;
}
template<typename T>
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
return m;
}
template<typename T>
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
return m;
}
}
}
}
#endif

View File

@@ -1,65 +1,59 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.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 __proxy_constructors_hpp__ #define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define __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(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>))));
}
}
}
/// \brief Generates a constructor function for use with ChaiScript
///
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
/// // Create a new function that creates a MyClass object using the (int, float) constructor
/// // and call that function "MyClass" so that it appears as a normal constructor to the user.
/// chai.add(constructor<MyClass (int, float)>(), "MyClass");
/// \endcode
template<typename T> template<typename T>
Proxy_Function constructor() Proxy_Function constructor()
{ {
T *f = 0; T *f = nullptr;
return (detail::build_constructor_(f)); return (dispatch::detail::build_constructor_(f));
} }
}
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
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)>))));
}
}
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +1,196 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp> #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define gettypeinfo(z,n,text) ti.push_back(detail::Get_Type_Info<Param ## n>::get());
#define casthelper(z,n,text) ,chaiscript::boxed_cast< Param ## n >(params[n])
#define comparetype(z,n,text) && ((detail::Get_Type_Info<Param ## n>::get() == params[n].get_type_info()))
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
#ifndef BOOST_PP_IS_ITERATING
#ifndef __proxy_functions_detail_hpp__
#define __proxy_functions_detail_hpp__
#include "boxed_value.hpp"
#include "type_info.hpp"
#include "handle_return.hpp"
#include <string>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <algorithm>
#include <functional>
#include <stdexcept> #include <stdexcept>
#include <string>
#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
* Exception thrown when there is a mismatch in number of
* parameters during Proxy_Function execution
*/
struct arity_error : std::range_error
{ {
arity_error(int t_got, int t_expected) /**
: std::range_error("Function dispatch arity mismatch"), * Exception thrown when there is a mismatch in number of
got(t_got), expected(t_expected) * parameters during Proxy_Function execution
*/
struct arity_error : std::range_error
{ {
} arity_error(int t_got, int t_expected)
: std::range_error("Function dispatch arity mismatch"),
virtual ~arity_error() throw() {} got(t_got), expected(t_expected)
int got;
int expected;
};
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions_detail.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
std::vector<Type_Info> ti;
ti.push_back(detail::Get_Type_Info<Ret>::get());
BOOST_PP_REPEAT(n, gettypeinfo, ~)
return ti;
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each paramter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params)
{
if (params.size() != n)
{ {
throw arity_error(params.size(), n);
} else {
return Handle_Return<Ret>::call(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~)));
} }
}
/** arity_error(const arity_error &) = default;
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarly used to prevent virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
* registration of two functions with the exact same signatures
*/ int got;
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> int expected;
bool compare_types(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)), };
const std::vector<Boxed_Value> &params) }
namespace dispatch
{
namespace detail
{ {
if (params.size() != n) /**
{ * Used by Proxy_Function_Impl to return a list of all param types
return false; * it contains.
} else { */
bool val = true BOOST_PP_REPEAT(n, comparetype, ~); template<typename Ret, typename ... Params>
if (val) return true; std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
{
try { /// \note somehow this is responsible for a large part of the code generation
BOOST_PP_REPEAT(n, trycast, ~); return { user_type<Ret>(), user_type<Params>()... };
} catch (const bad_boxed_cast &) { }
return false;
// Forward declaration
template<typename ... Rest>
struct Try_Cast;
template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...>
{
static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions &t_conversions)
{
boxed_cast<Param>(params[generation], &t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
}
};
// 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
* Proxy_Function_Impl object. This function is primarily used to prevent
* registration of two functions with the exact same signatures
*/
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
try {
Try_Cast<Params...>::do_try(params, 0, t_conversions);
} catch (const exception::bad_boxed_cast &) {
return false;
}
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));
} }
return true;
}
} }
}
}
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Fun>
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, t_conversions));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
call_func(fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};
}
}
} }
#endif #endif

View File

@@ -1,89 +1,179 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <boost/preprocessor.hpp> #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
#ifndef BOOST_PP_IS_ITERATING #include <functional>
#ifndef __register_function_hpp__ #include <type_traits>
#define __register_function_hpp__
#include "bind_first.hpp"
#include "dispatchkit.hpp" #include "dispatchkit.hpp"
#include <boost/function.hpp> #include "proxy_functions.hpp"
#include <boost/bind.hpp>
namespace chaiscript namespace chaiscript
{ {
template<typename T> namespace dispatch
Proxy_Function fun(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
namespace detail
{ {
/** namespace detail
* Helper function for register_member function {
*/ template<typename T>
template<typename T, typename Class> struct FunctionSignature
T &get_member(T Class::* m, Class *obj) {
{ };
return (obj->*m);
} template<typename Sig>
struct FunctionSignature<std::function<Sig> >
{
typedef Sig Signature;
};
template<typename Ret, typename ... Args>
std::function<Ret (Args...) > to_function(Ret (*func)(Args...))
{
return std::function<Ret (Args...)>(func);
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
{
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
/// std::function for member function pointers seems to be broken in MSVC
return std::function<Ret(Class &, Args...)>(std::mem_fn(func));
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
{
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
/// std::function for member function pointers seems to be broken in MSVC
return std::function<Ret (const Class &, Args...)>(std::mem_fn(func));
}
template<bool Object>
struct Fun_Helper
{
template<typename T>
static Proxy_Function go(T t)
{
/// \todo is it possible to reduce the number of templates generated here?
return Proxy_Function(
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
}
};
template<>
struct Fun_Helper<true>
{
template<typename T, typename Class>
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 free function, member function or data member
* Automatically create a get_member helper function for an object /// \param[in] t Function / member to expose
* to allow for runtime dispatched access to public data members ///
* for example, the case of std::pair<>::first and std::pair<>::second /// \b Example:
*/ /// \code
template<typename T, typename Class> /// int myfunction(const std::string &);
Proxy_Function fun(T Class::* m) /// class MyClass
/// {
/// public:
/// void memberfunction();
/// int memberdata;
/// };
///
/// chaiscript::ChaiScript chai;
/// chai.add(fun(&myfunction), "myfunction");
/// chai.add(fun(&MyClass::memberfunction), "memberfunction");
/// chai.add(fun(&MyClass::memberdata), "memberdata");
/// \endcode
///
/// \sa \ref adding_functions
template<typename T>
Proxy_Function fun(T t)
{ {
return fun(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1))); return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
}
/// \brief Creates a new Proxy_Function object from a std::function object
/// \param[in] f std::function to expose to ChaiScript
///
/// \b Example:
/// \code
/// std::function<int (char, float, std::string)> f = get_some_function();
/// chaiscript::ChaiScript chai;
/// chai.add(fun(f), "some_function");
/// \endcode
///
/// \sa \ref adding_functions
template<typename T>
Proxy_Function fun(const std::function<T> &f)
{
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
}
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
/// \param[in] t Function / member to expose
/// \param[in] q Value to bind to first parameter
///
/// \b Example:
/// \code
/// struct MyClass
/// {
/// void memberfunction(int);
/// };
///
/// MyClass obj;
/// chaiscript::ChaiScript chai;
/// // Add function taking only one argument, an int, and permanently bound to "obj"
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
/// \endcode
///
/// \sa \ref adding_functions
template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q)
{
return fun(detail::bind_first(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
/// \param[in] t Function / member to expose
/// \param[in] q Value to bind to first parameter
/// \param[in] r Value to bind to second parameter
///
/// \b Example:
/// \code
/// struct MyClass
/// {
/// void memberfunction(int);
/// };
///
/// MyClass obj;
/// chaiscript::ChaiScript chai;
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
/// // memberfunction() will be equivalent to obj.memberfunction(1)
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
/// \endcode
///
/// \sa \ref adding_functions
template<typename T, typename Q, typename R>
Proxy_Function fun(T t, const Q &q, const R &r)
{
return fun(detail::bind_first(detail::bind_first(t, q), r));
} }
} }
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
#include BOOST_PP_ITERATE()
# endif
#else
# define n BOOST_PP_ITERATION()
namespace chaiscript
{
/**
* Register a global function of n parameters with name
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Proxy_Function fun(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
return fun(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
}
/**
* Register a class method of n parameters with name
*/
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
return fun(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
}
/**
* Register a const class method of n parameters with name
*/
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
{
return fun(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
}
}
#endif #endif

View File

@@ -0,0 +1,453 @@
// 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;
}
protected:
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
: m_to(t_to), m_from(t_from)
{
}
virtual ~Type_Conversion_Base() {}
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())
{
std::shared_ptr<const To> data
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
} else {
std::shared_ptr<To> data
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
const To &data = dynamic_cast<const To &>(d);
return Boxed_Value(std::cref(data));
} else {
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
To &data = dynamic_cast<To &>(d);
return Boxed_Value(std::ref(data));
}
}
} else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
}
}
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public 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 std::make_shared<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 std::make_shared<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 std::make_shared<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
auto &&from = detail::Cast_Helper<From>::cast(t_bv, nullptr);
To to(from);
return chaiscript::Boxed_Value(to);
};
return std::make_shared<detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
}
}
#endif

View File

@@ -1,80 +1,130 @@
// 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, Jonathan Turner (jturner@minnow-lang.org) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (lefticus@gmail.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef __type_info_hpp__ #ifndef CHAISCRIPT_TYPE_INFO_HPP_
#define __type_info_hpp__ #define CHAISCRIPT_TYPE_INFO_HPP_
#include <boost/type_traits/is_const.hpp> #include <functional>
#include <boost/type_traits/is_void.hpp> #include <memory>
#include <boost/type_traits/is_reference.hpp> #include <string>
#include <boost/type_traits/is_pointer.hpp> #include <type_traits>
#include <boost/type_traits/remove_const.hpp> #include <typeinfo>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/ref.hpp>
namespace chaiscript namespace chaiscript
{ {
/**
* compile time deduced information about a type namespace detail
*/
struct Type_Info
{ {
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, template<typename T>
const std::type_info *t_ti, const std::type_info *t_bareti) struct Bare_Type
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), {
m_is_void(t_is_void), typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
m_type_info(t_ti), m_bare_type_info(t_bareti), };
m_is_unknown(false) }
{
}
Type_Info()
: m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_type_info(0), m_bare_type_info(0),
m_is_unknown(true)
{
}
Type_Info(const Type_Info &ti) /// \brief Compile time deduced information about a type
: m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference), class Type_Info
m_is_pointer(ti.m_is_pointer), {
m_is_void(ti.m_is_void), m_type_info(ti.m_type_info), public:
m_bare_type_info(ti.m_bare_type_info), CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
m_is_unknown(ti.m_is_unknown) bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
{ : m_type_info(t_ti), m_bare_type_info(t_bareti),
} m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
Type_Info &operator=(const Type_Info &ti) m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
{ m_is_undef(false)
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_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_unknown = ti.m_is_unknown;
return *this;
}
bool operator<(const Type_Info &ti) const
{
return m_type_info < ti.m_type_info;
}
bool operator==(const Type_Info &ti) const CHAISCRIPT_CONSTEXPR Type_Info()
{ : m_type_info(nullptr), m_bare_type_info(nullptr),
return ti.m_type_info == m_type_info; m_is_const(false), m_is_reference(false), m_is_pointer(false),
} m_is_void(false), m_is_arithmetic(false),
m_is_undef(true)
{
}
bool m_is_const; #if !defined(_MSC_VER) || _MSC_VER != 1800
bool m_is_reference; Type_Info(Type_Info&&) = default;
bool m_is_pointer; Type_Info& operator=(Type_Info&&) = default;
bool m_is_void; #endif
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info; Type_Info(const Type_Info&) = default;
bool m_is_unknown; Type_Info& operator=(const Type_Info&) = default;
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_type_info < ti.m_type_info;
}
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return ti.m_type_info == m_type_info
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
}
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_type_info != nullptr && (*m_type_info) == ti;
}
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
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);
}
CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_bare_type_info != nullptr
&& (*m_bare_type_info) == ti;
}
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
std::string name() const
{
if (m_type_info)
{
return m_type_info->name();
} else {
return "";
}
}
std::string bare_name() const
{
if (m_bare_type_info)
{
return m_bare_type_info->name();
} else {
return "";
}
}
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
{
return m_bare_type_info;
}
private:
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_const;
bool m_is_reference;
bool m_is_pointer;
bool m_is_void;
bool m_is_arithmetic;
bool m_is_undef;
}; };
namespace detail namespace detail
@@ -85,54 +135,110 @@ namespace chaiscript
template<typename T> template<typename T>
struct Get_Type_Info struct Get_Type_Info
{ {
static Type_Info get() typedef T type;
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<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,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(T), &typeid(T),
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::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> >
{ {
static Type_Info get() typedef T type;
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,
&typeid(boost::shared_ptr<T> ), std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type)); &typeid(std::shared_ptr<T> ),
&typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T> template<typename T>
struct Get_Type_Info<boost::reference_wrapper<T> > struct Get_Type_Info<const std::shared_ptr<T> &>
{ {
static Type_Info get() typedef T type;
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,
&typeid(boost::reference_wrapper<T> ), std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type)); &typeid(const std::shared_ptr<T> &),
&typeid(typename Bare_Type<T>::type));
} }
}; };
template<typename T>
struct Get_Type_Info<std::reference_wrapper<T> >
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(std::reference_wrapper<T> ),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<const std::reference_wrapper<T> &>
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(const std::reference_wrapper<T> &),
&typeid(typename Bare_Type<T>::type));
}
};
} }
/// \brief Creates a Type_Info object representing the type passed in
/// \tparam T Type of object to get a Type_Info for, derived from the passed in parameter
/// \return Type_Info for T
///
/// \b Example:
/// \code
/// int i;
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode
template<typename T> template<typename T>
Type_Info user_type(T) CHAISCRIPT_CONSTEXPR Type_Info user_type(const T &/*t*/)
{ {
return detail::Get_Type_Info<T>::get(); return detail::Get_Type_Info<T>::get();
} }
/// \brief Creates a Type_Info object representing the templated type
/// \tparam T Type of object to get a Type_Info for
/// \return Type_Info for T
///
/// \b Example:
/// \code
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \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();
} }
} }
#endif #endif

View File

@@ -0,0 +1,132 @@
// 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_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#include <string>
#include "../dispatchkit/dispatchkit.hpp"
namespace chaiscript
{
struct Operators {
enum Opers
{
boolean_flag,
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
non_const_flag,
assign, pre_increment, pre_decrement, assign_product, assign_sum,
assign_quotient, assign_difference,
non_const_int_flag,
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
assign_remainder, assign_bitwise_xor,
const_int_flag,
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
const_flag,
sum, quotient, product, difference, unary_plus, unary_minus,
invalid
};
static const char *to_string(Opers t_oper) {
const char *opers[] = {
"",
"==", "<", ">", "<=", ">=", "!=",
"",
"=", "++", "--", "*=", "+=",
"/=", "-=",
"",
"&=", "|=", "<<=", ">>=",
"%=", "^=",
"",
"<<", ">>", "%", "&", "|", "^", "~",
"",
"+", "/", "*", "-", "+", "-",
""
};
return opers[t_oper];
}
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{
if (t_str == "==")
{
return equals;
} else if (t_str == "<") {
return less_than;
} else if (t_str == ">") {
return greater_than;
} else if (t_str == "<=") {
return less_than_equal;
} else if (t_str == ">=") {
return greater_than_equal;
} else if (t_str == "!=") {
return not_equal;
} else if (t_str == "=") {
return assign;
} else if (t_str == "++") {
return pre_increment;
} else if (t_str == "--") {
return pre_decrement;
} else if (t_str == "*=") {
return assign_product;
} else if (t_str == "+=") {
return assign_sum;
} else if (t_str == "-=") {
return assign_difference;
} else if (t_str == "&=") {
return assign_bitwise_and;
} else if (t_str == "|=") {
return assign_bitwise_or;
} else if (t_str == "<<=") {
return assign_shift_left;
} else if (t_str == ">>=") {
return assign_shift_right;
} else if (t_str == "%=") {
return assign_remainder;
} else if (t_str == "^=") {
return assign_bitwise_xor;
} else if (t_str == "<<") {
return shift_left;
} else if (t_str == ">>") {
return shift_right;
} else if (t_str == "%") {
return remainder;
} else if (t_str == "&") {
return bitwise_and;
} else if (t_str == "|") {
return bitwise_or;
} else if (t_str == "^") {
return bitwise_xor;
} else if (t_str == "~") {
return bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return unary_plus;
} else {
return sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return unary_minus;
} else {
return difference;
}
} else if (t_str == "/") {
return quotient;
} else if (t_str == "*") {
return product;
} else {
return invalid;
}
}
};
}
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */

View File

@@ -0,0 +1,593 @@
// 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_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_
#include <algorithm>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
namespace chaiscript {
struct AST_Node;
} // namespace chaiscript
namespace chaiscript
{
/// Signature of module entry point that all binary loadable modules must implement.
typedef ModulePtr (*Create_Module_Func)();
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg
};
};
namespace
{
/// Helper lookup to get the name of each node type
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
return ast_node_types[ast_node_type];
}
}
/// \brief Convenience type for file positions
struct File_Position {
int line;
int column;
File_Position(int t_file_line, int t_file_column)
: line(t_file_line), column(t_file_column) { }
File_Position() : line(0), column(0) { }
};
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
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.
namespace exception
{
/// Errors generated during parsing or evaluation
struct eval_error : public std::runtime_error {
std::string reason;
File_Position start_position;
File_Position end_position;
std::string filename;
std::string detail;
std::vector<AST_NodePtr_Const> call_stack;
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_where, t_fname)),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
{}
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
eval_error(const eval_error &) = default;
std::string pretty_print() const
{
std::ostringstream ss;
ss << what();
if (call_stack.size() > 0) {
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
ss << '\n' << detail << '\n';
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
for (size_t j = 1; j < call_stack.size(); ++j) {
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
{
ss << '\n';
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
}
}
}
ss << '\n';
return ss.str();
}
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
private:
template<typename T>
static int id(const T& t)
{
return t->identifier;
}
template<typename T>
static std::string pretty(const T& t)
{
return t->pretty_print();
}
template<typename T>
static std::string fname(const T& t)
{
return *t->filename;
}
template<typename T>
static std::string startpos(const T& t)
{
std::ostringstream oss;
oss << t->start.line << ", " << t->start.column;
return oss.str();
}
static std::string format_why(const std::string &t_why)
{
return "Error: \"" + t_why + "\"";
}
static std::string format_types(const Const_Proxy_Function &t_func,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss)
{
int arity = t_func->get_arity();
std::vector<Type_Info> types = t_func->get_param_types();
std::string retval;
if (arity == -1)
{
retval = "(...)";
if (t_dot_notation)
{
retval = "(Object)." + retval;
}
} else if (types.size() <= 1) {
retval = "()";
} else {
std::stringstream ss;
ss << "(";
std::string paramstr;
for (size_t index = 1;
index != types.size();
++index)
{
paramstr += (types[index].is_const()?"const ":"");
paramstr += t_ss.get_type_name(types[index]);
if (index == 1 && t_dot_notation)
{
paramstr += ").(";
if (types.size() == 2)
{
paramstr += ", ";
}
} else {
paramstr += ", ";
}
}
ss << paramstr.substr(0, paramstr.size() - 2);
ss << ")";
retval = ss.str();
}
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
if (dynfun)
{
Proxy_Function f = dynfun->get_guard();
if (f)
{
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
if (dynfunguard)
{
retval += " : " + format_guard(dynfunguard->get_parse_tree());
}
}
retval += "\n Defined at " + format_location(dynfun->get_parse_tree());
}
return retval;
}
template<typename T>
static std::string format_guard(const T &t)
{
return t->pretty_print();
}
template<typename T>
static std::string format_location(const T &t)
{
std::ostringstream oss;
oss << "(" << *t->filename << " " << t->start.line << ", " << t->start.column << ")";
return oss.str();
}
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss)
{
std::stringstream ss;
if (t_functions.size() == 1)
{
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
} else {
ss << " " << t_functions.size() << " overloads available:\n";
for (const auto & t_function : t_functions)
{
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
}
}
return ss.str();
}
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss)
{
std::stringstream ss;
ss << "(";
if (!t_parameters.empty())
{
std::string paramstr;
for (auto itr = t_parameters.begin();
itr != t_parameters.end();
++itr)
{
paramstr += (itr->is_const()?"const ":"");
paramstr += t_ss.type_name(*itr);
if (itr == t_parameters.begin() && t_dot_notation)
{
paramstr += ").(";
if (t_parameters.size() == 1)
{
paramstr += ", ";
}
} else {
paramstr += ", ";
}
}
ss << paramstr.substr(0, paramstr.size() - 2);
}
ss << ")";
return ss.str();
}
static std::string format_filename(const std::string &t_fname)
{
std::stringstream ss;
if (t_fname != "__EVAL__")
{
ss << "in '" << t_fname << "' ";
} else {
ss << "during evaluation ";
}
return ss.str();
}
static std::string format_location(const File_Position &t_where)
{
std::stringstream ss;
ss << "at (" << t_where.line << ", " << t_where.column << ")";
return ss.str();
}
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
{
std::stringstream ss;
ss << format_why(t_why);
ss << " ";
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
ss << " ";
ss << format_filename(t_fname);
ss << " ";
ss << format_location(t_where);
return ss.str();
}
static std::string format(const std::string &t_why,
const std::vector<Boxed_Value> &t_parameters,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss)
{
std::stringstream ss;
ss << format_why(t_why);
ss << " ";
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
ss << " ";
return ss.str();
}
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname)
{
std::stringstream ss;
ss << format_why(t_why);
ss << " ";
ss << format_filename(t_fname);
ss << " ";
ss << format_location(t_where);
return ss.str();
}
};
/// Errors generated when loading a file
struct file_not_found_error : public std::runtime_error {
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
: std::runtime_error("File Not Found: " + t_filename)
{ }
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.
struct AST_Node : std::enable_shared_from_this<AST_Node> {
public:
const std::string text;
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
std::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
virtual std::string pretty_print() const
{
std::ostringstream oss;
oss << text;
for (auto & elem : this->children) {
oss << elem->pretty_print();
}
return oss.str();
}
/// Prints the contents of an AST node, including its children, recursively
std::string to_string(const std::string &t_prepend = "") const {
std::ostringstream oss;
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << '\n';
for (size_t j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
}
return oss.str();
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) const
{
try {
return eval_internal(t_e);
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this());
throw;
}
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
protected:
AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(std::move(t_ast_node_text)), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
text(std::move(t_ast_node_text)), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const
{
throw std::runtime_error("Undispatched ast_node (internal error)");
}
private:
// Copy and assignment explicitly unimplemented
AST_Node(const AST_Node &);
AST_Node& operator=(const AST_Node &);
};
namespace eval
{
namespace detail
{
/// Special type for returned values
struct Return_Value {
Boxed_Value retval;
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
};
/// Special type indicating a call to 'break'
struct Break_Loop {
Break_Loop() { }
};
/// Special type indicating a call to 'continue'
struct Continue_Loop {
Continue_Loop() { }
};
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_scope();
}
~Scope_Push_Pop()
{
m_de.pop_scope();
}
private:
chaiscript::detail::Dispatch_Engine &m_de;
};
/// Creates a new function call and pops it on destruction
struct Function_Push_Pop
{
Function_Push_Pop(const Function_Push_Pop &) = delete;
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_function_call();
}
~Function_Push_Pop()
{
m_de.pop_function_call();
}
void save_params(const std::vector<Boxed_Value> &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:
chaiscript::detail::Dispatch_Engine &m_de;
};
/// Creates a new scope then pops it on destruction
struct Stack_Push_Pop
{
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_stack();
}
~Stack_Push_Pop()
{
m_de.pop_stack();
}
private:
chaiscript::detail::Dispatch_Engine &m_de;
};
}
}
}
#endif /* _CHAISCRIPT_COMMON_HPP */

File diff suppressed because it is too large Load Diff

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,532 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_
#define CHAISCRIPT_PRELUDE_HPP_
namespace chaiscript {
struct ChaiScript_Prelude {
static std::string chaiscript_prelude() { return R""(
def lt(l, r) {
if (call_exists(`<`, l, r)) {
l < r
} else {
type_name(l) < type_name(r)
}
}
def gt(l, r) {
if (call_exists(`>`, l, r)) {
l > r
} else {
type_name(l) > type_name(r)
}
}
def eq(l, r) {
if (call_exists(`==`, l, r)) {
l == r
} else {
false
}
}
def new(x) {
eval(type_name(x))();
}
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x).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,285 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.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 new(x) { eval(type_name(x))(); } \
def clone(x) { eval(type_name(x))(x); } \
# to_string for Pair()\n\
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \
}\
# to_string for containers\n\
def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \
"[" + x.join(", ") + "]"; \
}\
# Basic to_string function\n\
def to_string(x) { \
internal_to_string(x); \
}\
# Prints to console with no carriage return\n\
def puts(x) { \
print_string(x.to_string()); \
} \
# Prints to console with carriage return\n\
def print(x) { \
println_string(x.to_string()); \
} \
# Returns the maximum value of two numbers\n\
def max(a, b) { if (a>b) { a } else { b } } \
# Returns the minimum value of two numbers\n\
def min(a, b) { if (a<b) { a } else { b } } \
# Returns true if the value is odd\n\
def odd(x) { if (x % 2 == 1) { true } else { false } } \
# Returns true if the value is even\n\
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\n\
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_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) {\
var retval = new(container); \
var r = retro(range(container)); \
while (!r.empty()) { \
retval.push_back(r.front()); \
r.pop_front(); \
} \
retval; \
} \
# Performs the second value function over the container first value\n\
def for_each(container, func) : call_exists(range, container) { \
var range = range(container); \
while (!range.empty()) { \
func(range.front()); \
range.pop_front(); \
} \
} \
def back_inserter(container) { \
bind(push_back, container, _); \
}\
\
def map(container, func, inserter) : call_exists(range, container) { \
var 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\n\
def map(container, func) { \
var 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.\n\
def foldl(container, func, initial) : call_exists(range, container){ \
var retval = initial; \
var 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\n\
def sum(container) { foldl(container, `+`, 0.0) } \
# Returns the product of the elements of the given value\n\
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\n\
def concat(x, y) : call_exists(clone, x) { \
var retval = x; \
var len = y.size(); \
var i = 0; \
while (i < len) { \
retval.push_back(y[i]); \
++i; \
} \
retval; \
} \
def take(container, num, inserter) : call_exists(range, container) { \
var r = range(container); \
var 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\n\
def take(container, num) {\
var retval = new(container); \
take(container, num, back_inserter(retval)); \
retval; \
}\
def take_while(container, f, inserter) : call_exists(range, container) { \
var 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\n\
def take_while(container, f) {\
var retval = new(container); \
take_while(container, f, back_inserter(retval)); \
retval;\
}\
def drop(container, num, inserter) : call_exists(range, container) { \
var r = range(container); \
var 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 \n\
def drop(container, num) {\
var retval = new(container); \
drop(container, num, back_inserter(retval)); \
retval; \
}\
def drop_while(container, f, inserter) : call_exists(range, container) { \
var 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\n\
def drop_while(container, f) {\
var 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.\n\
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \
var r = range(container); \
var 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\n\
def join(container, delim) { \
var retval = ""; \
var 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) { \
var 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\n\
def filter(container, f) { \
var retval = new(container); \
filter(container, f, back_inserter(retval));\
retval;\
}\
def generate_range(x, y, inserter) { \
var i = x; \
while (i <= y) { \
inserter(i); \
++i; \
} \
} \
# Returns a new Vector which represents the range from the first value to the second value\n\
def generate_range(x, y) { \
var 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\n\
def collate(x, y) { \
[x, y]; \
} \
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \
var r_x = range(x); \
var 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\n\
def zip_with(f, x, y) { \
var retval = Vector(); \
zip_with(f,x,y,back_inserter(retval)); \
retval;\
}\
# Returns a new Vector which joins matching elements of the first and second\n\
def zip(x, y) { \
zip_with(collate, x, y); \
}\
# Returns the position of the second value string in the first value string\n\
def find(str, substr) { \
int(find(str, substr, size_t(0))); \
} \
# Returns the position of last match of the second value string in the first value string\n\
def rfind(str, substr) { \
int(rfind(str, substr, size_t(-1))); \
} \
# Returns the position of the first match of elements in the second value string in the first value string\n\
def find_first_of(str, list) { \
int(find_first_of(str, list, size_t(0))); \
} \
# Returns the position of the last match of elements in the second value string in the first value string\n\
def find_last_of(str, list) { \
int(find_last_of(str, list, size_t(-1))); \
} \
# Returns the position of the first non-matching element in the second value string in the first value string\n\
def find_first_not_of(str, list) { \
int(find_first_not_of(str, list, size_t(0))); \
} \
# Returns the position of the last non-matching element in the second value string in the first value string\n\
def find_last_not_of(str, list) { \
int(find_last_not_of(str, list, size_t(-1))); \
} \
def ltrim(str) { \
drop_while(str, fun(x) { x == ' ' || x == '\t' }); \
} \
def rtrim(str) { \
reverse(drop_while(reverse(str), fun(x) { x == ' ' || x == '\t' })); \
} \
def trim(str) { \
ltrim(rtrim(str)); \
} \
)
#endif /* CHAISCRIPT_PRELUDE_HPP_ */

View File

@@ -0,0 +1,830 @@
/// This file is not technically part of the ChaiScript API. It is used solely for generating Doxygen docs
/// regarding the ChaiScript standard runtime library.
/// \brief Items in this namespace exist in the ChaiScript language runtime. They are not part of the C++ API
namespace ChaiScript_Language
{
/// \page LangStandardLibraryRef ChaiScript Language Standard Library Reference
///
/// ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly
/// as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available
/// to all standard ChaiScript applications, and provides a simple foundation for using numbers, strings, and ranges
/// (the general category of Range cs and their iteration).
///
/// \brief Generic concept of a value in ChaiScript.
///
/// The Object type exists merely as a concept. All objects in ChaiScript support this concept
/// and have the following methods available to them. All objects are stored internally as chaiscript::Boxed_Value types.
///
/// \sa chaiscript::Boxed_Value
class Object
{
public:
/// \brief Returns the Type_Info value for this Object
Type_Info get_type_info() const;
/// \brief Returns true if the Object is of the named type
bool is_type(string) const;
/// \brief Returns true if the Object is of the Type_Info passed in
bool is_type(Type_Info) const;
/// \brief Returns true if the Object is immutable
bool is_var_const() const;
/// \brief Returns true if the Object is a pointer and the pointer is null
bool is_var_null() const;
/// \brief Returns true if the Object is stored as a pointer
bool is_var_pointer() const;
/// \brief Returns true if the Object is stored as a reference
bool is_var_reference() const;
/// \brief Returns true if the Object does not contain a value is is undefined.
bool is_var_undef() const;
/// \brief Returns the registered name of the type of the object.
///
/// \sa Type_Info::name();
string type_name() const;
};
/// \brief Item returned from a Range object from a Map
class Map_Pair
{
public:
/// \brief Returns the key of the Map entry
const string first();
/// \brief Returns the value Object of the Map entry
Object second();
};
/// \brief Maps strings to Objects
///
/// ChaiScript has a built in shortcut for generating Map objects:
///
/// Example:
/// \code
/// eval> var m = ["a":1, "b":2];
/// [<a,1>, <b,2>]
/// eval> m.count("a");
/// 1
/// eval> m.count("c");
/// 0
/// eval> m.size();
/// 2
/// \endcode
///
/// Implemented as std::map<Boxed_Value>
///
/// \sa Map_Pair
/// \sa chaiscript::bootstrap::standard_library::map_type
class Map
{
public:
/// \brief Returns an object that implements the Range concept for the Map_Pair's in this Map
Range range();
/// \brief Returns an object that implements the Const_Range concept for the Map_Pair's in this Map
Const_Range range() const;
/// \brief Returns the number of elements in the Map
int size() const;
/// \brief Returns the item at the given key, creating an undefined Object if the key does not yet exist in the map
Object operator[](string);
/// \brief Clears the map of all items
void clear();
/// \brief Returns the number of items in the Map with the given key. Returns 0 or 1 since this is not an std::multimap.
int count(string) const;
/// \brief Returns true if the map contains no items
bool empty() const;
};
/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
class Container
{
public:
void push_back(Object);
Range range();
Const_Range range() const;
};
/// \brief Converts o into a string.
///
/// \code
/// eval> to_string(3).is_type("string") <br>
/// true<br>
/// \endcode
string to_string(Object o);
/// \brief Prints o to the terminal, without a trailing carriage return. Applies conversions to string automatically.
/// \code
/// eval> puts("hi, "); puts("there")
/// hi, thereeval>
/// \endcode
/// \sa to_string
/// \sa print
void puts(Object o);
/// \brief Prints o to the terminal, with a trailing carriage return. Applies conversions to string automatically
/// \code
/// eval> print("hello")
/// hello
/// eval>
/// \endcode
/// \sa to_string
/// \sa puts
void print(Object o);
/// \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 convertible to and from std::string
/// using the chaiscript::boxed_cast and chaiscript::var functions.
///
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
/// std::string of the same name.
///
/// \note Object and function notations are equivalent in ChaiScript. This means that
/// \c "bob".find("b") and \c find("bob", "b") are exactly the same. Most examples below follow the
/// second formation of the function calls.
/// \sa \ref keyworddef for extending existing C++ classes in ChaiScript
/// \sa chaiscript::bootstrap::standard_library::string_type
class string
{
public:
/// \brief Finds the first instance of substr.
/// \code
/// eval> find("abab", "ab")
/// 0
/// \endcode
int find(string s) const;
/// \brief Finds the last instance of substr.
/// \code
/// eval> rfind("abab", "ab")
/// 2
/// \endcode
int rfind(string s) const;
/// \brief Finds the first of characters in list in the string.
///
/// \code
/// eval> find_first_of("abab", "bec")
/// 1
/// \endcode
int find_first_of(string list) const;
/// \brief Finds the last of characters in list in the string.
///
/// \code
/// eval> find_last_of("abab", "bec")
/// 3
/// \endcode
int find_last_of(string list) const;
/// \brief Finds the first non-matching character to list in the str string.
///
/// \code
/// eval> find_first_not_of("abcd", "fec")
/// 0
/// \endcode
int find_first_not_of(string list) const;
/// \brief Finds the last non-matching character to list in the list string.
///
/// \code
/// eval> find_last_not_of("abcd", "fec")
/// 3
/// \endcode
int find_last_not_of(string list) const;
/// \brief Removes whitespace from the front of the string, returning a new string
///
/// \note This function is implemented as a ChaiScript function using the def member function notation.
///
/// \code
/// eval> ltrim(" bob")
/// bob
/// \endcode
///
/// \sa \ref keyworddef
string lstrim() const;
/// \brief Removes whitespace from the back of the string, returning a new string
///
/// \note This function is implemented as a ChaiScript function using the def member function notation.
///
/// \code
/// eval> rtrim("bob ") + "|"
/// bob|
/// \endcode
///
/// \sa \ref keyworddef
string rtrim() const;
/// \brief Removes whitespace from the front and back of the string, returning a new string
///
/// \note This function is implemented as a ChaiScript function using the def member function notation.
///
/// \code
/// eval> trim(" bob ") + "|"
/// bob|
/// \endcode
///
/// Equivalent to rtrim(ltrim(" bob "));
///
/// \sa \ref keyworddef
string trim() const;
/// \brief Returns the character at the given index in the string, const version
const char &operator[](int t_index) const;
/// \brief Returns the character at the given index in the string
char &operator[](int t_index);
/// \brief Returns underlying const char * for C api compatibility
const char *c_str() const;
/// \brief Returns a pointer to the raw data in the string
const char *data() const;
/// \brief Resets the string to empty
void clear();
/// \brief Returns true if the string is empty
bool empty() const;
/// \brief Returns the size of the string in bytes.
///
/// This function normally returns size_t in C++. In ChaiScript the return value is cast to int
/// for ease of use.
int size() const;
/// \brief Returns an object that implements the Range concept for the characters of this string
Range range();
/// \brief Returns an object that implements the Const_Range concept for the characters of this string
Const_Range range() const;
};
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
/// easy iteration over the elements in a container.
///
/// Implemented by the template chaiscript::bootstrap::standard_library::Bidir_Range
///
/// \sa Const_Range
class Range
{
public:
/// \brief Returns the last item of the range
Object back();
/// \brief Returns true if the front and back pointers have passed each other, if no items
/// are left in the Range
bool empty() const;
/// \brief Returns the first item of the range
Object front();
/// \brief Moves the back pointer back one.
///
/// \post back() returns the element at back() - 1;
void pop_back();
/// \brief Moves the front pointer forward one
///
/// \post front() returne the element at front() + 1;
void pop_front();
};
/// \brief A concept in ChaiScript that is implemented by \ref string, Vector and Map. It provides
/// easy iteration over the elements in a container. Contained values are const.
///
/// Implemented by the template chaiscript::bootstrap::standard_library::Const_Bidir_Range
///
/// \sa Range
class Const_Range
{
public:
/// \brief Returns the last item of the range
const Object back();
/// \brief Returns true if the front and back pointers have passed each other, if no items
/// are left in the Range
bool empty() const;
/// \brief Returns the first item of the range
const Object front();
/// \brief Moves the back pointer back one.
///
/// \post back() returns the element at back() - 1;
void pop_back();
/// \brief Moves the front pointer forward one
///
/// \post front() returne the element at front() + 1;
void pop_front();
};
/// \brief A vector of Objects
///
/// ChaiScript includes a shortcut for creating a Vector of Objects
///
/// Example:
/// \code
/// eval> var v = [1,2,3,4]
/// [1, 2, 3, 4]
/// eval> v[0];
/// 1
/// eval> v.size();
/// 4
/// \endcode
///
/// Implemented with std::vector<chaiscript::Boxed_Value>
///
/// \sa chaiscript::bootstrap::standard_library::vector_type
class Vector
{
public:
/// \brief returns the Object at the given index. Throws an exception if the index does not exist
Object operator[](int t_index);
/// \brief returns a const Object at the given index. Throws an exception if the index does not exist.
const Object operator[](int t_index) const;
/// \brief returns the last item in the Vector
Object back();
/// \brief Clears the Vector of all items
void clear();
/// \brief Returns true if the Vector is contains 0 items
bool empty();
/// \brief Erases the element at the given index
void erase_at(int t_index);
/// \brief Returns the first item in the Vector
Object front();
/// \brief Inserts a new item in the Vector at the given index. The item is not cloned on insert
///
/// \sa insert_ref
void insert_ref_at(int, Object);
/// \brief Inserts a new item in the Vector at the given index. The item is cloned on insert
///
/// \sa insert_ref
void insert_at(int, Object);
/// \brief Removes the last item from the Vector
void pop_back();
/// \brief Adds an item to the end of the Vector. The item is not cloned.
///
/// \sa push_back
void push_back_ref(Object);
/// \brief Adds an item to the end of the Vector. The item is cloned.
///
/// \sa push_back_ref
void push_back(Object);
/// \brief Returns a Range object for the entire vector
Range range();
/// \brief Returns a Const_Range object for the entire vector
Const_Range range() const;
/// \brief Returns the number of elements in the Vector
int size() const;
};
class Type_Info
{
public:
/// \brief Compares this Type_Info object with another one and returns true if the two types are the same
/// after const, pointer, reference are removed.
bool bare_equal(Type_Info t_ti) const;
/// \brief Returns the mangled C++ name for the type given by the compiler after const, pointer, reference is removed.
string cpp_bare_name() const;
/// \brief Returns the mangled C++ name for the type given by the compiler.
string cpp_name() const;
/// \brief Returns true if the type is const
bool is_type_const() const;
/// \brief Returns true if the type is a pointer
bool is_type_pointer() const;
/// \brief Returns true if the type is a reference
bool is_type_reference() const;
/// \brief Returns true if the type is undefined
bool is_type_undef() const;
/// \brief Returns true if the type is "void"
bool is_type_void() const;
/// \brief Returns the ChaiScript registered name for the type if one exists.
string name() const;
};
/// \brief Represents a function object in ChaiScript
///
/// A function object may be one function, such as:
/// \code
/// var f = fun(x) { return x; }
/// \endcode
///
/// Or it may represent multiple functions
/// \code
/// var f2 = `-`; // represents the unary - as well as the set of binary - operators
/// \endcode
///
/// Guarded function example
/// \code
/// def f3(x) : x > 2 {
/// return x;
/// }
/// \endcode
///
/// Examples in the function definitions below will reference these examples
class Function
{
public:
/// \brief Returns the annotation description of the function
string get_annotation() const;
/// \brief Returns the arity of the function, -1 if the function takes a variable number of parameters
///
/// Example:
/// \code
/// eval> f.get_arity()
/// 1
/// eval> f2.get_arity()
/// -1
/// \endcode
int get_arity() const;
/// \brief Returns a vector of the contained functions
///
/// Example:
/// \code
/// eval> f.get_contained_functions().size()
/// 0
/// eval> f2.get_contained_functions().size()
/// 11
/// eval> var v = f2.get_contained_functions();
/// v[0].get_arity()
/// 2
/// \endcode
Vector get_contained_functions() const;
/// \brief Returns a vector of the contained functions
///
/// Example:
/// \code
/// eval> f.get_guard() // Throws exception
/// Function does not have a guard
/// eval> f3.get_guard().get_arity()
/// 1
/// \endcode
Function get_guard() const;
/// \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.
///
/// 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
/// the same arity, then it represents the arity. If they have different arities, it returns only
/// one value - the return type.
///
/// For each parameter that is the same type, the type is returned. If the types are different
/// then a Type_Info for Object is returned.
///
/// Example:
/// \code
/// eval> f2.get_param_types().size(); // Returns a Type_Info for Object for the return type
/// 1
/// \endcode
Vector get_param_types() const;
/// \brief Returns true if the function has a guard to it. Always returns false for a conglomerate function
bool has_guard() const;
/// \brief Calls the function with the given set of parameters and returns the value;
///
/// Example:
/// \code
/// eval> `-`.call([2,1]);
/// 1
/// \endcode
Object call(Vector t_params) const;
}
/// \brief Returns the max of a or b. Requires that operator>(a, b) exists
/// Equivalent to
/// \code
/// return a>b?a:b;
/// \endcode
///
/// Example:
/// \code
/// eval> max(4, 10)
/// 10
/// \endcode
Object max(Object a, Object b);
/// \brief Returns the min of a or b. Requires that operator<(a, b) exists
///
/// Equivalent to
/// \code
/// return a<b?a:b;
/// \endcode
///
/// Example:
/// \code
/// eval> min(4, 10)
/// 4
/// \endcode
Object min(Object a, Object b);
/// \brief Returns true if x is an even integer.
///
/// Will also work on any non-integer type for which an operator%(x, int) exists
///
/// Example:
/// \code
/// eval> even(4)
/// true
/// \endcode
bool even(Object x);
/// \brief Returns true if x is an odd integer.
///
/// Will also work on any non-integer type for which an operator%(x, int) exists
///
/// Example:
/// \code
/// eval> odd(4)
/// false
/// \endcode
bool even(Object x);
/// \brief Applies the function f over each element in the Range c.
///
/// Example:
/// \code
/// eval> for_each([1, 2, 3], print)
/// 1
/// 2
/// 3
/// \endcode
void for_each(Range c, Function f);
/// \brief Applies f over each element in the Range c, joining all the results.
///
/// Example:
/// \code
/// eval> map([1, 2, 3], odd)
/// [true, false, true]
/// \endcode
Object map(Range c, Function f);
/// \brief Starts with the initial value and applies the function f to it and the first element of the Range c.
/// The result is then applied to the second element, and so on until the elements are exhausted.
///
/// Example:
/// \code
/// eval> foldl([1, 2, 3, 4], `+`, 0)
/// 10
/// \endcode
Object foldl(Range c, Function f, Object initial);
/// \brief Returns the sum total of the values in the Range c.
///
/// Example:
/// \code
/// eval> sum([1, 2, 3, 4])
/// 10
/// \endcode
///
/// Equivalent to:
/// \code
/// foldl(c, `+`, 0.0);
/// \endcode
Numeric sum(Range c);
/// \brief Returns the product of the value in the Range c.
///
/// Example:
/// \code
/// eval> product([1, 2, 3, 4])
/// 24
/// \endcode
///
/// Equivalent to:
/// \code
/// foldl(c, `*`, 1.0);
/// \endcode
Numeric product(Range c);
/// \brief Takes num elements from the Range c, returning them.
///
/// Example:
/// \code
/// eval> take([1, 2, 3, 4], 2)
/// [1, 2]
/// \endcode
///
/// \returns A container of the same type that was passed in
Object take(Range c, int num);
/// \brief Takes elements from the Range c that match function f, stopping at the first non-match, returning them as a new Vector.
///
/// Example:
/// \code
/// eval> take_while([1, 2, 3], odd)
/// [1]
/// \endcode
///
/// \returns A container of the same type that was passed in
Object take_while(Range c, Function f);
/// \brief Drops num elements from the Range c, returning the remainder.
///
/// Example:
/// \code
/// eval> drop([1, 2, 3, 4], 2)
/// [3, 4]
/// \endcode
///
/// \returns A container of the same type that was passed in
Object drop(Range c, int num);
/// \brief Drops elements from the Range c that match f, stopping at the first non-match, returning the remainder.
///
/// Example:
/// \code
/// eval> drop_while([1, 2, 3], odd)
/// [2, 3]
/// \endcode
Object drop_while(Range c, Function f);
/// \brief Similar to foldl, this takes the first two elements as its starting values for f. This assumes Range c has at least 2 elements.
///
/// Example:
/// \code
/// eval> reduce([1, 2, 3, 4], `+`)
/// 10
/// \endcode
Object reduce(Range c, Function f);
/// \brief Takes elements from Range c that match function f, return them.
///
/// Example:
/// \code
/// eval> filter([1, 2, 3, 4], odd)
/// [1, 3]
/// \endcode
Object filter(Range c, Function f);
/// \brief Joins the elements of the Range c into a string, delimiting each with the delim string.
///
/// Example:
/// \code
/// eval> join([1, 2, 3], "*")
/// 1*2*3
/// \endcode
string join(Range c, string delim);
/// \brief Returns the contents of the Container c in reversed order.
///
/// Example:
/// \code
/// eval> reverse([1, 2, 3, 4, 5, 6, 7])
/// [7, 6, 5, 4, 3, 2, 1]
/// \endcode
Container reverse(Container c);
/// \brief Generates a new Vector filled with values starting at x and ending with y.
///
/// Works on types supporting operator<=(x, y) and operator++(x)
///
/// Example:
/// \code
/// eval> generate_range(1, 10)
/// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
/// \endcode
Vector generate_range(Object x, Object y);
/// \brief Returns a new Range with x and y concatenated.
///
/// Example:
/// \code
/// eval> concat([1, 2, 3], [4, 5, 6])
/// [1, 2, 3, 4, 5, 6]
/// \endcode
Object concat(Range x, Range y);
/// \brief Returns a new Vector with x and y as its values.
///
/// Example:
/// \code
/// eval> collate(1, 2)
/// [1, 2]
/// \endcode
Vector collate(Object x, Object y);
/// \brief Applies f to elements of x and y, returning a new Vector with the result of each application.
///
/// Example:
/// \code
/// eval> zip_with(`+`, [1, 2, 3], [4, 5, 6])
/// [5, 7, 9]
/// \endcode
Vector zip_with(Function f, Range x, Range y);
/// \brief Collates elements of x and y, returning a new Vector with the result.
///
/// Example:
/// \code
/// eval> zip([1, 2, 3], [4, 5, 6])
/// [[1, 4], [2, 5], [3, 6]]
/// \endcode
Vector zip(Range x, Range y);
/// \brief returns true if there exists a call to the Function f that takes the given parameters
///
/// Example:
/// \code
/// eval> call_exists(`+`, 1, 2)
/// true
/// \endcode
bool call_exists(Function f, ...);
/// \brief Reverses a Range object so that the elements are accessed in reverse
Range retro(Range);
/// \brief Reverses a Const_Range object so that the elements are accessed in reverse
Const_Range retro(Const_Range);
/// \brief Raises the given object as an exception. Any type of object can be thrown.
///
/// Example:
/// \code
/// eval> try { throw(1); } catch (e) { print("Exception caught: " + to_string(e)); }
/// Exception caught: 1
/// \endcode
///
/// \sa \ref keywordtry
void throw(Object);
}

View File

@@ -0,0 +1,69 @@
// 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_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include <string>
#include <utility>
#include <vector>
#include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
namespace chaiscript
{
namespace utility
{
/// 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::functionoverload)), "functionoverload" },
/// {fun(static_cast<std::string(test::*)(int)>(&test::functionoverload)), "functionoverload" },
/// {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)
{
t_module.add(chaiscript::user_type<Class>(), t_class_name);
for(const chaiscript::Proxy_Function &ctor: t_constructors)
{
t_module.add(ctor, t_class_name);
}
for(const auto &fun: t_funcs)
{
t_module.add(fun.first, fun.second);
}
}
}
}
#endif

View File

@@ -1,4 +1,7 @@
Copyright 2009 Jason 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,196 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="chai-example"
ProjectGUID="{CE422E94-B360-4588-8C65-6A9BE80798F9}"
RootNamespace="chaiexample"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="C:\Programming\chaiscript\trunk\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\example.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Boost"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;C:\Programming\Boost\include\boost-1_38&quot;"
/>
<Tool
Name="VCLibrarianTool"
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
/>
<Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
/>
</VisualStudioPropertySheet>

View File

@@ -1,26 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chaiscript", "chaiscript.vcproj", "{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chai-example", "..\chai-example\chai-example.vcproj", "{CE422E94-B360-4588-8C65-6A9BE80798F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.ActiveCfg = Debug|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.Build.0 = Debug|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.ActiveCfg = Release|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.Build.0 = Release|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.ActiveCfg = Debug|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.Build.0 = Debug|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.ActiveCfg = Release|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,258 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="chaiscript"
ProjectGUID="{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
RootNamespace="chaiscript"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets=".\Boost.vsprops"
UseOfMFC="2"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UseUnicodeResponseFiles="false"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
DisableLanguageExtensions="true"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="4"
CompileAs="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets=".\Boost.vsprops"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\dispatchkit&quot;;&quot;$(ProjectDir)\..\..\chaiscript&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\main.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bootstrap.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bootstrap_stl.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\boxed_value.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\chaiscript.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_engine.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_eval.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_parser.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\language\chaiscript_prelude.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\dispatchkit.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\function_call.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\register_function.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\type_info.hpp"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

122
readme.md Normal file
View File

@@ -0,0 +1,122 @@
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
http://www.chaiscript.com
(c) 2009-2012 Jonathan Turner
(c) 2009-2015 Jason Turner
Release under the BSD license, see "license.txt" for details.
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
ground up to directly target C++ and take advantage of modern C++ development
techniques, working with the developer like he expects it to work. Being a
native C++ application, it has some advantages over existing embedded scripting
languages:
1. It uses a header-only approach, which makes it easy to integrate with
existing projects.
2. It maintains type safety between your C++ application and the user scripts.
3. It supports a variety of C++ techniques including callbacks, overloaded
functions, class methods, and stl containers.
Requirements
============
ChaiScript requires a C++11 compiler to build with support for variadic
templates. It has been tested with gcc 4.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
=====
* Add the ChaiScript include directory to your project's header search path
* Add `#include <chaiscript/chaiscript.hpp>` to your source file
* Instantiate the ChaiScript engine in your application. For example, create a
new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
* The default behavior is to load the ChaiScript standard library from a
loadable module. A second option is to compile the library into your code,
see below for an example.
Once instantiated, the engine is ready to start running ChaiScript source. You
have two main options for processing ChaiScript source: a line at a time using
`chai.eval(string)` and a file at a time using `chai.eval_file(fname)`
To make functions in your C++ code visible to scripts, they must be registered
with the scripting engine. To do so, call add:
chai.add(chaiscript::fun(&my_function), "my_function_name");
Once registered the function will be visible to scripts as "my_function_name"
Examples
========
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some
modifications to make it easier to use. For usage examples see the "samples"
directory, and for more in-depth look at the language, the unit tests in the
"unittests" directory cover the most ground.
For examples of how to register parts of your C++ application, see
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
possible way of working with the library. For further documentation generate
the doxygen documentation in the build folder or see the website
http://www.chaiscript.com.
The shortest complete example possible follows:
/// main.cpp
#include <chaiscript/chaiscript.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}
Or, if you want to compile the std lib into your code, which reduces
runtime requirements.
/// main.cpp
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}

View File

@@ -1,36 +0,0 @@
ChaiScript v1.0
http://www.chaiscript.com
(c) 2009 Jason Turner and Jonathan Turner
Release under the BSD license, see "license.txt" for details.
[Introduction]
ChaiScript is one of the first (and perhaps only) embedded scripting language designed from the ground up to directly target C++. Being a native C++ application, it has some advantages over existing embedded scripting languages:
1) It uses a header-only approach, which makes it easy to integrate with existing projects.
2) It maintains type safety between your C++ application and the user scripts.
3) It supports a variety of C++ techniques including callbacks, overloaded functions, class methods, and stl containers.
[Requirements]
ChaiScript requires a recent version of Boost (http://www.boost.org) to build.
[Usage]
* Add the ChaiScript include directory to your project's header search path
* Add "#include <chaiscript/chaiscript.hpp> to your source file
* Instantiate the ChaiScript engine in your application. For example, create a new engine with the name 'chai' like so: "chaiscript::ChaiScript_Engine chai"
Once instantiated, the engine is ready to start running ChaiScript source. You have two main options for processing ChaiScript source: a line at a time using "chai.evaluate_string(string)" and a file at a time using "chai.evaluate_file(fname)"
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call register_function:
dispatchkit::register_function(chai.get_eval_engine(), &my_function, "my_function_name");
Once registered the function will be visible to scripts as "my_function_name"
[Examples]
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some modifications to make it easier to use. For usage examples see the "samples" directory, and for more in-depth look at the language, the unit tests in the "unittests" directory cover the most ground.
For example of how to register parts of your C++ application, see "example.cpp" in the "src" directory.

156
releasenotes.md Normal file
View File

@@ -0,0 +1,156 @@
Notes:
=======
Current Version: 5.6.0
### 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,25 +0,0 @@
#!/bin/bash
successes=0
failures=0
echo -n "Running unit tests"
for file in unittests/*.chai
do
tstname=${file%.*}
tst="$tstname.txt"
./chaiscript_eval $file > /tmp/tstout.txt
diff $tst /tmp/tstout.txt
if [ "$?" -eq "0" ]
then
echo -n "."
successes=$((successes+1))
else
echo "[from failed test $file]"
failures=$((failures+1))
fi
done
echo ""
total=$((successes+failures))
echo "$successes out of $total succeeded"

View File

@@ -1,22 +0,0 @@
def add(x, y)
{
return x + y;
}
var b = bind(add, 2, _);
var c = bind(b, 3);
print(b(4));
print(c());
def concat(a,b,c,d)
{
return to_string(a) + to_string(b) + to_string(c) + to_string(d);
}
var d = bind(concat, _, " Hello ", _, " World ");
print(d(1, 3));
//This checks to make sure arity is handled correctly:
//print(d(1, 3, 4));

View File

@@ -1,3 +1,2 @@
var i = 1 var i = 1
var j = eval("5 + 4") var j = eval("5 + 4")
print(j)

176
samples/example.cpp Normal file
View File

@@ -0,0 +1,176 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <iostream>
#include <ctime>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/dispatchkit/function_call.hpp>
void log(const std::string &msg)
{
std::cout << "[" << time(nullptr) << "] " << msg << '\n';
}
void log(const std::string &module, const std::string &msg)
{
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
}
void bound_log(const std::string &msg)
{
log(msg);
}
void hello_world(const chaiscript::Boxed_Value & /*o*/)
{
std::cout << "Hello World\n";
}
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
{
std::cout << "Hello Constructor\n";
}
struct System
{
std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
void add_callback(const std::string &t_name,
const std::function<std::string (const std::string &)> &t_func)
{
m_callbacks[t_name] = t_func;
}
void do_callbacks(const std::string &inp)
{
log("Running Callbacks: " + inp);
for (std::map<std::string, std::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
itr != m_callbacks.end();
++itr)
{
log("Callback: " + itr->first, itr->second(inp));
}
}
};
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
{
std::cout << *p << '\n';
}
int main(int /*argc*/, char * /*argv*/[]) {
using namespace chaiscript;
ChaiScript chai;
//Create a new system object and share it with the chaiscript engine
System system;
chai.add(var(&system), "system");
//Add a bound callback method
chai.add(fun(&System::add_callback, system), "add_callback_bound");
//Register the two methods of the System structure.
chai.add(fun(&System::add_callback), "add_callback");
chai.add(fun(&System::do_callbacks), "do_callbacks");
chai.add(fun(&take_shared_ptr), "take_shared_ptr");
// Let's use chaiscript to add a new lambda callback to our system.
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
// in the "add_callback" function of struct System the chaiscript function is converted into a
// std::function, so it can be handled and called easily and type-safely
chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");
// Because we are sharing the "system" object with the chaiscript engine we have equal
// access to it both from within chaiscript and from C++ code
system.do_callbacks("TestString");
chai.eval("system.do_callbacks(\"TestString\");");
// The log function is overloaded, therefore we have to give the C++ compiler a hint as to which
// version we want to register. One way to do this is to create a typedef of the function pointer
// then cast your function to that typedef.
typedef void (*PlainLog)(const std::string &);
typedef void (*ModuleLog)(const std::string &, const std::string &);
chai.add(fun(PlainLog(&log)), "log");
chai.add(fun(ModuleLog(&log)), "log");
chai.eval("log(\"Test Message\")");
// A shortcut to using eval is just to use the chai operator()
chai("log(\"Test Module\", \"Test Message\");");
//Finally, it is possible to register any std::function as a system function, in this
//way, we can, for instance add a bound member function to the system
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
//Call bound version of do_callbacks
chai("do_callbacks()");
std::function<void ()> caller = chai.eval<std::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
caller();
//If we would like a type-safe return value from all call, we can use
//the templated version of eval:
int i = chai.eval<int>("5+5");
std::cout << "5+5: " << i << '\n';
//Add a new variable
chai("var scripti = 15");
//We can even get a handle to the variables in the system
int &scripti = chai.eval<int &>("scripti");
std::cout << "scripti: " << scripti << '\n';
scripti *= 2;
std::cout << "scripti (updated): " << scripti << '\n';
chai("print(\"Scripti from chai: \" + to_string(scripti))");
//To do: Add examples of handling Boxed_Values directly when needed
//Creating a functor on the stack and using it immediately
int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
std::stringstream ss;
ss << x;
log("Functor test output", ss.str());
chai.add(var(std::shared_ptr<int>()), "nullvar");
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
// test the global const action
chai.add_global_const(const_var(1), "constvar");
chai("def getvar() { return constvar; }");
chai("print( getvar() )");
//Ability to create our own container types when needed. std::vector and std::map are
//mostly supported currently
chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
// Test ability to register a function that excepts a shared_ptr version of a type
chai("take_shared_ptr(\"Hello World as a shared_ptr\");");
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
//Dynamic objects test
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
// chai.add(fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", std::placeholders::_1))), "attr");
chai.eval("var x = TestType()");
// chai.eval("x.attr = \"hi\"");
// chai.eval("print(x.attr)");
chai.eval("x.hello_world()");
}

View File

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

View File

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

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;
}

View File

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

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

View File

@@ -0,0 +1,91 @@
#include <iostream>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
#include <readline/history.h>
#endif
std::string get_next_command() {
#ifdef READLINE_AVAILABLE
char *input_raw;
input_raw = readline("eval> ");
add_history(input_raw);
return std::string(input_raw);
#else
std::string retval;
std::cout << "eval> ";
std::getline(std::cin, retval);
return retval;
#endif
}
void function(void)
{
// do nothing
}
class test
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript::State backupState;
public:
test()
: chai(chaiscript::Std_Lib::library())
{
backupState = chai.get_state();
}
~test(){}
void ResetState()
{
chai.set_state(backupState);
chai.add(chaiscript::fun(&function),"Whatever()");
}
void RunFile(std::string sFile)
{
try {
chaiscript::Boxed_Value val = chai.eval_file(sFile);
}
catch (std::exception &e) {
std::cout << e.what() << '\n';
}
}
};
int main(int /*argc*/, char * /*argv*/[]) {
test myChai;
std::string command = "";
//
// this loop increases memory usage, if RunFile is not called (just hitting enter)
// as soon RunFile gets called, memory will be freed.
//
// scenario1 - RunFile gets called every Loop: memory usage does not change
// scenario2 - RunFile gets never called (just hitting enter): memory usage increases every loop
// scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as
// low as in case 1 scenario3 :
while(command != "quit")
{
for(int i = 1; i < 200; i++)
myChai.ResetState();
if(command == "runfile")
myChai.RunFile("Test.chai");
command = get_next_command();
}
}

View File

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

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();
} }
} }

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