Compare commits

...

607 Commits

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

Closes #198
2015-08-01 10:05:38 -06:00
Jason Turner
9d17b18f26 add failing tests for #198
1<-1 fails to parse
2015-08-01 10:04:42 -06:00
Jason Turner
31b3195c17 Don't allow conversion to std::function on arity mismatch 2015-07-30 20:23:34 -06:00
Jason Turner
0d4e4090a0 Massive reorg of file position tracking
- Should make iterator errors almost impossible in the future
 - Fixes tracking of current line number
2015-07-30 16:53:27 -06:00
Jason Turner
b946af42cc Update fuzzy_tests to take into acount parsing fixes 2015-07-24 12:09:20 -06:00
Jason Turner
22339d10db Make order of params eval well defined 2015-07-24 12:07:46 -06:00
Jason Turner
b3d2350f33 Add test for order of operations 2015-07-24 11:49:23 -06:00
Jason Turner
3cae2aed1d Remove unused Inplace Eval ast node 2015-07-23 15:34:45 -06:00
Jason Turner
c6f262c675 Parse in-string eval at regular parse time
- don't delay and overcomplicate with an eval
2015-07-23 15:21:39 -06:00
Jason Turner
8239206ec5 Update fuzzy_tests now with more parser fixes in 2015-07-22 15:42:31 -06:00
Jason Turner
a2ff672b34 Memory error fixes
* prevent recognizing . as a number
 * do all checked iterator operations for incrementing through input
   stream
 * Verify that all is as expected when building up a dot notation call
2015-07-22 11:13:10 -06:00
Jason Turner
9a0a12d230 Bump version number to 5.7.2 2015-07-20 19:50:13 -06:00
Jason Turner
7d3c23fc22 Merge pull request #196 from ChaiScript/develop
Make release v5.7.1
2015-07-17 15:40:54 -06:00
Jason Turner
63ab117e7d Add release notes for 5.7.1 2015-07-17 14:58:40 -06:00
Jason Turner
93e7eb3fe5 Merge pull request #195 from ChaiScript/multithreaded_performance
Save stack & and prevent lookups
2015-07-16 19:06:19 -06:00
Jason Turner
419c2d72a8 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into multithreaded_performance
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
2015-07-16 18:12:09 -06:00
Jason Turner
e1c382211a Merge pull request #194 from ChaiScript/crash_fixes
Add crashes and fixes found during fuzzy testing
2015-07-16 17:41:22 -06:00
Jason Turner
6a7a934e3e Merge branch 'develop' of github.com:ChaiScript/ChaiScript into multithreaded_performance
Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
2015-07-16 13:16:04 -06:00
Jason Turner
1f72afc8f5 Add crashes and fixes found during fuzzy testing
* Let unhandled exceptions propogate to user
 * Report eval_error when break statement is not in loop
 * Fix handling of 0 length scripts closes #193
 * Don't crash on arity mismatch - Specifically affects the case where no overloads exist for a given function
 * Fix error printing for `bind` calls
 * Handle unexpected continue statement
 * Check arity during bind
 * Don't allow arith conversion on variadic function
 * Correct `bind` parameter match count
 * Add in expected Boxed_Value exception cases
 * Check access to AST, don't allow `;` in func def
 * Don't attempt arithmetic unary & call
 * Don't crash on 0 param call to `bind`
 * Catch errors during member function dispatch
 * Properly handle type of const bool &
2015-07-16 12:51:50 -06:00
Jason Turner
2fbc377119 More strongly typed handling of push_back wrapper
Closes #192
2015-07-11 18:36:07 -06:00
Jason Turner
563999f3b8 Add note about handling of thread contexts 2015-07-11 18:34:09 -06:00
Jason Turner
1ea608babe Better detect arithmetic types #192 2015-07-11 18:32:47 -06:00
Jason Turner
51355343f1 Add intro docs to user defined type conversions 2015-07-11 16:37:54 -06:00
Jason Turner
fe33a6aacb Add failing test for issue #192 2015-07-11 14:51:29 -06:00
Jason Turner
e117f50db0 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-07-04 08:44:28 -06:00
Jason Turner
37120f486f Handle user defined conversions of return types from functor 2015-07-04 08:43:52 -06:00
Jason Turner
484ff7a98b Add utility for converting std::vector types 2015-07-03 14:39:21 -06:00
Jason Turner
496f5aff7a Add test for passing non-const ref param 2015-07-03 14:16:24 -06:00
Jason Turner
b270a198dc Don't clone return values into vector/map 2015-07-02 22:10:09 -06:00
Jason Turner
9e93d61236 Allow user to disable nothread warning 2015-07-02 21:18:36 -06:00
Jason Turner
72aedca39c Fix wrapping of functions with move only params 2015-06-29 20:43:12 -06:00
Jason Turner
748c18f465 Save stack & and prevent lookups 2015-06-28 15:17:58 -06:00
Jason Turner
b9875e2844 Miscellaneous performance tweaks 2015-06-28 13:20:20 -06:00
Jason Turner
902f48cd4c Revert "Use placement new to avoid unique_ptr allocations"
This reverts commit 83281bff52.
2015-06-24 11:25:56 -06:00
Jason Turner
1526ac96c1 Move to clang 3.6 address sanitizer 2015-06-23 16:49:58 -06:00
Jason Turner
e339055e0b Address some warnings for clang/gcc 2015-06-23 16:07:57 -06:00
Jason Turner
4890b47460 Reduce unary operator overhead 2015-06-23 14:25:34 -06:00
Jason Turner
b53432cf28 Remove remaining uses of std::function 2015-06-23 13:02:43 -06:00
Jason Turner
a112d97141 Simplify a couple of random things 2015-06-23 11:48:01 -06:00
Jason Turner
83281bff52 Use placement new to avoid unique_ptr allocations 2015-06-23 11:11:56 -06:00
Jason Turner
05bec3b4a8 Avoid attempting convert_down when not possible
@arBmind this should be significant for you
2015-06-21 21:09:26 -06:00
Jason Turner
cd2fb1ec66 Normalize integer types in the loc saving 2015-06-20 11:45:34 -06:00
Jason Turner
ec33cf2709 Make local location saving atomic 2015-06-20 10:52:05 -06:00
Jason Turner
c7689f18ec Save local variable location after first pass 2015-06-20 10:28:27 -06:00
Jason Turner
3eb7700912 Add missing <iterator> 2015-06-20 07:45:00 -06:00
Jason Turner
c4633436ba Avoid placeholder lookup cost 2015-06-20 07:13:54 -06:00
Jason Turner
2870874d91 Fix clang build errors 2015-06-20 06:53:23 -06:00
Jason Turner
a147278a7e Fix debug builds 2015-06-19 20:59:40 -06:00
Jason Turner
a2577b983c Don't constantly re-create the function objects 2015-06-19 20:31:39 -06:00
Jason Turner
646563eb3f A couple of cleanups and fixes 2015-06-19 20:10:45 -06:00
Jason Turner
f9860216c9 Move to std::vector for local stack objects 2015-06-19 16:49:16 -06:00
Jason Turner
b7eb469ac1 Move to some standard algorithms 2015-06-19 14:57:54 -06:00
Jason Turner
bcf573cf26 Don't loop over already filtered functions 2015-06-19 14:23:08 -06:00
Jason Turner
1bf4170d8f Simplify dispatch 2015-06-19 11:47:16 -06:00
Jason Turner
6d632f6aa4 Normalize methods for numeric->string conversions 2015-06-19 06:18:49 -06:00
Jason Turner
835b5a90af Reduce to_string overloads down to what is necessary 2015-06-18 21:47:05 -06:00
Jason Turner
9e743e3147 Set up links to codecov.io for coverage status 2015-06-18 15:45:03 -06:00
Jason Turner
7adbc11869 Merge pull request #188 from ChaiScript/wchar_t_2
Add support for char16, char32 and wchar
2015-06-18 14:07:13 -06:00
Jason Turner
2442e9ae20 Register all character types 2015-06-18 13:01:54 -06:00
Jason Turner
0dcac05f2f Add numeric support for wide characters 2015-06-18 11:57:58 -06:00
Jason Turner
60a497b0a6 Move to codecov 2015-06-16 17:09:07 -06:00
Jason Turner
11b372f526 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-06-16 17:03:42 -06:00
Jason Turner
3d36ea6199 Add back CONSTEXPR for Type_Info 2015-06-16 17:01:01 -06:00
Jason Turner
cebeebdb7a Minor cleanups and versioning info added 2015-06-13 16:56:22 -06:00
Jason Turner
e5ccec0e89 Merge pull request #185 from kamilzubair/patch-1
Add two new examples. Thank you @kamilzubair
2015-06-13 07:47:41 -06:00
kamilzubair
62ca26c36c Add two new examples
- Add example how to expose base member from derived type
- Add example how to use STL
2015-06-11 09:11:43 +07:00
Jason Turner
68fa049d6c Fix g++4.6 build 2015-06-10 19:26:21 -06:00
Jason Turner
88ab00679f Fix spelling of Windows.h for cross compiling
Closes #176
2015-06-10 18:49:54 -06:00
Jason Turner
86482b0103 Correct docs for 'filter'
Closes #183
2015-06-10 18:44:30 -06:00
Jason Turner
f9e0193353 Add map .at method from c++11
closes #184
2015-06-10 18:41:50 -06:00
Jason Turner
ba492308f4 Move from multimap to sorted vector in dispatch 2015-06-08 15:19:32 -06:00
Jason Turner
d4e22c2c2c Merge remote-tracking branch 'origin/remove_std_function' into develop
Conflicts:
	include/chaiscript/dispatchkit/boxed_number.hpp
2015-06-08 14:34:02 -06:00
Jason Turner
b95526951f Address warnings on VS
We have to ignore many of these warnings due to the nature of Boxed_Number supporting any operation.
2015-06-08 13:18:52 -06:00
Jason Turner
e4be97eb79 Revert "Remove redundant Boxed_Number type operations"
This reverts commit 59eecab0e8.
2015-06-04 11:04:21 -06:00
Jason Turner
59eecab0e8 Remove redundant Boxed_Number type operations 2015-06-04 08:28:38 -06:00
Jason Turner
be159759ea Further boxed_number simplification 2015-06-03 21:24:09 -06:00
Jason Turner
1e41e73af2 Simplify boxed_number templates 2015-06-03 19:17:58 -06:00
Jason Turner
78819fd3a8 fixed boxed_number to_string impl 2015-06-03 18:39:49 -06:00
Jason Turner
c6c2bcc023 More template reduction in Boxed_Number 2015-06-03 08:59:01 -06:00
Jason Turner
e759a0c544 Reduce template instantiations 2015-06-03 07:00:28 -06:00
Jason Turner
b163065b3c Begin simplifying boxed_number implementation 2015-06-03 06:25:41 -06:00
Jason Turner
ecafb4aad0 Add missing cstring 2015-06-02 18:20:13 -06:00
Jason Turner
38a83e3e56 Fix MSVC2013 builds 2015-06-02 17:35:31 -06:00
Jason Turner
bacf546dff Merge branch 'develop' into remove_std_function
Conflicts:
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2015-06-02 16:16:22 -06:00
Jason Turner
85a6d85c1f Fix warnings
- use `(void)` to avoid "unused parameter" warnings
 - Move to clang-3.6 for thread sanitizer - found bug in 3.5's reporting
2015-06-02 13:53:07 -06:00
Jason Turner
7522a19af5 g++4.6 correction 2015-06-01 16:08:04 -06:00
Jason Turner
26a0034176 Fixes for g++4.6 2015-06-01 16:07:10 -06:00
Jason Turner
cb5fbff1e6 Merge branch 'develop' into remove_std_function 2015-06-01 15:57:45 -06:00
Jason Turner
ff378abf84 Merge branch 'coverity_scan' into develop 2015-06-01 15:57:13 -06:00
Jason Turner
520f9bc0d2 Work around bug in g++4.6
I'm going to have to start dropping support for older compilers soon.

The 4.6 line is 4 years old now, and 4.7 has these issues fixed
2015-06-01 15:49:50 -06:00
Jason Turner
cf3db70d5d Merge branch 'develop' into remove_std_function
Conflicts:
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
2015-06-01 14:53:09 -06:00
Jason Turner
7026229273 Apply Index expansion technique to simplify code
Thanks @sean-parent I saw the technique in your future implementation
2015-06-01 09:43:29 -06:00
Jason Turner
da8fa77558 Update readme.md 2015-05-30 18:48:55 -06:00
Jason Turner
9fe8150861 Wrap up the coveralls / codecov choices 2015-05-30 18:48:27 -06:00
Jason Turner
d56e32e2c4 Tweak coveralls settings 2015-05-30 18:35:46 -06:00
Jason Turner
7f871374fa Codecov and coveralls enabled 2015-05-30 18:07:06 -06:00
Jason Turner
2848e16ea1 Another attempt at getting codecov working 2015-05-30 17:59:36 -06:00
Jason Turner
916708ce29 Disable coveralls, use codecov 2015-05-30 17:22:00 -06:00
Jason Turner
cff635fb65 Enable 'codecov' 2015-05-30 17:02:06 -06:00
Jason Turner
f6600c90e4 Correct missing 'sudo' for travis setup 2015-05-30 16:07:12 -06:00
Jason Turner
3701477f7f More cleanups to travis configuration 2015-05-30 16:03:23 -06:00
Jason Turner
d13d080dee Remove constexpr from type_info 2015-05-30 15:50:21 -06:00
Jason Turner
61d5e2ad85 Revert "Work around coverity crash"
This reverts commit bb0d100513.

Conflicts:
	include/chaiscript/dispatchkit/dispatchkit.hpp
	include/chaiscript/dispatchkit/type_info.hpp
