Compare commits

...

209 Commits

Author SHA1 Message Date
Jason Turner
2c99e6cd32 Update release notes 2016-10-28 11:03:31 -06:00
Jason Turner
a38b254a98 Only allow class in top level scope
* Throw error if class is in unexpected place
 * Allow catching of `eval_error` from inside of script

closes #297
2016-10-28 10:56:12 -06:00
Jason Turner
77231461ca Add test for class inside of scope
Addresses #297
2016-10-28 09:01:40 -06:00
Jason Turner
0d4a99af82 Enable conversion to bool in conditionals
closes #295
2016-10-26 13:52:03 -06:00
Jason Turner
9f30d84f39 Add conversion to bool tests as conditionals 2016-10-26 12:29:30 -06:00
Jason Turner
508729ec77 Properly handle error reporting with method_missing 2016-10-26 10:08:53 -06:00
Jason Turner
ab07872857 Update to 5.8.6 2016-10-10 19:46:29 -06:00
Jason Turner
23c13e6570 Apply return optimization to lambdas
closes #289
2016-10-10 18:52:54 -06:00
Jason Turner
7339ff2c2f Update release notes for 5.8.5 2016-10-09 19:59:48 -06:00
Jason Turner
665125665a Bump to 5.8.5
- remove parsing of unary &, it was unused
2016-10-06 22:32:55 -06:00
Jason Turner
d1c7645a4e Backport inits for g++4.6 2016-10-06 15:19:47 -06:00
Jason Turner
58faea1cf2 Add conversion to bool compile test
Re: #275
2016-10-06 14:52:34 -06:00
Jason Turner
8b7fe33bf1 Fix order of operations for prefix and '*', '/'
The problem is that Prefix did not properly participate in
operator precedence. I've fixed this, at least for the moment,
by adding a final depth of precedence that can be called when
the depth gets to the bottom.

closes #285
2016-10-06 14:44:30 -06:00
Jason Turner
21495ebb40 Make sure atomics are initialized 2016-10-06 09:09:50 -06:00
Jason Turner
bec1b91b7b Increment to 5.8.4 2016-09-24 17:17:40 -06:00
Jason Turner
4b81a24a0a Fix numeric mixed-convesion operations 2016-09-24 17:15:17 -06:00
Jason Turner
cefb4d3c78 Update release notes for 5.x 2016-09-16 12:33:07 -06:00
Jason Turner
41c1c490c8 Add support for *& return types 2016-04-29 08:31:59 -06:00
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
129 changed files with 5945 additions and 2578 deletions

View File

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

View File

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

View File

@@ -17,4 +17,11 @@ compilers:
version: 12 version: 12
architecture: Win64 architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% 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

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

@@ -20,6 +20,7 @@ option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE) option(BUILD_SAMPLES "Build Samples Folder" FALSE)
option(RUN_FUZZY_TESTS "Run tests generated by AFL" 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(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) mark_as_advanced(USE_STD_MAKE_SHARED)
@@ -68,6 +69,13 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(LINKER_FLAGS "${LINKER_FLAGS} -flto") set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
endif() 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) option(PROFILE_GENERATE "Generate profile data" FALSE)
if (PROFILE_GENERATE) if (PROFILE_GENERATE)
add_definitions(-fprofile-generate) add_definitions(-fprofile-generate)
@@ -94,8 +102,8 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 7) set(CPACK_PACKAGE_VERSION_MINOR 8)
set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_VERSION_PATCH 6)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com") set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -115,16 +123,12 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
include(CTest) include(CTest)
include(CPack) include(CPack)
include(cmake/CheckCXX11Features.cmake)
if(NOT MINGW) if(NOT MINGW)
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib) find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
endif() endif()
if(HAS_CXX11_VARIADIC_TEMPLATES) if (UNIX AND NOT APPLE)
message(STATUS "Variadic Template support detected") find_program(VALGRIND NAMES valgrind PATH /usr/bin /usr/local/bin)
else()
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
endif() endif()
enable_testing() enable_testing()
@@ -154,11 +158,14 @@ else()
endif() endif()
if(MSVC) if(MSVC)
add_definitions(/W4) add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
# VS2013 doesn't have magic statics
if (MSVC_VERSION STREQUAL "1800") if (MSVC_VERSION STREQUAL "1800")
# VS2013 doesn't have magic statics
add_definitions(/w44640) add_definitions(/w44640)
else()
# enum warnings are too noisy on MSVC2013
add_definitions(/w34062)
endif() endif()
add_definitions(/bigobj) add_definitions(/bigobj)
@@ -171,10 +178,10 @@ if(MSVC)
# how to workaround or fix the error. So I'm disabling it globally. # how to workaround or fix the error. So I'm disabling it globally.
add_definitions(/wd4503) add_definitions(/wd4503)
else() else()
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -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") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-Weverything -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors) add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
else() else()
add_definitions(-Wnoexcept) add_definitions(-Wnoexcept)
endif() endif()
@@ -206,7 +213,7 @@ endif()
include_directories(include) include_directories(include)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp) set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -253,10 +260,14 @@ add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
if(BUILD_SAMPLES) if(BUILD_SAMPLES)
add_executable(example samples/example.cpp) add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS}) target_link_libraries(example ${LIBS})
add_executable(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) add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS}) target_link_libraries(memory_leak_test ${LIBS})
add_executable(inheritance samples/inheritance.cpp) add_executable(inheritance samples/inheritance.cpp)
target_link_libraries(inheritance ${LIBS}) 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) add_executable(fun_call_performance samples/fun_call_performance.cpp)
target_link_libraries(fun_call_performance ${LIBS}) target_link_libraries(fun_call_performance ${LIBS})
endif() endif()
@@ -272,6 +283,9 @@ endif()
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai) file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
list(SORT UNIT_TESTS) list(SORT UNIT_TESTS)
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) if (RUN_FUZZY_TESTS)
@@ -336,8 +350,8 @@ if(BUILD_TESTING)
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents}) string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
foreach(hit ${found_tests}) foreach(hit ${found_tests})
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit}) string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
add_test(${test_name} "${executable}" ${test_name}) add_test(compiled.${test_name} "${executable}" ${test_name})
set_tests_properties(${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}") set_tests_properties(compiled.${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
endforeach() endforeach()
endif() endif()
endif() endif()
@@ -371,12 +385,32 @@ if(BUILD_TESTING)
) )
set(TESTS "")
foreach(filename ${UNIT_TESTS}) foreach(filename ${UNIT_TESTS})
message(STATUS "Adding test ${filename}") message(STATUS "Adding unit test ${filename}")
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${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() 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 PROPERTY ENVIRONMENT
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/" "CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"

View File

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

16
appveyor.yml Normal file
View File

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

View File

@@ -77,19 +77,54 @@ chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc. It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
``` ```
chai.add(chaiscript::user_type<MyClass>, "MyClass"); chai.add(chaiscript::user_type<MyClass>(), "MyClass");
``` ```
## Adding Type Conversions ## Adding Type Conversions
User defined type conversions are possible, defined in either script or in C++. User defined type conversions are possible, defined in either script or in C++.
### ChaiScript Defined Conversions
Function objects (including lambdas) can be used to add type conversions
from inside of ChaiScript:
```
add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); });
```
### C++ Defined Conversions
Invoking a C++ type conversion possible with `static_cast`
```
chai.add(chaiscript::type_conversion<T, bool>());
```
Calling a user defined type conversion that takes a lambda
```
chai.add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { /* return converted thing */ }));
```
### Helpers
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition: A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
``` ```
chai.add(chaiscript::vector_conversion<std::vector<int>>()); 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>` This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
## Adding Objects ## Adding Objects
@@ -100,8 +135,9 @@ chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared
auto shareddouble = std::make_shared<double>(4.3); 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::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(chaiscript::const_var(somevar), "somevar"); // copied in and made const
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const chai.add_global_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 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 # Using STL
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself. ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
@@ -155,6 +191,28 @@ chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with an
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double 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 ## Sharing Values
``` ```
@@ -221,11 +279,13 @@ var k = 5; // initialized to 5 (integer)
var l := k; // reference to k var l := k; // reference to k
auto &m = 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 = 5; // creates a global variable. If global already exists, it is not re-added
GLOBAL g = 2; // global 'g' now equals 2 global g = 2; // global 'g' now equals 2
GLOBAL g2; global g2;
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once 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 ## Built in Types
@@ -354,6 +414,19 @@ o.f = fun(y) { print(this.x + y); }
o.f(10); // prints 13 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 ## method_missing
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

11
contrib/check_for_tabs.rb Executable file
View File

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

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_ #ifndef CHAISCRIPT_THREADING_HPP_
@@ -45,14 +45,14 @@ namespace chaiscript
class unique_lock : public std::unique_lock<T> class unique_lock : public std::unique_lock<T>
{ {
public: public:
unique_lock(T &t) : std::unique_lock<T>(t) {} explicit unique_lock(T &t) : std::unique_lock<T>(t) {}
}; };
template<typename T> template<typename T>
class shared_lock : public std::unique_lock<T> class shared_lock : public std::unique_lock<T>
{ {
public: public:
shared_lock(T &t) : std::unique_lock<T>(t) {} explicit shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {} void unlock() {}
}; };
@@ -60,7 +60,7 @@ namespace chaiscript
class lock_guard : public std::lock_guard<T> class lock_guard : public std::lock_guard<T>
{ {
public: 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 { }; class shared_mutex : public std::mutex { };
@@ -77,7 +77,7 @@ namespace chaiscript
{ {
public: public:
Thread_Storage(void *t_key) explicit Thread_Storage(void *t_key)
: m_key(t_key) : m_key(t_key)
{ {
} }
@@ -129,7 +129,7 @@ namespace chaiscript
{ {
public: public:
Thread_Storage(void *) explicit Thread_Storage(void *)
{ {
} }
@@ -160,13 +160,14 @@ namespace chaiscript
{ {
unique_lock<mutex> lock(m_mutex); 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; } if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(std::make_shared<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; return new_instance;
} }
@@ -182,7 +183,7 @@ namespace chaiscript
class unique_lock class unique_lock
{ {
public: public:
unique_lock(T &) {} explicit unique_lock(T &) {}
void lock() {} void lock() {}
void unlock() {} void unlock() {}
}; };
@@ -191,7 +192,7 @@ namespace chaiscript
class shared_lock class shared_lock
{ {
public: public:
shared_lock(T &) {} explicit shared_lock(T &) {}
void lock() {} void lock() {}
void unlock() {} void unlock() {}
}; };
@@ -200,7 +201,7 @@ namespace chaiscript
class lock_guard class lock_guard
{ {
public: public:
lock_guard(T &) {} explicit lock_guard(T &) {}
}; };
class shared_mutex { }; class shared_mutex { };
@@ -212,7 +213,7 @@ namespace chaiscript
class Thread_Storage class Thread_Storage
{ {
public: public:
Thread_Storage(void *) explicit Thread_Storage(void *)
{ {
} }

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_ #ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
@@ -40,7 +40,7 @@ namespace chaiscript
{ {
} }
bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(nullptr), m_what(std::move(t_what)) : to(nullptr), m_what(std::move(t_what))
{ {
} }

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
/// \file /// \file
@@ -248,13 +248,17 @@ namespace chaiscript
m->add( m->add(
fun( fun(
[](ContainerType &c, int index) -> typename ContainerType::reference { [](ContainerType &c, int index) -> typename ContainerType::reference {
return c.at(index); /// \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( m->add(
fun( fun(
[](const ContainerType &c, int index) -> typename ContainerType::const_reference { [](const ContainerType &c, int index) -> typename ContainerType::const_reference {
return c.at(index); /// \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; return m;
@@ -334,7 +338,12 @@ namespace chaiscript
"# Pushes the second value onto the container while making a clone of the value\n" "# Pushes the second value onto the container while making a clone of the value\n"
"def push_back(" + type + " container, x)\n" "def push_back(" + type + " container, x)\n"
"{ \n" "{ \n"
" container.push_back_ref(clone(x)) \n" " if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_back_ref(x) \n"
" } else { \n"
" container.push_back_ref(clone(x)); \n"
" }\n"
"} \n" "} \n"
); );
@@ -370,7 +379,12 @@ namespace chaiscript
"# Pushes the second value onto the front of container while making a clone of the value\n" "# Pushes the second value onto the front of container while making a clone of the value\n"
"def push_front(" + type + " container, x)\n" "def push_front(" + type + " container, x)\n"
"{ \n" "{ \n"
" container.push_front_ref(clone(x)) \n" " if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_front_ref(x) \n"
" } else { \n"
" container.push_front_ref(clone(x)); \n"
" }\n"
"} \n" "} \n"
); );
return "push_front_ref"; return "push_front_ref";
@@ -460,6 +474,30 @@ namespace chaiscript
m->add(fun(static_cast<elem_access>(&MapType::at)), "at"); m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
m->add(fun(static_cast<const_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); container_type<MapType>(type, m);
default_constructible_type<MapType>(type, m); default_constructible_type<MapType>(type, m);
assignable_type<MapType>(type, m); assignable_type<MapType>(type, m);
@@ -515,7 +553,7 @@ namespace chaiscript
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>)) if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
{ {
m->eval(R"( m->eval(R"(
def Vector::`==`(rhs) : type_match(rhs, this) { def Vector::`==`(Vector rhs) {
if ( rhs.size() != this.size() ) { if ( rhs.size() != this.size() ) {
return false; return false;
} else { } else {

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
@@ -16,7 +16,7 @@
namespace chaiscript namespace chaiscript
{ {
class Type_Conversions; class Type_Conversions_State;
namespace detail namespace detail
{ {
@@ -33,14 +33,14 @@ namespace chaiscript
template<typename Result> template<typename Result>
struct Cast_Helper_Inner struct Cast_Helper_Inner
{ {
typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type; typedef typename std::add_const<Result>::type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
if (ob.get_type_info().bare_equal_type_info(typeid(Result))) if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{ {
auto p = throw_if_null(ob.get_const_ptr()); auto p = throw_if_null(ob.get_const_ptr());
return std::cref(*static_cast<const Result *>(p)); return *static_cast<const Result *>(p);
} else { } else {
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
@@ -52,23 +52,17 @@ namespace chaiscript
{ {
}; };
/// Cast_Helper_Inner for casting to a const & type
template<typename Result>
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
{
};
/// Cast_Helper_Inner for casting to a const * type /// Cast_Helper_Inner for casting to a const * type
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const Result *> struct Cast_Helper_Inner<const Result *>
{ {
typedef const Result * Result_Type; typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
if (ob.get_type_info().bare_equal_type_info(typeid(Result))) if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{ {
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr())); return static_cast<const Result *>(ob.get_const_ptr());
} else { } else {
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
@@ -80,11 +74,40 @@ namespace chaiscript
struct Cast_Helper_Inner<Result *> struct Cast_Helper_Inner<Result *>
{ {
typedef Result * Result_Type; typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result)) if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
{ {
return static_cast<Result *>(throw_if_null(ob.get_ptr())); return static_cast<Result *>(ob.get_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
};
template<typename Result>
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
{
};
template<typename Result>
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
{
};
/// Cast_Helper_Inner for casting to a & type
template<typename Result>
struct Cast_Helper_Inner<const Result &>
{
typedef const Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else { } else {
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();
} }
@@ -99,7 +122,7 @@ namespace chaiscript
{ {
typedef Result& Result_Type; typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
{ {
@@ -116,7 +139,7 @@ namespace chaiscript
{ {
typedef std::shared_ptr<Result> Result_Type; typedef std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
return ob.get().cast<std::shared_ptr<Result> >(); return ob.get().cast<std::shared_ptr<Result> >();
} }
@@ -128,7 +151,7 @@ namespace chaiscript
{ {
typedef std::shared_ptr<const Result> Result_Type; typedef std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
if (!ob.get_type_info().is_const()) if (!ob.get_type_info().is_const())
{ {
@@ -150,6 +173,21 @@ 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");
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 /// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
template<typename Result> template<typename Result>
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> > struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
@@ -166,9 +204,9 @@ namespace chaiscript
template<> template<>
struct Cast_Helper_Inner<Boxed_Value> struct Cast_Helper_Inner<Boxed_Value>
{ {
typedef const Boxed_Value & Result_Type; typedef Boxed_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
return ob; return ob;
} }
@@ -178,11 +216,11 @@ namespace chaiscript
template<> template<>
struct Cast_Helper_Inner<Boxed_Value &> struct Cast_Helper_Inner<Boxed_Value &>
{ {
typedef Boxed_Value& Result_Type; typedef std::reference_wrapper<Boxed_Value> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
return const_cast<Boxed_Value &>(ob); return std::ref(const_cast<Boxed_Value &>(ob));
} }
}; };
@@ -236,7 +274,7 @@ namespace chaiscript
{ {
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type; typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{ {
return Cast_Helper_Inner<T>::cast(ob, t_conversions); return Cast_Helper_Inner<T>::cast(ob, t_conversions);
} }

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
@@ -43,16 +43,19 @@ namespace chaiscript
// this is OK, so we're disabling size/and sign type warnings // this is OK, so we're disabling size/and sign type warnings
#ifdef CHAISCRIPT_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4244 4018 4389 4146 4365 4267) #pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wfloat-equal" #pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wfloat-conversion"
#endif #endif
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
@@ -100,6 +103,7 @@ namespace chaiscript
:(Common_Types::t_uint64); :(Common_Types::t_uint64);
} }
static Common_Types get_common_type(const Boxed_Value &t_bv) static Common_Types get_common_type(const Boxed_Value &t_bv)
{ {
const Type_Info &inp_ = t_bv.get_type_info(); const Type_Info &inp_ = t_bv.get_type_info();
@@ -120,8 +124,12 @@ namespace chaiscript
return get_common_type(sizeof(unsigned int), false); return get_common_type(sizeof(unsigned int), false);
} else if (inp_ == typeid(long)) { } else if (inp_ == typeid(long)) {
return get_common_type(sizeof(long), true); return get_common_type(sizeof(long), true);
} else if (inp_ == typeid(long long)) {
return get_common_type(sizeof(long long), true);
} else if (inp_ == typeid(unsigned long)) { } else if (inp_ == typeid(unsigned long)) {
return get_common_type(sizeof(unsigned long), false); return get_common_type(sizeof(unsigned long), false);
} else if (inp_ == typeid(unsigned long long)) {
return get_common_type(sizeof(unsigned long long), false);
} else if (inp_ == typeid(std::int8_t)) { } else if (inp_ == typeid(std::int8_t)) {
return Common_Types::t_int8; return Common_Types::t_int8;
} else if (inp_ == typeid(std::int16_t)) { } else if (inp_ == typeid(std::int16_t)) {
@@ -513,6 +521,21 @@ namespace chaiscript
validate_boxed_number(bv); validate_boxed_number(bv);
} }
static bool is_floating_point(const Boxed_Value &t_bv)
{
const Type_Info &inp_ = t_bv.get_type_info();
if (inp_ == typeid(double)) {
return true;
} else if (inp_ == typeid(long double)) {
return true;
} else if (inp_ == typeid(float)) {
return true;
} else {
return false;
}
}
Boxed_Number get_as(const Type_Info &inp_) const Boxed_Number get_as(const Type_Info &inp_) const
{ {
if (inp_.bare_equal_type_info(typeid(int))) { if (inp_.bare_equal_type_info(typeid(int))) {
@@ -537,8 +560,12 @@ namespace chaiscript
return Boxed_Number(get_as<unsigned int>()); return Boxed_Number(get_as<unsigned int>());
} else if (inp_.bare_equal_type_info(typeid(long))) { } else if (inp_.bare_equal_type_info(typeid(long))) {
return Boxed_Number(get_as<long>()); return Boxed_Number(get_as<long>());
} else if (inp_.bare_equal_type_info(typeid(long long))) {
return Boxed_Number(get_as<long long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) { } else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
return Boxed_Number(get_as<unsigned long>()); return Boxed_Number(get_as<unsigned long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long long))) {
return Boxed_Number(get_as<unsigned long long>());
} else if (inp_.bare_equal_type_info(typeid(int8_t))) { } else if (inp_.bare_equal_type_info(typeid(int8_t))) {
return Boxed_Number(get_as<int8_t>()); return Boxed_Number(get_as<int8_t>());
} else if (inp_.bare_equal_type_info(typeid(int16_t))) { } else if (inp_.bare_equal_type_info(typeid(int16_t))) {
@@ -987,7 +1014,7 @@ namespace chaiscript
{ {
typedef Boxed_Number Result_Type; typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
{ {
return Boxed_Number(ob); return Boxed_Number(ob);
} }

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_ #ifndef CHAISCRIPT_BOXED_VALUE_HPP_
@@ -231,6 +231,50 @@ namespace chaiscript
return m_data->m_type_info.bare_equal(ti); return m_data->m_type_info.bare_equal(ti);
} }
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 bool is_null() const CHAISCRIPT_NOEXCEPT
{ {
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr); return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
@@ -297,6 +341,13 @@ namespace chaiscript
return *this; 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 /// \returns true if the two Boxed_Values share the same internal type
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
@@ -330,9 +381,9 @@ namespace chaiscript
/// ///
/// @sa @ref adding_objects /// @sa @ref adding_objects
template<typename T> 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 { namespace detail {

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_ #ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
@@ -61,6 +61,17 @@ namespace chaiscript {
Ret (Class::*m_func)(Param...); 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> template<typename T>
struct Function_Signature struct Function_Signature

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_ #ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
@@ -24,23 +24,55 @@ namespace chaiscript
{ {
namespace dispatch 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 class Dynamic_Object
{ {
public: public:
Dynamic_Object(std::string t_type_name) Dynamic_Object(std::string t_type_name)
: m_type_name(std::move(t_type_name)) : m_type_name(std::move(t_type_name)), m_option_explicit(false)
{ {
} }
Dynamic_Object() : m_type_name("") Dynamic_Object() : m_type_name(""), m_option_explicit(false)
{ {
} }
bool is_explicit() const
{
return m_option_explicit;
}
void set_explicit(const bool t_explicit)
{
m_option_explicit = t_explicit;
}
std::string get_type_name() const std::string get_type_name() const
{ {
return m_type_name; return m_type_name;
} }
const Boxed_Value &operator[](const std::string &t_attr_name) const
{
return get_attr(t_attr_name);
}
Boxed_Value &operator[](const std::string &t_attr_name)
{
return get_attr(t_attr_name);
}
const Boxed_Value &get_attr(const std::string &t_attr_name) const const Boxed_Value &get_attr(const std::string &t_attr_name) const
{ {
auto a = m_attrs.find(t_attr_name); auto a = m_attrs.find(t_attr_name);
@@ -59,11 +91,19 @@ namespace chaiscript
Boxed_Value &method_missing(const std::string &t_method_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); return get_attr(t_method_name);
} }
const Boxed_Value &method_missing(const std::string &t_method_name) const 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); return get_attr(t_method_name);
} }
@@ -75,6 +115,7 @@ namespace chaiscript
private: private:
std::string m_type_name; std::string m_type_name;
bool m_option_explicit;
std::map<std::string, Boxed_Value> m_attrs; std::map<std::string, Boxed_Value> m_attrs;
}; };

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_ #ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
@@ -115,6 +115,24 @@ namespace chaiscript
} }
}; };
template<typename Ret>
struct Handle_Return<Ret *&>
{
static Boxed_Value handle(Ret *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);
}
};
template<typename Ret> template<typename Ret>
struct Handle_Return<Ret *> struct Handle_Return<Ret *>
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_ #ifndef CHAISCRIPT_TYPE_INFO_HPP_
@@ -32,17 +32,17 @@ namespace chaiscript
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) 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_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic), + (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
m_is_undef(false) + (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))
{ {
} }
CHAISCRIPT_CONSTEXPR Type_Info() CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(nullptr), m_bare_type_info(nullptr), : m_type_info(nullptr), m_bare_type_info(nullptr),
m_is_const(false), m_is_reference(false), m_is_pointer(false), m_flags(1 << is_undef_flag)
m_is_void(false), m_is_arithmetic(false),
m_is_undef(true)
{ {
} }
@@ -60,6 +60,16 @@ namespace chaiscript
return m_type_info < ti.m_type_info; return m_type_info < ti.m_type_info;
} }
CHAISCRIPT_CONSTEXPR bool operator!=(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return !(operator==(ti));
}
CHAISCRIPT_CONSTEXPR bool operator!=(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return !(operator==(ti));
}
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT 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
@@ -83,12 +93,12 @@ namespace chaiscript
&& (*m_bare_type_info) == ti; && (*m_bare_type_info) == ti;
} }
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } 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_is_reference; } 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_is_void; } 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_is_arithmetic; } 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_is_undef; } 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_is_pointer; } CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_pointer_flag)) != 0; }
std::string name() const std::string name() const
{ {
@@ -118,12 +128,13 @@ namespace chaiscript
private: private:
const std::type_info *m_type_info; const std::type_info *m_type_info;
const std::type_info *m_bare_type_info; const std::type_info *m_bare_type_info;
bool m_is_const; unsigned int m_flags;
bool m_is_reference; static const int is_const_flag = 0;
bool m_is_pointer; static const int is_reference_flag = 1;
bool m_is_void; static const int is_pointer_flag = 2;
bool m_is_arithmetic; static const int is_void_flag = 3;
bool m_is_undef; static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5;
}; };
namespace detail namespace detail
@@ -161,6 +172,11 @@ namespace chaiscript
} }
}; };
template<typename T>
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
{
};
template<typename T> template<typename T>
struct Get_Type_Info<const std::shared_ptr<T> &> struct Get_Type_Info<const std::shared_ptr<T> &>
{ {

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_COMMON_HPP_ #ifndef CHAISCRIPT_COMMON_HPP_
@@ -34,7 +34,7 @@ namespace chaiscript
/// Types of AST nodes available to the parser and eval /// Types of AST nodes available to the parser and eval
class AST_Node_Type { class AST_Node_Type {
public: public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl, enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range, Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or, Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
@@ -47,7 +47,7 @@ namespace chaiscript
/// Helper lookup to get the name of each node type /// Helper lookup to get the name of each node type
const char *ast_node_type_to_string(int ast_node_type) { const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or", "Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
@@ -489,9 +489,9 @@ namespace chaiscript
} }
} }
static bool get_bool_condition(const Boxed_Value &t_bv) { static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
try { try {
return boxed_cast<bool>(t_bv); return t_ss->boxed_cast<bool>(t_bv);
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("Condition not boolean"); throw exception::eval_error("Condition not boolean");
@@ -582,12 +582,12 @@ namespace chaiscript
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds) Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds) : m_ds(t_ds)
{ {
m_ds.get()->new_function_call(m_ds.get().stack_holder()); m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
} }
~Function_Push_Pop() ~Function_Push_Pop()
{ {
m_ds.get()->pop_function_call(m_ds.get().stack_holder()); m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
} }
void save_params(const std::vector<Boxed_Value> &t_params) void save_params(const std::vector<Boxed_Value> &t_params)

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_ENGINE_HPP_ #ifndef CHAISCRIPT_ENGINE_HPP_
@@ -36,7 +36,9 @@
#else #else
#ifdef CHAISCRIPT_WINDOWS #ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN #define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h> #include <windows.h>
#endif #endif
#endif #endif
@@ -175,11 +177,11 @@ namespace chaiscript
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, nullptr,
t_err, t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<StringType>(&lpMsgBuf), reinterpret_cast<StringType>(&lpMsgBuf),
0, NULL ) != 0 && lpMsgBuf) 0, nullptr ) != 0 && lpMsgBuf)
{ {
retval = lpMsgBuf; retval = lpMsgBuf;
LocalFree(lpMsgBuf); LocalFree(lpMsgBuf);
@@ -284,14 +286,7 @@ namespace chaiscript
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
/// Evaluates the given file and looks in the 'use' paths /// Evaluates the given file and looks in the 'use' paths
const Boxed_Value internal_eval_file(const std::string &t_filename) { const Boxed_Value internal_eval_file(const std::string &t_filename) {
@@ -347,6 +342,7 @@ namespace chaiscript
m_engine.add_reserved_word("class"); m_engine.add_reserved_word("class");
m_engine.add_reserved_word("attr"); m_engine.add_reserved_word("attr");
m_engine.add_reserved_word("var"); m_engine.add_reserved_word("var");
m_engine.add_reserved_word("global");
m_engine.add_reserved_word("GLOBAL"); m_engine.add_reserved_word("GLOBAL");
m_engine.add_reserved_word("_"); m_engine.add_reserved_word("_");
@@ -372,11 +368,15 @@ namespace chaiscript
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); // m_engine.add(fun<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( m_engine.add(fun(
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) { [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
return t_fun(t_params, this->m_engine.conversions()); Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
return t_fun(t_params, s);
}), "call"); }), "call");
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name"); m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type"); m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
@@ -396,16 +396,21 @@ namespace chaiscript
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use"); m_engine.add(fun([this](const std::string &t_file){ return 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_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 std::string &t_str){ return internal_eval(t_str); }), "eval");
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return internal_eval_ast(t_ast); }), "eval"); m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
m_engine.add(fun(&parse), "parse");
m_engine.add(fun(&ChaiScript::version_major), "version_major"); m_engine.add(fun(&ChaiScript::version_major), "version_major");
m_engine.add(fun(&ChaiScript::version_minor), "version_minor"); m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch), "version_patch"); m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
m_engine.add(fun(&ChaiScript::version), "version"); 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_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){ 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");
} }
@@ -500,10 +505,10 @@ namespace chaiscript
// Let's see if this is a link that we should expand // Let's see if this is a link that we should expand
std::vector<char> buf(2048); std::vector<char> buf(2048);
const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size()); const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
if (pathlen > 0 && pathlen < 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_module_paths.insert(m_module_paths.begin(), dllpath+"/"); m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
@@ -517,6 +522,28 @@ namespace chaiscript
build_eval_system(ModulePtr()); build_eval_system(ModulePtr());
} }
const Boxed_Value eval(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
static AST_NodePtr parse(const std::string &t_input)
{
parser::ChaiScript_Parser parser;
if (parser.parse(t_input, "PARSE")) {
//parser.show_match_stack();
return parser.optimized_ast();
} else {
throw chaiscript::exception::eval_error("Unknown error while parsing");
}
}
static int version_major() static int version_major()
{ {
return chaiscript::version_major; return chaiscript::version_major;
@@ -534,11 +561,36 @@ namespace chaiscript
static std::string version() static std::string version()
{ {
std::stringstream ss; return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
ss << version_major() << "." << version_minor() << "." << version_patch();
return ss.str();
} }
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 std::string get_type_name(const Type_Info &ti) const
{ {
return m_engine.get_type_name(ti); return m_engine.get_type_name(ti);
@@ -608,6 +660,12 @@ namespace chaiscript
return *this; 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 /// \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 /// \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 /// are left out due to performance considerations involved in tracking the state

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_EVAL_HPP_ #ifndef CHAISCRIPT_EVAL_HPP_
@@ -44,16 +44,33 @@ namespace chaiscript
namespace detail namespace detail
{ {
/// Helper function that will set up the scope around a function call, including handling the named function parameters /// Helper function that will set up the scope around a function call, including handling the named function parameters
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> &t_locals=std::map<std::string, Boxed_Value>()) { static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr) {
chaiscript::detail::Dispatch_State state(t_ss); chaiscript::detail::Dispatch_State state(t_ss);
chaiscript::eval::detail::Scope_Push_Pop spp(state);
for (const auto &local : t_locals) { const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
t_ss.add_object(local.first, local.second); auto &stack = t_ss.get_stack_data(state.stack_holder()).back();
if (!stack.empty() && stack.back().first == "__this") {
return &stack.back().second;
} else if (!t_vals.empty()) {
return &t_vals[0];
} else {
return nullptr;
}
}();
chaiscript::eval::detail::Stack_Push_Pop tpp(state);
if (thisobj) state.add_object("this", *thisobj);
if (t_locals) {
for (const auto &local : *t_locals) {
state.add_object(local.first, local.second);
}
} }
for (size_t i = 0; i < t_param_names.size(); ++i) { for (size_t i = 0; i < t_param_names.size(); ++i) {
t_ss.add_object(t_param_names[i], t_vals[i]); if (t_param_names[i] != "this") {
state.add_object(t_param_names[i], t_vals[i]);
}
} }
try { try {
@@ -68,14 +85,15 @@ namespace chaiscript
public: public:
Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(t_oper)) m_oper(Operators::to_operator(t_oper)),
m_loc(0)
{ } { }
virtual ~Binary_Operator_AST_Node() {} virtual ~Binary_Operator_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
return do_oper(t_ss, m_oper, text, auto lhs = this->children[0]->eval(t_ss);
this->children[0]->eval(t_ss), auto rhs = this->children[1]->eval(t_ss);
this->children[1]->eval(t_ss)); return do_oper(t_ss, m_oper, text, lhs, rhs);
} }
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
@@ -101,8 +119,7 @@ namespace chaiscript
} else { } else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({t_lhs, t_rhs}); fpp.save_params({t_lhs, t_rhs});
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions());
return t_ss->call_function(t_oper_string, t_lhs, t_rhs);
} }
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
@@ -112,13 +129,14 @@ namespace chaiscript
private: private:
Operators::Opers m_oper; Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Int_AST_Node : public AST_Node { struct Int_AST_Node : public AST_Node {
public: public:
Int_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) : Int_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)), AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)),
m_value(std::move(t_bv)) { } m_value(std::move(t_bv)) { assert(text != ""); }
virtual ~Int_AST_Node() {} virtual ~Int_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
return m_value; return m_value;
@@ -149,7 +167,7 @@ namespace chaiscript
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)),
m_value(get_value(t_ast_node_text)), m_loc(0) m_value(get_value(t_ast_node_text)), m_loc(0)
{ } { }
virtual ~Id_AST_Node() {} virtual ~Id_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
@@ -236,8 +254,7 @@ namespace chaiscript
Boxed_Value fn(this->children[0]->eval(t_ss)); Boxed_Value fn(this->children[0]->eval(t_ss));
try { try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss.conversions());
return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss->conversions());
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@@ -286,73 +303,6 @@ namespace chaiscript
/// Used in the context of in-string ${} evals, so that no new scope is created
struct Inplace_Fun_Call_AST_Node : public AST_Node {
public:
Inplace_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(t_ast_node_text, AST_Node_Type::Inplace_Fun_Call, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 2); }
virtual ~Inplace_Fun_Call_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
std::vector<Boxed_Value> params;
params.reserve(this->children[1]->children.size());
for (const auto &child : this->children[1]->children) {
params.push_back(child->eval(t_ss));
}
Const_Proxy_Function fn;
try {
Boxed_Value bv = this->children[0]->eval(t_ss);
try {
fn = t_ss->boxed_cast<const Const_Proxy_Function &>(bv);
} catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
}
return (*fn)(params, t_ss->conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
}
catch(const exception::bad_boxed_cast &){
// handle the case where there is only 1 function to try to call and dispatch fails on it
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {fn}, false, *t_ss);
}
catch(const exception::arity_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
}
catch(const exception::guard_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
}
catch(detail::Return_Value &rv) {
return rv.retval;
}
}
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
int count = 0;
for (const auto &child : this->children) {
oss << child->pretty_print();
if (count == 0)
{
oss << "(";
}
++count;
}
oss << ")";
return oss.str();
}
};
struct Arg_AST_Node : public AST_Node { struct Arg_AST_Node : public AST_Node {
public: public:
Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
@@ -444,10 +394,15 @@ namespace chaiscript
public: public:
Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)), AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[1]->text)) m_oper(Operators::to_operator(children[1]->text)),
m_loc(0),
m_clone_loc(0)
{ assert(children.size() == 3); } { assert(children.size() == 3); }
Operators::Opers m_oper; Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_clone_loc;
virtual ~Equation_AST_Node() {} virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
@@ -483,14 +438,14 @@ namespace chaiscript
} else { } else {
if (!rhs.is_return_value()) if (!rhs.is_return_value())
{ {
rhs = t_ss->call_function("clone", rhs); rhs = t_ss->call_function("clone", m_clone_loc, {rhs}, t_ss.conversions());
} }
rhs.reset_return_value(); rhs.reset_return_value();
} }
} }
try { try {
return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs); return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
@@ -503,13 +458,14 @@ namespace chaiscript
else if (this->children[1]->text == ":=") { else if (this->children[1]->text == ":=") {
if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) { if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) {
lhs.assign(rhs); lhs.assign(rhs);
lhs.reset_return_value();
} else { } else {
throw exception::eval_error("Mismatched types in equation"); throw exception::eval_error("Mismatched types in equation");
} }
} }
else { else {
try { try {
return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs); return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
} catch(const exception::dispatch_error &e){ } catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
} }
@@ -560,7 +516,7 @@ namespace chaiscript
try { try {
Boxed_Value bv; Boxed_Value bv;
t_ss->add_object(idname, bv); t_ss.add_object(idname, bv);
return bv; return bv;
} }
catch (const exception::reserved_word_error &) { catch (const exception::reserved_word_error &) {
@@ -583,7 +539,7 @@ namespace chaiscript
struct Array_Call_AST_Node : public AST_Node { struct Array_Call_AST_Node : public AST_Node {
public: public:
Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Array_Call_AST_Node() {} virtual ~Array_Call_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
@@ -591,9 +547,8 @@ namespace chaiscript
std::vector<Boxed_Value> params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; std::vector<Boxed_Value> params{children[0]->eval(t_ss), children[1]->eval(t_ss)};
try { try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
fpp.save_params(params); fpp.save_params(params);
return t_ss->call_function("[]", params); return t_ss->call_function("[]", m_loc, params, t_ss.conversions());
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss ); throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
@@ -615,12 +570,16 @@ namespace chaiscript
return oss.str(); return oss.str();
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Dot_Access_AST_Node : public AST_Node { struct Dot_Access_AST_Node : public AST_Node {
public: public:
Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)), AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)),
m_loc(0),
m_array_loc(0),
m_fun_name( m_fun_name(
((children[2]->identifier == AST_Node_Type::Fun_Call) || (children[2]->identifier == AST_Node_Type::Array_Call))? ((children[2]->identifier == AST_Node_Type::Fun_Call) || (children[2]->identifier == AST_Node_Type::Array_Call))?
children[2]->children[0]->text:children[2]->text) { } children[2]->children[0]->text:children[2]->text) { }
@@ -629,6 +588,7 @@ namespace chaiscript
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value retval = children[0]->eval(t_ss); Boxed_Value retval = children[0]->eval(t_ss);
std::vector<Boxed_Value> params{retval}; std::vector<Boxed_Value> params{retval};
@@ -643,9 +603,7 @@ namespace chaiscript
fpp.save_params(params); fpp.save_params(params);
try { try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions());
t_ss->add_object("this", retval);
retval = t_ss->call_member(m_fun_name, std::move(params), has_function_params);
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
if (e.functions.empty()) if (e.functions.empty())
@@ -661,7 +619,7 @@ namespace chaiscript
if (this->children[2]->identifier == AST_Node_Type::Array_Call) { if (this->children[2]->identifier == AST_Node_Type::Array_Call) {
try { try {
retval = t_ss->call_function("[]", retval, this->children[2]->children[1]->eval(t_ss)); retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)}, t_ss.conversions());
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss); throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
@@ -672,6 +630,8 @@ namespace chaiscript
} }
private: private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_array_loc;
std::string m_fun_name; std::string m_fun_name;
}; };
@@ -745,7 +705,7 @@ namespace chaiscript
dispatch::make_dynamic_proxy_function( dispatch::make_dynamic_proxy_function(
[engine, lambda_node, param_names, captures](const std::vector<Boxed_Value> &t_params) [engine, lambda_node, param_names, captures](const std::vector<Boxed_Value> &t_params)
{ {
return detail::eval_function(engine, lambda_node, param_names, t_params, captures); return detail::eval_function(engine, lambda_node, param_names, t_params, &captures);
}, },
static_cast<int>(numparams), lambda_node, param_types static_cast<int>(numparams), lambda_node, param_types
) )
@@ -849,7 +809,7 @@ namespace chaiscript
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
try { try {
while (get_bool_condition(this->children[0]->eval(t_ss))) { while (get_bool_condition(this->children[0]->eval(t_ss), t_ss)) {
try { try {
this->children[1]->eval(t_ss); this->children[1]->eval(t_ss);
} catch (detail::Continue_Loop &) { } catch (detail::Continue_Loop &) {
@@ -876,7 +836,7 @@ namespace chaiscript
/// \todo do this better /// \todo do this better
// put class name in current scope so it can be looked up by the attrs and methods // put class name in current scope so it can be looked up by the attrs and methods
t_ss->add_object("_current_class_name", const_var(children[0]->text)); t_ss.add_object("_current_class_name", const_var(children[0]->text));
children[1]->eval(t_ss); children[1]->eval(t_ss);
@@ -891,7 +851,7 @@ namespace chaiscript
{ assert(children.size() == 3); } { assert(children.size() == 3); }
virtual ~Ternary_Cond_AST_Node() {} virtual ~Ternary_Cond_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
if (get_bool_condition(children[0]->eval(t_ss))) { if (get_bool_condition(children[0]->eval(t_ss), t_ss)) {
return children[1]->eval(t_ss); return children[1]->eval(t_ss);
} }
else { else {
@@ -908,7 +868,7 @@ namespace chaiscript
virtual ~If_AST_Node() {} virtual ~If_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
if (get_bool_condition(children[0]->eval(t_ss))) { if (get_bool_condition(children[0]->eval(t_ss), t_ss)) {
return children[1]->eval(t_ss); return children[1]->eval(t_ss);
} else { } else {
if (children.size() > 2) { if (children.size() > 2) {
@@ -918,7 +878,7 @@ namespace chaiscript
return children[i+1]->eval(t_ss); return children[i+1]->eval(t_ss);
} }
else if (children[i]->text == "else if") { else if (children[i]->text == "else if") {
if (get_bool_condition(children[i+1]->eval(t_ss))) { if (get_bool_condition(children[i+1]->eval(t_ss), t_ss)) {
return children[i+2]->eval(t_ss); return children[i+2]->eval(t_ss);
} }
} }
@@ -945,7 +905,7 @@ namespace chaiscript
try { try {
for ( for (
children[0]->eval(t_ss); children[0]->eval(t_ss);
get_bool_condition(children[1]->eval(t_ss)); get_bool_condition(children[1]->eval(t_ss), t_ss);
children[2]->eval(t_ss) children[2]->eval(t_ss)
) { ) {
try { try {
@@ -969,7 +929,7 @@ namespace chaiscript
struct Switch_AST_Node : public AST_Node { struct Switch_AST_Node : public AST_Node {
public: public:
Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Switch_AST_Node() {} virtual ~Switch_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
bool breaking = false; bool breaking = false;
@@ -985,7 +945,7 @@ namespace chaiscript
if (this->children[currentCase]->identifier == AST_Node_Type::Case) { if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here. //This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
try { try {
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) { if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) {
this->children[currentCase]->eval(t_ss); this->children[currentCase]->eval(t_ss);
hasMatched = true; hasMatched = true;
} }
@@ -996,7 +956,7 @@ namespace chaiscript
} }
else if (this->children[currentCase]->identifier == AST_Node_Type::Default) { else if (this->children[currentCase]->identifier == AST_Node_Type::Default) {
this->children[currentCase]->eval(t_ss); this->children[currentCase]->eval(t_ss);
breaking = true; hasMatched = true;
} }
} }
catch (detail::Break_Loop &) { catch (detail::Break_Loop &) {
@@ -1006,6 +966,8 @@ namespace chaiscript
} }
return Boxed_Value(); return Boxed_Value();
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Case_AST_Node : public AST_Node { struct Case_AST_Node : public AST_Node {
@@ -1043,16 +1005,20 @@ namespace chaiscript
struct Inline_Array_AST_Node : public AST_Node { struct Inline_Array_AST_Node : public AST_Node {
public: public:
Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)),
m_loc(0)
{ }
virtual ~Inline_Array_AST_Node() {} virtual ~Inline_Array_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
try { try {
std::vector<Boxed_Value> vec; std::vector<Boxed_Value> vec;
if (!children.empty()) { if (!children.empty()) {
vec.reserve(children[0]->children.size());
for (const auto &child : children[0]->children) { for (const auto &child : children[0]->children) {
auto obj = child->eval(t_ss); auto obj = child->eval(t_ss);
if (!obj.is_return_value()) { if (!obj.is_return_value()) {
vec.push_back(t_ss->call_function("clone", obj)); vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()));
} else { } else {
vec.push_back(std::move(obj)); vec.push_back(std::move(obj));
} }
@@ -1069,12 +1035,14 @@ namespace chaiscript
{ {
return "[" + AST_Node::pretty_print() + "]"; return "[" + AST_Node::pretty_print() + "]";
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Inline_Map_AST_Node : public AST_Node { struct Inline_Map_AST_Node : public AST_Node {
public: public:
Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Inline_Map_AST_Node() {} virtual ~Inline_Map_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try { try {
@@ -1083,7 +1051,7 @@ namespace chaiscript
for (const auto &child : children[0]->children) { for (const auto &child : children[0]->children) {
auto obj = child->children[1]->eval(t_ss); auto obj = child->children[1]->eval(t_ss);
if (!obj.is_return_value()) { if (!obj.is_return_value()) {
obj = t_ss->call_function("clone", obj); obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions());
} }
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj); retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj);
@@ -1096,6 +1064,7 @@ namespace chaiscript
} }
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Return_AST_Node : public AST_Node { struct Return_AST_Node : public AST_Node {
@@ -1148,7 +1117,7 @@ namespace chaiscript
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try { try {
Boxed_Value bv; Boxed_Value bv;
t_ss->add_object(this->children[0]->text, bv); t_ss.add_object(this->children[0]->text, bv);
return bv; return bv;
} }
catch (const exception::reserved_word_error &) { catch (const exception::reserved_word_error &) {
@@ -1163,7 +1132,8 @@ namespace chaiscript
public: public:
Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)), AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[0]->text, true)) m_oper(Operators::to_operator(children[0]->text, true)),
m_loc(0)
{ } { }
virtual ~Prefix_AST_Node() {} virtual ~Prefix_AST_Node() {}
@@ -1177,9 +1147,8 @@ namespace chaiscript
return Boxed_Number::do_oper(m_oper, bv); return Boxed_Number::do_oper(m_oper, bv);
} else { } else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
fpp.save_params({bv}); fpp.save_params({bv});
return t_ss->call_function(children[0]->text, std::move(bv)); return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)}, t_ss.conversions());
} }
} catch (const exception::dispatch_error &e) { } catch (const exception::dispatch_error &e) {
throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@@ -1188,6 +1157,7 @@ namespace chaiscript
private: private:
Operators::Opers m_oper; Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Break_AST_Node : public AST_Node { struct Break_AST_Node : public AST_Node {
@@ -1244,19 +1214,20 @@ namespace chaiscript
struct Inline_Range_AST_Node : public AST_Node { struct Inline_Range_AST_Node : public AST_Node {
public: public:
Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) : Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)), m_loc(0) { }
virtual ~Inline_Range_AST_Node() {} virtual ~Inline_Range_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try { try {
return t_ss->call_function("generate_range", auto oper1 = children[0]->children[0]->children[0]->eval(t_ss);
children[0]->children[0]->children[0]->eval(t_ss), auto oper2 = children[0]->children[0]->children[1]->eval(t_ss);
children[0]->children[0]->children[1]->eval(t_ss)); return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions());
} }
catch (const exception::dispatch_error &e) { catch (const exception::dispatch_error &e) {
throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss);
} }
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Annotation_AST_Node : public AST_Node { struct Annotation_AST_Node : public AST_Node {
@@ -1294,9 +1265,9 @@ namespace chaiscript
if (dispatch::Param_Types( if (dispatch::Param_Types(
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)}
).match(std::vector<Boxed_Value>{t_except}, t_ss->conversions())) ).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()))
{ {
t_ss->add_object(name, t_except); t_ss.add_object(name, t_except);
if (catch_block->children.size() == 2) { if (catch_block->children.size() == 2) {
//Variable capture, no guards //Variable capture, no guards
@@ -1342,11 +1313,8 @@ namespace chaiscript
try { try {
retval = this->children[0]->eval(t_ss); retval = this->children[0]->eval(t_ss);
} }
catch (exception::eval_error &) { catch (const exception::eval_error &e) {
if (this->children.back()->identifier == AST_Node_Type::Finally) { retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
this->children.back()->children[0]->eval(t_ss);
}
throw;
} }
catch (const std::runtime_error &e) { catch (const std::runtime_error &e) {
retval = handle_exception(t_ss, Boxed_Value(std::ref(e))); retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
@@ -1433,7 +1401,7 @@ namespace chaiscript
if (guardnode) { if (guardnode) {
guard = dispatch::make_dynamic_proxy_function( guard = dispatch::make_dynamic_proxy_function(
[engine, t_param_names, guardnode](const std::vector<Boxed_Value> &t_params) { [engine, t_param_names, guardnode](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params, std::map<std::string, Boxed_Value>()); return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params);
}, },
static_cast<int>(numparams), guardnode); static_cast<int>(numparams), guardnode);
} }
@@ -1450,7 +1418,7 @@ namespace chaiscript
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name, std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
dispatch::make_dynamic_proxy_function( dispatch::make_dynamic_proxy_function(
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) { [engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params, std::map<std::string, Boxed_Value>()); return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
}, },
static_cast<int>(numparams), node, param_types, l_annotation, guard static_cast<int>(numparams), node, param_types, l_annotation, guard
) )
@@ -1466,7 +1434,7 @@ namespace chaiscript
t_ss->add(std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name, t_ss->add(std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
dispatch::make_dynamic_proxy_function( dispatch::make_dynamic_proxy_function(
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) { [engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params, std::map<std::string, Boxed_Value>()); return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
}, },
static_cast<int>(numparams), node, param_types, l_annotation, guard), type), static_cast<int>(numparams), node, param_types, l_annotation, guard), type),
function_name); function_name);
@@ -1527,8 +1495,8 @@ namespace chaiscript
virtual ~Logical_And_AST_Node() {} virtual ~Logical_And_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
return const_var(get_bool_condition(children[0]->eval(t_ss)) return const_var(get_bool_condition(children[0]->eval(t_ss), t_ss)
&& get_bool_condition(children[2]->eval(t_ss))); && get_bool_condition(children[2]->eval(t_ss), t_ss));
} }
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
@@ -1544,8 +1512,8 @@ namespace chaiscript
{ assert(children.size() == 3); } { assert(children.size() == 3); }
virtual ~Logical_Or_AST_Node() {} virtual ~Logical_Or_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
return const_var(get_bool_condition(children[0]->eval(t_ss)) return const_var(get_bool_condition(children[0]->eval(t_ss), t_ss)
|| get_bool_condition(children[2]->eval(t_ss))); || get_bool_condition(children[2]->eval(t_ss), t_ss));
} }
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE

File diff suppressed because it is too large Load Diff

View File

@@ -41,25 +41,25 @@ def new(x) {
} }
def clone(double x) { def clone(double x) {
double(x).copy_var_attrs(x) double(x).clone_var_attrs(x)
} }
def clone(string x) { def clone(string x) {
string(x).copy_var_attrs(x) string(x).clone_var_attrs(x)
} }
def clone(vector x) { def clone(vector x) {
vector(x).copy_var_attrs(x) vector(x).clone_var_attrs(x)
} }
def clone(int x) { def clone(int x) {
int(x).copy_var_attrs(x) int(x).clone_var_attrs(x)
} }
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
{ {
eval(type_name(x))(x).copy_var_attrs(x); eval(type_name(x))(x).clone_var_attrs(x);
} }
@@ -145,11 +145,6 @@ def reverse(container) {
retval; retval;
} }
# Return a range from a range
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
{
clone(r);
}
def range(r) : call_exists(range_internal, r) def range(r) : call_exists(range_internal, r)
{ {
@@ -158,6 +153,13 @@ def range(r) : call_exists(range_internal, r)
ri; ri;
} }
# Return a range from a range
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
{
clone(r);
}
# The retro attribute that contains the underlying range # The retro attribute that contains the underlying range
attr retro::m_range; attr retro::m_range;

View File

@@ -0,0 +1,663 @@
// From github.com/nbsdx/SimpleJSON.
// Released under the DWTFYW PL
//
#pragma once
#ifndef SIMPLEJSON_HPP
#define SIMPLEJSON_HPP
#include <cstdint>
#include <cmath>
#include <cctype>
#include <string>
#include <deque>
#include <map>
#include <type_traits>
#include <initializer_list>
#include <ostream>
#include <iostream>
#include "../chaiscript_defines.hpp"
namespace json {
using std::map;
using std::deque;
using std::string;
using std::enable_if;
using std::initializer_list;
using std::is_same;
using std::is_convertible;
using std::is_integral;
using std::is_floating_point;
namespace {
string json_escape( const string &str ) {
string output;
for( unsigned i = 0; i < str.length(); ++i )
switch( str[i] ) {
case '\"': output += "\\\""; break;
case '\\': output += "\\\\"; break;
case '\b': output += "\\b"; break;
case '\f': output += "\\f"; break;
case '\n': output += "\\n"; break;
case '\r': output += "\\r"; break;
case '\t': output += "\\t"; break;
default : output += str[i]; break;
}
return output;
}
bool isspace(const char c)
{
#ifdef CHAISCRIPT_MSVC
// MSVC warns on these line in some circumstances
#pragma warning(push)
#pragma warning(disable : 6330)
#endif
return ::isspace(c) != 0;
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
}
class JSON
{
union BackingData {
BackingData( double d ) : Float( d ){}
BackingData( long l ) : Int( l ){}
BackingData( bool b ) : Bool( b ){}
BackingData( string s ) : String( new string( s ) ){}
BackingData() : Int( 0 ){}
deque<JSON> *List;
map<string,JSON> *Map;
string *String;
double Float;
long Int;
bool Bool;
} Internal;
public:
enum class Class {
Null,
Object,
Array,
String,
Floating,
Integral,
Boolean
};
template <typename Container>
class JSONWrapper {
Container *object;
public:
JSONWrapper( Container *val ) : object( val ) {}
JSONWrapper( std::nullptr_t ) : object( nullptr ) {}
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); }
typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); }
};
template <typename Container>
class JSONConstWrapper {
const Container *object;
public:
JSONConstWrapper( const Container *val ) : object( val ) {}
JSONConstWrapper( std::nullptr_t ) : object( nullptr ) {}
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); }
typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); }
};
JSON() : Internal(), Type( Class::Null ){}
explicit JSON(Class type)
: Internal(), Type(Class::Null)
{
SetType( type );
}
JSON( initializer_list<JSON> list )
: Internal(), Type(Class::Null)
{
SetType( Class::Object );
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i )
operator[]( i->ToString() ) = *std::next( i );
}
JSON( JSON&& other )
: Internal( other.Internal )
, Type( other.Type )
{ other.Type = Class::Null; other.Internal.Map = nullptr; }
JSON& operator=( JSON&& other ) {
Internal = other.Internal;
Type = other.Type;
other.Internal.Map = nullptr;
other.Type = Class::Null;
return *this;
}
JSON( const JSON &other ) {
switch( other.Type ) {
case Class::Object:
Internal.Map =
new map<string,JSON>( other.Internal.Map->begin(),
other.Internal.Map->end() );
break;
case Class::Array:
Internal.List =
new deque<JSON>( other.Internal.List->begin(),
other.Internal.List->end() );
break;
case Class::String:
Internal.String =
new string( *other.Internal.String );
break;
default:
Internal = other.Internal;
}
Type = other.Type;
}
JSON& operator=( const JSON &other ) {
if (&other == this) return *this;
switch( other.Type ) {
case Class::Object:
Internal.Map =
new map<string,JSON>( other.Internal.Map->begin(),
other.Internal.Map->end() );
break;
case Class::Array:
Internal.List =
new deque<JSON>( other.Internal.List->begin(),
other.Internal.List->end() );
break;
case Class::String:
Internal.String =
new string( *other.Internal.String );
break;
default:
Internal = other.Internal;
}
Type = other.Type;
return *this;
}
~JSON() {
switch( Type ) {
case Class::Array:
delete Internal.List;
break;
case Class::Object:
delete Internal.Map;
break;
case Class::String:
delete Internal.String;
break;
default:;
}
}
template <typename T>
JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = 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. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_ #ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_ #define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include <string> #include <string>
#include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "../chaiscript.hpp" #include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp" #include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp" #include "../dispatchkit/type_info.hpp"
#include "../dispatchkit/operators.hpp"
namespace chaiscript namespace chaiscript
@@ -62,6 +64,42 @@ namespace chaiscript
t_module.add(fun.first, fun.second); t_module.add(fun.first, fun.second);
} }
} }
template<typename Enum, typename ModuleType>
typename std::enable_if<std::is_enum<Enum>::value, void>::type
add_class(ModuleType &t_module,
const std::string &t_class_name,
#ifdef CHAISCRIPT_GCC_4_6
const std::vector<std::pair<int, std::string>> &t_constants
#else
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants
#endif
)
{
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
using namespace chaiscript::bootstrap::operators;
t_module.add([](){
// add some comparison and assignment operators
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
}());
#ifdef CHAISCRIPT_GCC_4_6
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
#else
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
#endif
for (const auto &constant : t_constants)
{
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
}
}
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,56 @@
Notes: Notes:
======= =======
Current Version: 5.7.1
Current Version: 5.8.6
### Changes since 5.8.5
* Optimize away `return` statements in lambdas also
* Allow conversions to bool in conditionals
* Don't allow `class` statements inside of scopes
* Properly error when a dynamic object non-function member is called
### Changes since 5.8.4
* Fix order of operations for prefix operators
* Make sure atomics are initialized properly
* Remove parsing of unused prefix `&` operator
### Changes since 5.8.3
* Fix case with some numeric conversions mixed with numerics that do not need conversion
### Changes since 5.8.2
* Add support for reference of pointer return types
### 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 ### Changes since 5.7.0
* Build time reduction * Build time reduction

103
samples/factory.cpp Normal file
View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <iostream> #include <iostream>
@@ -89,24 +89,24 @@ std::vector<std::string> default_search_paths()
std::vector<char> buf(2048); std::vector<char> buf(2048);
ssize_t size = -1; 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 (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 (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));
} }
} }
@@ -316,7 +316,7 @@ int main(int argc, char *argv[])
////for (int i = 0; i < 1000; i++) ////for (int i = 0; i < 1000; i++)
////{ ////{
//// chai.eval("puts(helloWorld(\"Bob12345\"));"); //// chai.eval("puts(helloWorld(\"Bob12345\"));");
////} ////}
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai"); //chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");

View File

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

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#include <iostream> #include <iostream>
@@ -66,7 +66,7 @@ std::vector<std::string> default_search_paths()
#ifdef CHAISCRIPT_WINDOWS // force no unicode #ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096]; CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path)-1); int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
std::string exepath(path, size); std::string exepath(path, size);
@@ -88,24 +88,24 @@ std::vector<std::string> default_search_paths()
std::vector<char> buf(2048); std::vector<char> buf(2048);
ssize_t size = -1; 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 (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 (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));
} }
} }
@@ -344,17 +344,16 @@ int main(int argc, char *argv[])
mode = eFile; mode = eFile;
} }
chaiscript::Boxed_Value val ;
try { try {
switch ( mode ) { switch ( mode ) {
case eInteractive: case eInteractive:
interactive(chai); interactive(chai);
break; break;
case eCommand: case eCommand:
val = chai.eval(arg); chai.eval(arg);
break; break;
case eFile: case eFile:
val = chai.eval_file(arg); chai.eval_file(arg);
} }
} }
catch (const chaiscript::exception::eval_error &ee) { catch (const chaiscript::exception::eval_error &ee) {

View File

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

View File

@@ -114,6 +114,16 @@ std::shared_ptr<TestBaseType> null_factory()
return std::shared_ptr<TestBaseType>(); 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() std::string hello_world()
{ {
return "Hello World"; return "Hello World";
@@ -209,6 +219,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::type_conversion<const char *, std::string>()); m->add(chaiscript::type_conversion<const char *, std::string>());
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2"); 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; return m;
} }

View File

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

View File

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

View File

@@ -13,9 +13,9 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
try { try {
To ret = chaiscript::boxed_cast<To>(bv); To ret = chaiscript::boxed_cast<To>(bv);
use(ret); use(ret);
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) { } catch (const chaiscript::exception::bad_boxed_cast &e) {
if (expectedpass) { if (expectedpass) {
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n'; std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
return false; return false;
} else { } else {
return true; return true;
@@ -54,12 +54,13 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
} }
template<typename Type> template<typename Type>
bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr, bool ConstTPtr, bool TPtrConst, bool do_test(const Boxed_Value &bv,
bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT, bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool SharedPtrTRef, bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
bool ConstWrappedRefRef, bool ConstWrappedConstRefRef, bool Number, bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef,
bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, bool ConstTPtrConstRef) bool ConstWrappedConstRefRef, bool Number, bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef,
bool ConstTPtrConstRef)
{ {
bool passed = true; bool passed = true;
passed &= test_type_conversion<Type>(bv, T); passed &= test_type_conversion<Type>(bv, T);
@@ -72,8 +73,8 @@ bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTR
passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst); passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst);
passed &= test_type_conversion<std::shared_ptr<Type> >(bv, SharedPtrT); passed &= test_type_conversion<std::shared_ptr<Type> >(bv, SharedPtrT);
passed &= test_type_conversion<std::shared_ptr<const Type> >(bv, SharedConstPtrT); passed &= test_type_conversion<std::shared_ptr<const Type> >(bv, SharedConstPtrT);
passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, false); passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, SharedPtrTRef);
passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false); //passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
passed &= test_type_conversion<const std::shared_ptr<Type> >(bv, ConstSharedPtrT); passed &= test_type_conversion<const std::shared_ptr<Type> >(bv, ConstSharedPtrT);
passed &= test_type_conversion<const std::shared_ptr<const Type> >(bv, ConstSharedConstPtrT); passed &= test_type_conversion<const std::shared_ptr<const Type> >(bv, ConstSharedConstPtrT);
passed &= test_type_conversion<const std::shared_ptr<Type> &>(bv, ConstSharedPtrTRef); passed &= test_type_conversion<const std::shared_ptr<Type> &>(bv, ConstSharedPtrTRef);
@@ -115,37 +116,37 @@ bool built_in_type_test(const T &initial, bool ispod)
T i = T(initial); T i = T(initial);
passed &= do_test<T>(var(i), true, true, true, true, true, passed &= do_test<T>(var(i), true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
ispod, ispod, ispod, true, true); ispod, ispod, ispod, true, true);
passed &= do_test<T>(const_var(i), true, true, false, true, false, passed &= do_test<T>(const_var(i), true, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
false, true, false, true, false, false, false, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
passed &= do_test<T>(var(&i), true, true, true, true, true, passed &= do_test<T>(var(&i), true, true, true, true, true,
true, true, true, false, false, true, true, true, false, false,
false, false, false, false, true, false, false, false, false, false, true,
true, true, true, true, true, true, true, true, true, true,
ispod, ispod, ispod, true, true); ispod, ispod, ispod, true, true);
passed &= do_test<T>(const_var(&i), true, true, false, true, false, passed &= do_test<T>(const_var(&i), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
passed &= do_test<T>(var(std::ref(i)), true, true, true, true, true, passed &= do_test<T>(var(std::ref(i)), true, true, true, true, true,
true, true, true, false, false, true, true, true, false, false,
false, false, false, false, true, false, false, false, false, false, true,
true, true, true, true, true, true, true, true, true, true,
ispod, ispod, ispod, true, true); ispod, ispod, ispod, true, true);
passed &= do_test<T>(var(std::cref(i)), true, true, false, true, false, passed &= do_test<T>(var(std::cref(i)), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
@@ -156,33 +157,33 @@ bool built_in_type_test(const T &initial, bool ispod)
passed &= do_test<T>(var(i), true, true, true, true, true, passed &= do_test<T>(var(i), true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
ispod, ispod, ispod, true, true); ispod, ispod, ispod, true, true);
// But a pointer or reference to it should be necessarily const // But a pointer or reference to it should be necessarily const
passed &= do_test<T>(var(&ir), true, true, false, true, false, passed &= do_test<T>(var(&ir), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
passed &= do_test<T>(var(std::ref(ir)), true, true, false, true, false, passed &= do_test<T>(var(std::ref(ir)), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
// Make sure const of const works too // Make sure const of const works too
passed &= do_test<T>(const_var(&ir), true, true, false, true, false, passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
passed &= do_test<T>(const_var(std::ref(ir)), true, true, false, true, false, passed &= do_test<T>(const_var(std::ref(ir)), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
@@ -192,14 +193,14 @@ bool built_in_type_test(const T &initial, bool ispod)
const T*cip = &i; const T*cip = &i;
passed &= do_test<T>(var(cip), true, true, false, true, false, passed &= do_test<T>(var(cip), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
// make sure const of const works // make sure const of const works
passed &= do_test<T>(const_var(cip), true, true, false, true, false, passed &= do_test<T>(const_var(cip), true, true, false, true, false,
true, false, true, false, false, true, false, true, false, false,
false, false, false, false, false, false, false, false, false, false, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
@@ -209,13 +210,13 @@ bool built_in_type_test(const T &initial, bool ispod)
passed &= do_test<T>(var(ip), true, true, true, true, true, passed &= do_test<T>(var(ip), true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
ispod, ispod, ispod, true, true); ispod, ispod, ispod, true, true);
passed &= do_test<T>(const_var(ip), true, true, false, true, false, passed &= do_test<T>(const_var(ip), true, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
false, true, false, true, false, false, false, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
@@ -224,14 +225,14 @@ bool built_in_type_test(const T &initial, bool ispod)
passed &= do_test<T>(var(ipc), true, true, false, true, false, passed &= do_test<T>(var(ipc), true, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
false, true, false, true, false, false, false, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);
// const of this should be the same, making sure it compiles // const of this should be the same, making sure it compiles
passed &= do_test<T>(const_var(ipc), true, true, false, true, false, passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
false, true, false, true, false, false, false, true, false, true, false,
true, false, true, false, true, true, false, true, false, true,
ispod, ispod, ispod, false, true); ispod, ispod, ispod, false, true);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
try {
parse("{ class C { var data; def C() {} } }")
assert_false(true)
} catch (e) {
assert_true(true)
}

View File

@@ -1,32 +1,31 @@
// All of these are necessary because of catch.hpp. It's OK, they'll be // All of these are necessary because of catch.hpp. It's OK, they'll be
// caught in other cpp files if chaiscript causes them // caught in other cpp files if chaiscript causes them
#include <chaiscript/utility/utility.hpp>
#ifdef CHAISCRIPT_MSVC #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4190 4640 28251 4702 6330) #pragma warning(disable : 4062 4242 4640 4702 6330 28251)
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wparentheses"
#endif #endif
#ifdef __llvm__
#pragma clang diagnostic push #include <chaiscript/chaiscript.hpp>
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" #include <chaiscript/utility/utility.hpp>
#pragma clang diagnostic ignored "-Wold-style-cast" #include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#include <clocale>
#include "catch.hpp" #include "catch.hpp"
// lambda_tests // lambda_tests
@@ -396,7 +395,7 @@ class Short_Comparison_Test {
public: public:
Short_Comparison_Test() : value_(5) {} Short_Comparison_Test() : value_(5) {}
short get_value() { return value_; } short get_value() const { return value_; }
short value_; short value_;
}; };
@@ -518,6 +517,65 @@ TEST_CASE("Utility_Test utility class wrapper")
} }
enum Utility_Test_Numbers
{
ONE,
TWO,
THREE
};
void do_something_with_enum_vector(const std::vector<Utility_Test_Numbers> &v)
{
CHECK(v.size() == 3);
CHECK(v[0] == ONE);
CHECK(v[1] == THREE);
CHECK(v[2] == TWO);
}
TEST_CASE("Utility_Test utility class wrapper for enum")
{
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
using namespace chaiscript;
chaiscript::utility::add_class<Utility_Test_Numbers>(*m,
"Utility_Test_Numbers",
{ { ONE, "ONE" },
{ TWO, "TWO" },
{ THREE, "THREE" }
}
);
chaiscript::ChaiScript chai;
chai.add(m);
CHECK(chai.eval<Utility_Test_Numbers>("ONE ") == 0);
CHECK(chai.eval<Utility_Test_Numbers>("TWO ") == 1);
CHECK(chai.eval<Utility_Test_Numbers>("THREE ") == 2);
CHECK(chai.eval<bool>("ONE == 0"));
chai.add(chaiscript::fun(&do_something_with_enum_vector), "do_something_with_enum_vector");
chai.add(chaiscript::vector_conversion<std::vector<Utility_Test_Numbers>>());
CHECK_NOTHROW(chai.eval("var a = [ONE, TWO, THREE]"));
CHECK_NOTHROW(chai.eval("do_something_with_enum_vector([ONE, THREE, TWO])"));
CHECK_NOTHROW(chai.eval("[ONE]"));
const auto v = chai.eval<std::vector<Utility_Test_Numbers>>("a");
CHECK(v.size() == 3);
CHECK(v.at(1) == TWO);
CHECK(chai.eval<bool>("ONE == ONE"));
CHECK(chai.eval<bool>("ONE != TWO"));
CHECK_NOTHROW(chai.eval("var o = ONE; o = TWO"));
}
////// Object copy count test ////// Object copy count test
class Object_Copy_Count_Test class Object_Copy_Count_Test
@@ -743,3 +801,183 @@ TEST_CASE("Test Derived->Base with non-polymorphic classes")
chai.add(chaiscript::fun(&myfunction), "myfunction"); chai.add(chaiscript::fun(&myfunction), "myfunction");
CHECK(chai.eval<int>("myfunction(d)") == 2); CHECK(chai.eval<int>("myfunction(d)") == 2);
} }
struct TestCppVariableScope
{
void print()
{
std::cout << "Printed" << std::endl;
}
};
TEST_CASE("Variable Scope When Calling From C++")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::user_type<TestCppVariableScope>(), "Test");
chai.add(chaiscript::constructor<TestCppVariableScope()>(), "Test");
chai.add(chaiscript::fun(&TestCppVariableScope::print), "print");
chai.eval(R"(var t := Test();
def func()
{
t.print();
}
)");
CHECK_THROWS(chai.eval("func()"));
chai.eval("dump_object(t)");
auto func = chai.eval<std::function<void()>>("func");
CHECK_THROWS(func());
}
TEST_CASE("Variable Scope When Calling From C++ 2")
{
chaiscript::ChaiScript chai;
chai.eval("var obj = 2;");
auto func = chai.eval<std::function<void()>>("fun(){ return obj; }");
CHECK_THROWS(func());
}
void ulonglong(unsigned long long i) {
std::cout << i << '\n';
}
void longlong(long long i) {
std::cout << i << '\n';
}
TEST_CASE("Test long long dispatch")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&longlong), "longlong");
chai.add(chaiscript::fun(&ulonglong), "ulonglong");
chai.eval("longlong(15)");
chai.eval("ulonglong(15)");
}
struct Returned_Converted_Config
{
int num_iterations;
int something_else;
std::string a_string;
std::function<int (const std::string &)> a_function;
};
TEST_CASE("Return of converted type from script")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::constructor<Returned_Converted_Config ()>(), "Returned_Converted_Config");
chai.add(chaiscript::fun(&Returned_Converted_Config::num_iterations), "num_iterations");
chai.add(chaiscript::fun(&Returned_Converted_Config::something_else), "something_else");
chai.add(chaiscript::fun(&Returned_Converted_Config::a_string), "a_string");
chai.add(chaiscript::fun(&Returned_Converted_Config::a_function), "a_function");
chai.add(chaiscript::vector_conversion<std::vector<Returned_Converted_Config>>());
auto c = chai.eval<std::vector<Returned_Converted_Config>>(R"(
var c = Returned_Converted_Config();
c.num_iterations = 5;
c.something_else = c.num_iterations * 2;
c.a_string = "string";
c.a_function = fun(s) { s.size(); }
print("making vector");
var v = [];
print("adding config item");
v.push_back_ref(c);
print("returning vector");
v;
)");
std::cout << typeid(decltype(c)).name() << std::endl;
std::cout << "Info: " << c.size() << " " << &c[0] << std::endl;
std::cout << "num_iterations " << c[0].num_iterations << '\n'
<< "something_else " << c[0].something_else << '\n'
<< "a_string " << c[0].a_string << '\n'
<< "a_function " << c[0].a_function("bob") << '\n';
chai.add(chaiscript::user_type<Returned_Converted_Config>(), "Returned_Converted_Config");
}
int get_value_a(const std::map<std::string, int> &t_m)
{
return t_m.at("a");
}
TEST_CASE("Map conversions")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
chai.add(chaiscript::fun(&get_value_a), "get_value_a");
const auto c = chai.eval<int>(R"(
var m = ["a": 42];
get_value_a(m);
)");
CHECK(c == 42);
}
TEST_CASE("Parse floats with non-posix locale")
{
#ifdef CHAISCRIPT_MSVC
std::setlocale(LC_ALL, "en-ZA");
#else
std::setlocale(LC_ALL, "en_ZA.utf8");
#endif
chaiscript::ChaiScript chai;
const double parsed = chai.eval<double>("print(1.3); 1.3");
CHECK(parsed == Approx(1.3));
const std::string str = chai.eval<std::string>("to_string(1.3)");
CHECK(str == "1.3");
}
bool FindBitmap(int &ox, int &oy, long) {
ox = 1;
oy = 2;
return true;
}
TEST_CASE("Mismatched numeric types only convert necessary params")
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&FindBitmap), "FindBitmap");
int x = 0;
int y = 0;
chai.add(chaiscript::var(&x), "x");
chai.add(chaiscript::var(&y), "y");
chai.eval( "if ( FindBitmap ( x, y, 0) ) { print(\"found at \" + to_string(x) + \", \" + to_string(y))}" );
CHECK(x == 1);
CHECK(y == 2);
}
TEST_CASE("type_conversion to bool")
{
auto module = std::make_shared<chaiscript::Module>();
struct T {
operator bool() const { return true; }
};
module->add(chaiscript::type_conversion<T, bool>());
}

View File

@@ -0,0 +1,17 @@
// all we care is that this executes, really
add_type_conversion(type("int"), type("bool"), fun(int i) { return i != 0; });
if (0) {
assert_true(false);
}
while (0) {
assert_true(false);
}
for (; 0; ) {
assert_true(false);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

3
unittests/json_1.chai Normal file
View File

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

1
unittests/json_10.chai Normal file
View File

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

14
unittests/json_11.chai Normal file
View File

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

1
unittests/json_12.chai Normal file
View File

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

1
unittests/json_13.chai Normal file
View File

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

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