2015-05-30 15:47:22 -06:00
Jason Turner
023a3edf40 Fix static usage of Type_Info objects 2015-05-30 15:36:25 -06:00
Jason Turner
4b577f1f2a Undefined types are never equal 2015-05-30 15:15:08 -06:00
Jason Turner
ac280a6971 Fix name() lookups 2015-05-30 14:14:48 -06:00
Jason Turner
d2f855e3f9 Cleanup g++-5 support for travis 2015-05-30 14:07:29 -06:00
Jason Turner
114e3939f6 Fix shell if command in travis 2015-05-30 13:55:34 -06:00
Jason Turner
ee672f5132 Further travis / coverity cleanups 2015-05-30 13:43:49 -06:00
Jason Turner
aa60cffe85 Add g++5.1 cleanup coverity use 2015-05-30 13:34:34 -06:00
Jason Turner
bb0d100513 Work around coverity crash
I'm not 100% convinced on these changes, but they might be for the
better.
2015-05-30 07:33:34 -06:00
Jason Turner
70326a5dff Try to distill travis / coverity settings 2015-05-30 06:32:14 -06:00
Jason Turner
cfc67f619a Travis 2015-05-29 23:08:27 -06:00
Jason Turner
1a02903b99 Another attempt with coverity support, add debugging 2015-05-29 22:47:53 -06:00
Jason Turner
f274d6beb3 Another attempt at coverity 2015-05-29 22:31:27 -06:00
Jason Turner
a04fe9d5a5 Fix env variables layout? 2015-05-29 22:19:59 -06:00
Jason Turner
f54bd484e6 Attempt to fix build matrix and coverity 2015-05-29 20:31:07 -06:00
Jason Turner
8ed4e6fad8 Fix coverity settings? 2015-05-29 20:17:13 -06:00
Jason Turner
c9312c0b7a Enable coverity scan? hopefully 2015-05-29 19:59:25 -06:00
Jason Turner
bb2938307c Move prelude into stdlib so it's not included everywhere 2015-05-23 16:16:39 -06:00
Jason Turner
919c3f2b4a Finish removing std::function and std::bind internally 2015-05-23 13:10:29 -06:00
Jason Turner
e0234d942e Various cleanups and fixes for older compilers 2015-05-22 19:40:56 -06:00
Jason Turner
df724b5c33 Completely remove Proxy_Function_Impl 2015-05-22 12:13:49 -06:00
Jason Turner
0b812942d4 Finish removing std::function<> 2015-05-22 11:35:58 -06:00
Jason Turner
48933bc32c Use std::ref to make free functions callable 2015-05-22 10:28:28 -06:00
Jason Turner
630c618ae7 Remove automagic wrapping to std::function<> 2015-05-22 09:39:21 -06:00
Jason Turner
03143a9f83 Phase one of getting rid of std::function usage 2015-05-22 09:30:42 -06:00
Jason Turner
33a929ef93 one more attempt to ignore catch.hpp from coverage 2015-05-20 20:06:06 -06:00
Jason Turner
e608d14a4f Attempt again to clean up coverage reporting 2015-05-20 18:43:28 -06:00
Jason Turner
e43b1b8d0d Make sure we are not also doing coverage testing on catch.hpp 2015-05-20 16:46:07 -06:00
Jason Turner
c32af523c3 Remove -n from coveralls call 2015-05-20 16:02:29 -06:00
Jason Turner
37b73f0e3c Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-05-20 15:04:22 -06:00
Jason Turner
13381ffa43 Add test, tweak coverage reporting 2015-05-20 15:04:04 -06:00
Jason Turner
2129c5318b Merge pull request #179 from ChaiScript/lambda_type_resolution
Lambda type resolution
2015-05-20 12:30:36 -06:00
Jason Turner
515ee711ce Remove unnecessary code 2015-05-20 12:00:41 -06:00
Jason Turner
bc8a4c42fa Get non-polymorphic Derived->Base conversions working 2015-05-20 11:08:07 -06:00
Jason Turner
051f483d20 Add failing non-polymorphic Derived->Base test 2015-05-20 09:48:46 -06:00
Jason Turner
da39b8403b Remove more usage of new 2015-05-19 14:15:21 -06:00
Jason Turner
5fa44d5eef Automatically deduce types of lambda for fun() 2015-05-19 13:47:34 -06:00
Jason Turner
dec88db26c Minor efficiency improvement by pre sizing match stack 2015-05-19 10:55:38 -06:00
Jason Turner
9da9012701 Fix version number mismatch 2015-05-13 06:20:25 -06:00
Jason Turner
f35c2fdb03 Update readme.md 2015-05-08 14:12:51 -06:00
Jason Turner
bb74d06b18 Merge pull request #177 from totalgee/patch-1
Fixing minor typos in cheatsheet
2015-05-08 08:04:32 -06:00
Glen Fraser
c21c21dfda Fixed minor typos in cheatsheet 2015-05-08 15:57:59 +02:00
Jason Turner
ef92b6619e Increment develop to 5.7.1 2015-05-06 14:18:28 -06:00
Jason Turner
fd2539145a Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2015-05-06 14:16:04 -06:00
Jason Turner
25f9dcf13e Add release notes for 5.7.0 2015-05-06 14:15:29 -06:00
Jason Turner
fc4b739839 Merge pull request #175 from totalgee/develop
Added elapsed time helper to chai executable
2015-05-06 09:50:06 -06:00
Glen Fraser
bd176cfde2 Renamed timer function to now(), added perf unit test 2015-05-06 11:37:37 +02:00
Jason Turner
04f01eee98 Add notes about literal numerics 2015-05-05 09:51:16 -06:00
Jason Turner
cf4efacbe8 Add 'GLOBAL' keyword #122
Also provides functionality that makes things like overriding the built in
'print' possible. See #67
2015-05-04 11:47:36 -06:00
Glen Fraser
b818799800 Added getTimeInSeconds() helper to chai executable 2015-05-04 19:41:25 +02:00
Jason Turner
fdcc5959c7 Fix tests failing w/MSVC2013 because of formatting 2015-05-03 10:31:10 -06:00
Jason Turner
74a992fad9 VS2015 thread_local doesn't seem ready for primetime yet 2015-05-03 08:43:43 -06:00
Jason Turner
d210f0e4e1 Enable thread_local in more cases, ignore clang warnings 2015-05-02 21:05:45 -06:00
Jason Turner
c0dd0a3041 Use static const true/false on platforms with magic statics 2015-05-02 15:27:51 -06:00
Jason Turner
45baf6f8e9 Global const values for booleans
- Reduces number of Boxed_Value constructions greatly
2015-05-02 13:08:23 -06:00
Jason Turner
e64e4b0877 Fix tests broken by last cleanup 2015-05-01 19:54:14 -06:00
Jason Turner
e286b9a9aa Never access data after moving it! 2015-05-01 07:22:43 -06:00
Jason Turner
d77921f1b5 Reorg of parsing code for maintainability / performance 2015-04-30 22:05:56 -06:00
Jason Turner
ebc6468178 Remove all /analyze from VS12, it's too slow
But still use it on VS14
2015-04-29 16:59:17 -06:00
Jason Turner
3e5034ecf8 Merge branch 'smaller_make_shared' into develop 2015-04-29 16:58:34 -06:00
Jason Turner
c52ad3d827 Merge pull request #174 from totalgee/develop
Support scientific notation for floating point (issue #173)
2015-04-29 16:50:39 -06:00
Glen Fraser
8fc61bf51c Fixing build error with tolower() on Windows 2015-04-29 21:52:34 +02:00
Jason Turner
dc6d039a72 Add documentation note workaround for libc++ 2015-04-29 13:41:58 -06:00
Jason Turner
2e72fde0ba Horrible workaround for libc++
Libc++ appears to have a problem with dynamic_casting between types
where one of them is a template that has been forward declared. This is
the only case that I see this problem coming up.

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

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

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

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

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

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

Results

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

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

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

42
.decent_ci-Linux.yaml Normal file
View File

@@ -0,0 +1,42 @@
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 -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "clang"
build_tag: "LibC++"
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "clang"
build_tag: AddressSanitizer
version: "3.6"
skip_packaging: true
cmake_extra_flags: -DRUN_FUZZY_TESTS:BOOL=TRUE -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
- name: "clang"
build_tag: ThreadSanitizer
version: "3.6"
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"
build_tag: "NoThreads"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF
collect_performance_results: true
- name: "gcc"
version: "4.8"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "gcc"
version: "4.6"
skip_packaging: true
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: cppcheck
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:unittests/catch.hpp" --force --suppress="unusedFunction:*"
- name: custom_check
commands:
- ./contrib/check_for_tabs.rb
- ./contrib/check_for_todos.rb

5
.decent_ci-MacOS.yaml Normal file
View File

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

27
.decent_ci-Windows.yaml Normal file
View File

@@ -0,0 +1,27 @@
compilers:
- name: Visual Studio
version: 14
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true
- name: Visual Studio
version: 14
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true
- name: Visual Studio
version: 12
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 12
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 14
build_type: Debug
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

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

41
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,41 @@
# Contributing to ChaiScript
Thank you for contributing!
# Pull Requests
Please follow the existing style in the code you are patching.
- two space indent
- no tabs EVER
- match the existing indentation level
All ChaiScript commits are run through a large set of builds and analysis on all supported platforms. Those results are posted on the
[build dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html). No PR will be accepted until all tests pass.
The build system has full integration with GitHub and you will be notified automatically if all tests have passed.
# Issues
Please do not post a "chaiscript is too slow", "chaiscript compiles too slowly", or "chaiscript needs more documentation" issue
without first reading the following notes.
## ChaiScript is Too Slow
We are actively working on constently improving the runtime performance of ChaiScript. With the performance being
[monitored with each commit](http://chaiscript.com/ChaiScript-BuildResults/performance.html).
If you feel you *must* post an issue about performance, please post a complete example that illustrates the exact case you
feel should be better optimized.
Any issue request regarding performance without a complete example of the issue experienced will be closed.
## ChaiScript Compiles Too Slowly
This is also something we are actively working on. If you need highly optimized build times, please see [this discussion
on the discourse site](http://discourse.chaiscript.com/t/slow-build-times/94).
## ChaiScript Needs More Documentation
If you have a question that is not addressed in the [cheatsheet](https://github.com/ChaiScript/ChaiScript/blob/develop/cheatsheet.md)
please open an issue so we can get the Cheatsheet updated.

10
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,10 @@
* Compiler Used:
* Operating System:
* Architecture (ARM/x86/32bit/64bit/etc):
### Expected Behavior
### Actual Behavior
### Minimal Example to Reproduce Behavior

8
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,8 @@
Issue this pull request references: #
Changes proposed in this pull request
-
-
-

View File

@@ -2,30 +2,55 @@ language: cpp
compiler:
- gcc
env:
- GCC_VER=4.6
- GCC_VER=4.8
matrix:
- GCC_VER="4.6"
- GCC_VER="4.8"
global:
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
- secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM="
before_install:
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
- 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
- sudo apt-get install -qq g++-$GCC_VER
script:
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug .
- make -j2
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi
- make test
- mkdir gcov
- find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \;
- $GCOV -d -o gcov gcov/*.gcda
- coveralls -n -E ".*\.cpp"
- if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
after_script:
- contrib/codeanalysis/runcppcheck.sh
- if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
notifications:
email:
recipients:
- jason@emptycrate.com
on_success: always
on_failure: always
env:
global:
secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
webhooks:
urls:
- https://webhooks.gitter.im/e/4be9a2720eaa1bb2a6c9
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
addons:
coverity_scan:
project:
name: "ChaiScript/ChaiScript"
description: "Build submitted via Travis CI"
notification_email: jason@emptycrate.com
build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . "
build_command: "cmake --build . -- -j2"
branch_pattern: coverity_scan

View File

@@ -1,18 +1,32 @@
cmake_minimum_required(VERSION 2.8)
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW)
endif()
IF(BIICODE)
INIT_BIICODE_BLOCK()
ADD_BIICODE_TARGETS()
ELSE()
# Your regular CMakeLists configuration here
project(chaiscript)
# MINGW does not yet support C++11's concurrency features
if(MINGW)
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" FALSE)
else()
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
endif()
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE)
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE)
mark_as_advanced(USE_STD_MAKE_SHARED)
if(USE_STD_MAKE_SHARED)
add_definitions(-DCHAISCRIPT_USE_STD_MAKE_SHARED)
endif()
if(CMAKE_COMPILER_IS_GNUCC)
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
@@ -36,11 +50,45 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
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(GPROF_OUTPUT "Generate profile data" FALSE)
if (GPROF_OUTPUT)
add_definitions(-pg)
set(LINKER_FLAGS "${LINKER_FLAGS} -pg")
endif()
option(PROFILE_GENERATE "Generate profile data" FALSE)
if (PROFILE_GENERATE)
add_definitions(-fprofile-generate)
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}")
@@ -54,8 +102,8 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 3)
set(CPACK_PACKAGE_VERSION_PATCH 1)
set(CPACK_PACKAGE_VERSION_MINOR 8)
set(CPACK_PACKAGE_VERSION_PATCH 2)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -75,16 +123,12 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest)
include(CPack)
include(cmake/CheckCXX11Features.cmake)
if(NOT MINGW)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
endif()
if(HAS_CXX11_VARIADIC_TEMPLATES)
message(STATUS "Variadic Template support detected")
else()
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
if (UNIX AND NOT APPLE)
find_program(VALGRIND NAMES valgrind PATH /usr/bin /usr/local/bin)
endif()
enable_testing()
@@ -114,7 +158,16 @@ else()
endif()
if(MSVC)
add_definitions(/W4 /w44640)
add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
if (MSVC_VERSION STREQUAL "1800")
# VS2013 doesn't have magic statics
add_definitions(/w44640)
else()
# enum warnings are too noisy on MSVC2013
add_definitions(/w34062)
endif()
add_definitions(/bigobj)
# Note on MSVC compiler flags.
# The code base selective disables warnings as necessary when the compiler is complaining too much
@@ -125,7 +178,13 @@ if(MSVC)
# 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 -pedantic ${CPP11_FLAG})
add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
else()
add_definitions(-Wnoexcept)
endif()
if(APPLE)
add_definitions(-Wno-sign-compare)
@@ -154,7 +213,7 @@ endif()
include_directories(include)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -201,8 +260,16 @@ add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
if(BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
target_link_libraries(test_num_exceptions ${LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS})
add_executable(inheritance samples/inheritance.cpp)
target_link_libraries(inheritance ${LIBS})
add_executable(factory samples/factory.cpp)
target_link_libraries(factory ${LIBS})
add_executable(fun_call_performance samples/fun_call_performance.cpp)
target_link_libraries(fun_call_performance ${LIBS})
endif()
@@ -210,16 +277,91 @@ if(BUILD_MODULES)
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS})
add_library(reflection MODULE src/reflection.cpp)
target_link_libraries(reflection ${LIBS})
set(MODULES stl_extra reflection)
set(MODULES stl_extra)
endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
list(SORT UNIT_TESTS)
file(GLOB PERFORMANCE_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/ ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/*.chai)
list(SORT PERFORMANCE_TESTS)
if (RUN_FUZZY_TESTS)
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
)
file(GLOB FUZZY_CRASH_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/id*)
list(SORT FUZZY_CRASH_TESTS)
file(GLOB FUZZY_EXCEPTION_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/id*)
list(SORT FUZZY_EXCEPTION_TESTS)
foreach(filename ${FUZZY_CRASH_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai "-e" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
endforeach()
set_property(TEST ${FUZZY_CRASH_TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_BINARY_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
foreach(filename ${FUZZY_EXCEPTION_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai "--exception" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
endforeach()
set_property(TEST ${FUZZY_EXCEPTION_TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
endif()
if(BUILD_TESTING)
# Add catch tests macro
macro(ADD_CATCH_TESTS executable)
if (MSVC)
file(TO_NATIVE_PATH "${QT_LIBRARY_DIR}" QT_LIB_PATH)
set(NEWPATH "${QT_LIB_PATH};$ENV{PATH}")
else()
set(NEWPATH $ENV{PATH})
endif()
get_target_property(target_files ${executable} SOURCES)
foreach(source ${target_files})
if(NOT "${source}" MATCHES "/moc_.*cxx")
string(REGEX MATCH .*cpp source "${source}")
if(source)
file(READ "${source}" contents)
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
foreach(hit ${found_tests})
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
add_test(compiled.${test_name} "${executable}" ${test_name})
set_tests_properties(compiled.${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
endforeach()
endif()
endif()
endforeach()
endmacro()
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
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) }")
@@ -229,80 +371,65 @@ if(BUILD_TESTING)
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
add_test(version_check_2 chai --version )
set_property(TEST version_check_2
PROPERTY ENVIRONMENT
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
PROPERTY PASS_REGULAR_EXPRESSION "${CHAI_VERSION}"
)
add_test(help chai --help )
set_property(TEST help
PROPERTY ENVIRONMENT
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
set(TESTS "")
foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
message(STATUS "Adding unit test ${filename}")
add_test(unit.${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
list(APPEND TESTS unit.${filename})
endforeach()
set_property(TEST ${UNIT_TESTS}
if (RUN_PERFORMANCE_TESTS)
foreach(filename ${PERFORMANCE_TESTS})
message(STATUS "Adding performance test ${filename}")
add_test(NAME performance.${filename} COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.${filename} $<TARGET_FILE:chai> ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/${filename})
list(APPEND TESTS performance.${filename})
endforeach()
add_executable(profile_cpp_calls_2 performance_tests/profile_cpp_calls_2.cpp)
target_link_libraries(profile_cpp_calls_2 ${LIBS})
add_test(NAME performance.profile_cpp_calls_2 COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_cpp_calls_2 $<TARGET_FILE:profile_cpp_calls_2>)
add_executable(profile_fun_wrappers performance_tests/profile_fun_wrappers.cpp)
target_link_libraries(profile_fun_wrappers ${LIBS})
add_test(NAME performance.profile_fun_wrappers COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_fun_wrappers $<TARGET_FILE:profile_fun_wrappers>)
endif()
set_property(TEST ${TESTS}
PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
)
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(compiled_tests unittests/compiled_tests.cpp)
target_link_libraries(compiled_tests ${LIBS})
ADD_CATCH_TESTS(compiled_tests)
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
target_link_libraries(dynamic_object_test ${LIBS})
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
target_link_libraries(functor_creation_test ${LIBS})
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
target_link_libraries(functor_cast_test ${LIBS})
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
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(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(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)
@@ -311,10 +438,6 @@ if(BUILD_TESTING)
target_link_libraries(integer_literal_test ${LIBS})
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp)
target_link_libraries(arithmetic_conversions_test ${LIBS})
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test)
if(MULTITHREAD_SUPPORT_ENABLED)
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
target_link_libraries(multithreaded_test ${LIBS})
@@ -366,3 +489,6 @@ configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @O
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
DESTINATION lib/pkgconfig)
ENDIF()

View File

@@ -40,7 +40,7 @@ PROJECT_NUMBER = ${CHAI_VERSION}
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = ${CMAKE_BINARY_DIR}/docs
PROJECT_BRIEF = "An easy to use embedded scripting language for C++."
# With the PROJECT_LOGO tag one can specify an logo or icon that is
# included in the documentation. The maximum height of the logo should not

29
LICENSE Normal file
View File

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

16
appveyor.yml Normal file
View File

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

5
biicode.conf Normal file
View File

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

435
cheatsheet.md Normal file
View File

@@ -0,0 +1,435 @@
# ChaiScript Versioning
ChaiScript tries to follow the [Semantic Versioning](http://semver.org/) scheme. This basically means:
* Major Version Number: API changes / breaking changes
* Minor Version Number: New Features
* Patch Version Number: Minor changes / enhancements
# Initializing ChaiScript
```
chaiscript::ChaiScript chai; // loads stdlib from loadable module on file system
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdlib
```
# Adding Things To The Engine
## Adding a Function / Method / Member
### General
```
chai.add(chaiscript::fun(&function_name), "function_name");
chai.add(chaiscript::fun(&Class::method_name), "method_name");
chai.add(chaiscript::fun(&Class::member_name), "member_name");
```
### With Overloads
#### Preferred
```
chai.add(chaiscript::fun<ReturnType (ParamType1, ParamType2)>(&function_with_overloads), "function_name");
```
#### Alternative
```
chai.add(chaiscript::fun(std::static_cast<ReturnType (*)(ParamType1, ParamType2)>(&function_with_overloads)), "function_name");
```
This overload technique is also used when exposing base member using derived type
```
struct Base
{
int data;
};
struct Derived : public Base
{};
chai.add(chaiscript::fun(static_cast<int(Derived::*)>(&Derived::data)), "data");
```
### Lambda
```
chai.add(
chaiscript::fun<std::string (bool)>(
[](bool type) {
if (type) { return "x"; }
else { return "y"; }
}), "function_name");
```
### Constructors
```
chai.add(chaiscript::constructor<MyType ()>(), "MyType");
chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
```
## Adding Types
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
```
chai.add(chaiscript::user_type<MyClass>(), "MyClass");
```
## Adding Type Conversions
User defined type conversions are possible, defined in either script or in C++.
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
```
chai.add(chaiscript::vector_conversion<std::vector<int>>());
```
A helper function also exists for strongly typed and ChaiScript `Map` function conversion definition:
```
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
```
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
## Adding Objects
```
chai.add(chaiscript::var(somevar), "somevar"); // copied in
chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared between C++ and chai
auto shareddouble = std::make_shared<double>(4.3);
chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai
chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const, throws if object exists
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists
chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object
```
# Using STL
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
```
typedef std::vector<std::pair<int, std::string>> data_list;
data_list my_list{ make_pair(0, "Hello"), make_pair(1, "World") };
chai.add(chaiscript::bootstrap::standard_library::vector_type<data_list>("DataList"));
chai.add(chaiscript::bootstrap::standard_library::pair_type<data_list::value_type>("DataElement"));
chai.add(chaiscript::var(&my_list), "data_list");
chai.eval(R"_(
for(var i=0; i<data_list.size(); ++i)
{
print(to_string(data_list[i].first) + " " + data_list[i].second)
}
)_");
```
# Executing Script
## General
```
chai.eval("print(\"Hello World\")");
chai.eval(R"(print("Hello World"))");
```
## Unboxing Return Values
Returns values are of the type `Boxed_Value` which is meant to be opaque to the programmer. Use one of the unboxing methods to access the internal data.
### Prefered
```
chai.eval<double>("5.3 + 2.1"); // returns 7.4 as a C++ double
```
### Alternative
```
auto v = chai.eval("5.3 + 2.1");
chai.boxed_cast<double>(v); // extracts double value from boxed_value and applies known conversions
chaiscript::boxed_cast<double>(v); // free function version, does not know about conversions
```
### Converting Between Algebraic Types
```
chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with any number type
// which is equivalent to, but much more automatic than:
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
```
### Conversion Caveats
Conversion to `std::shared_ptr<T> &` is supported for function calls, but if you attempt to keep a reference to a `shared_ptr<>` you might invoke undefined behavior
```cpp
// ok this is supported, you can register it with chaiscript engine
void nullify_shared_ptr(std::shared_ptr<int> &t) {
t == nullptr
}
```
```cpp
int main()
{
// do some stuff and create a chaiscript instance
std::shared_ptr<int> &ptr = chai.eval<std::shared_ptr<int> &>(somevalue);
// DO NOT do this. Taking a non-const reference to a shared_ptr is not
// supported and causes undefined behavior in the chaiscript engine
}
```
## Sharing Values
```
double &d = chai.eval("var i = 5.2; i"); // d is now a reference to i in the script
std::shared_ptr<double> d = chai.eval("var i = 5.2; i"); // same result but reference counted
d = 3;
chai.eval("print(i)"); // prints 3
```
## Catching Eval Errors
```
try {
chai.eval("2.3 + \"String\"");
} catch (const chaiscript::exception::eval_error &e) {
std::cout << "Error\n" << e.pretty_print() << '\n';
}
```
## Catching Errors Thrown From Script
```
try {
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
} catch (const double e) {
} catch (int) {
} catch (float) {
} catch (const std::string &) {
} catch (const std::exception &e) {
// This is the one what will be called in the specific throw() above
}
```
## Sharing Functions
```
auto p = chai.eval<std::function<std::string (double)>>("to_string");
p(5); // calls chaiscript's 'to_string' function, returning std::string("5")
```
Note: backtick treats operators as normal functions
```
auto p = chai.eval<std::function<int (int, int)>>(`+`);
p(5, 6); // calls chaiscript's '+' function, returning 11
```
```
auto p = chai.eval<std::function<std::string (int, double)>>("fun(x,y) { to_string(x) + to_string(y); }");
p(3,4.2); // evaluates the lambda function, returning the string "34.2" to C++
```
# Language Reference
## Variables
```
var i; // uninitialized variable, can take any value on first assignment;
auto j; // equiv to var
var k = 5; // initialized to 5 (integer)
var l := k; // reference to k
auto &m = k; // reference to k
global g = 5; // creates a global variable. If global already exists, it is not re-added
global g = 2; // global 'g' now equals 2
global g2;
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hit more than once
GLOBAL g3; // all upper case version also accepted
```
## Built in Types
```
var v = [1,2,3u,4ll,"16", `+`]; // creates vector of heterogenous values
var m = ["a":1, "b":2]; // map of string:value pairs
```
Floating point values default to `double` type and integers default to `int` type. All C++ suffixes
such as `f`, `ll`, `u` as well as scientific notation are supported
```
1.0 // double
1.0f // float
1.0l // long double
1 // int
1u // unsigned int
1ul // unsigned long
1ull // unsigned long long
```
Literals are automatically sized, just as in C++. For example: `10000000000` is > 32bits and the appropriate type is used to hold it
on your platform.
## Functions
Note that any type of ChaiScript function can be passed freely to C++ and automatically
converted into an `std::function` object.
### General
```
def myfun(x, y) { x + y; } // last statement in body is the return value
def myfun(x, y) { return x + y; } // equiv
```
### Optionally Typed
```
def myfun(x, int y) { x + y; } // requires y to be an int
```
### With Guards
```
def myfun(x, int y) : y > 5 { x - y; } // only called if y > 5
```
### Methods
Methods and functions are mostly equivalent
```
def string::add(int y) { this + to_string(y); }
def add(string s, int y) { s + to_string(y); } //equiv functionality
// calling new function/method
"a".add(1); // returns a1
add("a", 1); // returns a1, either calling syntax works with either def above
```
### Lambdas
```
var l = fun(x) { x * 15; }
l(2) // returns 30
var a = 13
var m = fun[a](x) { x * a; }
m(3); // a was captured (by reference), returns 39
var n = bind(fun(x,y) { x * y; }, _, 10);
n(2); // returns 20
```
## ChaiScript Defined Types
Define a type called "MyType" with one member value "a" and a getter
### Preferred
```
class MyType {
var value;
def MyType() { this.value = "a"; }
def get_value() { "Value Is: " + this.value; }
};
```
### Alternative
```
attr MyType::value;
def MyType::MyType() { this.value = "a"; }
def MyType::get_value() { "Value Is: " + this.value; }
```
### Using
```
var m = MyType(); // calls constructor
print(m.get_value()); // prints "Value Is: a"
print(get_value(m)); // prints "Value Is: a"
```
## Dynamic Objects
All ChaiScript defined types and generic Dynamic_Object support dynamic parameters
```
var o = Dynamic_Object();
o.f = fun(x) { print(x); }
o.f(3); // prints "3"
```
Implicit 'this' is allowed:
```
var o = Dynamic_Object();
o.x = 3;
o.f = fun(y) { print(this.x + y); }
o.f(10); // prints 13
```
### Option Explicit
If you want to disable dynamic parameter definitions, you can `set_explicit`.
```
class My_Class {
def My_Class() {
this.set_explicit(true);
this.x = 2; // this would fail with explicit set to true
}
};
```
## method_missing
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate
method cannot be found
```
def method_missing(int i, string name, Vector v) {
print("method_missing(${i}, ${name}), ${v.size()} params");
}
5.bob(1,2,3); // prints "method_missing(5, bob, 3 params)"
```
`method_missing` signature can be either 2 parameters or 3 parameters. If the signature contains two parameters
it is treated as a property. If the property contains a function then additional parameters are passed to
the contained function.
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
# Built In Functions
## Evaluation
```
eval("4 + 5") // dynamically eval script string and returns value of last statement
eval_file("filename") // evals file and returns value of last statement
use("filename") // evals file exactly once and returns value of last statement
// if the file had already been 'used' nothing happens and undefined is returned
```
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

11
contrib/check_for_tabs.rb Executable file
View File

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

11
contrib/check_for_todos.rb Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env ruby
require 'json'
`grep -rPIHni 'todo' src/* include/* samples/*`.lines { |line|
if /(?<filename>.+(hpp|cpp|chai)):(?<linenumber>[0-9]+):(?<restofline>.+)/ =~ line
puts(JSON.dump({:line => linenumber, :filename => filename, :tool => "todo_checker", :message => "todo: #{restofline.strip}", :messagetype => "info"}))
end
}

View File

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

View File

@@ -1,12 +1,12 @@
#!/bin/bash
pushd ..
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.64/cppcheck-1.65.tar.bz2
tar -xvf cppcheck-1.65.tar.bz2
cd cppcheck-1.65
make -j2
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.65/cppcheck --enable=all -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
../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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_
@@ -75,7 +75,7 @@
///
/// @subsection compiling Compiling ChaiScript Applications
///
/// ChaiScript is a header only library with only one dependecy: The
/// 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
@@ -112,7 +112,7 @@
///
/// @subsubsection evalmethod Method 'eval'
///
/// The eval method is somewhat more verbose and can be used to get typesafely return values
/// The eval method is somewhat more verbose and can be used to get type safely return values
/// from the script.
///
/// ~~~~~~~~{.cpp}
@@ -170,7 +170,7 @@
///
/// ~~~~~~~~~{.cpp}
/// chai.add_global_const(const_var(i), "i");
/// chai("def somefun() { print(i); }; sumfun();");
/// chai("def somefun() { print(i); }; somefun();");
/// ~~~~~~~~~
///
/// @subsubsection adding_functions Adding Functions
@@ -311,7 +311,7 @@
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
///
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
/// 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.
@@ -497,6 +497,21 @@
/// 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
@@ -648,6 +663,19 @@
///
/// @sa @ref LangObjectSystemRef
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordauto auto
///
/// Defines a variable
///
/// ~~~~~~~~
/// Variable ::= "auto" identifier
/// ~~~~~~~~
///
/// Synonym for @ref keywordvar
///
/// -----------------------------------------------------------------------
///
/// @section keywordbreak break
@@ -667,13 +695,13 @@
/// 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
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[type] arg ("," [type] 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.
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
/// guards: guarding statement that act as a prerequisite for the function. Optional.
/// { }: scoped block as function body. Required.
///
@@ -750,12 +778,13 @@
/// @section keywordtry try
/// ~~~~~~~~
/// Try Block ::= "try" block
/// ("catch" ["(" variable ")"] [":" guards] block)+
/// ("catch" ["(" [type] variable ")"] [":" guards] block)+
/// ["finally" block]
/// ~~~~~~~~
///
/// @sa ChaiScript_Language::throw
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordwhile while
@@ -767,6 +796,19 @@
/// ~~~~~~~~
///
/// This loop can be broken using the @ref keywordbreak command.
///
///
/// -----------------------------------------------------------------------
///
/// @section keywordvar var
///
/// Defines a variable
///
/// ~~~~~~~~
/// Variable ::= "var" identifier
/// ~~~~~~~~
///
/// Synonym for @ref keywordauto
/// @namespace chaiscript

View File

@@ -1,28 +1,71 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DEFINES_HPP_
#define CHAISCRIPT_DEFINES_HPP_
#ifdef _MSC_VER
#define CHAISCRIPT_STRINGIZE(x) "" #x
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEC
#if _MSC_VER <= 1800
#define CHAISCRIPT_MSVC_12
#endif
#else
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
#endif
#ifndef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_HAS_MAGIC_STATICS
#endif
#include <vector>
#if defined( _LIBCPP_VERSION )
#define CHAISCRIPT_LIBCPP
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
#define CHAISCRIPT_WINDOWS
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
/// Currently only g++>=4.8supports this natively
#if defined(_WIN32)
#if defined(__llvm__)
#define CHAISCRIPT_COMPILER_NAME "clang(windows)"
#elif defined(__GNUC__)
#define CHAISCRIPT_COMPILER_NAME "gcc(mingw)"
#else
#define CHAISCRIPT_COMPILER_NAME "msvc"
#endif
#else
#if defined(__llvm__)
#define CHAISCRIPT_COMPILER_NAME "clang"
#elif defined(__GNUC__)
#define CHAISCRIPT_COMPILER_NAME "gcc"
#else
#define CHAISCRIPT_COMPILER_NAME "unknown"
#endif
#endif
#if (defined(CHAISCRIPT_MSVC) && !defined(CHAISCRIPT_MSVC_12)) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
/// Currently only g++>=4.8 supports this natively
/// \todo Make this support other compilers when possible
#define CHAISCRIPT_HAS_THREAD_LOCAL
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__)
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
#define CHAISCRIPT_GCC_4_6
#endif
#if defined(__llvm__)
#define CHAISCRIPT_CLANG
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG)
#define CHAISCRIPT_OVERRIDE override
#else
#define CHAISCRIPT_OVERRIDE
@@ -35,7 +78,7 @@
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#ifdef CHAISCRIPT_MSVC
#ifdef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_NOEXCEPT throw()
#define CHAISCRIPT_CONSTEXPR
#else
@@ -43,11 +86,107 @@
#define CHAISCRIPT_CONSTEXPR constexpr
#endif
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 3;
static const int version_patch = 1;
}
#ifdef _DEBUG
#define CHAISCRIPT_DEBUG true
#else
#define CHAISCRIPT_DEBUG false
#endif
#include <memory>
#include <string>
#include <cmath>
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 8;
static const int version_patch = 2;
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
static const bool debug_build = CHAISCRIPT_DEBUG;
template<typename B, typename D, typename ...Arg>
inline std::shared_ptr<B> make_shared(Arg && ... arg)
{
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
return std::make_shared<D>(std::forward<Arg>(arg)...);
#else
return std::shared_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
#endif
}
template<typename Iter, typename Distance>
Iter advance_copy(Iter iter, Distance distance) {
std::advance(iter, static_cast<typename std::iterator_traits<Iter>::difference_type>(distance));
return iter;
}
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
{
T t = 0;
for (char c = *t_str; (c = *t_str); ++t_str) {
if (c < '0' || c > '9') {
return t;
}
t *= 10;
t += c - '0';
}
return t;
}
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
{
T t = 0;
T base = 0;
T decimal_place = 0;
bool exponent = false;
bool neg_exponent = false;
const auto final_value = [](const T val, const T baseval, const bool hasexp, const bool negexp) -> T {
if (!hasexp) {
return val;
} else {
return baseval * std::pow(T(10), val*T(negexp?-1:1));
}
};
for(; *t_str != '\0'; ++t_str) {
char c = *t_str;
if (c == '.') {
decimal_place = 10;
} else if (c == 'e' || c == 'E') {
exponent = true;
decimal_place = 0;
base = t;
t = 0;
} else if (c == '-' && exponent) {
neg_exponent = true;
} else if (c == '+' && exponent) {
neg_exponent = false;
} else if (c < '0' || c > '9') {
return final_value(t, base, exponent, neg_exponent);
} else if (decimal_place < T(10)) {
t *= T(10);
t += T(c - '0');
} else {
t += (T(c - '0') / (T(decimal_place)));
decimal_place *= 10;
}
}
return final_value(t, base, exponent, neg_exponent);
}
template<typename T>
T parse_num(const std::string &t_str)
{
return parse_num<T>(t_str.c_str());
}
}
#endif

View File

@@ -18,6 +18,13 @@
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.chai"
#include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS
#include <future>
#endif
/// @file
///
@@ -40,6 +47,15 @@ namespace chaiscript
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([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
#endif
lib->add(json_wrap::library());
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
return lib;
}

View File

@@ -1,20 +1,25 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, 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
#ifndef CHAISCRIPT_NO_THREADS_WARNING
#pragma message ("ChaiScript is compiling without thread safety.")
#endif
#endif
#include "chaiscript_defines.hpp"
/// \file
///
@@ -40,14 +45,14 @@ namespace chaiscript
class unique_lock : public std::unique_lock<T>
{
public:
unique_lock(T &t) : std::unique_lock<T>(t) {}
explicit unique_lock(T &t) : std::unique_lock<T>(t) {}
};
template<typename T>
class shared_lock : public std::unique_lock<T>
{
public:
shared_lock(T &t) : std::unique_lock<T>(t) {}
explicit shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
@@ -55,7 +60,7 @@ namespace chaiscript
class lock_guard : public std::lock_guard<T>
{
public:
lock_guard(T &t) : std::lock_guard<T>(t) {}
explicit lock_guard(T &t) : std::lock_guard<T>(t) {}
};
class shared_mutex : public std::mutex { };
@@ -72,7 +77,7 @@ namespace chaiscript
{
public:
Thread_Storage(void *t_key)
explicit Thread_Storage(void *t_key)
: m_key(t_key)
{
}
@@ -82,16 +87,27 @@ namespace chaiscript
t().erase(m_key);
}
inline T *operator->() const
inline const T *operator->() const
{
return &(t()[m_key]);
}
inline T &operator*() const
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:
@@ -113,33 +129,45 @@ namespace chaiscript
{
public:
Thread_Storage(void *)
explicit Thread_Storage(void *)
{
}
inline T *operator->() const
inline const T *operator->() const
{
return get_tls().get();
}
inline T &operator*() const
inline const T &operator*() const
{
return *get_tls();
}
inline T *operator->()
{
return get_tls().get();
}
inline T &operator*()
{
return *get_tls();
}
private:
/// \todo this leaks thread instances. It needs to be culled from time to time
std::shared_ptr<T> get_tls() const
{
unique_lock<mutex> lock(m_mutex);
auto itr = m_instances.find(std::this_thread::get_id());
const auto id = std::this_thread::get_id();
auto itr = m_instances.find(id);
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(new T());
std::shared_ptr<T> new_instance(std::make_shared<T>());
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
m_instances.insert(std::make_pair(id, new_instance));
return new_instance;
}
@@ -155,7 +183,7 @@ namespace chaiscript
class unique_lock
{
public:
unique_lock(T &) {}
explicit unique_lock(T &) {}
void lock() {}
void unlock() {}
};
@@ -164,7 +192,7 @@ namespace chaiscript
class shared_lock
{
public:
shared_lock(T &) {}
explicit shared_lock(T &) {}
void lock() {}
void unlock() {}
};
@@ -173,7 +201,7 @@ namespace chaiscript
class lock_guard
{
public:
lock_guard(T &) {}
explicit lock_guard(T &) {}
};
class shared_mutex { };
@@ -185,7 +213,7 @@ namespace chaiscript
class Thread_Storage
{
public:
Thread_Storage(void *)
explicit Thread_Storage(void *)
{
}

View File

@@ -26,9 +26,11 @@ namespace chaiscript {
{
}
bad_any_cast(const bad_any_cast &) = default;
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occured
/// \brief Description of what error occurred
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();
@@ -44,17 +46,30 @@ namespace chaiscript {
private:
struct Data
{
explicit Data(const std::type_info &t_type)
: m_type(t_type)
{
}
Data &operator=(const Data &) = delete;
virtual ~Data() {}
virtual void *data() = 0;
virtual const std::type_info &type() const = 0;
virtual std::shared_ptr<Data> clone() const = 0;
const std::type_info &type() const
{
return m_type;
}
virtual std::unique_ptr<Data> clone() const = 0;
const std::type_info &m_type;
};
template<typename T>
struct Data_Impl : Data
{
Data_Impl(T t_type)
: m_type(typeid(T)),
explicit Data_Impl(T t_type)
: Data(typeid(T)),
m_data(std::move(t_type))
{
}
@@ -66,23 +81,17 @@ namespace chaiscript {
return &m_data;
}
const std::type_info &type() const CHAISCRIPT_OVERRIDE
std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
{
return m_type;
}
std::shared_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
{
return std::shared_ptr<Data>(new Data_Impl<T>(m_data));
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
}
Data_Impl &operator=(const Data_Impl&) = delete;
const std::type_info &m_type;
T m_data;
};
std::shared_ptr<Data> m_data;
std::unique_ptr<Data> m_data;
public:
// construct/copy/destruct
@@ -98,12 +107,19 @@ namespace chaiscript {
}
}
template<typename ValueType>
Any(const ValueType &t_value)
: m_data(std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value)))
#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);
@@ -111,13 +127,6 @@ namespace chaiscript {
return *this;
}
template<typename ValueType>
Any & operator=(const ValueType &t_value)
{
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
return *this;
}
template<typename ToType>
ToType &cast() const
{
@@ -127,7 +136,6 @@ namespace chaiscript {
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
@@ -138,9 +146,7 @@ namespace chaiscript {
// modifiers
Any & swap(Any &t_other)
{
std::shared_ptr<Data> data = t_other.m_data;
t_other.m_data = m_data;
m_data = data;
std::swap(t_other.m_data, m_data);
return *this;
}

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
@@ -10,6 +10,7 @@
#include <string>
#include <typeinfo>
#include "../chaiscript_defines.hpp"
#include "type_info.hpp"
namespace chaiscript {
@@ -28,25 +29,26 @@ namespace chaiscript
class bad_boxed_cast : public std::bad_cast
{
public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
std::string t_what) CHAISCRIPT_NOEXCEPT
: from(t_from), to(&t_to), m_what(std::move(t_what))
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
{
}
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
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: " + t_from.name() + " to: " + t_to.name())
{
}
bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(nullptr), m_what(std::move(t_what))
{
}
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occured
/// \brief Description of what error occurred
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
@@ -14,115 +14,56 @@ namespace chaiscript
namespace detail
{
template<int>
struct Placeholder
template<typename T>
T* get_pointer(T *t)
{
};
template<>
struct Placeholder<1>
{
static decltype(std::placeholders::_1) value() { return std::placeholders::_1; }
};
template<>
struct Placeholder<2>
{
static decltype(std::placeholders::_2) value() { return std::placeholders::_2; }
};
template<>
struct Placeholder<3>
{
static decltype(std::placeholders::_3) value() { return std::placeholders::_3; }
};
template<>
struct Placeholder<4>
{
static decltype(std::placeholders::_4) value() { return std::placeholders::_4; }
};
template<>
struct Placeholder<5>
{
static decltype(std::placeholders::_5) value() { return std::placeholders::_5; }
};
template<>
struct Placeholder<6>
{
static decltype(std::placeholders::_6) value() { return std::placeholders::_6; }
};
template<>
struct Placeholder<7>
{
static decltype(std::placeholders::_7) value() { return std::placeholders::_7; }
};
template<>
struct Placeholder<8>
{
static decltype(std::placeholders::_8) value() { return std::placeholders::_8; }
};
template<>
struct Placeholder<9>
{
static decltype(std::placeholders::_9) value() { return std::placeholders::_9; }
};
template<>
struct Placeholder<10>
{
static decltype(std::placeholders::_10) value() { return std::placeholders::_10; }
};
template<int count, int maxcount, typename Sig>
struct Bind_First
{
template<typename F, typename ... InnerParams>
static std::function<Sig> bind(F f, InnerParams ... innerparams)
{
return Bind_First<count - 1, maxcount, Sig>::bind(f, innerparams..., Placeholder<maxcount - count + 1>::value());
}
};
template<int maxcount, typename Sig>
struct Bind_First<0, maxcount, Sig>
{
template<typename F, typename ... InnerParams>
static std::function<Sig> bind(F f, InnerParams ... innerparams)
{
return std::bind(f, innerparams...);
}
};
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
return t;
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
template<typename T>
T* get_pointer(const std::reference_wrapper<T> &t)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, 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, o);
return &t.get();
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O o)
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
{
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(std::forward<O>(o), std::forward<Param>(param)...);
}
);
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(o, std::forward<Param>(param)...);
});
}

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
@@ -10,21 +10,20 @@
#include <cstdint>
#include <exception>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>
#include <iterator>
#include "bad_boxed_cast.hpp"
#include "boxed_cast.hpp"
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "dispatchkit.hpp"
#include "dynamic_cast_conversion.hpp"
#include "type_conversions.hpp"
#include "dynamic_object.hpp"
#include "operators.hpp"
#include "proxy_constructors.hpp"
@@ -32,6 +31,8 @@
#include "proxy_functions_detail.hpp"
#include "register_function.hpp"
#include "type_info.hpp"
#include "../utility/utility.hpp"
#include "../language/chaiscript_common.hpp"
namespace chaiscript
{
@@ -44,23 +45,56 @@ namespace chaiscript
/// \param[in] v Boxed_Number to copy into the new object
/// \returns The newly created object.
template<typename P1>
std::shared_ptr<P1> construct_pod(Boxed_Number v)
std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
{
std::shared_ptr<P1> p(new P1());
Boxed_Value bv(p);
Boxed_Number nb(bv);
nb = v;
return p;
return std::make_shared<P1>(v.get_as<P1>());
}
}
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
ModulePtr array(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
typedef typename std::remove_extent<T>::type ReturnType;
const auto extent = std::extent<T>::value;
m->add(user_type<T>(), type);
m->add(fun(
[extent](T& t, size_t index)->ReturnType &{
if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
} else {
return t[index];
}
}
), "[]"
);
m->add(fun(
[extent](const T &t, size_t index)->const ReturnType &{
if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
} else {
return t[index];
}
}
), "[]"
);
m->add(fun(
[extent](const T &) {
return extent;
}), "size");
return m;
}
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(constructor<T (const T &)>(), type);
return m;
@@ -71,7 +105,7 @@ namespace chaiscript
/// \param[in,out] m module to add comparison operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
{
operators::equal<T>(m);
operators::greater_than<T>(m);
@@ -92,7 +126,7 @@ namespace chaiscript
/// \sa copy_constructor
/// \sa constructor
template<typename T>
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(constructor<T ()>(), type);
copy_constructor<T>(type, m);
@@ -104,16 +138,14 @@ namespace chaiscript
/// \param[in] type The name of the type
/// \param[in,out] m The Module to add the constructor to
template<typename T>
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&detail::construct_pod<T>), type);
return m;
}
/**
* to_string function for internal use. Uses ostream operator<<
*/
/// to_string function for internal use. Uses ostream operator<<
template<typename Input>
std::string to_string(Input i)
{
@@ -122,53 +154,60 @@ namespace chaiscript
return ss.str();
}
/**
* Internal function for converting from a string to a value
* uses ostream operator >> to perform the conversion
*/
/// Internal function for converting from a string to a value
/// uses ostream operator >> to perform the conversion
template<typename Input>
Input parse_string(const std::string &i)
auto parse_string(const std::string &i)
-> typename std::enable_if<
!std::is_same<Input, wchar_t>::value
&& !std::is_same<Input, char16_t>::value
&& !std::is_same<Input, char32_t>::value,
Input>::type
{
std::stringstream ss(i);
Input t;
ss >> t;
return t;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename Input>
auto parse_string(const std::string &)
-> typename std::enable_if<
std::is_same<Input, wchar_t>::value
|| std::is_same<Input, char16_t>::value
|| std::is_same<Input, char32_t>::value,
Input>::type
{
throw std::runtime_error("Parsing of wide characters is not yet supported");
}
/// Add all common functions for a POD type. All operators, and
/// common conversions
template<typename T>
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<T>(), name);
m->add(constructor<T ()>(), name);
m->add(constructor<T()>(), name);
construct_pod<T>(name, m);
m->add(fun(&to_string<T>), "to_string");
m->add(fun(&parse_string<T>), "to_" + name);
return m;
}
/**
* "clone" function for a shared_ptr type. This is used in the case
* where you do not want to make a deep copy of an object during cloning
* but want to instead maintain the shared_ptr. It is needed internally
* for handling of Proxy_Function object (that is,
* function variables.
*/
/// "clone" function for a shared_ptr type. This is used in the case
/// where you do not want to make a deep copy of an object during cloning
/// but want to instead maintain the shared_ptr. It is needed internally
/// for handling of Proxy_Function object (that is,
/// function variables.
template<typename Type>
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
{
return p;
}
/**
* Specific version of shared_ptr_clone just for Proxy_Functions
*/
/// Specific version of shared_ptr_clone just for Proxy_Functions
template<typename Type>
std::shared_ptr<typename std::remove_const<Type>::type>
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
@@ -178,11 +217,9 @@ namespace chaiscript
/**
* Assignment function for shared_ptr objects, does not perform a copy of the
* object pointed to, instead maintains the shared_ptr concept.
* Similar to shared_ptr_clone. Used for Proxy_Function.
*/
/// Assignment function for shared_ptr objects, does not perform a copy of the
/// object pointed to, instead maintains the shared_ptr concept.
/// Similar to shared_ptr_clone. Used for Proxy_Function.
template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
{
@@ -196,16 +233,12 @@ namespace chaiscript
}
}
/**
* Class consisting of only static functions. All default bootstrapping occurs
* from this class.
*/
/// Class consisting of only static functions. All default bootstrapping occurs
/// from this class.
class Bootstrap
{
private:
/**
* Function allowing for assignment of an unknown type to any other value
*/
/// Function allowing for assignment of an unknown type to any other value
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
{
if (lhs.is_undef())
@@ -218,19 +251,17 @@ namespace chaiscript
static void print(const std::string &s)
{
std::cout << s;
fwrite(s.c_str(), 1, s.size(), stdout);
}
static void println(const std::string &s)
{
std::cout << s << std::endl;
puts(s.c_str());
}
/**
* Add all arithmetic operators for PODs
*/
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
/// Add all arithmetic operators for PODs
static void opers_arithmetic_pod(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&Boxed_Number::equals), "==");
m->add(fun(&Boxed_Number::less_than), "<");
@@ -269,21 +300,22 @@ namespace chaiscript
}
/**
* Create a bound function object. The first param is the function to bind
* the remaining parameters are the args to bind into the
* result
*/
/// Create a bound function object. The first param is the function to bind
/// the remaining parameters are the args to bind into the result
static Boxed_Value bind_function(const std::vector<Boxed_Value> &params)
{
if (params.size() < 2)
{
throw exception::arity_error(static_cast<int>(params.size()), 2);
if (params.empty()) {
throw exception::arity_error(0, 1);
}
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1)
{
throw exception::arity_error(static_cast<int>(params.size()), f->get_arity());
}
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
}
@@ -291,29 +323,15 @@ namespace chaiscript
static bool has_guard(const Const_Proxy_Function &t_pf)
{
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_guard()) {
return true;
} else {
return false;
}
} else {
return false;
}
return pf && pf->get_guard();
}
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
{
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf && pf->get_guard())
{
if (pf->get_guard())
{
return pf->get_guard();
} else {
throw std::runtime_error("Function does not have a guard");
}
return pf->get_guard();
} else {
throw std::runtime_error("Function does not have a guard");
}
@@ -328,9 +346,7 @@ namespace chaiscript
return e.what();
}
/**
* Boolean specialization of internal to_string function
*/
/// Boolean specialization of internal to_string function
static std::string bool_to_string(bool b)
{
if (b)
@@ -357,48 +373,92 @@ namespace chaiscript
return vbv;
}
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
return pf && pf->get_parse_tree();
}
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf && pf->get_parse_tree())
{
return pf->get_parse_tree();
} else {
throw std::runtime_error("Function does not have a parse tree");
}
}
template<typename Function>
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
{
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
return [f](const dispatch::Proxy_Function_Base *b) {
return do_return_boxed_value_vector(f, b);
};
}
public:
/// \brief perform all common bootstrap functions for std::string, void and POD types
/// \param[in,out] m Module to add bootstrapped functions to
/// \returns passed in ModulePtr, or newly created one if default argument is used
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module()))
static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<void>(), "void");
m->add(user_type<bool>(), "bool");
m->add(user_type<Boxed_Value>(), "Object");
m->add(user_type<Boxed_Number>(), "Number");
m->add(user_type<Proxy_Function>(), "Function");
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
m->add(user_type<std::exception>(), "exception");
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m->add(user_type<std::out_of_range>(), "out_of_range");
m->add(user_type<std::logic_error>(), "logic_error");
m->add(chaiscript::base_class<std::exception, std::logic_error>());
m->add(chaiscript::base_class<std::logic_error, std::out_of_range>());
m->add(chaiscript::base_class<std::exception, std::out_of_range>());
m->add(user_type<std::runtime_error>(), "runtime_error");
m->add(chaiscript::base_class<std::exception, std::runtime_error>());
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::get_attr), "get_attr");
m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
m->eval("def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->eval(R""(
def Dynamic_Object::clone() {
auto &new_o = Dynamic_Object(this.get_type_name());
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
new_o;
}
)"");
m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard");
@@ -408,10 +468,16 @@ namespace chaiscript
m->add(fun(&Boxed_Value::is_const), "is_var_const");
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
m->add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m->add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
operators::equal<Type_Info>(m);
@@ -430,13 +496,17 @@ namespace chaiscript
basic_constructors<bool>("bool", m);
operators::assign<bool>(m);
operators::equal<bool>(m);
operators::not_equal<bool>(m);
m->add(fun(&to_string<const std::string &>), "internal_to_string");
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
m->add(fun(&Bootstrap::bool_to_string), "to_string");
m->add(fun(&unknown_assign), "=");
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
m->add(fun(&to_string<char>), "to_string");
m->add(fun(&Boxed_Number::to_string), "to_string");
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<long double>("long_double", m);
bootstrap_pod_type<float>("float", m);
@@ -444,8 +514,13 @@ namespace chaiscript
bootstrap_pod_type<long>("long", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<long long>("long_long", m);
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<wchar_t>("wchar_t", m);
bootstrap_pod_type<char16_t>("char16_t", m);
bootstrap_pod_type<char32_t>("char32_t", m);
bootstrap_pod_type<std::int8_t>("int8_t", m);
bootstrap_pod_type<std::int16_t>("int16_t", m);
bootstrap_pod_type<std::int32_t>("int32_t", m);
@@ -463,15 +538,88 @@ namespace chaiscript
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))),
"bind");
m->add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
m->add(fun(
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
t_lhs.assign(t_rhs);
}
), "="
);
m->add(fun(&Boxed_Value::type_match), "type_match");
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
return retval;
})), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
{ {fun(&File_Position::line), "line"},
{fun(&File_Position::column), "column"} }
);
chaiscript::utility::add_class<AST_Node>(*m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
{fun(&AST_Node::identifier), "identifier"},
{fun(&AST_Node::filename), "filename"},
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::to_string), "to_string"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_node.children.begin(), t_node.children.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
return retval;
})), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
return m;
}
};

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
/// \file
@@ -14,10 +14,8 @@
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
#include <functional>
#include <iterator>
#include <memory>
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <vector>
@@ -179,13 +177,13 @@ namespace chaiscript
/// Add Bidir_Range support for the given ContainerType
template<typename Bidir_Type>
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<Bidir_Type>(), type + "_Range");
copy_constructor<Bidir_Type>(type + "_Range", m);
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range");
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
m->add(fun(&Bidir_Type::empty), "empty");
m->add(fun(&Bidir_Type::pop_front), "pop_front");
@@ -228,12 +226,11 @@ namespace chaiscript
std::advance(itr, pos);
container.erase(itr);
}
}
}
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
@@ -244,19 +241,25 @@ namespace chaiscript
/// Add random_access_container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const;
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
//to throw an exception in an out of bounds condition.
m->add(
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
fun(
[](ContainerType &c, int index) -> typename ContainerType::reference {
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
m->add(
fun(std::function<typename ContainerType::const_reference (const ContainerType *, int)>
(std::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
fun(
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
return m;
}
@@ -265,9 +268,9 @@ namespace chaiscript
/// Add assignable concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Assignable.html
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
basic_constructors<ContainerType>(type, m);
copy_constructor<ContainerType>(type, m);
operators::assign<ContainerType>(m);
return m;
}
@@ -276,11 +279,11 @@ namespace chaiscript
/// Add container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Container.html
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{
m->add(fun( std::function<size_t (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
m->add(fun([](const ContainerType *a) { return a->size(); } ), "size");
m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
m->add(fun([](ContainerType *a) { a->clear(); } ), "clear");
return m;
}
@@ -288,7 +291,7 @@ namespace chaiscript
/// Add default constructable concept to the given Type
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(constructor<Type ()>(), type);
return m;
@@ -300,17 +303,17 @@ namespace chaiscript
/// Add sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Sequence.html
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
insert_name = "insert_ref_at";
} else {
insert_name = "insert_at";
}
m->add(fun(&detail::insert_at<ContainerType>),
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "insert_ref_at";
} else {
return "insert_at";
}
}());
m->add(fun(&detail::insert_at<ContainerType>), insert_name);
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
return m;
@@ -320,22 +323,36 @@ namespace chaiscript
/// Add back insertion sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
typedef typename ContainerType::reference (ContainerType::*backptr)();
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
std::string push_back_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
m->add(fun(static_cast<push_back>(&ContainerType::push_back)), push_back_name);
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
[&]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
m->eval(
"# Pushes the second value onto the container while making a clone of the value\n"
"def push_back(" + type + " container, x)\n"
"{ \n"
" if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_back_ref(x) \n"
" } else { \n"
" container.push_back_ref(clone(x)); \n"
" }\n"
"} \n"
);
return "push_back_ref";
} else {
return "push_back";
}
}());
m->add(fun(&ContainerType::pop_back), "pop_back");
return m;
}
@@ -345,24 +362,38 @@ namespace chaiscript
/// Front insertion sequence
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
typedef typename ContainerType::reference (ContainerType::*frontptr)();
typedef void (ContainerType::*pushptr)(typename ContainerType::const_reference);
typedef void (ContainerType::*popptr)();
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
typedef void (ContainerType::*pop_ptr)();
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
std::string push_front_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_front_name = "push_front_ref";
} else {
push_front_name = "push_front";
}
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
[&]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
m->eval(
"# Pushes the second value onto the front of container while making a clone of the value\n"
"def push_front(" + type + " container, x)\n"
"{ \n"
" if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_front_ref(x) \n"
" } else { \n"
" container.push_front_ref(clone(x)); \n"
" }\n"
"} \n"
);
return "push_front_ref";
} else {
return "push_front";
}
}());
m->add(fun(static_cast<pushptr>(&ContainerType::push_front)), push_front_name);
m->add(fun(static_cast<popptr>(&ContainerType::pop_front)), "pop_front");
m->add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
return m;
}
@@ -370,7 +401,7 @@ namespace chaiscript
/// bootstrap a given PairType
/// http://www.sgi.com/tech/stl/pair.html
template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<PairType>(), type);
@@ -393,7 +424,7 @@ namespace chaiscript
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
@@ -404,7 +435,7 @@ namespace chaiscript
/// Add unique associative container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
{
m->add(fun(detail::count<ContainerType>), "count");
@@ -414,15 +445,16 @@ namespace chaiscript
m->add(fun(&detail::insert<ContainerType>), "insert");
std::string insert_name;
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value))
{
insert_name = "insert_ref";
} else {
insert_name = "insert";
}
m->add(fun(&detail::insert_ref<ContainerType>),
[]()->std::string{
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
return "insert_ref";
} else {
return "insert";
}
}());
m->add(fun(&detail::insert_ref<ContainerType>), insert_name);
return m;
}
@@ -430,15 +462,44 @@ namespace chaiscript
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<MapType>(), type);
typedef typename MapType::mapped_type &(MapType::*elemaccess)(const typename MapType::key_type &);
typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const;
m->add(fun(static_cast<elemaccess>(&MapType::operator[])), "[]");
m->add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
{
m->eval(R"(
def Map::`==`(Map rhs) {
if ( rhs.size() != this.size() ) {
return false;
} else {
auto r1 = range(this);
auto r2 = range(rhs);
while (!r1.empty())
{
if (!eq(r1.front().first, r2.front().first) || !eq(r1.front().second, r2.front().second))
{
return false;
}
r1.pop_front();
r2.pop_front();
}
true;
}
} )"
);
}
container_type<MapType>(type, m);
default_constructible_type<MapType>(type, m);
assignable_type<MapType>(type, m);
unique_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m);
@@ -451,7 +512,7 @@ namespace chaiscript
/// hopefully working List type
/// http://www.sgi.com/tech/stl/List.html
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<ListType>(), type);
@@ -470,12 +531,15 @@ namespace chaiscript
/// Create a vector type with associated concepts
/// http://www.sgi.com/tech/stl/Vector.html
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<VectorType>(), type);
typedef typename VectorType::reference (VectorType::*frontptr)();
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
back_insertion_sequence_type<VectorType>(type, m);
@@ -488,24 +552,26 @@ namespace chaiscript
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
{
m->eval("def Vector::`==`(rhs) : type_match(rhs, this) { \
if ( rhs.size() != this.size() ) { \
return false; \
} else { \
auto r1 = range(this); \
auto r2 = range(rhs); \
while (!r1.empty()) \
{ \
if (!eq(r1.front(), r2.front())) \
{ \
return false; \
} \
r1.pop_front(); \
r2.pop_front(); \
} \
return true; \
} \
}");
m->eval(R"(
def Vector::`==`(Vector rhs) {
if ( rhs.size() != this.size() ) {
return false;
} else {
auto r1 = range(this);
auto r2 = range(rhs);
while (!r1.empty())
{
if (!eq(r1.front(), r2.front()))
{
return false;
}
r1.pop_front();
r2.pop_front();
}
true;
}
} )"
);
}
return m;
@@ -514,7 +580,7 @@ namespace chaiscript
/// Add a String container
/// http://www.sgi.com/tech/stl/basic_string.html
template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<String>(), type);
operators::addition<String>(m);
@@ -528,32 +594,46 @@ namespace chaiscript
input_range_type<String>(type, m);
//Special case: add push_back to string (which doesn't support other back_insertion operations
std::string push_back_name;
if (typeid(typename String::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
m->add(fun(&String::push_back), push_back_name);
typedef std::function<size_t (const String *, const String &, size_t)> find_func;
m->add(fun(&String::push_back),
[]()->std::string{
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
return "push_back_ref";
} else {
return "push_back";
}
}());
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find(f, pos); } )), "find");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ) ), "rfind");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ) ), "find_first_of");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ) ), "find_last_of");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of");
m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
m->add(fun( std::function<void (String *)>( [](String *s) { return s->clear(); } ) ), "clear");
m->add(fun( std::function<bool (const String *)>( [](const String *s) { return s->empty(); } ) ), "empty");
m->add(fun( std::function<size_t (const String *)>( [](const String *s) { return s->size(); } ) ), "size");
m->add(fun([](String *s) { s->clear(); } ), "clear");
m->add(fun([](const String *s) { return s->empty(); } ), "empty");
m->add(fun([](const String *s) { return s->size(); } ), "size");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->c_str(); } ) ), "c_str");
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->data(); } ) ), "data");
m->add(fun( std::function<String (const String *, size_t, size_t)>( [](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ) ), "substr");
m->add(fun([](const String *s) { return s->c_str(); } ), "c_str");
m->add(fun([](const String *s) { return s->data(); } ), "data");
m->add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
return m;
}
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
template<typename FutureType>
ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
{
m->add(user_type<FutureType>(), type);
m->add(fun([](const FutureType &t) { return t.valid(); }), "valid");
m->add(fun(&FutureType::get), "get");
m->add(fun(&FutureType::wait), "wait");
return m;
}

View File

@@ -1,24 +1,21 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, 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 "dynamic_cast_conversion.hpp"
#include "type_conversions.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Dynamic_Cast_Conversions;
class Type_Conversions;
namespace detail {
namespace exception {
class bad_any_cast;
@@ -72,48 +69,38 @@ namespace chaiscript
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions = nullptr)
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *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 (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << std::endl;
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
} catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << std::endl;
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_down_cast<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
}
} else {
// If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#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>(t_conversions->saves(), bv), t_conversions);
} catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
}
} 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));
}
}
}

View File

@@ -1,13 +1,12 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, 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>
@@ -17,37 +16,33 @@
namespace chaiscript
{
class Dynamic_Cast_Conversions;
class Type_Conversions_State;
namespace detail
{
// Cast_Helper_Inner helper classes
/**
* Generic Cast_Helper_Inner, for casting to any type
*/
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;
typedef typename std::add_const<Result>::type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.is_ref())
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
if (!ob.get_type_info().is_const())
{
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
} else {
return ob.get().cast<std::reference_wrapper<const Result> >();
}
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
if (!ob.get_type_info().is_const())
{
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
} else {
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
}
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
@@ -57,105 +52,106 @@ namespace chaiscript
{
};
/**
* Cast_Helper_Inner for casting to a const & type
*/
template<typename Result>
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
{
};
/**
* Cast_Helper_Inner for casting to a const * type
*/
/// 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 Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.is_ref())
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
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();
}
return static_cast<const Result *>(ob.get_const_ptr());
} 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();
}
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
/**
* Cast_Helper_Inner for casting to a * type
*/
/// 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 Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.is_ref())
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
{
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
return static_cast<Result *>(ob.get_ptr());
} else {
return (ob.get().cast<std::shared_ptr<Result> >()).get();
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
/**
* Cast_Helper_Inner for casting to a & type
*/
template<typename Result>
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
{
};
template<typename Result>
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
{
};
/// Cast_Helper_Inner for casting to a & type
template<typename Result>
struct Cast_Helper_Inner<const Result &>
{
typedef const Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
/// 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 Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.is_ref())
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return ob.get().cast<std::reference_wrapper<Result> >();
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
} else {
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
return r;
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
/**
* Cast_Helper_Inner for casting to a std::shared_ptr<> type
*/
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
template<typename Result>
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
struct Cast_Helper_Inner<std::shared_ptr<Result> >
{
typedef typename std::shared_ptr<Result> Result_Type;
typedef std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob.get().cast<std::shared_ptr<Result> >();
}
};
/**
* Cast_Helper_Inner for casting to a std::shared_ptr<const> type
*/
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
template<typename Result>
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
{
typedef typename std::shared_ptr<const Result> Result_Type;
typedef std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const())
{
@@ -166,9 +162,7 @@ namespace chaiscript
}
};
/**
* Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
*/
/// 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> >
{
@@ -179,10 +173,22 @@ namespace chaiscript
{
};
template<typename Result>
struct Cast_Helper_Inner<std::shared_ptr<Result> &>
{
static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
/**
* Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
*/
typedef Boxed_Value::Sentinel<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
return ob.pointer_sentinel(res);
}
};
/// 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> >
{
@@ -194,24 +200,32 @@ namespace chaiscript
};
/**
* Cast_Helper_Inner for casting to a Boxed_Value type
*/
/// Cast_Helper_Inner for casting to a Boxed_Value type
template<>
struct Cast_Helper_Inner<Boxed_Value>
{
typedef const Boxed_Value & Result_Type;
typedef Boxed_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob;
return ob;
}
};
/**
* Cast_Helper_Inner for casting to a const Boxed_Value & type
*/
/// Cast_Helper_Inner for casting to a Boxed_Value & type
template<>
struct Cast_Helper_Inner<Boxed_Value &>
{
typedef std::reference_wrapper<Boxed_Value> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return std::ref(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>
{
@@ -223,9 +237,7 @@ namespace chaiscript
};
/**
* Cast_Helper_Inner for casting to a std::reference_wrapper type
*/
/// 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 &>
{
@@ -256,15 +268,13 @@ namespace chaiscript
{
};
/**
* The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
*/
/// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
template<typename T>
struct Cast_Helper
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,17 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
#define CHAISCRIPT_BOXED_VALUE_HPP_
#include <functional>
#include <map>
#include <memory>
#include <type_traits>
#include "../chaiscript_threading.hpp"
#include "../chaiscript_defines.hpp"
#include "any.hpp"
#include "type_info.hpp"
@@ -35,11 +34,12 @@ namespace chaiscript
struct Data
{
Data(const Type_Info &ti,
const chaiscript::detail::Any &to,
chaiscript::detail::Any to,
bool tr,
const void *t_void_ptr)
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
m_is_ref(tr)
const void *t_void_ptr,
bool t_return_value)
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
m_is_ref(tr), m_return_value(t_return_value)
{
}
@@ -50,76 +50,114 @@ namespace chaiscript
m_is_ref = rhs.m_is_ref;
m_data_ptr = rhs.m_data_ptr;
m_const_data_ptr = rhs.m_const_data_ptr;
m_return_value = rhs.m_return_value;
if (rhs.m_attrs)
{
m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*rhs.m_attrs));
}
return *this;
}
~Data()
{
}
Data(const Data &) = delete;
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
Data(Data &&) = default;
Data &operator=(Data &&rhs) = default;
#endif
Type_Info m_type_info;
chaiscript::detail::Any m_obj;
void *m_data_ptr;
const void *m_const_data_ptr;
std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>> m_attrs;
bool m_is_ref;
bool m_return_value;
};
struct Object_Data
{
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
{
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
chaiscript::detail::Any(),
false,
nullptr)
nullptr,
t_return_value)
;
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
{
return get(*obj);
return get(*obj, t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
{
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(obj),
false,
obj.get()
obj.get(),
t_return_value
);
}
template<typename T>
static std::shared_ptr<Data> get(T *t)
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
{
return get(std::ref(*t));
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
{
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(obj),
true,
&obj.get()
);
}
template<typename T>
static std::shared_ptr<Data> get(const T& t)
{
auto p = std::make_shared<T>(t);
auto ptr = obj.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(p),
chaiscript::detail::Any(std::move(obj)),
false,
p.get()
ptr,
t_return_value
);
}
template<typename T>
static std::shared_ptr<Data> get(T *t, bool t_return_value)
{
return get(std::ref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
{
return get(std::cref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
{
auto p = &obj.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
true,
p,
t_return_value
);
}
template<typename T>
static std::shared_ptr<Data> get(T t, bool t_return_value)
{
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,
t_return_value
);
}
@@ -129,7 +167,8 @@ namespace chaiscript
Type_Info(),
chaiscript::detail::Any(),
false,
nullptr
nullptr,
false
);
}
@@ -137,27 +176,26 @@ namespace chaiscript
public:
/// Basic Boxed_Value constructor
template<typename T>
explicit Boxed_Value(T t)
: m_data(Object_Data::get(t))
template<typename T,
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
explicit Boxed_Value(T &&t, bool t_return_value = false)
: m_data(Object_Data::get(std::forward<T>(t), t_return_value))
{
}
/// 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()
: 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)
{
@@ -172,72 +210,159 @@ namespace chaiscript
return *this;
}
/// shared data assignment, same as copy construction
Boxed_Value &operator=(const Boxed_Value &rhs)
{
Boxed_Value temp(rhs);
swap(temp);
return *this;
}
const Type_Info &get_type_info() const
const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info;
}
/// return true if the object is uninitialized
bool is_undef() const
bool is_undef() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.is_undef();
}
bool is_const() const
bool is_const() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.is_const();
}
bool is_type(const Type_Info &ti) const
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.bare_equal(ti);
}
bool is_null() const
template<typename T>
struct Sentinel {
Sentinel(std::shared_ptr<T> &ptr, Data &data)
: m_ptr(ptr), m_data(data)
{
}
~Sentinel()
{
// save new pointer data
m_data.get().m_data_ptr = m_ptr.get().get();
m_data.get().m_const_data_ptr = m_ptr.get().get();
}
Sentinel& operator=(Sentinel&&s) {
m_ptr = std::move(s.m_ptr);
m_data = std::move(s.m_data);
}
Sentinel(Sentinel &&s)
: m_ptr(std::move(s.m_ptr)),
m_data(std::move(s.m_data))
{
}
operator std::shared_ptr<T>&() const
{
return m_ptr.get();
}
Sentinel &operator=(const Sentinel &) = delete;
Sentinel(Sentinel&) = delete;
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
std::reference_wrapper<Data> m_data;
};
template<typename T>
Sentinel<T> pointer_sentinel(std::shared_ptr<T> &ptr) const
{
return Sentinel<T>(ptr, *(m_data.get()));
}
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
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_obj;
}
bool is_ref() const
bool is_ref() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_is_ref;
}
bool is_pointer() const
bool is_return_value() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_return_value;
}
void reset_return_value() const CHAISCRIPT_NOEXCEPT
{
m_data->m_return_value = false;
}
bool is_pointer() const CHAISCRIPT_NOEXCEPT
{
return !is_ref();
}
void *get_ptr() const
void *get_ptr() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_data_ptr;
}
const void *get_const_ptr() const
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_const_data_ptr;
}
Boxed_Value get_attr(const std::string &t_name)
{
if (!m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>());
}
auto &attr = (*m_data->m_attrs)[t_name];
if (attr) {
return Boxed_Value(attr, Internal_Construction());
} else {
Boxed_Value bv; //default construct a new one
attr = bv.m_data;
return bv;
}
}
Boxed_Value &copy_attrs(const Boxed_Value &t_obj)
{
if (t_obj.m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*t_obj.m_data->m_attrs));
}
return *this;
}
Boxed_Value &clone_attrs(const Boxed_Value &t_obj)
{
copy_attrs(t_obj);
reset_return_value();
return *this;
}
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(Boxed_Value l, Boxed_Value r)
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
{
return l.get_type_info() == r.get_type_info();
}
private:
// necessary to avoid hitting the templated && constructor of Boxed_Value
struct Internal_Construction{};
Boxed_Value(const std::shared_ptr<Data> &t_data, Internal_Construction)
: m_data(t_data) {
}
std::shared_ptr<Data> m_data;
};
@@ -256,9 +381,9 @@ namespace chaiscript
///
/// @sa @ref adding_objects
template<typename T>
Boxed_Value var(T t)
Boxed_Value var(T &&t)
{
return Boxed_Value(t);
return Boxed_Value(std::forward<T>(t));
}
namespace detail {
@@ -269,7 +394,7 @@ namespace chaiscript
template<typename T>
Boxed_Value const_var_impl(const T &t)
{
return Boxed_Value(std::shared_ptr<typename std::add_const<T>::type >(new T(t)));
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
}
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
@@ -335,7 +460,18 @@ namespace chaiscript
return detail::const_var_impl(t);
}
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
inline Boxed_Value const_var(bool b) {
static auto t = detail::const_var_impl(true);
static auto f = detail::const_var_impl(false);
if (b) {
return t;
} else {
return f;
}
}
#endif
}

View File

@@ -0,0 +1,107 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
#define CHAISCRIPT_CALLABLE_TRAITS_HPP_
#include <memory>
namespace chaiscript {
namespace dispatch {
namespace detail {
template<typename Class, typename ... Param>
struct Constructor
{
template<typename ... Inner>
std::shared_ptr<Class> operator()(Inner&& ... inner) const {
return std::make_shared<Class>(std::forward<Inner>(inner)...);
}
};
template<typename Ret, typename Class, typename ... Param>
struct Const_Caller
{
Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(const Class &o, Inner&& ... inner) const {
return (o.*m_func)(std::forward<Inner>(inner)...);
}
Ret (Class::*m_func)(Param...) const;
};
template<typename Ret, typename ... Param>
struct Fun_Caller
{
Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(Inner&& ... inner) const {
return (m_func)(std::forward<Inner>(inner)...);
}
Ret(*m_func)(Param...);
};
template<typename Ret, typename Class, typename ... Param>
struct Caller
{
Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(Class &o, Inner&& ... inner) const {
return (o.*m_func)(std::forward<Inner>(inner)...);
}
Ret (Class::*m_func)(Param...);
};
template<typename T>
struct Arity
{
};
template<typename Ret, typename ... Params>
struct Arity<Ret (Params...)>
{
static const size_t arity = sizeof...(Params);
};
template<typename T>
struct Function_Signature
{
};
template<typename Ret, typename ... Params>
struct Function_Signature<Ret (Params...)>
{
typedef Ret Return_Type;
typedef Ret (Signature)(Params...);
};
template<typename Ret, typename T, typename ... Params>
struct Function_Signature<Ret (T::*)(Params...) const>
{
typedef Ret Return_Type;
typedef Ret (Signature)(Params...);
};
template<typename T>
struct Callable_Traits
{
typedef typename Function_Signature<decltype(&T::operator())>::Signature Signature;
typedef typename Function_Signature<decltype(&T::operator())>::Return_Type Return_Type;
};
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,294 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#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)
{
}
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
};
}
namespace detail
{
class Dynamic_Conversion
{
public:
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0;
const Type_Info &base() const
{
return m_base;
}
const Type_Info &derived() const
{
return m_derived;
}
protected:
Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived)
: m_base(t_base), m_derived(t_derived)
{
}
virtual ~Dynamic_Conversion() {}
private:
Type_Info m_base;
Type_Info m_derived;
};
template<typename From, typename To>
class Dynamic_Caster
{
public:
static Boxed_Value cast(const Boxed_Value &t_from)
{
if (t_from.get_type_info().bare_equal(user_type<From>()))
{
if (t_from.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
std::shared_ptr<const To> data
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
} else {
std::shared_ptr<To> data
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
if (!data)
{
throw std::bad_cast();
}
return Boxed_Value(data);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
const To &data = dynamic_cast<const To &>(d);
return Boxed_Value(std::cref(data));
} else {
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
To &data = dynamic_cast<To &>(d);
return Boxed_Value(std::ref(data));
}
}
} else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
}
}
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Dynamic_Conversion
{
public:
Dynamic_Conversion_Impl()
: Dynamic_Conversion(user_type<Base>(), 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);
}
};
}
class Dynamic_Cast_Conversions
{
public:
Dynamic_Cast_Conversions()
{
}
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
: m_conversions(t_other.get_conversions())
{
}
void add_conversion(const std::shared_ptr<detail::Dynamic_Conversion> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion);
}
template<typename Base, typename Derived>
bool dynamic_cast_converts() const
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
{
return has_conversion(base, derived) || has_conversion(derived, base);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
{
try {
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
template<typename Derived>
Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const
{
try {
return get_conversion(base.get_type_info(), user_type<Derived>())->convert_down(base);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation");
}
}
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end();
}
std::shared_ptr<detail::Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived) const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
auto itr =
find(base, derived);
if (itr != m_conversions.end())
{
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
}
}
private:
std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
const Type_Info &base, const Type_Info &derived) const
{
for (auto itr = m_conversions.begin();
itr != m_conversions.end();
++itr)
{
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
{
return itr;
}
}
return m_conversions.end();
}
std::set<std::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return m_conversions;
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<std::shared_ptr<detail::Dynamic_Conversion> > m_conversions;
};
typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
/// want automatic conversions up your inheritance hierarchy.
///
/// Create a new base class registration for applying to a module or to the chaiscript engine
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
/// if you have a type that is introduced in a loadable module and is used by multiple modules
/// (through a tertiary dll that is shared between the modules, static linking the new type
/// into both loadable modules would not be portable), you need to register the base type
/// relationship in all modules that use the newly added type in a polymorphic way.
///
/// Example:
/// \code
/// class Base
/// {};
/// class Derived : public Base
/// {};
///
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<Base, Derived>());
/// \endcode
///
template<typename Base, typename Derived>
Dynamic_Cast_Conversion base_class()
{
//Can only be used with related polymorphic types
//may be expanded some day to support conversions other than child -> parent
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::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<Base, Derived>());
}
}
#endif

View File

@@ -1,29 +1,20 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, 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 "proxy_functions.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Dynamic_Cast_Conversions;
class Type_Conversions;
namespace dispatch {
class Proxy_Function_Base;
} // namespace dispatch
@@ -33,24 +24,90 @@ namespace chaiscript
{
namespace dispatch
{
struct option_explicit_set : std::runtime_error {
option_explicit_set(const std::string &t_param_name)
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
{
}
option_explicit_set(const option_explicit_set &) = default;
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
};
class Dynamic_Object
{
public:
Dynamic_Object(std::string t_type_name)
: m_type_name(std::move(t_type_name))
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
{
}
Dynamic_Object() : m_type_name(""), m_option_explicit(false)
{
}
bool is_explicit() const
{
return m_option_explicit;
}
void set_explicit(const bool t_explicit)
{
m_option_explicit = t_explicit;
}
std::string get_type_name() const
{
return m_type_name;
}
Boxed_Value get_attr(const std::string &t_attr_name)
const Boxed_Value &operator[](const std::string &t_attr_name) const
{
return get_attr(t_attr_name);
}
Boxed_Value &operator[](const std::string &t_attr_name)
{
return get_attr(t_attr_name);
}
const Boxed_Value &get_attr(const std::string &t_attr_name) const
{
auto a = m_attrs.find(t_attr_name);
if (a != m_attrs.end()) {
return a->second;
} else {
throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
}
}
Boxed_Value &get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
}
Boxed_Value &method_missing(const std::string &t_method_name)
{
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
throw option_explicit_set(t_method_name);
}
return get_attr(t_method_name);
}
const Boxed_Value &method_missing(const std::string &t_method_name) const
{
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
throw option_explicit_set(t_method_name);
}
return get_attr(t_method_name);
}
std::map<std::string, Boxed_Value> get_attrs() const
{
return m_attrs;
@@ -58,238 +115,11 @@ namespace chaiscript
private:
std::string m_type_name;
bool m_option_explicit;
std::map<std::string, Boxed_Value> m_attrs;
};
namespace detail
{
/**
* A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(t_func->get_param_types()),
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)),
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;
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
if (df)
{
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 Dynamic_Cast_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 int get_arity() const CHAISCRIPT_OVERRIDE
{
return m_func->get_arity();
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const 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 Dynamic_Cast_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::shared_ptr<Type_Info> &ti, const Dynamic_Cast_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::shared_ptr<Type_Info> &ti, const Dynamic_Cast_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::shared_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())),
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 Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
}
virtual int get_arity() const CHAISCRIPT_OVERRIDE
{
// "this" is not considered part of the arity
return m_func->get_arity() - 1;
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
}
}
#endif

View File

@@ -0,0 +1,253 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
#include <cassert>
#include <map>
#include <memory>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "proxy_functions.hpp"
#include "type_info.hpp"
#include "dynamic_object.hpp"
namespace chaiscript {
class Type_Conversions;
namespace dispatch {
class Proxy_Function_Base;
} // namespace dispatch
} // namespace chaiscript
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
bool t_is_attribute = false)
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
m_is_attribute(t_is_attribute)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
const Type_Info &t_ti,
bool t_is_attribute = false)
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>()),
m_is_attribute(t_is_attribute)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
{
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &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_State &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_State &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_State &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_State &t_conversions) const
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
bool m_is_attribute;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
std::string t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
m_type_name(std::move(t_type_name)), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
auto begin = tl.begin();
auto end = tl.end();
if (begin != end)
{
++begin;
}
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
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_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
std::vector<Boxed_Value> new_params{bv};
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
};
}
}
}
#endif

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
@@ -23,6 +23,7 @@ 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;
@@ -31,7 +32,7 @@ namespace chaiscript
protected:
template<typename T>
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
}

View File

@@ -1,24 +1,24 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_HPP_
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include "boxed_cast.hpp"
#include "function_call_detail.hpp"
#include "proxy_functions.hpp"
#include "callable_traits.hpp"
namespace chaiscript {
class Boxed_Value;
class Dynamic_Cast_Conversions;
class Type_Conversions_State;
namespace detail {
template <typename T> struct Cast_Helper;
} // namespace detail
@@ -28,66 +28,65 @@ namespace chaiscript
{
namespace dispatch
{
/**
* Build a function caller that knows how to dispatch on a set of functions
* example:
* std::function<void (int)> f =
* build_function_caller(dispatchkit.get_function("print"));
* \returns A std::function object for dispatching
* \param[in] funcs the set of functions to dispatch on.
*/
/// Build a function caller that knows how to dispatch on a set of functions
/// example:
/// std::function<void (int)> f =
/// build_function_caller(dispatchkit.get_function("print"));
/// \returns A std::function object for dispatching
/// \param[in] funcs the set of functions to dispatch on.
template<typename FunctionType>
std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
{
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
[](const Const_Proxy_Function &f) {
return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
});
if (!has_arity_match) {
throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
}
FunctionType *p=nullptr;
return detail::build_function_caller_helper(p, funcs, t_conversions);
}
/**
* Build a function caller for a particular Proxy_Function object
* useful in the case that a function is being pass out from scripting back
* into code
* example:
* void my_function(Proxy_Function f)
* {
* std::function<void (int)> local_f =
* build_function_caller(f);
* }
* \returns A std::function object for dispatching
* \param[in] func A function to execute.
*/
/// Build a function caller for a particular Proxy_Function object
/// useful in the case that a function is being pass out from scripting back
/// into code
/// example:
/// void my_function(Proxy_Function f)
/// {
/// std::function<void (int)> local_f =
/// build_function_caller(f);
/// }
/// \returns A std::function object for dispatching
/// \param[in] func A function to execute.
template<typename FunctionType>
std::function<FunctionType>
functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions)
functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
{
std::vector<Const_Proxy_Function> funcs;
funcs.push_back(func);
return functor<FunctionType>(funcs, t_conversions);
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
}
/**
* Helper for automatically unboxing a Boxed_Value that contains a function object
* and creating a typesafe C++ function caller from it.
*/
/// Helper for automatically unboxing a Boxed_Value that contains a function object
/// and creating a typesafe C++ function caller from it.
template<typename FunctionType>
std::function<FunctionType>
functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions)
functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
}
}
namespace detail{
/**
* Cast helper to handle automatic casting to const std::function &
*/
/// 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 Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@@ -98,15 +97,13 @@ namespace chaiscript
}
};
/**
* Cast helper to handle automatic casting to std::function
*/
/// 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 Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@@ -117,15 +114,13 @@ namespace chaiscript
}
};
/**
* Cast helper to handle automatic casting to const std::function
*/
/// 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 Dynamic_Cast_Conversions *t_conversions)
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{

View File

@@ -1,13 +1,12 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#include <algorithm>
#include <functional>
#include <memory>
#include <string>
@@ -17,7 +16,7 @@
#include "boxed_cast.hpp"
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "dynamic_cast_conversion.hpp"
#include "type_conversions.hpp"
#include "proxy_functions.hpp"
namespace chaiscript
@@ -26,17 +25,21 @@ namespace chaiscript
{
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, bool is_arithmetic>
struct Function_Caller_Ret
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
if (t_conversions) {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
}
}
};
@@ -47,9 +50,15 @@ namespace chaiscript
struct Function_Caller_Ret<Ret, true>
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
if (t_conversions) {
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
}
}
};
@@ -61,9 +70,15 @@ namespace chaiscript
struct Function_Caller_Ret<void, false>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
dispatch::dispatch(t_funcs, params, t_conversions);
if (t_conversions) {
dispatch::dispatch(t_funcs, params, *t_conversions);
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
dispatch::dispatch(t_funcs, params, state);
}
}
};
@@ -73,31 +88,60 @@ namespace chaiscript
template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper
{
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Dynamic_Cast_Conversions &t_conversions)
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)
template<typename ... P>
Ret operator()(P&& ... param)
{
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value>::call(m_funcs, {
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
}, m_conversions
);
if (m_conversions) {
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, &state
);
} else {
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, nullptr
);
}
}
template<typename P, typename Q>
static auto box(Q&& q) -> typename std::enable_if<std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
{
return Boxed_Value(std::ref(std::forward<Q>(q)));
}
template<typename P, typename Q>
static auto box(Q&& q) -> typename std::enable_if<!std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
{
return Boxed_Value(std::forward<Q>(q));
}
template<typename P>
static Boxed_Value box(Boxed_Value bv)
{
return bv;
}
std::vector<Const_Proxy_Function> m_funcs;
Dynamic_Cast_Conversions m_conversions;
const Type_Conversions *m_conversions;
};
/// \todo what happens if t_conversions is deleted out from under us?!
template<typename Ret, typename ... Params>
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
{
/*
if (funcs.size() == 1)
{
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
@@ -111,8 +155,9 @@ namespace chaiscript
// 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:Dynamic_Cast_Conversions()));
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
}
}
}

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
@@ -9,13 +9,10 @@
#include <functional>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
#include <type_traits>
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript {
class Boxed_Number;
@@ -25,6 +22,9 @@ namespace chaiscript
{
namespace dispatch
{
template<class T, class U> class Proxy_Function_Callable_Impl;
template<class T> class Assignable_Proxy_Function_Impl;
namespace detail
{
/**
@@ -33,9 +33,85 @@ namespace chaiscript
template<typename Ret>
struct Handle_Return
{
static Boxed_Value handle(const Ret &r)
template<typename T,
typename = typename std::enable_if<std::is_pod<typename std::decay<T>::type>::value>::type>
static Boxed_Value handle(T r)
{
return const_var(r);
return Boxed_Value(std::move(r), true);
}
template<typename T,
typename = typename std::enable_if<!std::is_pod<typename std::decay<T>::type>::value>::type>
static Boxed_Value handle(T &&r)
{
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);
}
};
template<typename Ret>
struct Handle_Return<const std::function<Ret> &>
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
);
}
};
template<typename Ret>
struct Handle_Return<std::function<Ret>>
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>>>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
};
template<typename Ret>
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
};
template<typename Ret>
struct Handle_Return<std::function<Ret> &>
{
static Boxed_Value handle(std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(f),
std::shared_ptr<std::function<Ret>>())
);
}
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
);
}
};
@@ -44,7 +120,16 @@ namespace chaiscript
{
static Boxed_Value handle(Ret *p)
{
return Boxed_Value(p);
return Boxed_Value(p, true);
}
};
template<typename Ret>
struct Handle_Return<const Ret *>
{
static Boxed_Value handle(const Ret *p)
{
return Boxed_Value(p, true);
}
};
@@ -53,7 +138,7 @@ namespace chaiscript
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
return Boxed_Value(r, true);
}
};
@@ -62,7 +147,7 @@ namespace chaiscript
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
return Boxed_Value(r, true);
}
};
@@ -71,7 +156,7 @@ namespace chaiscript
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
return Boxed_Value(r, true);
}
};
@@ -80,7 +165,7 @@ namespace chaiscript
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
return Boxed_Value(std::cref(r), true);
}
};

View File

@@ -1,13 +1,14 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, 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
{
@@ -15,442 +16,446 @@ namespace chaiscript
{
namespace operators
{
template<typename Ret, typename L, typename R>
Ret assign(L l, R r)
{
return (l = r);
}
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 Ret, typename L, typename R>
Ret assign_bitwise_and(L l, R r)
{
return (l &= r);
}
template<typename L, typename R>
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
{
return (l &= r);
}
template<typename Ret, typename L, typename R>
Ret assign_xor(L l, R r)
{
return (l ^= r);
}
template<typename L, typename R>
auto assign_xor(L l, R r) -> decltype((l^=r))
{
return (l ^= r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_or(L l, R 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 Ret, typename L, typename R>
Ret assign_difference(L l, R r)
{
return (l -= r);
}
template<typename L, typename R>
auto assign_difference(L l, R r) -> decltype(( l -= r))
{
return (l -= r);
}
template<typename Ret, typename L, typename R>
Ret assign_left_shift(L l, R 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 Ret, typename L, typename R>
Ret assign_product(L l, R r)
{
return (l *= r);
}
template<typename L, typename R>
auto assign_product(L l, R r) -> decltype(( l *= r ))
{
return (l *= r);
}
template<typename Ret, typename L, typename R>
Ret assign_quotient(L l, R r)
{
return (l /= r);
}
template<typename L, typename R>
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
{
return (l /= r);
}
template<typename Ret, typename L, typename R>
Ret assign_remainder(L l, R r)
{
return (l %= r);
}
template<typename L, typename R>
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
{
return (l %= r);
}
template<typename Ret, typename L, typename R>
Ret assign_right_shift(L l, R r)
{
return (l >>= r);
}
template<typename L, typename R>
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
{
return (l >>= r);
}
template<typename Ret, typename L, typename R>
Ret assign_sum(L l, R 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 Ret, typename L>
Ret prefix_decrement(L l)
{
return (--l);
}
template<typename L>
auto prefix_decrement(L l) -> decltype(( --l ))
{
return (--l);
}
template<typename Ret, typename L>
Ret prefix_increment(L l)
{
return (++l);
}
template<typename L>
auto prefix_increment(L l) -> decltype(( ++l ))
{
return (++l);
}
template<typename Ret, typename L, typename R>
Ret equal(L l, R r)
{
return (l == r);
}
template<typename L, typename R>
auto equal(L l, R r) -> decltype(( l == r ))
{
return (l == r);
}
template<typename Ret, typename L, typename R>
Ret greater_than(L l, R r)
{
return (l > r);
}
template<typename L, typename R>
auto greater_than(L l, R r) -> decltype(( l > r ))
{
return (l > r);
}
template<typename Ret, typename L, typename R>
Ret greater_than_equal(L l, R 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 Ret, typename L, typename R>
Ret less_than(L l, R r)
{
return (l < r);
}
template<typename L, typename R>
auto less_than(L l, R r) -> decltype(( l < r ))
{
return (l < r);
}
template<typename Ret, typename L, typename R>
Ret less_than_equal(L l, R 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 Ret, typename L>
Ret logical_compliment(L l)
{
return (!l);
}
template<typename L>
auto logical_compliment(L l) -> decltype(( !l ))
{
return (!l);
}
template<typename Ret, typename L, typename R>
Ret not_equal(L l, R r)
{
return (l != r);
}
template<typename L, typename R>
auto not_equal(L l, R r) -> decltype(( l != r ))
{
return (l != r);
}
template<typename Ret, typename L, typename R>
Ret addition(L l, R r)
{
return (l + r);
}
template<typename L, typename R>
auto addition(L l, R r) -> decltype(( l + r ))
{
return (l + r);
}
template<typename Ret, typename L>
Ret unary_plus(L l)
{
return (+l);
}
template<typename L>
auto unary_plus(L l) -> decltype(( +l ))
{
return (+l);
}
template<typename Ret, typename L, typename R>
Ret subtraction(L l, R r)
{
return (l - r);
}
template<typename L, typename R>
auto subtraction(L l, R r) -> decltype(( l - r ))
{
return (l - r);
}
template<typename Ret, typename L>
Ret unary_minus(L l)
{
template<typename L>
auto unary_minus(L l) -> decltype(( -l ))
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4146)
return (-l);
return (-l);
#pragma warning(pop)
#else
return (-l);
return (-l);
#endif
}
}
template<typename Ret, typename L, typename R>
Ret bitwise_and(L l, R r)
{
return (l & r);
}
template<typename L, typename R>
auto bitwise_and(L l, R r) -> decltype(( l & r ))
{
return (l & r);
}
template<typename Ret, typename L>
Ret bitwise_compliment(L l)
{
return (~l);
}
template<typename L>
auto bitwise_compliment(L l) -> decltype(( ~l ))
{
return (~l);
}
template<typename Ret, typename L, typename R>
Ret bitwise_xor(L l, R r)
{
return (l ^ r);
}
template<typename L, typename R>
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
{
return (l ^ r);
}
template<typename Ret, typename L, typename R>
Ret bitwise_or(L l, R r)
{
return (l | r);
}
template<typename L, typename R>
auto bitwise_or(L l, R r) -> decltype(( l | r ))
{
return (l | r);
}
template<typename Ret, typename L, typename R>
Ret division(L l, R r)
{
return (l / r);
}
template<typename L, typename R>
auto division(L l, R r) -> decltype(( l / r ))
{
return (l / r);
}
template<typename Ret, typename L, typename R>
Ret left_shift(L l, R r)
{
return l << r;
}
template<typename L, typename R>
auto left_shift(L l, R r) -> decltype(( l << r ))
{
return l << r;
}
template<typename Ret, typename L, typename R>
Ret multiplication(L l, R r)
{
return l * r;
}
template<typename L, typename R>
auto multiplication(L l, R r) -> decltype(( l * r ))
{
return l * r;
}
template<typename Ret, typename L, typename R>
Ret remainder(L l, R r)
{
return (l % r);
}
template<typename Ret, typename L, typename R>
Ret right_shift(L l, R 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()))
ModulePtr assign(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign<T &, T &, const T&>), "=");
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
return m;
}
template<typename T>
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_xor(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
return m;
}
template<typename T>
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_difference(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
return m;
}
template<typename T>
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_left_shift(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
return m;
}
template<typename T>
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_product(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
return m;
}
template<typename T>
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_quotient(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
return m;
}
template<typename T>
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_remainder(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
return m;
}
template<typename T>
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_right_shift(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
return m;
}
template<typename T>
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
ModulePtr assign_sum(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
return m;
}
template<typename T>
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
ModulePtr prefix_decrement(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&prefix_decrement<T &, T &>), "--");
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
return m;
}
template<typename T>
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
ModulePtr prefix_increment(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&prefix_increment<T &, T &>), "++");
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
return m;
}
template<typename T>
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
ModulePtr equal(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&equal<bool, const T&, const T&>), "==");
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
return m;
}
template<typename T>
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
ModulePtr greater_than(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
return m;
}
template<typename T>
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
ModulePtr greater_than_equal(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
return m;
}
template<typename T>
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
ModulePtr less_than(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&less_than<bool, const T&, const T&>), "<");
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
return m;
}
template<typename T>
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
ModulePtr less_than_equal(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
return m;
}
template<typename T>
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
ModulePtr logical_compliment(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&logical_compliment<bool, const T &>), "!");
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
return m;
}
template<typename T>
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
ModulePtr not_equal(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&not_equal<bool, const T &, const T &>), "!=");
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
return m;
}
template<typename T>
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
ModulePtr addition(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&addition<T, const T &, const T &>), "+");
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
return m;
}
template<typename T>
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
ModulePtr unary_plus(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&unary_plus<T, const T &>), "+");
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
return m;
}
template<typename T>
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
ModulePtr subtraction(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&subtraction<T, const T &, const T &>), "-");
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
return m;
}
template<typename T>
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
ModulePtr unary_minus(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&unary_minus<T, const T &>), "-");
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
return m;
}
template<typename T>
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
ModulePtr bitwise_and(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
return m;
}
template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
ModulePtr bitwise_compliment(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&bitwise_compliment<T, const T &>), "~");
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
return m;
}
template<typename T>
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
ModulePtr bitwise_xor(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
return m;
}
template<typename T>
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
ModulePtr bitwise_or(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
return m;
}
template<typename T>
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
ModulePtr division(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&division<T, const T &, const T &>), "/");
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
return m;
}
template<typename T>
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
ModulePtr left_shift(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
return m;
}
template<typename T>
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
ModulePtr multiplication(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&multiplication<T, const T &, const T &>), "*");
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
return m;
}
template<typename T>
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
ModulePtr remainder(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&remainder<T, const T &, const T &>), "%");
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
return m;
}
template<typename T>
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
ModulePtr right_shift(ModulePtr m = std::make_shared<Module>())
{
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
return m;
}
}

View File

@@ -1,34 +1,29 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#include "proxy_functions.hpp"
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class, typename ... Params>
std::shared_ptr<Class> constructor_(Params ... params)
{
return std::shared_ptr<Class>(new Class(params...));
}
template<typename Class, typename ... Params >
Proxy_Function build_constructor_(Class (*)(Params...))
{
typedef std::shared_ptr<Class> (sig)(Params...);
return Proxy_Function(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>))));
auto call = dispatch::detail::Constructor<Class, Params...>();
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class> (Params...), decltype(call)>>(call));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,14 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#include <algorithm>
#include <functional>
#include <stdexcept>
#include <string>
#include <vector>
#include "../chaiscript_defines.hpp"
@@ -18,9 +16,10 @@
#include "boxed_value.hpp"
#include "handle_return.hpp"
#include "type_info.hpp"
#include "callable_traits.hpp"
namespace chaiscript {
class Dynamic_Cast_Conversions;
class Type_Conversions_State;
namespace exception {
class bad_boxed_cast;
} // namespace exception
@@ -42,6 +41,8 @@ namespace chaiscript
{
}
arity_error(const arity_error &) = default;
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
int got;
@@ -53,29 +54,6 @@ namespace chaiscript
{
namespace detail
{
template<typename ... Rest>
struct Build_Param_Type_List;
template<typename Param, typename ... Rest>
struct Build_Param_Type_List<Param, Rest...>
{
static void build(std::vector<Type_Info> &t_params)
{
t_params.push_back(chaiscript::detail::Get_Type_Info<Param>::get());
Build_Param_Type_List<Rest...>::build(t_params);
}
};
// 0th case
template<>
struct Build_Param_Type_List<>
{
static void build(std::vector<Type_Info> &)
{
}
};
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
@@ -83,15 +61,15 @@ namespace chaiscript
template<typename Ret, typename ... Params>
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
{
/// \todo this code was previously using { chaiscript::detail::Get_Type_Info<Ret>::get()... }
/// but this seems to indicate another bug with MSVC's uniform initializer lists
std::vector<Type_Info> params;
params.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
Build_Param_Type_List<Params...>::build(params);
return params;
/// \note somehow this is responsible for a large part of the code generation
return { user_type<Ret>(), user_type<Params>()... };
}
#ifdef CHAISCRIPT_GCC_4_6
/// \todo REMOVE THIS WHEN WE DROP G++4.6
// Forward declaration
template<typename ... Rest>
struct Try_Cast;
@@ -99,7 +77,7 @@ namespace chaiscript
template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...>
{
static void do_try(const std::vector<Boxed_Value> &params, int generation, const Dynamic_Cast_Conversions &t_conversions)
static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions_State &t_conversions)
{
boxed_cast<Param>(params[generation], &t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
@@ -110,7 +88,7 @@ namespace chaiscript
template<>
struct Try_Cast<>
{
static void do_try(const std::vector<Boxed_Value> &, int, const Dynamic_Cast_Conversions &)
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions_State &)
{
}
};
@@ -118,13 +96,13 @@ namespace chaiscript
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarly used to prevent
* Proxy_Function_Impl object. This function is primarily used to prevent
* registration of two functions with the exact same signatures
*/
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
Try_Cast<Params...>::do_try(params, 0, t_conversions);
} catch (const exception::bad_boxed_cast &) {
@@ -138,9 +116,9 @@ namespace chaiscript
struct Call_Func
{
template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
}
@@ -153,9 +131,9 @@ namespace chaiscript
#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 Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
}
@@ -166,13 +144,13 @@ namespace chaiscript
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each paramter to the expected type.
* 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 Dynamic_Cast_Conversions &t_conversions)
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
if (params.size() == sizeof...(Params))
{
@@ -182,6 +160,82 @@ namespace chaiscript
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
}
#else
template<size_t ... I>
struct Indexes
{
};
template<size_t S, size_t ... I>
struct Make_Indexes
{
typedef typename Make_Indexes<S-1, I..., sizeof...(I)>::indexes indexes;
};
template<size_t ... I>
struct Make_Indexes<0, I...>
{
typedef Indexes<I...> indexes;
};
/**
* 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, size_t ... I>
bool compare_types_cast(Indexes<I...>, Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
(void)params; (void)t_conversions;
(void)std::initializer_list<int>{(boxed_cast<Params>(params[I], &t_conversions), 0)...};
return true;
} catch (const exception::bad_boxed_cast &) {
return false;
}
}
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*f)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return compare_types_cast(indexes(), f, params, t_conversions);
}
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
(void)params; (void)t_conversions;
return f(boxed_cast<Params>(params[I], &t_conversions)...);
}
/**
* 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 Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return call_func(sig, indexes(), f, params, t_conversions);
}
#endif
}
}
@@ -197,20 +251,20 @@ namespace chaiscript
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 Dynamic_Cast_Conversions &t_conversions)
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), 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 Dynamic_Cast_Conversions &t_conversions)
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(fun, params, t_conversions);
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};

View File

@@ -1,81 +1,19 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
#include <functional>
#include <type_traits>
#include "bind_first.hpp"
#include "dispatchkit.hpp"
#include "proxy_functions.hpp"
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
template<typename T>
struct FunctionSignature
{
};
template<typename Sig>
struct FunctionSignature<std::function<Sig> >
{
typedef Sig Signature;
};
template<typename Ret, typename ... Args>
std::function<Ret (Args...) > to_function(Ret (*func)(Args...))
{
return std::function<Ret (Args...)>(func);
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
{
/// \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
/// \param[in] t Function / member to expose
@@ -98,29 +36,52 @@ namespace chaiscript
///
/// \sa \ref adding_functions
template<typename T>
Proxy_Function fun(T t)
Proxy_Function fun(const T &t)
{
return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
typedef typename dispatch::detail::Callable_Traits<T>::Signature Signature;
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
}
template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...))
{
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*t_func)(Param...) const)
{
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*t_func)(Param...))
{
auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
}
/// \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)
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
{
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<T, Class>>(m));
}
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
/// \param[in] t Function / member to expose
@@ -141,9 +102,9 @@ namespace chaiscript
///
/// \sa \ref adding_functions
template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q)
Proxy_Function fun(T &&t, const Q &q)
{
return fun(detail::bind_first(t, q));
return fun(detail::bind_first(std::forward<T>(t), q));
}
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
@@ -167,11 +128,11 @@ namespace chaiscript
///
/// \sa \ref adding_functions
template<typename T, typename Q, typename R>
Proxy_Function fun(T t, const Q &q, const R &r)
Proxy_Function fun(T &&t, Q &&q, R &&r)
{
return fun(detail::bind_first(detail::bind_first(t, q), r));
return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
}
}

View File

@@ -0,0 +1,644 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#include <atomic>
#include <memory>
#include <set>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <typeinfo>
#include "../chaiscript_threading.hpp"
#include "bad_boxed_cast.hpp"
#include "boxed_cast_helper.hpp"
#include "boxed_value.hpp"
#include "type_info.hpp"
namespace chaiscript
{
namespace exception
{
class bad_boxed_dynamic_cast : public bad_boxed_cast
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(w)
{
}
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
};
class bad_boxed_type_cast : public bad_boxed_cast
{
public:
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(w)
{
}
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
};
}
namespace detail
{
class Type_Conversion_Base
{
public:
virtual Boxed_Value convert(const Boxed_Value &from) const = 0;
virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0;
const Type_Info &to() const
{
return m_to;
}
const Type_Info &from() const
{
return m_from;
}
virtual bool bidir() const
{
return true;
}
virtual ~Type_Conversion_Base() {}
protected:
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
: m_to(t_to), m_from(t_from)
{
}
private:
Type_Info m_to;
Type_Info m_from;
};
template<typename From, typename To>
class Static_Caster
{
public:
static Boxed_Value cast(const Boxed_Value &t_from)
{
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
{
if (t_from.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
return Boxed_Value(
[&]()->std::shared_ptr<const To>{
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
} else {
throw std::bad_cast();
}
}()
);
} else {
return Boxed_Value(
[&]()->std::shared_ptr<To>{
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
} else {
throw std::bad_cast();
}
}()
);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
const To &data = static_cast<const To &>(d);
return Boxed_Value(std::cref(data));
} else {
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
To &data = static_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 From, typename To>
class Dynamic_Caster
{
public:
static Boxed_Value cast(const Boxed_Value &t_from)
{
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
{
if (t_from.is_pointer())
{
// Dynamic cast out the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
return Boxed_Value(
[&]()->std::shared_ptr<const To>{
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
} else {
throw std::bad_cast();
}
}()
);
} else {
return Boxed_Value(
[&]()->std::shared_ptr<To>{
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
} else {
#ifdef CHAISCRIPT_LIBCPP
/// \todo fix this someday after libc++ is fixed.
if (std::string(typeid(To).name()).find("Assignable_Proxy_Function") != std::string::npos) {
auto from = detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr);
if (std::string(typeid(*from).name()).find("Assignable_Proxy_Function_Impl") != std::string::npos) {
return std::static_pointer_cast<To>(from);
}
}
#endif
throw std::bad_cast();
}
}()
);
}
} else {
// Pull the reference out of the contained boxed value, which we know is the type we want
if (t_from.is_const())
{
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
const To &data = dynamic_cast<const To &>(d);
return Boxed_Value(std::cref(data));
} else {
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
To &data = dynamic_cast<To &>(d);
return Boxed_Value(std::ref(data));
}
}
} else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
}
}
};
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Type_Conversion_Base
{
public:
Dynamic_Conversion_Impl()
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
{
}
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
{
return Dynamic_Caster<Base, Derived>::cast(t_base);
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
{
return Static_Caster<Derived, Base>::cast(t_derived);
}
};
template<typename Base, typename Derived>
class Static_Conversion_Impl : public Type_Conversion_Base
{
public:
Static_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
{
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types");
}
virtual bool bidir() const CHAISCRIPT_OVERRIDE
{
return false;
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
{
return Static_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);
}
virtual bool bidir() const CHAISCRIPT_OVERRIDE
{
return false;
}
private:
Callable m_func;
};
}
class Type_Conversions
{
public:
struct Conversion_Saves
{
Conversion_Saves()
: enabled(false)
{}
bool enabled;
std::vector<Boxed_Value> saves;
};
struct Less_Than
{
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
{
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(t_other.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);
} else {
return false;
}
}
template<typename To>
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
{
try {
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
if (t_saves.enabled) t_saves.saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
} 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(Conversion_Saves &t_saves, const Boxed_Value &to) const
{
try {
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
if (t_saves.enabled) t_saves.saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
}
}
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val)
{
t_saves.enabled = t_val;
}
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves)
{
std::vector<Boxed_Value> ret;
std::swap(ret, t_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_bidir(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());
}
}
Conversion_Saves &conversion_saves() const {
return *m_conversion_saves;
}
private:
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
const Type_Info &to, const Type_Info &from) const
{
return std::find_if(m_conversions.begin(), m_conversions.end(),
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion) -> bool
{
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
}
);
}
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;
}
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;
};
class Type_Conversions_State
{
public:
Type_Conversions_State(const Type_Conversions &t_conversions,
Type_Conversions::Conversion_Saves &t_saves)
: m_conversions(t_conversions),
m_saves(t_saves)
{
}
const Type_Conversions *operator->() const {
return &m_conversions.get();
}
const Type_Conversions *get() const {
return &m_conversions.get();
}
Type_Conversions::Conversion_Saves &saves() const {
return m_saves;
}
private:
std::reference_wrapper<const Type_Conversions> m_conversions;
std::reference_wrapper<Type_Conversions::Conversion_Saves> m_saves;
};
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
/// 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(typename std::enable_if<std::is_polymorphic<Base>::value && std::is_polymorphic<Derived>::value>::type* = nullptr)
{
//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");
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Dynamic_Conversion_Impl<Base, Derived>>();
}
template<typename Base, typename Derived>
Type_Conversion base_class(typename std::enable_if<!std::is_polymorphic<Base>::value || !std::is_polymorphic<Derived>::value>::type* = nullptr)
{
//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");
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Static_Conversion_Impl<Base, Derived>>();
}
template<typename Callable>
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to,
const Callable &t_func)
{
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
}
template<typename From, typename To, typename Callable>
Type_Conversion type_conversion(const Callable &t_function)
{
auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value {
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
return chaiscript::Boxed_Value(t_function(detail::Cast_Helper<const From &>::cast(t_bv, nullptr)));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
}
template<typename From, typename To>
Type_Conversion type_conversion()
{
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
return chaiscript::Boxed_Value(To(detail::Cast_Helper<From>::cast(t_bv, nullptr)));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
}
template<typename To>
Type_Conversion vector_conversion()
{
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
To vec;
vec.reserve(from_vec.size());
for (const Boxed_Value &bv : from_vec) {
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
}
return Boxed_Value(std::move(vec));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
}
template<typename To>
Type_Conversion map_conversion()
{
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
To map;
for (const std::pair<std::string, Boxed_Value> &p : from_map) {
map.insert(std::make_pair(p.first, detail::Cast_Helper<typename To::mapped_type>::cast(p.second, nullptr)));
}
return Boxed_Value(std::move(map));
};
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
}
}
#endif

View File

@@ -1,17 +1,16 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
#define CHAISCRIPT_TYPE_INFO_HPP_
#include <functional>
#include <memory>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <string>
namespace chaiscript
{
@@ -25,84 +24,71 @@ namespace chaiscript
};
}
/// \brief Compile time deduced information about a type
class Type_Info
{
public:
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
: 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),
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_is_undef(false)
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
+ (static_cast<unsigned int>(t_is_void) << is_void_flag)
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
{
}
Type_Info()
CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(nullptr), m_bare_type_info(nullptr),
m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_is_arithmetic(false),
m_is_undef(true)
m_flags(1 << is_undef_flag)
{
}
Type_Info(const Type_Info &ti)
: m_type_info(ti.m_type_info),
m_bare_type_info(ti.m_bare_type_info),
m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
m_is_pointer(ti.m_is_pointer),
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
m_is_undef(ti.m_is_undef)
{
}
#if !defined(_MSC_VER) || _MSC_VER != 1800
Type_Info(Type_Info&&) = default;
Type_Info& operator=(Type_Info&&) = default;
#endif
Type_Info &operator=(const Type_Info &ti)
{
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_const = ti.m_is_const;
m_is_reference = ti.m_is_reference;
m_is_pointer = ti.m_is_pointer;
m_is_void = ti.m_is_void;
m_is_arithmetic = ti.m_is_arithmetic;
m_is_undef = ti.m_is_undef;
return *this;
}
Type_Info(const Type_Info&) = default;
Type_Info& operator=(const Type_Info&) = default;
bool operator<(const Type_Info &ti) const
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_type_info < ti.m_type_info;
}
bool operator==(const Type_Info &ti) const
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return ti.m_type_info == m_type_info
return ti.m_type_info == m_type_info
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
}
bool operator==(const std::type_info &ti) const
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_type_info != nullptr && (*m_type_info) == ti;
}
bool bare_equal(const Type_Info &ti) const
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return ti.m_bare_type_info == m_bare_type_info
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
}
bool bare_equal_type_info(const std::type_info &ti) const
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;
}
bool is_const() const { return m_is_const; }
bool is_reference() const { return m_is_reference; }
bool is_void() const { return m_is_void; }
bool is_arithmetic() const { return m_is_arithmetic; }
bool is_undef() const { return m_is_undef || m_bare_type_info == nullptr; }
bool is_pointer() const { return m_is_pointer; }
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_const_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_reference_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_void_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_undef_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_pointer_flag)) != 0; }
std::string name() const
{
@@ -124,33 +110,39 @@ namespace chaiscript
}
}
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;
unsigned int m_flags;
static const int is_const_flag = 0;
static const int is_reference_flag = 1;
static const int is_pointer_flag = 2;
static const int is_void_flag = 3;
static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5;
};
namespace detail
{
/**
* Helper used to create a Type_Info object
*/
/// Helper used to create a Type_Info object
template<typename T>
struct Get_Type_Info
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
static Type_Info get()
{
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,
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
&typeid(T),
(std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(T),
&typeid(typename Bare_Type<T>::type));
}
};
@@ -160,26 +152,31 @@ namespace chaiscript
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
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,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(std::shared_ptr<T> ),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
{
};
template<typename T>
struct Get_Type_Info<const std::shared_ptr<T> &>
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
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,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(const std::shared_ptr<T> &),
&typeid(typename Bare_Type<T>::type));
}
@@ -190,11 +187,11 @@ namespace chaiscript
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
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,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(std::reference_wrapper<T> ),
&typeid(typename Bare_Type<T>::type));
}
@@ -205,21 +202,16 @@ namespace chaiscript
{
typedef T type;
CHAISCRIPT_CONSTEXPR static Type_Info get()
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,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(const std::reference_wrapper<T> &),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Stripped_Type
{
typedef typename Bare_Type<typename detail::Get_Type_Info<T>::type>::type type;
};
}
/// \brief Creates a Type_Info object representing the type passed in
@@ -232,7 +224,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode
template<typename T>
CHAISCRIPT_CONSTEXPR Type_Info user_type(const T &/*t*/)
Type_Info user_type(const T &/*t*/)
{
return detail::Get_Type_Info<T>::get();
}
@@ -247,7 +239,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \endcode
template<typename T>
CHAISCRIPT_CONSTEXPR Type_Info user_type()
Type_Info user_type()
{
return detail::Get_Type_Info<T>::get();
}

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
@@ -9,8 +9,6 @@
#include <string>
#include "../dispatchkit/dispatchkit.hpp"
namespace chaiscript
{

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_
@@ -26,6 +26,7 @@ struct AST_Node;
namespace chaiscript
{
/// Signature of module entry point that all binary loadable modules must implement.
typedef ModulePtr (*Create_Module_Func)();
@@ -33,11 +34,11 @@ namespace chaiscript
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
};
};
@@ -46,11 +47,11 @@ namespace chaiscript
/// Helper lookup to get the name of each node type
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop"};
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
return ast_node_types[ast_node_type];
}
@@ -67,8 +68,34 @@ namespace chaiscript
File_Position() : line(0), column(0) { }
};
struct Parse_Location {
Parse_Location(std::string t_fname="", const int t_start_line=0, const int t_start_col=0,
const int t_end_line=0, const int t_end_col=0)
: start(t_start_line, t_start_col),
end(t_end_line, t_end_col),
filename(std::make_shared<std::string>(std::move(t_fname)))
{
}
Parse_Location(std::shared_ptr<std::string> t_fname, const int t_start_line=0, const int t_start_col=0,
const int t_end_line=0, const int t_end_col=0)
: start(t_start_line, t_start_col),
end(t_end_line, t_end_col),
filename(std::move(t_fname))
{
}
File_Position start;
File_Position end;
std::shared_ptr<std::string> filename;
};
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
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.
@@ -76,20 +103,19 @@ namespace chaiscript
{
/// Errors generated during parsing or evaluation
struct eval_error : public std::runtime_error {
struct eval_error : std::runtime_error {
std::string reason;
File_Position start_position;
File_Position end_position;
std::string filename;
std::string detail;
std::vector<AST_NodePtr> call_stack;
std::vector<AST_NodePtr_Const> call_stack;
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
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))
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why,
@@ -103,7 +129,7 @@ namespace chaiscript
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)
reason(t_why), start_position(t_where), filename(t_fname)
{}
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
@@ -111,25 +137,27 @@ namespace chaiscript
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]) << ")" << std::endl;
ss << std::endl << detail << std::endl;
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 << std::endl;
ss << '\n';
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
}
}
}
ss << std::endl;
ss << '\n';
return ss.str();
}
@@ -150,16 +178,16 @@ namespace chaiscript
}
template<typename T>
static std::string fname(const T& t)
static const std::string &fname(const T& t)
{
return *t->filename;
return t->filename();
}
template<typename T>
static std::string startpos(const T& t)
{
std::ostringstream oss;
oss << t->start.line << ", " << t->start.column;
oss << t->start().line << ", " << t->start().column;
return oss.str();
}
@@ -226,8 +254,7 @@ namespace chaiscript
if (f)
{
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
if (dynfunguard)
{
retval += " : " + format_guard(dynfunguard->get_parse_tree());
@@ -249,10 +276,13 @@ namespace chaiscript
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();
if (t) {
std::ostringstream oss;
oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
return oss.str();
} else {
return "(internal)";
}
}
@@ -263,13 +293,13 @@ namespace chaiscript
std::stringstream ss;
if (t_functions.size() == 1)
{
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
} else {
ss << " " << t_functions.size() << " overloads available:" << std::endl;
ss << " " << t_functions.size() << " overloads available:\n";
for (const auto & t_function : t_functions)
{
ss << " " << format_types((t_function), t_dot_notation, t_ss) << std::endl;
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
}
}
@@ -389,11 +419,12 @@ namespace chaiscript
/// Errors generated when loading a file
struct file_not_found_error : public std::runtime_error {
struct file_not_found_error : 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 {}
};
@@ -403,13 +434,24 @@ namespace chaiscript
/// \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;
const std::string text;
Parse_Location location;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
const std::string &filename() const {
return *location.filename;
}
const File_Position &start() const {
return location.start;
}
const File_Position &end() const {
return location.end;
}
virtual std::string pretty_print() const
{
std::ostringstream oss;
@@ -425,23 +467,19 @@ namespace chaiscript
/// Prints the contents of an AST node, including its children, recursively
std::string to_string(const std::string &t_prepend = "") {
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 << std::endl;
for (size_t j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
for (auto & elem : this->children) {
oss << elem->to_string(t_prepend + " ");
}
return oss.str();
}
std::string internal_to_string() {
return to_string();
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const
{
try {
return eval_internal(t_e);
@@ -451,34 +489,41 @@ namespace chaiscript
}
}
static bool get_bool_condition(const Boxed_Value &t_bv) {
try {
return boxed_cast<bool>(t_bv);
}
catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("Condition not boolean");
}
}
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);
}
virtual ~AST_Node() {}
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, Parse_Location t_loc,
std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
identifier(t_id), text(std::move(t_ast_node_text)),
location(std::move(t_loc)),
children(std::move(t_children))
{
}
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 &)
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) 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 &);
AST_Node(const AST_Node &) = delete;
AST_Node& operator=(const AST_Node &) = delete;
};
@@ -486,12 +531,11 @@ namespace chaiscript
{
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) { }
Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
};
@@ -510,75 +554,77 @@ namespace chaiscript
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_de.new_scope();
m_ds.get()->new_scope(m_ds.get().stack_holder());
}
~Scope_Push_Pop()
{
m_de.pop_scope();
m_ds.get()->pop_scope(m_ds.get().stack_holder());
}
private:
// explicitly unimplemented copy and assignment
Scope_Push_Pop(const Scope_Push_Pop &);
Scope_Push_Pop& operator=(const Scope_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
};
/// Creates a new function call and pops it on destruction
struct Function_Push_Pop
{
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
Function_Push_Pop(const Function_Push_Pop &) = delete;
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_de.new_function_call();
m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
}
~Function_Push_Pop()
{
m_de.pop_function_call();
m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
}
void save_params(const std::vector<Boxed_Value> &t_params)
{
m_de.save_function_params(t_params);
m_ds.get()->save_function_params(t_params);
}
void save_params(std::initializer_list<Boxed_Value> t_params)
{
m_ds.get()->save_function_params(std::move(t_params));
}
private:
// explicitly unimplemented copy and assignment
Function_Push_Pop(const Function_Push_Pop &);
Function_Push_Pop& operator=(const Function_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
};
/// Creates a new scope then pops it on destruction
struct Stack_Push_Pop
{
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_de.new_stack();
m_ds.get()->new_stack(m_ds.get().stack_holder());
}
~Stack_Push_Pop()
{
m_de.pop_stack();
m_ds.get()->pop_stack(m_ds.get().stack_holder());
}
private:
// explicitly unimplemented copy and assignment
Stack_Push_Pop(const Stack_Push_Pop &);
Stack_Push_Pop& operator=(const Stack_Push_Pop &);
chaiscript::detail::Dispatch_Engine &m_de;
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
};
}
}

View File

@@ -1,15 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_ENGINE_HPP_
#define CHAISCRIPT_ENGINE_HPP_
#include <cassert>
#include <cstring>
#include <algorithm>
#include <exception>
#include <fstream>
#include <functional>
@@ -18,7 +16,6 @@
#include <mutex>
#include <set>
#include <stdexcept>
#include <string>
#include <vector>
#include "../chaiscript_defines.hpp"
@@ -26,7 +23,7 @@
#include "../dispatchkit/boxed_cast_helper.hpp"
#include "../dispatchkit/boxed_value.hpp"
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/dynamic_cast_conversion.hpp"
#include "../dispatchkit/type_conversions.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "chaiscript_common.hpp"
@@ -39,15 +36,16 @@
#else
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
#include <windows.h>
#endif
#endif
#include "../dispatchkit/exception_specification.hpp"
#include "chaiscript_parser.hpp"
#include "chaiscript_prelude.chai"
namespace chaiscript
{
@@ -61,9 +59,8 @@ namespace chaiscript
{
}
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT
{
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
};
}
@@ -151,8 +148,8 @@ namespace chaiscript
return std::string(t_str.begin(), t_str.end());
}
#ifdef _UNICODE
template<typename T>
#if defined(_UNICODE) || defined(UNICODE)
template<typename T>
static std::wstring to_proper_string(const T &t_str)
{
return to_wstring(t_str);
@@ -167,11 +164,11 @@ namespace chaiscript
static std::string get_error_message(DWORD t_err)
{
#ifdef _UNICODE
typedef LPWSTR StringType;
typedef LPTSTR StringType;
#if defined(_UNICODE) || defined(UNICODE)
std::wstring retval = L"Unknown Error";
#else
typedef LPSTR StringType;
std::string retval = "Unknown Error";
#endif
StringType lpMsgBuf = nullptr;
@@ -180,11 +177,11 @@ namespace chaiscript
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
nullptr,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(StringType)&lpMsgBuf,
0, NULL ) != 0 && lpMsgBuf)
reinterpret_cast<StringType>(&lpMsgBuf),
0, nullptr ) != 0 && lpMsgBuf)
{
retval = lpMsgBuf;
LocalFree(lpMsgBuf);
@@ -265,8 +262,8 @@ namespace chaiscript
std::map<std::string, detail::Loadable_Module_Ptr> m_loaded_modules;
std::set<std::string> m_active_loaded_modules;
std::vector<std::string> m_modulepaths;
std::vector<std::string> m_usepaths;
std::vector<std::string> m_module_paths;
std::vector<std::string> m_use_paths;
chaiscript::detail::Dispatch_Engine m_engine;
@@ -277,25 +274,37 @@ namespace chaiscript
parser::ChaiScript_Parser parser;
if (parser.parse(t_input, t_filename)) {
//parser.show_match_stack();
return parser.ast()->eval(m_engine);
return parser.optimized_ast()->eval(m_engine);
} else {
return Boxed_Value();
}
}
catch (const chaiscript::eval::detail::Return_Value &rv) {
catch (chaiscript::eval::detail::Return_Value &rv) {
return rv.retval;
}
}
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
/// Evaluates the given file and looks in the 'use' paths
const Boxed_Value internal_eval_file(const std::string &t_filename) {
for (const auto &path : m_use_paths)
{
try {
const auto appendedpath = path + t_filename;
return do_eval(load_file(appendedpath), appendedpath, true);
} catch (const exception::file_not_found_error &) {
// failed to load, try the next path
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
// failed to load by any name
throw exception::file_not_found_error(t_filename);
}
@@ -330,6 +339,11 @@ namespace chaiscript
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("class");
m_engine.add_reserved_word("attr");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("global");
m_engine.add_reserved_word("GLOBAL");
m_engine.add_reserved_word("_");
if (t_lib)
@@ -337,39 +351,66 @@ namespace chaiscript
add(t_lib);
}
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, std::ref(m_engine)), "dump_system");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, std::ref(m_engine)), "dump_object");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&chaiscript::detail::Dispatch_Engine::call_exists, std::ref(m_engine), std::placeholders::_1))),
"call_exists");
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
m_engine.add(fun([this](){ m_engine.dump_system(); }), "dump_system");
m_engine.add(fun([this](const Boxed_Value &t_bv){ m_engine.dump_object(t_bv); }), "dump_object");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_type){ return m_engine.is_type(t_bv, t_type); }), "is_type");
m_engine.add(fun([this](const Boxed_Value &t_bv){ return m_engine.type_name(t_bv); }), "type_name");
m_engine.add(fun([this](const std::string &t_f){ return m_engine.function_exists(t_f); }), "function_exists");
m_engine.add(fun([this](){ return m_engine.get_function_objects(); }), "get_functions");
m_engine.add(fun([this](){ return m_engine.get_scripting_objects(); }), "get_objects");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
m_engine.add(
dispatch::make_dynamic_proxy_function(
[this](const std::vector<Boxed_Value> &t_params) {
return m_engine.call_exists(t_params);
})
, "call_exists");
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
//
//
m_engine.add(fun(
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
return t_fun(t_params, s);
}), "call");
typedef std::string (ChaiScript::*load_mod_1)(const std::string&);
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
m_engine.add(fun([this](const std::string &t_type_name){ return m_engine.get_type(t_type_name, true); }), "type");
m_engine.add(fun(&ChaiScript::use, this), "use");
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
m_engine.add(fun(
[=](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
}
), "add_type_conversion");
m_engine.add(fun(&ChaiScript::version_major, this), "version_major");
m_engine.add(fun(&ChaiScript::version_minor, this), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch, this), "version_patch");
m_engine.add(fun(&ChaiScript::version, this), "version");
m_engine.add(fun(&ChaiScript::add_global_const, this), "add_global_const");
m_engine.add(fun(&ChaiScript::add_global, this), "add_global");
do_eval(ChaiScript_Prelude::chaiscript_prelude(), "standard prelude");
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
m_engine.add(fun(&parse), "parse");
m_engine.add(fun(&ChaiScript::version_major), "version_major");
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
m_engine.add(fun(&ChaiScript::version), "version");
m_engine.add(fun(&ChaiScript::compiler_version), "compiler_version");
m_engine.add(fun(&ChaiScript::compiler_name), "compiler_name");
m_engine.add(fun(&ChaiScript::compiler_id), "compiler_id");
m_engine.add(fun(&ChaiScript::debug_build), "debug_build");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
}
@@ -381,7 +422,7 @@ namespace chaiscript
throw chaiscript::exception::file_not_found_error(t_filename);
}
std::streampos size = infile.tellg();
const auto size = infile.tellg();
infile.seekg(0, std::ios::beg);
assert(size >= 0);
@@ -390,7 +431,7 @@ namespace chaiscript
{
return std::string();
} else {
std::vector<char> v(static_cast<unsigned int>(size));
std::vector<char> v(static_cast<size_t>(size));
infile.read(&v[0], size);
return std::string(v.begin(), v.end());
}
@@ -404,16 +445,16 @@ namespace chaiscript
ChaiScript(const ModulePtr &t_lib,
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_modulepaths(std::move(t_modulepaths)), m_usepaths(std::move(t_usepaths))
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
{
if (m_modulepaths.empty())
if (m_module_paths.empty())
{
m_modulepaths.push_back("");
m_module_paths.push_back("");
}
if (m_usepaths.empty())
if (m_use_paths.empty())
{
m_usepaths.push_back("");
m_use_paths.push_back("");
}
build_eval_system(t_lib);
@@ -428,16 +469,16 @@ namespace chaiscript
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_modulepaths(std::move(t_modulepaths)), m_usepaths(std::move(t_usepaths))
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
{
if (m_modulepaths.empty())
if (m_module_paths.empty())
{
m_modulepaths.push_back("");
m_module_paths.push_back("");
}
if (m_usepaths.empty())
if (m_use_paths.empty())
{
m_usepaths.push_back("");
m_use_paths.push_back("");
}
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
@@ -446,7 +487,7 @@ namespace chaiscript
union cast_union
{
void (ChaiScript::*in_ptr)(const std::string&);
Boxed_Value (ChaiScript::*in_ptr)(const std::string&);
void *out_ptr;
};
@@ -454,9 +495,9 @@ namespace chaiscript
memset( &rInfo, 0, sizeof(rInfo) );
cast_union u;
u.in_ptr = &ChaiScript::use;
if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
std::string dllpath(rInfo.dli_fname);
size_t lastslash = dllpath.rfind('/');
const size_t lastslash = dllpath.rfind('/');
if (lastslash != std::string::npos)
{
dllpath.erase(lastslash);
@@ -464,15 +505,15 @@ namespace chaiscript
// Let's see if this is a link that we should expand
std::vector<char> buf(2048);
size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && pathlen < buf.size())
const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size())
{
dllpath = std::string(&buf.front(), pathlen);
dllpath = std::string(&buf.front(), static_cast<size_t>(pathlen));
}
m_modulepaths.insert(m_modulepaths.begin(), dllpath+"/");
}
#endif
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
}
#endif
// attempt to load the stdlib
@@ -481,61 +522,120 @@ namespace chaiscript
build_eval_system(ModulePtr());
}
int version_major() const
const Boxed_Value eval(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
static AST_NodePtr parse(const std::string &t_input)
{
parser::ChaiScript_Parser parser;
if (parser.parse(t_input, "PARSE")) {
//parser.show_match_stack();
return parser.optimized_ast();
} else {
throw chaiscript::exception::eval_error("Unknown error while parsing");
}
}
static int version_major()
{
return chaiscript::version_major;
}
int version_minor() const
static int version_minor()
{
return chaiscript::version_minor;
}
int version_patch() const
static int version_patch()
{
return chaiscript::version_patch;
}
std::string version() const
static std::string version()
{
std::stringstream ss;
ss << version_major() << "." << version_minor() << "." << version_patch();
return ss.str();
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
{
return chaiscript::compiler_name;
}
static bool debug_build()
{
return chaiscript::debug_build;
}
std::string get_type_name(const Type_Info &ti) const
{
return m_engine.get_type_name(ti);
}
template<typename T>
std::string get_type_name() const
{
return get_type_name(user_type<T>());
}
/// \brief Loads and parses a file. If the file is already, it is not reloaded
/// The use paths specified at ChaiScript construction time are searched for the
/// requested file.
///
/// \param[in] t_filename Filename to load and evaluate
void use(const std::string &t_filename)
Boxed_Value use(const std::string &t_filename)
{
for (size_t i = 0; i < m_usepaths.size(); ++i)
for (const auto &path : m_use_paths)
{
try {
const std::string appendedpath = m_usepaths[i] + t_filename;
const auto appendedpath = path + t_filename;
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
Boxed_Value retval;
if (m_used_files.count(appendedpath) == 0)
{
l2.unlock();
eval_file(appendedpath);
retval = eval_file(appendedpath);
l2.lock();
m_used_files.insert(appendedpath);
}
return; // return, we loaded it, or it was already loaded
} catch (const exception::file_not_found_error &) {
if (i == m_usepaths.size() - 1)
{
throw exception::file_not_found_error(t_filename);
}
return retval; // return, we loaded it, or it was already loaded
} catch (const exception::file_not_found_error &) {
// failed to load, try the next path
}
}
// failed to load by any name
throw exception::file_not_found_error(t_filename);
}
/// \brief Adds a constant object that is available in all contexts and to all threads
@@ -560,7 +660,15 @@ namespace chaiscript
return *this;
}
ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name)
{
m_engine.set_global(t_bv, t_name);
return *this;
}
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
/// \warning State object does not contain the user defined type conversions of the engine. They
/// are left out due to performance considerations involved in tracking the state
/// \sa ChaiScript::get_state
/// \sa ChaiScript::set_state
struct State
@@ -583,7 +691,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai;
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
/// \endcode
State get_state()
State get_state() const
{
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
@@ -666,7 +774,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
/// \endcode
ChaiScript &add(const Dynamic_Cast_Conversion &d)
ChaiScript &add(const Type_Conversion &d)
{
m_engine.add(d);
return *this;
@@ -686,7 +794,7 @@ namespace chaiscript
/// \param[in] t_module_name Name of the module to load
///
/// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript)
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|"").
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|".bundle"|"").
///
/// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>".
/// If no file can be found matching the search criteria and containing the appropriate entry point
@@ -703,29 +811,23 @@ namespace chaiscript
version_stripped_name.erase(version_pos);
}
std::vector<std::string> prefixes;
prefixes.push_back("lib");
prefixes.push_back("cyg");
prefixes.push_back("");
std::vector<std::string> prefixes{"lib", "cyg", ""};
std::vector<std::string> postfixes;
postfixes.push_back(".dll");
postfixes.push_back(".so");
postfixes.push_back("");
std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
for (auto & elem : m_modulepaths)
for (auto & elem : m_module_paths)
{
for (auto & prefix : prefixes)
{
for (auto & postfix : postfixes)
{
try {
std::string name = elem + prefix + t_module_name + postfix;
// std::cerr << "trying location: " << name << std::endl;
const auto name = elem + prefix + t_module_name + postfix;
// std::cerr << "trying location: " << name << '\n';
load_module(version_stripped_name, name);
return name;
} catch (const chaiscript::exception::load_module_error &e) {
// std::cerr << "error: " << e.what() << std::endl;
// std::cerr << "error: " << e.what() << '\n';
errors.push_back(e);
// Try next set
}
@@ -832,7 +934,7 @@ namespace chaiscript
///
/// \param[in] t_input Script to execute
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
/// \param[in] t_filename Optional filename to report to the user for where the error occurred. Useful
/// in special cases where you are loading a file internally instead of using eval_file
///
/// \return result of the script execution
@@ -866,7 +968,7 @@ namespace chaiscript
}
}
/// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result.
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
/// \tparam T Type to extract from the result value of the script execution
/// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -38,11 +38,28 @@ def eq(l, r) {
def new(x) {
eval(type_name(x))();
}
}
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x);
def clone(double x) {
double(x).clone_var_attrs(x)
}
def clone(string x) {
string(x).clone_var_attrs(x)
}
def clone(vector x) {
vector(x).clone_var_attrs(x)
}
def clone(int x) {
int(x).clone_var_attrs(x)
}
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{
eval(type_name(x))(x).clone_var_attrs(x);
}
@@ -56,11 +73,6 @@ def to_string(x) : call_exists(range, x) && !x.is_type("string"){
"[" + x.join(", ") + "]";
}
# Basic to_string function
def to_string(x) {
internal_to_string(x);
}
# Prints to console with no carriage return
def puts(x) {
print_string(x.to_string());
@@ -115,18 +127,6 @@ def even(x)
}
# 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)
@@ -136,8 +136,8 @@ def insert_at(container, pos, x)
# Returns the reverse of the given container
def reverse(container) {
auto retval = new(container);
auto r = range(container);
auto retval := new(container);
auto r := range(container);
while (!r.empty()) {
retval.push_back(r.back());
r.pop_back();
@@ -145,10 +145,18 @@ def reverse(container) {
retval;
}
def range(r) : call_exists(range_internal, r)
{
var ri := range_internal(r);
ri.get_var_attr("internal_obj") := r;
ri;
}
# Return a range from a range
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
{
return clone(r);
{
clone(r);
}
@@ -200,19 +208,19 @@ def retro::empty()
# Performs the second value function over the container first value
def for_each(container, func) : call_exists(range, container) {
var t_range = range(container);
var t_range := range(container);
while (!t_range.empty()) {
func(t_range.front());
t_range.pop_front();
}
}
def back_inserter(container) {
bind(push_back, container, _);
def back_inserter(container) {
bind(push_back, container, _);
}
def contains(container, item, compare_func) : call_exists(range, container) {
auto t_range = range(container);
auto t_range := range(container);
while (!t_range.empty()) {
if ( compare_func(t_range.front(), item) ) {
return true;
@@ -220,15 +228,15 @@ def contains(container, item, compare_func) : call_exists(range, container) {
t_range.pop_front();
}
return false;
false;
}
def contains(container, item) {
return contains(container, item, eq)
contains(container, item, eq)
}
def map(container, func, inserter) : call_exists(range, container) {
auto range = range(container);
auto range := range(container);
while (!range.empty()) {
inserter(func(range.front()));
range.pop_front();
@@ -237,7 +245,7 @@ def map(container, func, inserter) : call_exists(range, container) {
# Performs the second value function over the container first value. Creates a new container with the results
def map(container, func) {
auto retval = new(container);
auto retval := new(container);
map(container, func, back_inserter(retval));
retval;
}
@@ -245,7 +253,7 @@ def map(container, func) {
# Performs the second value function over the container first value. Starts with initial and continues with each element.
def foldl(container, func, initial) : call_exists(range, container){
auto retval = initial;
auto range = range(container);
auto range := range(container);
while (!range.empty()) {
retval = (func(range.front(), retval));
range.pop_front();
@@ -266,8 +274,8 @@ def product(container) {
# Returns a new container with the elements of the first value concatenated with the elements of the second value
def concat(x, y) : call_exists(clone, x) {
auto retval = x;
auto inserter = back_inserter(retval);
auto range = range(y);
auto inserter := back_inserter(retval);
auto range := range(y);
while (!range.empty()) {
inserter(range.front());
range.pop_front();
@@ -277,7 +285,7 @@ def concat(x, y) : call_exists(clone, x) {
def take(container, num, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
auto i = num;
while ((i > 0) && (!r.empty())) {
inserter(r.front());
@@ -289,14 +297,14 @@ def take(container, num, inserter) : call_exists(range, container) {
# Returns a new container with the given number of elements taken from the container
def take(container, num) {
auto retval = new(container);
auto retval := new(container);
take(container, num, back_inserter(retval));
retval;
}
def take_while(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
while ((!r.empty()) && f(r.front())) {
inserter(r.front());
r.pop_front();
@@ -306,14 +314,14 @@ def take_while(container, f, inserter) : call_exists(range, container) {
# Returns a new container with the given elements match the second value function
def take_while(container, f) {
auto retval = new(container);
auto retval := new(container);
take_while(container, f, back_inserter(retval));
retval;
}
def drop(container, num, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
auto i = num;
while ((i > 0) && (!r.empty())) {
r.pop_front();
@@ -328,14 +336,14 @@ def drop(container, num, inserter) : call_exists(range, container) {
# Returns a new container with the given number of elements dropped from the given container
def drop(container, num) {
auto retval = new(container);
auto retval := new(container);
drop(container, num, back_inserter(retval));
retval;
}
def drop_while(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
while ((!r.empty())&& f(r.front())) {
r.pop_front();
}
@@ -348,7 +356,7 @@ def drop_while(container, f, inserter) : call_exists(range, container) {
# Returns a new container with the given elements dropped that match the second value function
def drop_while(container, f) {
auto retval = new(container);
auto retval := new(container);
drop_while(container, f, back_inserter(retval));
retval;
}
@@ -356,7 +364,7 @@ def drop_while(container, f) {
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) {
auto r = range(container);
auto r := range(container);
auto retval = r.front();
r.pop_front();
retval = func(retval, r.front());
@@ -372,7 +380,7 @@ def reduce(container, func) : container.size() >= 2 && call_exists(range, contai
# Returns a string of the elements in container delimited by the second value string
def join(container, delim) {
auto retval = "";
auto range = range(container);
auto range := range(container);
if (!range.empty()) {
retval += to_string(range.front());
range.pop_front();
@@ -387,7 +395,7 @@ def join(container, delim) {
def filter(container, f, inserter) : call_exists(range, container) {
auto r = range(container);
auto r := range(container);
while (!r.empty()) {
if (f(r.front())) {
inserter(r.front());
@@ -399,7 +407,7 @@ def filter(container, f, inserter) : call_exists(range, container) {
# Returns a new Vector which match the second value function
def filter(container, f) {
auto retval = new(container);
auto retval := new(container);
filter(container, f, back_inserter(retval));
retval;
}
@@ -416,7 +424,7 @@ def generate_range(x, y, inserter) {
# Returns a new Vector which represents the range from the first value to the second value
def generate_range(x, y) {
auto retval = Vector();
auto retval := Vector();
generate_range(x,y,back_inserter(retval));
retval;
}
@@ -429,8 +437,8 @@ def collate(x, y) {
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) {
auto r_x = range(x);
auto r_y = range(y);
auto r_x := range(x);
auto r_y := range(y);
while (!r_x.empty() && !r_y.empty()) {
inserter(f(r_x.front(), r_y.front()));
r_x.pop_front();
@@ -441,7 +449,7 @@ def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y)
# Returns a new Vector which joins matching elements of the second and third value with the first value function
def zip_with(f, x, y) {
auto retval = Vector();
auto retval := Vector();
zip_with(f,x,y,back_inserter(retval));
retval;
}
@@ -454,37 +462,37 @@ def zip(x, y) {
# Returns the position of the second value string in the first value string
def string::find(substr) : is_type(substr, "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(substr) : is_type(substr, "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(list) : is_type(list, "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(list) : is_type(list, "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(list) : is_type(list, "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(list) : is_type(list, "string") {
def string::find_last_not_of(string list) {
find_last_not_of(this, list, size_t(-1));
}
@@ -504,8 +512,8 @@ def string::trim() {
}
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
auto range = range(container);
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;
@@ -513,12 +521,12 @@ def find(container, value, compare_func) : call_exists(range, container) && is_t
range.pop_front();
}
}
return range;
range;
}
def find(container, value) {
return find(container, value, eq)
find(container, value, eq)
}

View File

@@ -112,7 +112,7 @@ class Map
};
/// \brief A concept implemented by string, Vector and Map. It is convertable to Range, default constructable and back_insertable
/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
class Container
{
public:
@@ -153,10 +153,10 @@ void print(Object o);
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
///
/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string
/// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string
/// using the chaiscript::boxed_cast and chaiscript::var functions.
///
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
/// std::string of the same name.
///
/// \note Object and function notations are equivalent in ChaiScript. This means that
@@ -309,7 +309,7 @@ class Range
/// \brief Moves the front pointer forward one
///
/// \post front() returne the element at front() + 1;
/// \post front() returns the element at front() + 1;
void pop_front();
};
@@ -340,7 +340,7 @@ class Const_Range
/// \brief Moves the front pointer forward one
///
/// \post front() returne the element at front() + 1;
/// \post front() returns the element at front() + 1;
void pop_front();
};
@@ -519,7 +519,7 @@ class Function
/// \brief Returns a vector of Type_Info objects that represent the param types for this function.
/// The first value in the list is the return type.
///
/// If this function is a conglomeration of several functions (get_contained_values().size() > 0)
/// If this function is a conglomerate of several functions (get_contained_values().size() > 0)
/// then the function returns as many Type_Info objects as it can. If the functions contained all have
/// the same arity, then it represents the arity. If they have different arities, it returns only
/// one value - the return type.
@@ -534,7 +534,7 @@ class Function
/// \endcode
Vector get_param_types() const;
/// \brief Returns true if the function has a guard to it. Always returns falls for a conglomerate function
/// \brief Returns true if the function has a guard to it. Always returns false for a conglomerate function
bool has_guard() const;
/// \brief Calls the function with the given set of parameters and returns the value;
@@ -718,14 +718,14 @@ Object drop_while(Range c, Function f);
Object reduce(Range c, Function f);
/// \brief Takes elements from Range c that match function f, return them.
/// \brief Takes elements from Container 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);
Object filter(Container c, Function f);
/// \brief Joins the elements of the Range c into a string, delimiting each with the delim string.

View File

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

View File

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

View File

@@ -1,19 +1,21 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
#include "../dispatchkit/operators.hpp"
namespace chaiscript
@@ -21,8 +23,29 @@ namespace chaiscript
namespace utility
{
/// \todo Use of this utility, and uniform initializer lists, is causing memory errors in MSVC
/// Single step command for registering a class with ChaiScript
///
/// \param[in,out] t_module Model to add class to
/// \param[in] t_class_name Name of the class being registered
/// \param[in] t_constructors Vector of constructors to add
/// \param[in] t_funcs Vector of methods to add
///
/// \example Adding a basic class to ChaiScript in one step
///
/// \code
/// chaiscript::utility::add_class<test>(*m,
/// "test",
/// { constructor<test ()>(),
/// constructor<test (const test &)>() },
/// { {fun(&test::function), "function"},
/// {fun(&test::function2), "function2"},
/// {fun(&test::function3), "function3"},
/// {fun(static_cast<std::string(test::*)(double)>(&test::function_overload)), "function_overload" },
/// {fun(static_cast<std::string(test::*)(int)>(&test::function_overload)), "function_overload" },
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
/// }
/// );
///
template<typename Class, typename ModuleType>
void add_class(ModuleType &t_module,
const std::string &t_class_name,
@@ -36,13 +59,47 @@ namespace chaiscript
t_module.add(ctor, t_class_name);
}
for(auto fun: t_funcs)
for(const auto &fun: t_funcs)
{
t_module.add(fun.first, fun.second);
}
}
template<typename Enum, typename ModuleType>
typename std::enable_if<std::is_enum<Enum>::value, void>::type
add_class(ModuleType &t_module,
const std::string &t_class_name,
#ifdef CHAISCRIPT_GCC_4_6
const std::vector<std::pair<int, std::string>> &t_constants
#else
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants
#endif
)
{
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
using namespace chaiscript::bootstrap::operators;
t_module.add([](){
// add some comparison and assignment operators
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
}());
#ifdef CHAISCRIPT_GCC_4_6
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
#else
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
#endif
for (const auto &constant : t_constants)
{
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,18 @@
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)
Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=master)](http://codecov.io/github/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)
Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=develop)](http://codecov.io/github/ChaiScript/ChaiScript?branch=develop)
<a href="https://scan.coverity.com/projects/5297">
<img alt="Coverity Scan Build Status"
src="https://img.shields.io/coverity/scan/5297.svg"/>
</a>
ChaiScript
http://www.chaiscript.com
(c) 2009-2012 Jonathan Turner
(c) 2009-2014 Jason Turner
(c) 2009-2016 Jason Turner
Release under the BSD license, see "license.txt" for details.
@@ -16,6 +20,8 @@ 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
@@ -33,9 +39,10 @@ Requirements
============
ChaiScript requires a C++11 compiler to build with support for variadic
templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx). MacOS
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.
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
=====

View File

@@ -1,6 +1,137 @@
Notes:
=======
Current Version: 5.3.1
Current Version: 5.8.2
### Changes since 5.8.1
* Allow casting to non-const & std::shared_ptr<T>
### Changes since 5.8.0
* Fix parsing of floats to be locale independent #250
* Various warning fixes on various platforms
### Changes since 5.7.1
* Make all parser iterator operations range checked
* Parse in-string eval statements once, not once for each execution
* Fix parsing of operators (ie 1<-1 now parses)
* Fix variable scoping for functors
* Exception reduction
* Various object lifetime fixes
* Add JSON support for load / save #207
* Numeric overload resolution fixes #209
* Fix long long #208
* Add octal escapes in strings #211
* Fixed sizing of binary literals #213
* Added support for != with bool values #217
* Various value assignment vector fixes
* Fixed broken hex escape sequences from @ChristianKaeser
* Multiply defined symbols fixes #232 @RaptorFactor
* Add add_class<Enum> helper #233 @vrennert
* Cheatsheet fixes #235 @mlamby
* Fix parsing of strings inside of in-string eval statements
* Allow lower-case global keyword
* Enable thread-local on MSVC (should be significant performance boost)
### Changes since 5.7.0
* Build time reduction
* Build size reduction
* Performance increases
* Fixed ~20 crash-bugs found with fuzzy testing #194
* Let unhandled exceptions propogate to user
* Report eval_error when break statement is not in loop
* Fix handling of 0 length scripts closes #193
* Don't crash on arity mismatch - Specifically affects the case where no overloads exist for a given function
* Fix error printing for `bind` calls
* Handle unexpected continue statement
* Check arity during bind
* Don't allow arith conversion on variadic function
* Correct `bind` parameter match count
* Add in expected Boxed_Value exception cases
* Check access to AST, don't allow `;` in func def
* Don't attempt arithmetic unary & call
* Don't crash on 0 param call to `bind`
* Catch errors during member function dispatch
* Properly handle type of const bool &
* Automatic deduction of lambda type signatures
* Work with non-polymorphic parent/child conversions
* Move to codecov for coverage reporting
* Add `.at` method for Map objects
* Various corrections for support of move-only objects
### Changes since 5.6.0
* Significant code cleanups and reduction
* Smaller builds
* Faster compiles
* Less runtime memory usage
* ~2x faster runtimes
* biicode support
* method_missing feature added #164 @arBmind
* Generic objects with dynamic properties support
* Add ability to call functions contained in properties
* Add lambda captures
* Create [cheatsheet.md](cheatsheet.md) for all-in-one reference of features
* Fix support for libc++
* Eliminate clone of return value stored locally
* Eliminate 'return' statements when last line of function
* Reduce number of runtime exceptions occuring
* Reduce copies / moves of return values.
* make `use` statement return value of last statement in file
* Add ability to access fixed array sizes
* Add support for scientific notation floating point literals #174 @totalgee
### Changes since 5.5.1
* Throw exception on integer divide by 0
* Add optional type specification to function declarations
```
def func(int i, j, double k) {
// i must be an int.
// j can be anything
// k must be a double
// normal conversion rules still apply
}
```
* Many minor fixes for compiler warnings
* Add support for `std::future` and `std::async`
```
var f := async(someFunction);
var f2 := async(someFunction2);
// someFunction and someFunction2 are running in parallel now
f.get();
f2.get();
```
* Fully support r-value returns, supporting move-only objects and reducing object copies
### Changes since 5.5.0
* 30% performance increase
* Fix handling of object stack, resulting in greatly reduced memory usage
* Code cleanups
### Changes since 5.4.0
* 2x performance increase
* Significant code cleanups
* Throw exception if user attempts to call function on null object
* Allow user defined type conversions
* Fix object lifetime for nested function calls made at the global scope
* Fix returning of boolean values from function calls
### Changes since 5.3.1
* Decreased compile time and build size
* Make "reflection" module built in (losing some of the time / build size gains)
* Add new "class" syntax for ChaiScript defined methods and attributes see: [unittests/class.chai](unittests/class.chai) for examples
* Minor performance enhancements
* major to_string performance enhancements
* Provide API for retrieving registered type name #124
* Added strong reference to container to range object #132
### Changes since 5.3.0
* Add automatic conversion of arithmetic return types, following the same

View File

@@ -13,12 +13,12 @@
void log(const std::string &msg)
{
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
std::cout << "[" << time(nullptr) << "] " << msg << '\n';
}
void log(const std::string &module, const std::string &msg)
{
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
}
void bound_log(const std::string &msg)
@@ -28,12 +28,12 @@ void bound_log(const std::string &msg)
void hello_world(const chaiscript::Boxed_Value & /*o*/)
{
std::cout << "Hello World" << std::endl;
std::cout << "Hello World\n";
}
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
{
std::cout << "Hello Constructor" << std::endl;
std::cout << "Hello Constructor\n";
}
@@ -62,20 +62,21 @@ struct System
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
{
std::cout << *p << std::endl;
std::cout << *p << '\n';
}
int main(int /*argc*/, char * /*argv*/[]) {
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");
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
//Register the two methods of the System structure.
chai.add(fun(&System::add_callback), "add_callback");
@@ -122,7 +123,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//the templated version of eval:
int i = chai.eval<int>("5+5");
std::cout << "5+5: " << i << std::endl;
std::cout << "5+5: " << i << '\n';
//Add a new variable
chai("var scripti = 15");
@@ -130,9 +131,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
//We can even get a handle to the variables in the system
int &scripti = chai.eval<int &>("scripti");
std::cout << "scripti: " << scripti << std::endl;
std::cout << "scripti: " << scripti << '\n';
scripti *= 2;
std::cout << "scripti (updated): " << scripti << std::endl;
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

103
samples/factory.cpp Normal file
View File

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

View File

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

136
samples/inheritance.cpp Normal file
View File

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

View File

@@ -54,7 +54,7 @@ class test
chaiscript::Boxed_Value val = chai.eval_file(sFile);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
std::cout << e.what() << '\n';
}
}
@@ -70,12 +70,12 @@ int main(int /*argc*/, char * /*argv*/[]) {
std::string command = "";
//
// this loop increases memoryusage, if RunFile is not called (just hitting enter)
// 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: memoryusage does not change
// scenario2 - RunFile gets never called (just hitting enter): memoryusage increases every loop
// scenario3 - RunFile gets in changing intervals: memoryusage goes up and down, but never as
// 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")

View File

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

View File

@@ -1,14 +1,17 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, 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>
#ifdef READLINE_AVAILABLE
@@ -17,15 +20,15 @@
#else
char *mystrdup (const char *s) {
size_t len = strlen(s) + 1; // Space for length plus nul
char *d = static_cast<char*>(malloc (len));
size_t len = strlen(s); // Space for length plus nul
char *d = static_cast<char*>(malloc (len+1));
if (d == nullptr) return nullptr; // No memory
#ifdef CHAISCRIPT_MSVC
strcpy_s(d, len, s); // Copy the characters
strcpy_s(d, len+1, s); // Copy the characters
#else
strncpy(d,s,len); // Copy the characters
d[len] = '\0';
#endif
d[len] = '\0';
return d; // Return the new string
}
@@ -63,7 +66,7 @@ std::vector<std::string> default_search_paths()
#ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
std::string exepath(path, size);
@@ -85,24 +88,24 @@ std::vector<std::string> default_search_paths()
std::vector<char> buf(2048);
ssize_t size = -1;
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
if (exepath.empty())
{
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
}
if (exepath.empty())
{
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
{
exepath = std::string(&buf.front(), size);
exepath = std::string(&buf.front(), static_cast<size_t>(size));
}
}
@@ -136,26 +139,22 @@ std::vector<std::string> default_search_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;
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
std::cout << "Additionally, you can inspect the runtime system using:\n";
std::cout << " dump_system() - outputs all functions registered to the system\n";
std::cout << " dump_object(x) - dumps information about the given symbol\n";
} 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::cout << "usage : chai [option]+\n";
std::cout << "option:" << '\n';
std::cout << " -h | --help" << '\n';
std::cout << " -i | --interactive" << '\n';
std::cout << " -c | --command cmd" << '\n';
std::cout << " -v | --version" << '\n';
std::cout << " - --stdin" << '\n';
std::cout << " filepath" << '\n';
}
}
void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
bool throws_exception(const std::function<void ()> &f)
{
try {
@@ -231,7 +230,7 @@ void interactive(chaiscript::ChaiScript& chai)
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
}
catch (...) {} //If we can't, do nothing
}
@@ -239,17 +238,24 @@ void interactive(chaiscript::ChaiScript& chai)
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 << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
}
std::cout << std::endl;
std::cout << '\n';
}
catch (const std::exception &e) {
std::cout << e.what();
std::cout << std::endl;
std::cout << '\n';
}
}
}
double now()
{
using namespace std::chrono;
auto now = high_resolution_clock::now();
return duration_cast<duration<double>>(now.time_since_epoch()).count();
}
int main(int argc, char *argv[])
{
@@ -287,9 +293,12 @@ int main(int argc, char *argv[])
chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
chai.add(chaiscript::fun(&now), "now");
bool eval_error_ok = false;
bool boxed_exception_ok = false;
for (int i = 0; i < argc; ++i) {
if ( i == 0 && argc > 1 ) {
@@ -305,7 +314,7 @@ int main(int argc, char *argv[])
if ( arg == "-c" || arg == "--command" ) {
if ( (i+1) >= argc ) {
std::cout << "insufficient input following " << arg << std::endl;
std::cout << "insufficient input following " << arg << '\n';
return EXIT_FAILURE;
} else {
arg = argv[++i];
@@ -317,36 +326,56 @@ int main(int argc, char *argv[])
arg += line + '\n' ;
}
} else if ( arg == "-v" || arg == "--version" ) {
arg = "version(0)" ;
arg = "print(version())" ;
} else if ( arg == "-h" || arg == "--help" ) {
arg = "help(-1)";
} else if ( arg == "-e" || arg == "--evalerrorok" ) {
eval_error_ok = true;
continue;
} else if ( arg == "--exception" ) {
boxed_exception_ok = true;
continue;
} else if ( arg == "-i" || arg == "--interactive" ) {
mode = eInteractive ;
} else if ( arg.find('-') == 0 ) {
std::cout << "unrecognised argument " << arg << std::endl;
std::cout << "unrecognised argument " << arg << '\n';
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 : val = chai.eval_file(arg); break;
default : std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
case eInteractive:
interactive(chai);
break;
case eCommand:
chai.eval(arg);
break;
case eFile:
chai.eval_file(arg);
}
}
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.pretty_print();
std::cout << std::endl;
return EXIT_FAILURE;
std::cout << '\n';
if (!eval_error_ok) {
return EXIT_FAILURE;
}
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
return EXIT_FAILURE;
catch (const chaiscript::Boxed_Value &e) {
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
if (!boxed_exception_ok) {
return EXIT_FAILURE;
}
}
// catch (std::exception &e) {
// std::cout << e.what() << '\n';
// return EXIT_FAILURE;
// }
}
return EXIT_SUCCESS;

View File

@@ -1,129 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <chaiscript/utility/utility.hpp>
#include <string>
// MSVC doesn't like that we are using C++ return types from our C declared module
// but this is the best way to do it for cross platform compatibility
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4190)
#endif
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return true;
} else {
return false;
}
} else {
return false;
}
}
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
{
return pf->get_parse_tree();
} else {
throw std::runtime_error("Function does not have a parse tree");
}
} else {
throw std::runtime_error("Function does not have a parse tree");
}
}
#ifdef __llvm__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#endif
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
{
chaiscript::ModulePtr m(new chaiscript::Module());
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
using namespace chaiscript;
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(&chaiscript::exception::eval_error::call_stack), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
{ {fun(&File_Position::line), "line"},
{fun(&File_Position::column), "column"} }
);
chaiscript::utility::add_class<AST_Node>(*m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
{fun(&AST_Node::identifier), "identifier"},
{fun(&AST_Node::filename), "filename"},
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::internal_to_string), "internal_to_string"},
{fun(&AST_Node::children), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
return m;
}
#ifdef __llvm__
#pragma clang diagnostic pop
#endif
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp>
@@ -23,7 +23,11 @@
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
{
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
auto module = chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
module->add(chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector"));
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
return module;
}
#ifdef __llvm__

View File

@@ -1,13 +1,26 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <string>
class TestBaseType
{
public:
TestBaseType() : val(10), const_val(15) { }
TestBaseType(int) : val(10), const_val(15) {}
TestBaseType(int *) : val(10), const_val(15) {}
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(push)
#pragma warning(disable : 4351)
#endif
// MSVC 12 warns that we are using new (correct) behavior
TestBaseType() : val(10), const_val(15), mdarray{} { }
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(pop)
#endif
TestBaseType(const TestBaseType &) = default;
virtual ~TestBaseType() {}
virtual int func() { return 0; }
@@ -18,8 +31,41 @@ class TestBaseType
int val;
const int const_val;
int mdarray[2][3][5];
std::function<int (int)> func_member;
void set_string_val(std::string &t_str)
{
t_str = "42";
}
private:
TestBaseType &operator=(const TestBaseType &);
TestBaseType &operator=(const TestBaseType &) = delete;
};
class Type2
{
public:
Type2(TestBaseType t_bt)
: m_bt(std::move(t_bt)),
m_str("Hello World")
{
}
int get_val() const
{
return m_bt.val;
}
const char *get_str() const
{
return m_str.c_str();
}
private:
TestBaseType m_bt;
std::string m_str;
};
enum TestEnum
@@ -36,27 +82,46 @@ class TestDerivedType : public TestBaseType
{
public:
virtual ~TestDerivedType() {}
TestDerivedType(const TestDerivedType &) = default;
TestDerivedType() = default;
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
int derived_only_func() { return 19; }
private:
TestDerivedType &operator=(const TestDerivedType &);
TestDerivedType &operator=(const TestDerivedType &) = delete;
};
class TestMoreDerivedType : public TestDerivedType
{
public:
TestMoreDerivedType(const TestMoreDerivedType &) = default;
TestMoreDerivedType() = default;
virtual ~TestMoreDerivedType() {}
};
std::shared_ptr<TestBaseType> derived_type_factory()
{
return std::shared_ptr<TestBaseType>(new TestDerivedType());
return std::make_shared<TestDerivedType>();
}
std::shared_ptr<TestBaseType> more_derived_type_factory()
{
return std::shared_ptr<TestBaseType>(new TestMoreDerivedType());
return std::make_shared<TestMoreDerivedType>();
}
std::shared_ptr<TestBaseType> null_factory()
{
return std::shared_ptr<TestBaseType>();
}
void update_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
{
ptr = std::make_shared<TestDerivedType>();
}
void nullify_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
{
ptr = nullptr;
}
std::string hello_world()
@@ -64,9 +129,11 @@ std::string hello_world()
return "Hello World";
}
static int global_i = 1;
int *get_new_int()
{
return new int(1);
return &global_i;
}
// MSVC doesn't like that we are using C++ return types from our C declared module
@@ -90,6 +157,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
m->add(chaiscript::user_type<Type2>(), "Type2");
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
@@ -111,6 +179,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory");
m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory");
m->add(chaiscript::fun(&null_factory), "null_factory");
m->add(chaiscript::fun(&TestDerivedType::func), "func");
@@ -118,7 +187,21 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&TestBaseType::val), "val");
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
#ifndef CHAISCRIPT_MSVC_12
// we cannot support these in MSVC_12 because of a bug in the implementation of
// std::reference_wrapper
// Array types
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
m->add(chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5"));
m->add(chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5"));
m->add(chaiscript::bootstrap::array<int[5]>("IntArray_5"));
// end array types
#endif
// member that is a function
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
m->add(chaiscript::fun(&get_new_int), "get_new_int");
@@ -129,6 +212,16 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&to_int), "to_int");
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
m->add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { return Type2(t_bt); }));
m->add(chaiscript::fun(&Type2::get_val), "get_val");
m->add(chaiscript::fun(&Type2::get_str), "get_str");
m->add(chaiscript::type_conversion<const char *, std::string>());
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
m->add(chaiscript::fun(&update_shared_ptr), "update_shared_ptr");
m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr");
return m;
}

View File

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

View File

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

View File

@@ -1,70 +0,0 @@
// Tests to make sure that type conversions happen only when they should
#include <chaiscript/chaiscript.hpp>
void f1(int)
{
}
void f4(std::string)
{
}
void f2(int)
{
}
void f3(double)
{
}
void f_func_return(const std::function<unsigned int (unsigned long)> &f)
{
// test the ability to return an unsigned with auto conversion
f(4);
}
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&f1), "f1");
chai.add(chaiscript::fun(&f2), "f2");
chai.add(chaiscript::fun(&f3), "f2");
chai.add(chaiscript::fun(&f1), "f3");
chai.add(chaiscript::fun(&f4), "f3");
chai.add(chaiscript::fun(&f_func_return), "func_return");
// no overloads
chai.eval("f1(0)");
chai.eval("f1(0l)");
chai.eval("f1(0ul)");
chai.eval("f1(0ll)");
chai.eval("f1(0ull)");
chai.eval("f1(0.0)");
chai.eval("f1(0.0f)");
chai.eval("f1(0.0l)");
// expected overloads
chai.eval("f2(1)");
chai.eval("f2(1.0)");
// 1 non-arithmetic overload
chai.eval("f2(1.0)");
// various options for returning with conversions from chaiscript
chai.eval("func_return(fun(x) { return 5u; })");
chai.eval("func_return(fun(x) { return 5; })");
chai.eval("func_return(fun(x) { return 5.0f; })");
// this is the one call we expect to fail, ambiguous overloads
try {
chai.eval("f2(1.0l)");
} catch (const std::exception &) {
return EXIT_SUCCESS;
}
// if the last one did not throw, we failed
return EXIT_FAILURE;
}

View File

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

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