Compare commits

...

230 Commits

Author SHA1 Message Date
Jason Turner
93bc6109e7 Merge branch 'develop' into typed_function_ordering 2016-12-05 19:19:41 -07:00
Jason Turner
92c2ade1cd More relase note updates 2016-12-05 12:13:19 -07:00
Jason Turner
6b7481e6a1 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-12-05 12:11:51 -07:00
Jason Turner
d096f926d3 Update release notes 2016-12-05 12:11:32 -07:00
Jason Turner
fb7f8f194c Add support for r-value parameters and unique_ptr
Notes
 * Due to the limitations for how Boxed_Value is handled
   the unique_ptrs must still be wrapped in a shared_ptr
 * However, this caveat does not directly affect the user
2016-12-05 12:07:56 -07:00
Jason Turner
78f885ec61 Merge pull request #310 from M2tM/patch-1
nullify_shared_ptr changing == to = in documentation.
2016-12-03 14:01:01 -07:00
Jason Turner
d6d50478de Make constexpr members const 2016-12-03 07:59:06 -07:00
Jason Turner
defdb53a55 Fix regression from last commit on single char operators 2016-12-02 23:26:54 -07:00
Jason Turner
0dea62dd54 Finish removing runtime string comparisons
* Now virtually all parser string work is done at compile time
 * Continuing the work started by @niXman
2016-12-02 23:01:57 -07:00
Jason Turner
590905f4b3 Add notes on base_class conversions 2016-12-02 20:32:47 -07:00
Michael Hamilton
9218dda001 nullify_shared_ptr changing == to = in documentation. 2016-12-01 22:24:47 -08:00
Jason Turner
9e17514b57 Move away from class level statics
- Avoiding potential issues with linking and multiple symbol definitions
2016-12-01 15:20:48 -07:00
Jason Turner
5f402e71dd Move away from macro, get slight perf boost with hand rolled compare 2016-12-01 14:47:23 -07:00
Jason Turner
95e119fffe Merge github.com:niXman/ChaiScript into develop 2016-12-01 14:03:56 -07:00
Jason Turner
f17439a9d3 Add scope around condition in for/while
* solves issue with rapidly expanding memory usage if
   function variable use stack is growing rapidly
2016-12-01 13:42:40 -07:00
Jason Turner
940e0c2d86 Merge pull request #306 from StanEpp/develop
Added add_class overload for scoped enums.
2016-12-01 10:10:49 -07:00
Jason Turner
e8c03b33c6 Merge pull request #307 from sjaustirni/develop
Fixed a bug in the first example in the docs
2016-11-29 11:25:25 -07:00
sjaustirni
b68f917677 Fixed a bug in the first example
This example has been forgotten to be updated, despite other being up to date.
2016-11-26 15:43:28 +01:00
Stan
7f4af72244 Added add_class overload for scoped enums. 2016-11-23 20:39:21 +01:00
Jason Turner
6757b66f95 Merge pull request #305 from mlamby/patch-2
Add break statement to cheatsheet.md
2016-11-20 18:05:37 -07:00
Michael Lamb
c9034a0485 Add break statement to cheatsheet.md
Added information about the existence of the break statement to the loop section.
2016-11-21 11:57:52 +11:00
Jason Turner
50dcbc8c7e Simplify Symbol parsing.
closes #301
2016-11-13 15:14:41 -07:00
niXman
1ea91faf52 parser optimization Three 2016-11-08 01:11:46 +02:00
niXman
745e0c0f0b parser optimization step Two 2016-11-04 09:15:02 +02:00
niXman
c42477f2eb parser optimization step One 2016-11-03 22:47:48 +02:00
Jason Turner
335a02f165 Add release notes on if-init expressions 2016-11-01 13:04:49 -06:00
Jason Turner
012f1ffff5 Remove incorrect override 2016-10-30 21:51:00 -06:00
Jason Turner
9925b20fad Cleanups found with PMD's CPD 2016-10-29 09:41:55 -06:00
Jason Turner
28122f7cb0 Fix single parameter constructors found by cppcheck 2016-10-28 15:49:40 -06:00
Jason Turner
b1f1803759 Some cleanups found by clang's analyzer 2016-10-28 14:53:01 -06:00
Jason Turner
359897a442 Flesh out parser and tracer usage cases 2016-10-28 13:36:10 -06:00
Jason Turner
ffcd7e3a76 Merge branch 'release-5.x' into develop 2016-10-28 11:04:15 -06:00
Jason Turner
2c99e6cd32 Update release notes 2016-10-28 11:03:31 -06:00
Jason Turner
332a62769b Merge branch 'release-5.x' into develop 2016-10-28 10:57:55 -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
4119e6e7d8 Merge branch 'develop' into typed_function_ordering 2016-10-26 14:33:33 -06:00
Jason Turner
eefd50a6bc Merge branch 'release-5.x' into develop 2016-10-26 14:05:28 -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
8b18e301d2 Merge branch 'release-5.x' into develop 2016-10-26 12:24:40 -06:00
Jason Turner
508729ec77 Properly handle error reporting with method_missing 2016-10-26 10:08:53 -06:00
Jason Turner
0fe78f7ba5 Make sure to not break non-basic interface 2016-10-26 08:47:49 -06:00
Jason Turner
6202149b4f Merge pull request #294 from roig/fixCompilerErrors
Fix some GCC compiler errors.
2016-10-26 08:41:15 -06:00
Daniel Guzman
4ad661475b Fix some GCC compiler errors. 2016-10-22 16:49:53 +02:00
Jason Turner
6d309b7516 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-10-17 20:55:47 -06:00
Jason Turner
7d9e1b3af7 Add ability to disable loading external files
* Options are passed to ChaiScript constructor
 * load_module / eval_file / use can be disabled
   from script context
2016-10-17 20:51:15 -06:00
Jason Turner
b99ccafa07 Fix some MSVC issues
* Add error if you are using too low of an MSVC compiler
 * Fix some warnings
2016-10-16 16:04:33 -06:00
Jason Turner
c97a69537d Add ability to get current script context
closes #277
2016-10-13 20:44:13 -06:00
Jason Turner
fac8f3ec90 Merge branch 'release-5.x' into develop 2016-10-10 20:09:40 -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
aa9267726f Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-10-09 20:03:39 -06:00
Jason Turner
396e78d295 Merge branch 'release-5.x' of github.com:ChaiScript/ChaiScript into develop 2016-10-09 20:03:22 -06:00
Jason Turner
1efcddd335 Update releasenotes.md 2016-10-08 07:38:49 -06:00
Jason Turner
21ccb1d1d0 Fix module loading 2016-10-07 21:54:40 -06:00
Jason Turner
c37c901a0c Fix MSVC build
closes #287
2016-10-07 21:39:19 -06:00
Jason Turner
690b96d9ee Change fuzzy tests to account for prefix & changes 2016-10-07 11:26:30 -06:00
Jason Turner
d638d87a0f Fix function reassignment 2016-10-07 09:36:38 -06:00
Jason Turner
b091439567 Merge branch 'release-5.x' into develop 2016-10-07 09:13:19 -06:00
Jason Turner
7cc100e3d7 Make ChaiScript constructor public... 2016-10-06 09:36:43 -06:00
Jason Turner
b2907fc608 Merge branch 'release-5.x' into develop 2016-10-05 15:14:58 -06:00
Jason Turner
3b2c82ba2c Add 6.0.0 release notes 2016-09-16 14:20:11 -06:00
Jason Turner
8cb3bd4af8 Fix gcc 4.9 build 2016-09-16 12:47:01 -06:00
Jason Turner
26e6f51fa8 Add notes on bound member function 2016-09-16 12:39:42 -06:00
Jason Turner
87294fc89d Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-09-16 12:38:44 -06:00
Jason Turner
9cc0ce01b9 Merge pull request #265 from profiler-bg/patch-1
Update cheatsheet.md
2016-09-16 12:38:31 -06:00
Jason Turner
c9ee707972 Merge branch 'release-5.x' into develop 2016-09-16 12:33:58 -06:00
Jason Turner
4e6e63ab5d Cleanups and split up into _basic options 2016-08-27 10:33:44 -06:00
Jason Turner
7561aa8828 Get all unit tests passing 2016-06-29 21:06:31 -06:00
Jason Turner
e44724c780 Fix debug/clang build issues 2016-06-29 17:27:07 -06:00
Jason Turner
b0f07cbe5d Merge branch 'develop' into cleanups_and_reworkds 2016-06-29 16:11:00 -06:00
Jason Turner
62639a4359 Get building with libc++ again 2016-06-29 16:06:27 -06:00
Jason Turner
176d608bb4 Merge pull request #276 from ELynx/develop
Add UTF-8 escape notation to parser
2016-06-29 15:03:40 -06:00
Jason Turner
a1d90c95f0 Create DesignGoals.md 2016-06-28 10:34:30 -06:00
Jason Turner
a14f1983e8 Handle a few more optimization cases 2016-06-27 12:56:43 -06:00
ELynx
5642e062e6 Fix unittest 2016-06-27 18:02:50 +03:00
Jason Turner
9e16cc2a79 Simplify and normalize if block code 2016-06-27 08:56:03 -06:00
ELynx
201fef49c6 More standard compliant, use converter only where available 2016-06-27 17:40:43 +03:00
ELynx
58ebb22c55 clean-up conversion for other than std:string 2016-06-27 16:03:32 +03:00
ELynx
830b7c93ca Fix unit test, limit unit test to UTF-8 2016-06-27 15:26:07 +03:00
ELynx
368a3b78a2 create holder class 2016-06-27 13:46:37 +03:00
ELynx
e3e90de02a Proper comparison in unit tests; remove leftover static keyword 2016-06-27 13:09:32 +03:00
ELynx
8478ddc470 Move details to detail namespace, make to standard 2016-06-27 12:45:38 +03:00
ELynx
2adefaf46d Basic unit tests 2016-06-27 12:39:03 +03:00
ELynx
bd26355516 No warnings from MSVC 2016-06-27 12:38:50 +03:00
ELynx
19a730b78b Basic support for Unicode 'slash'uABCD escape notation - parser understands escape sequence and following data 2016-06-27 11:52:22 +03:00
Jason Turner
e3d1741c63 Add C++17-style if-init blocks 2016-06-26 22:10:53 -06:00
Jason Turner
09bdec4882 Add ranged-for loops
closes [#145]
2016-06-26 20:00:01 -06:00
Jason Turner
c31ebb5665 Move checking of valid object names to parse time 2016-06-23 10:23:40 -06:00
Jason Turner
52a191df9e Add optimization for unused return values 2016-06-19 20:20:51 -06:00
Jason Turner
228c942b6c Use std::exchange 2016-06-07 12:26:30 -06:00
Jason Turner
09ed0ca573 Merge pull request #270 from rmpowell77/issue_269
Fix for: samples/example.cpp crashes #269
2016-05-14 15:00:21 -06:00
Richard Powell
ee68ff20ed Fix for: samples/example.cpp crashes #269
Add the system as global.
2016-05-14 09:40:22 -06:00
Jason Turner
b72eed3921 Update docs to reflect C++14 closes #268 2016-05-12 08:55:01 -06:00
Jason Turner
039d0edce3 Move to std::next instead of homebrewed function 2016-05-12 08:53:38 -06:00
Jason Turner
7b3f06b269 Even more scope / block simplification 2016-05-03 14:41:16 -06:00
Jason Turner
5373bbd52e Add Fold-Right optimizer 2016-05-03 10:21:59 -06:00
Jason Turner
17821be1e2 Reduce shared_ptr copies during dispatch 2016-05-03 08:51:44 -06:00
Jason Turner
9a526bc1ec Allow constant folding to do conversions also 2016-05-01 12:46:15 -06:00
Jason Turner
03803ee4c4 Initial take on Tracer hooks
This will allow the user to add hooks in for debugging / execution
tracing / throttling / etc for each node execution

The cost is *almost* 0 if no tracing is enabled.
2016-04-30 20:53:01 -06:00
Jason Turner
dcedd64032 Merge branch 'develop' into cleanups_and_reworkds 2016-04-29 10:40:38 -06:00
Jason Turner
d34d74205c Merge branch 'release-5.x' into develop 2016-04-29 10:40:26 -06:00
Jason Turner
70cdbef693 Fix threading build 2016-04-29 07:09:57 -06:00
Jason Turner
f6c69f2826 Allow folding of if blocks 2016-04-25 21:32:48 -06:00
Jason Turner
184ca7f7b2 Create Block reducing optimizer 2016-04-24 07:49:00 -06:00
Jason Turner
71caf5006f Pull constant folding optimizer out 2016-04-23 22:27:34 -06:00
Jason Turner
4dbf1ee2bd Pull out Return_Optimizer 2016-04-23 22:12:08 -06:00
Jason Turner
4324a700ad Fix instring eval parsing 2016-04-23 21:00:32 -06:00
Jason Turner
5b78d5a898 Make optimizer pluggable 2016-04-23 20:22:17 -06:00
Jason Turner
ff2ab6bb8d Make optimizer split out 2016-04-23 15:52:19 -06:00
Jason Turner
25575564c0 Make module load error much more explicit 2016-04-23 15:47:39 -06:00
Jason Turner
683164650a Add ability to 'compile' for loops 2016-04-21 08:09:10 -06:00
Jason Turner
647f8842fd Optimize dispatch for perfect match case 2016-04-20 09:20:38 -06:00
Jason Turner
7d11b7c5f1 Merge branch 'develop' into typed_function_ordering 2016-04-20 06:41:37 -06:00
Jason Turner
6d6f79b1a4 Only pop min/max if they were defined previously 2016-04-18 14:38:25 -06:00
Jason Turner
06b2893bfb Update tests for removal of ChaiScript_Parser from stdlib 2016-04-17 21:15:59 -06:00
Jason Turner
7ab6bce7fa Untangle chaiscript_engine from the rest of it 2016-04-17 21:14:01 -06:00
Jason Turner
f9294c8cbe Remove ChaiScript_Parser from stdlib, unnecessary 2016-04-17 16:55:08 -06:00
Jason Turner
80cc18bf2f Make type_info fully constexpr
- Minor hit in compile size
 - Minor improvement in runtime
2016-04-17 08:15:24 -06:00
Jason Turner
c68488388e Remove some unused code in Boxed_Value 2016-04-16 22:14:02 -06:00
Jason Turner
7d5a97aa2f Clean up if block parsing and eval 2016-04-16 15:39:32 -06:00
Jason Turner
83c6df11f0 Fix global reference assignment 2016-04-16 14:30:12 -06:00
Jason Turner
10b984556d Add global & test 2016-04-16 14:23:11 -06:00
Jason Turner
cf2fa09d6c Eliminate branching in var decl 2016-04-16 14:13:14 -06:00
Jason Turner
f3f84594ee A few parser cleanups 2016-04-16 12:04:18 -06:00
Jason Turner
57aa874c6e Revert "Prefer make_unique over make_shared"
This reverts commit 5a947b5035.
2016-04-16 09:02:38 -06:00
Jason Turner
32bd936a18 Remove 'annotation' feature 2016-04-16 07:52:39 -06:00
Jason Turner
498339c202 Remove some dead parser code 2016-04-16 07:35:30 -06:00
Jason Turner
56b4f465a1 Add warning on platforms without thread_local 2016-04-15 23:09:20 -06:00
Jason Turner
1a42614441 Remove unnecessary code 2016-04-15 23:02:42 -06:00
Jason Turner
6fa83bca85 Remove Do_Call helper class 2016-04-15 15:31:19 -06:00
Hristo Petrov
fd57bec676 Update cheatsheet.md
Added missing parameters to the examples of "Adding Method / Member"
2016-04-15 16:11:36 +01:00
Jason Turner
14307194e9 Merge pull request #264 from ELynx/develop
Expose std::vector and std::list resize, reserve and capacity methods
2016-04-15 08:18:13 -06:00
ELynx
62e34c097c Add capacity check; fix vector_reserve unittest 2016-04-15 14:12:07 +03:00
ELynx
cdb9dcc154 Fix list unittest 2016-04-15 14:08:03 +03:00
ELynx
14d429853b Add typename; pass value to resize by const referene 2016-04-15 14:00:01 +03:00
ELynx
e8ff1f9d7e Proper template types for resizable_type and reservable_type 2016-04-15 13:39:51 +03:00
ELynx
49ef5306a9 Add resize to stl list and vector; add reserve to stl vector 2016-04-15 13:15:30 +03:00
Jason Turner
7d9dbc3d86 Fix some boxed_cast issues introduced with refactor 2016-04-14 19:06:37 -06:00
Jason Turner
49dfdfd15a Fix some boxed_cast and exception issues 2016-04-14 12:03:55 -06:00
Jason Turner
720395e47a clean up reflection tests for new capabilities 2016-04-14 09:31:38 -06:00
Jason Turner
5e0a882b18 Bootstrap simplifications 2016-04-13 21:08:25 -06:00
Jason Turner
9603d3910a Get multifile compiling 2016-04-13 15:26:36 -06:00
Jason Turner
6f0d02f158 Massive simplification of boxed_cast. More planned 2016-04-13 14:09:08 -06:00
Jason Turner
8d808f75c0 Remove pretty_print functionality 2016-04-13 12:04:55 -06:00
Jason Turner
2a1632f213 Merge branch 'develop' into cleanups_and_reworkds 2016-04-11 17:48:31 -06:00
Jason Turner
e57f11fcf4 Merge pull request #262 from rollbear/develop
Pass Module by reference instead of shared ptr
2016-04-11 16:58:27 -06:00
Bjorn Fahller
2fe794fcae Do not return Module& from internal funcs on Module&
A slight improvement in built binary size is achieved by not having
to generate code for the return.
2016-04-11 18:16:30 +02:00
Jason Turner
b594043eef Clean up redundant code 2016-04-11 09:36:23 -06:00
Jason Turner
fe8f8a89a7 Implement constant expression folding 2016-04-11 08:19:02 -06:00
Jason Turner
40694c798c Eliminate Str_AST_Node 2016-04-10 23:12:35 -06:00
Jason Turner
443828fa23 More parser simplification 2016-04-10 22:27:35 -06:00
Jason Turner
866db4ee8b Reduce instances of Str_AST_Node 2016-04-10 21:38:44 -06:00
Jason Turner
5e97f459d8 Remove unnecessary false 2016-04-10 19:01:55 -06:00
Jason Turner
e02ac78195 Remove Char_AST_Node 2016-04-10 18:57:23 -06:00
Jason Turner
62cd8031ac Make quoted strings into Constants 2016-04-10 18:29:16 -06:00
Jason Turner
61dfcb00c0 Move int/float into Constant 2016-04-10 17:19:48 -06:00
Jason Turner
4bf619c80f some initialization and destructor cleanups 2016-04-09 22:10:06 -06:00
Jason Turner
08a68f310a Move to strongly typed algebraic enum 2016-04-09 21:50:23 -06:00
Jason Turner
641ac1a1ae Split up ifdef'd module code 2016-04-09 21:49:12 -06:00
Jason Turner
2400c64c82 Move to strongly typed enums for node types 2016-04-09 21:15:07 -06:00
Jason Turner
1e584048ce Remove std::function from bind_first 2016-04-09 21:00:07 -06:00
Bjorn Fahller
7865f8e7f2 Keep ModulePtr kompatible functions
Since use of (one of) the functions in bootstrap_stl.hpp is in a
sample, chances are there are people using them in real world
application code. Thus the backwards compatible versions.
2016-04-09 21:09:45 +02:00
Bjorn Fahller
5ff97979fd Pass Module by reference instead of shared ptr
This gives a small but noticeable compile time improvement as
well as a measurable, albeit not great, reduction in size of the
stdlib.
2016-04-09 15:42:55 +02:00
Jason Turner
5567e767a3 Change some {{ code 2016-04-04 15:57:14 -06:00
Jason Turner
5a947b5035 Prefer make_unique over make_shared 2016-04-04 15:36:38 -06:00
Jason Turner
6ecbaab2fe Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-03-30 13:02:07 -06:00
Jason Turner
dd6b38cafb Merge branch 'release-5.x' into develop 2016-03-30 13:01:46 -06:00
Jason Turner
6e6795e914 Merge pull request #260 from ELynx/develop
Fix description of get_guard()
2016-03-30 12:08:14 -06:00
Eduard
33c966b8d6 Fix description of get_guard() 2016-03-30 18:14:12 +03:00
Jason Turner
f7b52f6c39 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-03-26 17:34:54 -06:00
Jason Turner
2f2f789f48 Fix parsing of '' strings. found by AFL 2016-03-26 17:34:36 -06:00
Jason Turner
06783b7f65 Add fuzzy testing notes 2016-03-25 07:04:39 -06:00
Jason Turner
a45c76721f Add fuzzy test files 2016-03-25 07:02:41 -06:00
Jason Turner
3627efe03b Move away from shared_lock
It's not supported by enough standard library implementations yet
2016-03-16 20:14:48 -06:00
Jason Turner
1cd7a1b972 Change unsigned to size_t 2016-03-16 19:59:56 -06:00
Jason Turner
df9466e2a7 Remove unneeded overloads / make explicit 2016-03-16 19:50:59 -06:00
Jason Turner
dc8aa372c1 Less manual managing of JSON internal state 2016-03-16 19:39:10 -06:00
Jason Turner
bcc25222dd Code reorg to reduce anon namespace 2016-03-16 19:08:50 -06:00
Jason Turner
6507a6e68e Update naming of JSON functions 2016-03-16 18:52:02 -06:00
Jason Turner
5872b020fa First pass at updating JSON lib
* eliminate manual memory management
2016-03-16 18:32:10 -06:00
Jason Turner
82a69ca043 Merge branch 'develop' into typed_function_ordering 2016-03-15 12:46:47 -06:00
Jason Turner
c57ea79d0d Update reference to prelude 2016-03-13 16:26:46 -06:00
Jason Turner
b424d1f9cb delimit chaiscript text blocks 2016-03-13 15:33:23 -06:00
Jason Turner
7dcd6b8447 Implement member pointer value support
closes #245
2016-03-12 22:04:01 -07:00
Jason Turner
de63529887 Add failing test for pointer based member data
Issue #245
2016-03-12 20:08:15 -07:00
Jason Turner
d95f59fa97 Add test for dynamic object assignments 2016-03-12 19:50:58 -07:00
Jason Turner
d5ae30191d Add =, ==, and != for Dynamic_Objects
closes #251
2016-03-12 12:44:05 -07:00
Jason Turner
16ffbca6d6 Simplify type_info comparisons 2016-03-12 08:36:53 -07:00
Jason Turner
afa3f2249c Mark i as unused for the sake of MSVC 0th case 2016-03-12 08:16:25 -07:00
Jason Turner
c5f4a4dfd8 various c++11/c++14 cleanups 2016-03-12 07:05:29 -07:00
Jason Turner
34a2001a7b Reduce lookups into stack indexes 2016-03-12 07:05:12 -07:00
Jason Turner
16c4a11990 More C++11/C++14 updates 2016-03-11 18:17:04 -07:00
Jason Turner
6f01568a9a Fix function_member call from last commit 2016-03-11 15:28:33 -07:00
Jason Turner
dfb2394b0b Merge branch 'update_travis_toolchain' into typed_function_ordering 2016-03-11 15:00:28 -07:00
Jason Turner
a363ef5e0e C++11/14 updates 2016-03-11 14:45:40 -07:00
Jason Turner
a3365a9c4a Enable use of shared_mutex now on C++14 2016-03-11 13:45:01 -07:00
Jason Turner
9a5ef38d4a Simplify exception_specification types
* move to variadic
 * delete lots of implementation details
2016-03-11 10:57:20 -07:00
Jason Turner
5247de7d1b use a global void value for returning unknown values 2016-03-11 10:21:39 -07:00
Jason Turner
cd1b3f8887 Virtual / override / public cleanups 2016-03-11 09:24:00 -07:00
Jason Turner
11ee71ba27 Fix index type 2016-03-10 14:45:07 -07:00
Jason Turner
91ba9e25c0 Remove g++ 4.8 from builds 2016-03-10 14:06:43 -07:00
Jason Turner
978f80751f Update proxy_functions_detail to c++14 2016-03-10 12:33:07 -07:00
Jason Turner
0ac5657661 Merge branch 'update_travis_toolchain' of github.com:ChaiScript/ChaiScript into update_travis_toolchain 2016-03-07 21:24:53 -07:00
Jason Turner
cfc8a3d214 Warning cleanups and simplification 2016-03-07 21:24:21 -07:00
Jason Turner
85163e08cc Add missing <array> header include 2016-03-07 16:19:40 -07:00
Jason Turner
019c6b2830 Cleanup of ChaiScript_Parser
From episode 1 of C++ Weekly.
2016-03-07 15:36:12 -07:00
Jason Turner
c71dd8051b Merge branch 'update_travis_toolchain' of github.com:ChaiScript/ChaiScript into update_travis_toolchain 2016-03-07 14:25:47 -07:00
Jason Turner
fe8f571f47 Add test_module to set of required modules during build 2016-03-07 07:16:57 -07:00
Jason Turner
947d7c2591 Merge branch 'develop' into update_travis_toolchain
Conflicts:
	.decent_ci-Windows.yaml
	CMakeLists.txt
	include/chaiscript/chaiscript_defines.hpp
2016-03-05 21:12:14 -07:00
Jason Turner
6f6227879a Merge branch 'release-5.x' into develop 2016-03-05 20:28:44 -07:00
Jason Turner
e014308154 Create supporters.md 2016-03-05 18:32:44 -07:00
Jason Turner
467392e17d Update readme.md 2016-03-05 18:26:15 -07:00
Jason Turner
cf5913f890 Add gitter appveyor webhook 2016-03-05 17:45:11 -07:00
Jason Turner
33e27b4f85 Reorganize builds run on decent_ci 2016-03-04 13:48:20 -07:00
Jason Turner
c07f413694 Merge branch 'develop' into typed_function_ordering 2016-03-04 13:33:29 -07:00
Jason Turner
b5b6e5a5a3 Drop ifdef'd code for gcc4.6 and msvc12 2016-03-04 11:15:39 -07:00
Jason Turner
a0f3eafe30 Merge branch 'develop' into update_travis_toolchain 2016-03-04 10:33:54 -07:00
Jason Turner
463f688978 Update to C++14 compiler flags 2016-03-04 09:48:35 -07:00
Jason Turner
70c6ed713b Add new compilers and remove deprecated ones 2016-03-04 09:24:50 -07:00
Jason Turner
649edf1dd1 Add g++ 4.9 and 5 to travis ... hopefully 2016-02-18 10:26:58 -07:00
Jason Turner
172ab7b8e4 Merge branch 'develop' into typed_function_ordering 2016-02-18 08:57:55 -07:00
Jason Turner
fe8ddd1869 Merge branch 'develop' into typed_function_ordering 2016-01-20 18:32:16 -07:00
Jason Turner
5cb6f6a1a2 Merge branch 'develop' into typed_function_ordering 2016-01-20 18:28:28 -07:00
Jason Turner
95256417ac Merge branch 'add_performance_tests' of github.com:ChaiScript/ChaiScript into typed_function_ordering 2015-10-25 15:00:08 -06:00
Jason Turner
2d2251c1da Merge branch 'develop' of github.com:ChaiScript/ChaiScript into typed_function_ordering 2015-08-26 18:58:34 -06:00
Jason Turner
0adacc0b5e Merge branch 'develop' of github.com:ChaiScript/ChaiScript into typed_function_ordering 2015-08-26 18:47:43 -06:00
Jason Turner
818fd0b823 Add function ordering test 2015-08-26 18:47:32 -06:00
Jason Turner
bd9af5eff4 Order typed functions over untyped
specifically the chaiscript defined ones
2015-08-14 21:58:54 -06:00
108 changed files with 5895 additions and 4890 deletions

View File

@@ -1,12 +1,12 @@
compilers:
- name: "clang"
version: "3.5"
version: "3.6"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "clang"
build_tag: "LibC++"
version: "3.5"
version: "3.6"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "clang"
@@ -19,17 +19,28 @@ compilers:
version: "3.6"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
- name: "clang"
version: "3.7"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "clang"
build_tag: "LibC++"
version: "3.7"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "gcc"
version: "4.8"
version: "4.9"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "gcc"
version: "4.9"
skip_packaging: true
build_tag: "NoThreads"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF
collect_performance_results: true
- name: "gcc"
version: "4.8"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "gcc"
version: "4.6"
version: "5"
skip_packaging: true
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true

View File

@@ -10,13 +10,6 @@ compilers:
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true
- name: Visual Studio
version: 12
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 12
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 14
build_type: Debug
@@ -25,3 +18,4 @@ compilers:
compiler_extra_flags: /analyze
skip_packaging: true

View File

@@ -3,8 +3,8 @@ compiler:
- gcc
env:
matrix:
- GCC_VER="4.6"
- GCC_VER="4.8"
- GCC_VER="4.9"
- GCC_VER="5"
global:
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
@@ -13,7 +13,7 @@ env:
before_install:
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
- if [ "$GCC_VER" = "5" ]; then export COVERAGE=1 CPPCHECK=1; fi
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
- sudo pip install cpp-coveralls
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y

View File

@@ -101,9 +101,9 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 8)
set(CPACK_PACKAGE_VERSION_PATCH 5)
set(CPACK_PACKAGE_VERSION_MAJOR 6)
set(CPACK_PACKAGE_VERSION_MINOR 0)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -148,13 +148,13 @@ endif()
if(CMAKE_COMPILER_IS_GNUCC)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_LESS 4.8)
set(CPP11_FLAG "-std=c++0x")
if(GCC_VERSION VERSION_LESS 4.9)
set(CPP11_FLAG "-std=c++1y")
else()
set(CPP11_FLAG "-std=c++11")
set(CPP11_FLAG "-std=c++14")
endif()
else()
set(CPP11_FLAG "-std=c++11")
set(CPP11_FLAG "-std=c++14")
endif()
if(MSVC)
@@ -213,7 +213,7 @@ endif()
include_directories(include)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/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(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.hpp 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)
@@ -249,31 +249,37 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
add_library(stdlib STATIC static_libs/chaiscript_stdlib.cpp)
add_library(parser STATIC static_libs/chaiscript_parser.cpp)
add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib.cpp)
add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib_module.cpp)
target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
set(CHAISCRIPT_LIBS stdlib parser)
add_executable(chai src/main.cpp ${Chai_INCLUDES})
target_link_libraries(chai ${LIBS})
add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
target_link_libraries(chai ${LIBS} ${CHAISCRIPT_LIBS})
if(BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
target_link_libraries(test_num_exceptions ${LIBS})
target_link_libraries(test_num_exceptions ${LIBS} ${CHAISCRIPT_LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
target_link_libraries(memory_leak_test ${LIBS})
target_link_libraries(memory_leak_test ${LIBS} ${CHAISCRIPT_LIBS})
add_executable(inheritance samples/inheritance.cpp)
target_link_libraries(inheritance ${LIBS})
target_link_libraries(inheritance ${LIBS} ${CHAISCRIPT_LIBS})
add_executable(factory samples/factory.cpp)
target_link_libraries(factory ${LIBS})
target_link_libraries(factory ${LIBS} ${CHAISCRIPT_LIBS})
add_executable(fun_call_performance samples/fun_call_performance.cpp)
target_link_libraries(fun_call_performance ${LIBS})
target_link_libraries(fun_call_performance ${LIBS} ${CHAISCRIPT_LIBS})
endif()
if(BUILD_MODULES)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS})
@@ -292,7 +298,7 @@ if (RUN_FUZZY_TESTS)
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
)
@@ -418,7 +424,7 @@ if(BUILD_TESTING)
if(NOT UNIT_TEST_LIGHT)
add_executable(compiled_tests unittests/compiled_tests.cpp)
target_link_libraries(compiled_tests ${LIBS})
target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS})
ADD_CATCH_TESTS(compiled_tests)
@@ -431,11 +437,11 @@ if(BUILD_TESTING)
add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
target_link_libraries(c_linkage_test ${LIBS})
target_link_libraries(c_linkage_test ${LIBS} ${CHAISCRIPT_LIBS})
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
target_link_libraries(integer_literal_test ${LIBS})
target_link_libraries(integer_literal_test ${LIBS} ${CHAISCRIPT_LIBS})
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
if(MULTITHREAD_SUPPORT_ENABLED)
@@ -459,9 +465,6 @@ if(BUILD_TESTING)
target_link_libraries(multifile_test ${LIBS})
add_test(NAME MultiFile_Test COMMAND multifile_test)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
endif()
endif()

28
DesignGoals.md Normal file
View File

@@ -0,0 +1,28 @@
# Introduction
This document outlines the principles that drive the development of ChaiScript. ChaiScript does not intent to be the perfect tool for *every* situation, but it does intend to be a good general purpose tool for *most* situations.
# Goals
1. Trivially easy to integrate with C++ projects
2. 0 external depenencies
3. "Perfect" integration with C++
* Direct mapping between ChaiScript objects and C++ objects
* Direct mapping between ChaiScript functions and C++ functions
* Direct mapping between ChaiScript exceptions and C++ exceptions
3. Never surprise the C++ developer
* Object lifetimes managed by the stack
* Familiar syntax to C++ developers
4. Perform "well enough" to not get in the way
# Alternatives
## Sol2
If you are looking for the fastest performing scripting language and don't mind Lua, you might want to consider [sol2](https://github.com/ThePhD/sol2).
## SWIG
If you are looking for the most flexible solution to be able to support multiple target languages, consider [SWIG](http://swig.org)

View File

@@ -1,4 +1,4 @@
version: 5.7.2.{build}
version: 5.8.x.{build}
os: Visual Studio 2015
environment:
matrix:
@@ -14,3 +14,9 @@ build_script:
cmake --build . --config Debug
test_script:
- cmd: ctest -C Debug
notifications:
- provider: Webhook
url: https://webhooks.gitter.im/e/9ff725a985b5679d1d5d
on_build_success: true
on_build_failure: true
on_build_status_changed: false

View File

@@ -27,6 +27,13 @@ chai.add(chaiscript::fun(&Class::method_name), "method_name");
chai.add(chaiscript::fun(&Class::member_name), "member_name");
```
### Bound Member Functions
```
chai.add(chaiscript::fun(&Class::method_name, Class_instance_ptr), "method_name");
chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name");
```
### With Overloads
#### Preferred
@@ -84,6 +91,49 @@ chai.add(chaiscript::user_type<MyClass>(), "MyClass");
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 */ }));
```
### Class Hierarchies
If you want objects to be convertable between base and derived classes, you must tell ChaiScritp about the relationship.
```
chai.add(chaiscript::base_class<Base, Derived>());
```
If you have multiple classes in your inheritance graph, you will probably want to tell ChaiScript about all relationships.
```
chai.add(chaiscript::base_class<Base, Derived>());
chai.add(chaiscript::base_class<Derived, MoreDerived>());
chai.add(chaiscript::base_class<Base, MoreDerived>());
```
### Helpers
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
```
@@ -97,6 +147,7 @@ chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
```
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
## Adding Objects
@@ -111,6 +162,7 @@ chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global cons
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists
chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object
```
# Using STL
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
@@ -170,7 +222,7 @@ Conversion to `std::shared_ptr<T> &` is supported for function calls, but if you
```cpp
// ok this is supported, you can register it with chaiscript engine
void nullify_shared_ptr(std::shared_ptr<int> &t) {
t == nullptr
t = nullptr
}
```
@@ -260,6 +312,44 @@ if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hi
GLOBAL g3; // all upper case version also accepted
```
## Looping
```
// c-style for loops
for (var i = 0; i < 100; ++i) { print(i); }
```
```
// while
while (some_condition()) { /* do something */ }
```
```
// ranged for
for (x : [1,2,3]) { print(i); }
```
Each of the loop styles can be broken using the `break` statement. For example:
```
while (some_condition()) {
/* do something */
if (another_condition()) { break; }
}
```
## Conditionals
```
if (expression) { }
```
```
// C++17-style init-if blocks
// Value of 'statement' is scoped for entire `if` block
if (statement; expression) { }
```
## Built in Types
```
@@ -418,9 +508,33 @@ the contained function.
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
## Context
* `__LINE__` Current file line number
* `__FILE__` Full path of current file
* `__CLASS__` Name of current class
* `__FUNC__` Mame of current function
# Built In Functions
## Disabling Built-Ins
When constructing a ChaiScript object, a vector of parameters can be passed in to disable or enable various built-in methods.
Current options:
```
enum class Options
{
Load_Modules,
No_Load_Modules,
External_Scripts,
No_External_Scripts
};
```
## Evaluation
```
@@ -432,4 +546,7 @@ use("filename") // evals file exactly once and returns value of last statement
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor
## JSON
* `from_json` converts a JSON string into its strongly typed (map, vector, int, double, string) representations
* `to_json` converts a ChaiScript object (either a `Object` or one of map, vector, int, double, string) tree into its JSON string representation

View File

@@ -0,0 +1,61 @@
# My dict
for="for"
while="while"
def="def"
fun="fun"
if="if"
else="else"
and="&&"
or="||"
auto="auto"
var="var"
begin_block="{"
end_block="}"
empty_vec="[]"
string="string"
vector="Vector"
map="Map"
return="return"
break="break"
true="true"
false="false"
class="class"
attr="attr"
var="var"
global="global"
empty_lambda=" fun(){} "
empty_fun=" def empty_fun() {} "
continue="continue"
float=" 1.1f "
double=" 2.2 "
long_double=" 2.2ll "
unsigned=" 3u "
unsigned_long=" 4ul "
unsigned_long_long=" 4ull "
long_long=" 5ll "
attr="attr"
reference_del="auto &"
int8=" int8_t(1) "
int16=" int16_t(2) "
int32=" int32_t(3) "
int64=" int64_t(4) "
uint8=" uint8_t(1) "
uint16=" uint16_t(2) "
uint32=" uint32_t(3) "
uint64=" uint64_t(4) "
int8t="int8_t"
int16t="int16_t"
int32t="int32_t"
int64t="int64_t"
uint8t="uint8_t"
uint16t="uint16_t"
uint32t="uint32_t"
uint64t="uint64_t"

View File

@@ -0,0 +1,17 @@
Command line used to find this crash:
../../Downloads/afl-1.80b/afl-fuzz -i- -o findings -x chaiscript.dict -- ../a.out unit_test.inc @@
If you can't reproduce a bug outside of afl-fuzz, be sure to set the same
memory limit. The limit used for this fuzzing session was 50.0 MB.
Need a tool to minimize test cases before investigating the crashes or sending
them to a vendor? Check out the afl-tmin that comes with the fuzzer!
Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop
me a mail at <lcamtuf@coredump.cx> once the issues are fixed - I'd love to
add your finds to the gallery at:
http://lcamtuf.coredump.cx/afl/
Thanks :-)

View File

@@ -0,0 +1,5 @@
def greet {
return("hello")
}
fun(){ "world" }

View File

@@ -65,7 +65,7 @@
/// int main()
/// {
/// chaiscript::ChaiScript chai;
/// chai.add(&function, "function");
/// chai.add(chaiscript::fun(&function), "function");
///
/// double d = chai.eval<double>("function(3, 4.75);");
/// }
@@ -695,11 +695,10 @@
/// Begins a function or method definition
///
/// ~~~~~~~~
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// ~~~~~~~~
///
/// annotation: meta-annotation on function, currently used as documentation. Optional.
/// identifier: name of function. Required.
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
/// guards: guarding statement that act as a prerequisite for the function. Optional.
@@ -817,16 +816,26 @@
/// @namespace chaiscript::detail
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
#include "chaiscript_defines.hpp"
#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/function_call.hpp"
#include "dispatchkit/dynamic_object.hpp"
#include "dispatchkit/boxed_number.hpp"
#include "language/chaiscript_eval.hpp"
#include "language/chaiscript_engine.hpp"
#include "chaiscript_basic.hpp"
#include "language/chaiscript_parser.hpp"
#include "chaiscript_stdlib.hpp"
namespace chaiscript
{
class ChaiScript : public ChaiScript_Basic
{
public:
ChaiScript(std::vector<std::string> t_modulepaths = {},
std::vector<std::string> t_usepaths = {},
const std::vector<Options> &t_opts = {})
: ChaiScript_Basic(
chaiscript::Std_Lib::library(),
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
t_modulepaths, t_usepaths, t_opts)
{
}
};
}
#endif /* CHAISCRIPT_HPP_ */

View File

@@ -0,0 +1,39 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_BASIC_HPP_
#define CHAISCRIPT_BASIC_HPP_
#include "chaiscript_defines.hpp"
#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/function_call.hpp"
#include "dispatchkit/dynamic_object.hpp"
#include "dispatchkit/boxed_number.hpp"
#include "language/chaiscript_eval.hpp"
#include "language/chaiscript_engine.hpp"
// This file includes all of the basic requirements for ChaiScript,
// to use, you might do something like:
//
/*
#include "chaiscript_stdlib.hpp"
#include "language/chaiscript_parser.hpp"
ChaiScript_Basic chai(
chaiscript::Std_Lib::library(),
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>());
*/
// If you want a fully packaged ready to go ChaiScript, use chaiscript.hpp
#endif /* CHAISCRIPT_BASIC_HPP_ */

View File

@@ -12,17 +12,13 @@
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEC
#if _MSC_VER <= 1800
#define CHAISCRIPT_MSVC_12
#endif
static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later required");
#else
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
#endif
#ifndef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_HAS_MAGIC_STATICS
#endif
#include <vector>
#if defined( _LIBCPP_VERSION )
@@ -51,26 +47,15 @@
#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
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
/// \todo Make this support other compilers when possible
#define CHAISCRIPT_HAS_THREAD_LOCAL
#endif
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
#define CHAISCRIPT_GCC_4_6
#endif
#if defined(__llvm__)
#define CHAISCRIPT_CLANG
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG)
#define CHAISCRIPT_OVERRIDE override
#else
#define CHAISCRIPT_OVERRIDE
#endif
#ifdef CHAISCRIPT_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
@@ -78,12 +63,8 @@
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#ifdef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_NOEXCEPT throw()
#define CHAISCRIPT_CONSTEXPR
#else
#define CHAISCRIPT_NOEXCEPT noexcept
#define CHAISCRIPT_CONSTEXPR constexpr
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(CHAISCRIPT_CLANG)
#define CHAISCRIPT_UTF16_UTF32
#endif
#ifdef _DEBUG
@@ -97,9 +78,9 @@
#include <cmath>
namespace chaiscript {
static const int version_major = 5;
static const int version_minor = 8;
static const int version_patch = 5;
static const int version_major = 6;
static const int version_minor = 0;
static const int version_patch = 0;
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
@@ -115,18 +96,59 @@ namespace chaiscript {
#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;
struct Build_Info {
static int version_major()
{
return chaiscript::version_major;
}
static int version_minor()
{
return chaiscript::version_minor;
}
static int version_patch()
{
return chaiscript::version_patch;
}
static std::string version()
{
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
{
return chaiscript::compiler_name;
}
static bool debug_build()
{
return chaiscript::debug_build;
}
};
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) {
for (char c = *t_str; (c = *t_str) != 0; ++t_str) {
if (c < '0' || c > '9') {
return t;
}
@@ -187,6 +209,18 @@ namespace chaiscript {
return parse_num<T>(t_str.c_str());
}
enum class Options
{
No_Load_Modules,
Load_Modules,
No_External_Scripts,
External_Scripts
};
static inline std::vector<Options> default_options()
{
return {Options::Load_Modules, Options::External_Scripts};
}
}
#endif

View File

@@ -14,11 +14,17 @@
#include <vector>
#include "chaiscript_defines.hpp"
#include "dispatchkit/dispatchkit.hpp"
#include "language/chaiscript_common.hpp"
#include "dispatchkit/function_call.hpp"
//#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/operators.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.chai"
//#include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.hpp"
#include "dispatchkit/register_function.hpp"
#include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS
@@ -38,21 +44,20 @@ namespace chaiscript
static ModulePtr library()
{
using namespace bootstrap;
auto lib = std::make_shared<Module>();
bootstrap::Bootstrap::bootstrap(*lib);
ModulePtr lib = Bootstrap::bootstrap();
lib->add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
lib->add(standard_library::string_type<std::string>("string"));
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
bootstrap::standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
bootstrap::standard_library::string_type<std::string>("string", *lib);
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
#ifndef CHAISCRIPT_NO_THREADS
lib->add(standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future"));
bootstrap::standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);
lib->add(chaiscript::fun([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
#endif
lib->add(json_wrap::library());
json_wrap::library(*lib);
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );

View File

@@ -42,28 +42,16 @@ namespace chaiscript
#ifndef CHAISCRIPT_NO_THREADS
template<typename T>
class unique_lock : public std::unique_lock<T>
{
public:
explicit unique_lock(T &t) : std::unique_lock<T>(t) {}
};
using unique_lock = std::unique_lock<T>;
template<typename T>
class shared_lock : public std::unique_lock<T>
{
public:
explicit shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
using shared_lock = std::unique_lock<T>;
template<typename T>
class lock_guard : public std::lock_guard<T>
{
public:
explicit lock_guard(T &t) : std::lock_guard<T>(t) {}
};
using lock_guard = std::lock_guard<T>;
class shared_mutex : public std::mutex { };
using shared_mutex = std::mutex;
using std::mutex;
@@ -120,6 +108,9 @@ namespace chaiscript
#else
#pragma message ("Threading without thread_local support is not well supported.")
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///

View File

@@ -21,23 +21,20 @@ namespace chaiscript {
class bad_any_cast : public std::bad_cast
{
public:
bad_any_cast() CHAISCRIPT_NOEXCEPT
: m_what("bad any cast")
{
}
bad_any_cast() = default;
bad_any_cast(const bad_any_cast &) = default;
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
~bad_any_cast() noexcept override = default;
/// \brief Description of what error occurred
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
const char * what() const noexcept override
{
return m_what.c_str();
}
private:
std::string m_what;
std::string m_what = "bad any cast";
};
}
@@ -53,9 +50,10 @@ namespace chaiscript {
Data &operator=(const Data &) = delete;
virtual ~Data() {}
virtual ~Data() = default;
virtual void *data() = 0;
const std::type_info &type() const
{
return m_type;
@@ -74,14 +72,12 @@ namespace chaiscript {
{
}
virtual ~Data_Impl() {}
virtual void *data() CHAISCRIPT_OVERRIDE
void *data() override
{
return &m_data;
}
std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
std::unique_ptr<Data> clone() const override
{
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
}
@@ -96,6 +92,8 @@ namespace chaiscript {
public:
// construct/copy/destruct
Any() = default;
Any(Any &&) = default;
Any &operator=(Any &&t_any) = default;
Any(const Any &t_any)
{
@@ -107,10 +105,6 @@ namespace chaiscript {
}
}
#if !defined(_MSC_VER) || _MSC_VER != 1800
Any(Any &&) = default;
Any &operator=(Any &&t_any) = default;
#endif
template<typename ValueType,
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
@@ -139,10 +133,6 @@ namespace chaiscript {
}
~Any()
{
}
// modifiers
Any & swap(Any &t_other)
{
@@ -158,8 +148,7 @@ namespace chaiscript {
const std::type_info & type() const
{
if (m_data)
{
if (m_data) {
return m_data->type();
} else {
return typeid(void);

View File

@@ -30,32 +30,32 @@ namespace chaiscript
{
public:
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
std::string t_what) CHAISCRIPT_NOEXCEPT
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
std::string t_what) noexcept
: from(t_from), to(&t_to), m_what(std::move(t_what))
{
}
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
{
}
explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(nullptr), m_what(std::move(t_what))
explicit bad_boxed_cast(std::string t_what) noexcept
: m_what(std::move(t_what))
{
}
bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
~bad_boxed_cast() noexcept override = default;
/// \brief Description of what error occurred
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
const char * what() const noexcept override
{
return m_what.c_str();
}
Type_Info from; ///< Type_Info contained in the Boxed_Value
const std::type_info *to; ///< std::type_info of the desired (but failed) result type
const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type
private:
std::string m_what;

View File

@@ -27,45 +27,52 @@ namespace chaiscript
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
auto bind_first(Ret (*f)(P1, Param...), O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(std::forward<O>(o), std::forward<Param>(param)...);
}
);
return [f, o](Param...param) -> Ret {
return f(std::forward<O>(o), std::forward<Param>(param)...);
};
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
auto bind_first(Ret (Class::*f)(Param...), O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
return [f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
};
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
return [f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
};
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
auto bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(o, std::forward<Param>(param)...);
});
return [f, o](Param...param) -> Ret {
return f(o, std::forward<Param>(param)...);
};
}
template<typename F, typename O, typename Ret, typename Class, typename P1, typename ... Param>
auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
{
return [fo, o, f](Param ...param) -> Ret {
return (fo.*f)(o, std::forward<Param>(param)...);
};
}
template<typename F, typename O>
auto bind_first(const F &f, O&& o)
{
return bind_first(f, std::forward<O>(o), &F::operator());
}
}
}

View File

@@ -7,57 +7,21 @@
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
#define CHAISCRIPT_BOOTSTRAP_HPP_
#include <cstdint>
#include <exception>
#include <functional>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>
#include <iterator>
#include "bad_boxed_cast.hpp"
#include "boxed_cast.hpp"
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "dispatchkit.hpp"
#include "type_conversions.hpp"
#include "dynamic_object.hpp"
#include "operators.hpp"
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "proxy_functions_detail.hpp"
#include "register_function.hpp"
#include "type_info.hpp"
#include "../utility/utility.hpp"
#include "../language/chaiscript_common.hpp"
#include "register_function.hpp"
namespace chaiscript
{
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
namespace bootstrap
{
namespace detail
{
/// \brief Constructs a new POD value object from a Boxed_Number
/// \param[in] v Boxed_Number to copy into the new object
/// \returns The newly created object.
template<typename P1>
std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
{
return std::make_shared<P1>(v.get_as<P1>());
}
}
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
ModulePtr array(const std::string &type, ModulePtr m = std::make_shared<Module>())
void array(const std::string &type, Module& m)
{
typedef typename std::remove_extent<T>::type ReturnType;
const auto extent = std::extent<T>::value;
m->add(user_type<T>(), type);
m->add(fun(
m.add(user_type<T>(), type);
m.add(fun(
[extent](T& t, size_t index)->ReturnType &{
if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
@@ -68,7 +32,7 @@ namespace chaiscript
), "[]"
);
m->add(fun(
m.add(fun(
[extent](const T &t, size_t index)->const ReturnType &{
if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
@@ -79,33 +43,29 @@ namespace chaiscript
), "[]"
);
m->add(fun(
m.add(fun(
[extent](const T &) {
return extent;
}), "size");
return m;
}
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
/// \returns The passed in Module
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared<Module>())
void copy_constructor(const std::string &type, Module& m)
{
m->add(constructor<T (const T &)>(), type);
return m;
m.add(constructor<T (const T &)>(), type);
}
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
/// \tparam T Type to create comparison operators for
/// \param[in,out] m module to add comparison operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
/// \returns the passed in Module.
template<typename T>
ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
void opers_comparison(Module& m)
{
operators::equal<T>(m);
operators::greater_than<T>(m);
@@ -113,7 +73,6 @@ namespace chaiscript
operators::less_than<T>(m);
operators::less_than_equal<T>(m);
operators::not_equal<T>(m);
return m;
}
@@ -122,15 +81,14 @@ namespace chaiscript
/// \param[in] type The name of the type to add the constructors for.
/// \param[in,out] m The Module to add the basic constructors to
/// \tparam T Type to generate basic constructors for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
/// \returns The passed in Module
/// \sa copy_constructor
/// \sa constructor
template<typename T>
ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared<Module>())
void basic_constructors(const std::string &type, Module& m)
{
m->add(constructor<T ()>(), type);
m.add(constructor<T ()>(), type);
copy_constructor<T>(type, m);
return m;
}
/// \brief Adds a constructor for a POD type
@@ -138,22 +96,12 @@ namespace chaiscript
/// \param[in] type The name of the type
/// \param[in,out] m The Module to add the constructor to
template<typename T>
ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared<Module>())
void construct_pod(const std::string &type, Module& m)
{
m->add(fun(&detail::construct_pod<T>), type);
return m;
m.add(fun([](const Boxed_Number &bn){ return bn.get_as<T>(); }), type);
}
/// to_string function for internal use. Uses ostream operator<<
template<typename Input>
std::string to_string(Input i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
/// Internal function for converting from a string to a value
/// uses ostream operator >> to perform the conversion
template<typename Input>
@@ -185,14 +133,13 @@ namespace chaiscript
/// Add all common functions for a POD type. All operators, and
/// common conversions
template<typename T>
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared<Module>())
void bootstrap_pod_type(const std::string &name, Module& m)
{
m->add(user_type<T>(), name);
m->add(constructor<T()>(), name);
m.add(user_type<T>(), name);
m.add(constructor<T()>(), name);
construct_pod<T>(name, m);
m->add(fun(&parse_string<T>), "to_" + name);
return m;
m.add(fun(&parse_string<T>), "to_" + name);
}
@@ -202,15 +149,14 @@ namespace chaiscript
/// for handling of Proxy_Function object (that is,
/// function variables.
template<typename Type>
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
auto shared_ptr_clone(const std::shared_ptr<Type> &p)
{
return p;
}
/// Specific version of shared_ptr_clone just for Proxy_Functions
template<typename Type>
std::shared_ptr<typename std::remove_const<Type>::type>
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
std::shared_ptr<typename std::remove_const<Type>::type> shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
{
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
}
@@ -261,43 +207,41 @@ namespace chaiscript
/// Add all arithmetic operators for PODs
static void opers_arithmetic_pod(ModulePtr m = std::make_shared<Module>())
static void opers_arithmetic_pod(Module& m)
{
m->add(fun(&Boxed_Number::equals), "==");
m->add(fun(&Boxed_Number::less_than), "<");
m->add(fun(&Boxed_Number::greater_than), ">");
m->add(fun(&Boxed_Number::greater_than_equal), ">=");
m->add(fun(&Boxed_Number::less_than_equal), "<=");
m->add(fun(&Boxed_Number::not_equal), "!=");
m->add(fun(&Boxed_Number::pre_decrement), "--");
m->add(fun(&Boxed_Number::pre_increment), "++");
m->add(fun(&Boxed_Number::sum), "+");
m->add(fun(&Boxed_Number::unary_plus), "+");
m->add(fun(&Boxed_Number::unary_minus), "-");
m->add(fun(&Boxed_Number::difference), "-");
m->add(fun(&Boxed_Number::assign_bitwise_and), "&=");
m->add(fun(&Boxed_Number::assign), "=");
m->add(fun(&Boxed_Number::assign_bitwise_or), "|=");
m->add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
m->add(fun(&Boxed_Number::assign_remainder), "%=");
m->add(fun(&Boxed_Number::assign_shift_left), "<<=");
m->add(fun(&Boxed_Number::assign_shift_right), ">>=");
m->add(fun(&Boxed_Number::bitwise_and), "&");
m->add(fun(&Boxed_Number::bitwise_complement), "~");
m->add(fun(&Boxed_Number::bitwise_xor), "^");
m->add(fun(&Boxed_Number::bitwise_or), "|");
m->add(fun(&Boxed_Number::assign_product), "*=");
m->add(fun(&Boxed_Number::assign_quotient), "/=");
m->add(fun(&Boxed_Number::assign_sum), "+=");
m->add(fun(&Boxed_Number::assign_difference), "-=");
m->add(fun(&Boxed_Number::quotient), "/");
m->add(fun(&Boxed_Number::shift_left), "<<");
m->add(fun(&Boxed_Number::product), "*");
m->add(fun(&Boxed_Number::remainder), "%");
m->add(fun(&Boxed_Number::shift_right), ">>");
m.add(fun(&Boxed_Number::equals), "==");
m.add(fun(&Boxed_Number::less_than), "<");
m.add(fun(&Boxed_Number::greater_than), ">");
m.add(fun(&Boxed_Number::greater_than_equal), ">=");
m.add(fun(&Boxed_Number::less_than_equal), "<=");
m.add(fun(&Boxed_Number::not_equal), "!=");
m.add(fun(&Boxed_Number::pre_decrement), "--");
m.add(fun(&Boxed_Number::pre_increment), "++");
m.add(fun(&Boxed_Number::sum), "+");
m.add(fun(&Boxed_Number::unary_plus), "+");
m.add(fun(&Boxed_Number::unary_minus), "-");
m.add(fun(&Boxed_Number::difference), "-");
m.add(fun(&Boxed_Number::assign_bitwise_and), "&=");
m.add(fun(&Boxed_Number::assign), "=");
m.add(fun(&Boxed_Number::assign_bitwise_or), "|=");
m.add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
m.add(fun(&Boxed_Number::assign_remainder), "%=");
m.add(fun(&Boxed_Number::assign_shift_left), "<<=");
m.add(fun(&Boxed_Number::assign_shift_right), ">>=");
m.add(fun(&Boxed_Number::bitwise_and), "&");
m.add(fun(&Boxed_Number::bitwise_complement), "~");
m.add(fun(&Boxed_Number::bitwise_xor), "^");
m.add(fun(&Boxed_Number::bitwise_or), "|");
m.add(fun(&Boxed_Number::assign_product), "*=");
m.add(fun(&Boxed_Number::assign_quotient), "/=");
m.add(fun(&Boxed_Number::assign_sum), "+=");
m.add(fun(&Boxed_Number::assign_difference), "-=");
m.add(fun(&Boxed_Number::quotient), "/");
m.add(fun(&Boxed_Number::shift_left), "<<");
m.add(fun(&Boxed_Number::product), "*");
m.add(fun(&Boxed_Number::remainder), "%");
m.add(fun(&Boxed_Number::shift_right), ">>");
}
/// Create a bound function object. The first param is the function to bind
@@ -337,26 +281,6 @@ namespace chaiscript
}
}
static void throw_exception(const Boxed_Value &bv) {
throw bv;
}
static std::string what(const std::exception &e)
{
return e.what();
}
/// Boolean specialization of internal to_string function
static std::string bool_to_string(bool b)
{
if (b)
{
return "true";
} else {
return "false";
}
}
template<typename FunctionType>
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
const dispatch::Proxy_Function_Base *b)
@@ -392,7 +316,7 @@ namespace chaiscript
}
template<typename Function>
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
static auto return_boxed_value_vector(const Function &f)
{
return [f](const dispatch::Proxy_Function_Base *b) {
return do_return_boxed_value_vector(f, b);
@@ -403,94 +327,123 @@ namespace chaiscript
public:
/// \brief perform all common bootstrap functions for std::string, void and POD types
/// \param[in,out] m Module to add bootstrapped functions to
/// \returns passed in ModulePtr, or newly created one if default argument is used
static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
/// \returns passed in Module
static void bootstrap(Module& m)
{
m->add(user_type<void>(), "void");
m->add(user_type<bool>(), "bool");
m->add(user_type<Boxed_Value>(), "Object");
m->add(user_type<Boxed_Number>(), "Number");
m->add(user_type<Proxy_Function>(), "Function");
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
m->add(user_type<std::exception>(), "exception");
m.add(user_type<void>(), "void");
m.add(user_type<bool>(), "bool");
m.add(user_type<Boxed_Value>(), "Object");
m.add(user_type<Boxed_Number>(), "Number");
m.add(user_type<Proxy_Function>(), "Function");
m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
m.add(user_type<std::exception>(), "exception");
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m.add(fun([](const std::exception &e){ return std::string(e.what()); }), "what");
m->add(user_type<std::out_of_range>(), "out_of_range");
m->add(user_type<std::logic_error>(), "logic_error");
m->add(chaiscript::base_class<std::exception, std::logic_error>());
m->add(chaiscript::base_class<std::logic_error, std::out_of_range>());
m->add(chaiscript::base_class<std::exception, std::out_of_range>());
m.add(user_type<std::out_of_range>(), "out_of_range");
m.add(user_type<std::logic_error>(), "logic_error");
m.add(chaiscript::base_class<std::exception, std::logic_error>());
m.add(chaiscript::base_class<std::logic_error, std::out_of_range>());
m.add(chaiscript::base_class<std::exception, std::out_of_range>());
m->add(user_type<std::runtime_error>(), "runtime_error");
m->add(chaiscript::base_class<std::exception, std::runtime_error>());
m.add(user_type<std::runtime_error>(), "runtime_error");
m.add(chaiscript::base_class<std::exception, std::runtime_error>());
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m.add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
m.add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
m.add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
m.add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
m.add(fun(&dispatch::Dynamic_Object::has_attr), "has_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<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->eval(R""(
m.eval(R"chaiscript(
def Dynamic_Object::clone() {
auto &new_o = Dynamic_Object(this.get_type_name());
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
new_o;
}
)"");
m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard");
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
}
m->add(fun(&Boxed_Value::is_undef), "is_var_undef");
m->add(fun(&Boxed_Value::is_null), "is_var_null");
m->add(fun(&Boxed_Value::is_const), "is_var_const");
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
m->add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m->add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
var rhs_attrs := rhs.get_attrs();
var lhs_attrs := lhs.get_attrs();
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
if (rhs_attrs.size() != lhs_attrs.size()) {
true;
} else {
return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } );
}
}
def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
var rhs_attrs := rhs.get_attrs();
var lhs_attrs := lhs.get_attrs();
if (rhs_attrs.size() != lhs_attrs.size()) {
false;
} else {
return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } );
}
}
)chaiscript");
m.add(fun(&has_guard), "has_guard");
m.add(fun(&get_guard), "get_guard");
m.add(fun(&Boxed_Value::is_undef), "is_var_undef");
m.add(fun(&Boxed_Value::is_null), "is_var_null");
m.add(fun(&Boxed_Value::is_const), "is_var_const");
m.add(fun(&Boxed_Value::is_ref), "is_var_reference");
m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
m.add(fun(&Boxed_Value::is_type), "is_type");
m.add(fun(&Boxed_Value::get_attr), "get_var_attr");
m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
m.add(user_type<Type_Info>(), "Type_Info");
m.add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
operators::equal<Type_Info>(m);
m->add(fun(&Type_Info::is_const), "is_type_const");
m->add(fun(&Type_Info::is_reference), "is_type_reference");
m->add(fun(&Type_Info::is_void), "is_type_void");
m->add(fun(&Type_Info::is_undef), "is_type_undef");
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
m->add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
m->add(fun(&Type_Info::name), "cpp_name");
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
m->add(fun(&Type_Info::bare_equal), "bare_equal");
m.add(fun(&Type_Info::is_const), "is_type_const");
m.add(fun(&Type_Info::is_reference), "is_type_reference");
m.add(fun(&Type_Info::is_void), "is_type_void");
m.add(fun(&Type_Info::is_undef), "is_type_undef");
m.add(fun(&Type_Info::is_pointer), "is_type_pointer");
m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
m.add(fun(&Type_Info::name), "cpp_name");
m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
m.add(fun(&Type_Info::bare_equal), "bare_equal");
basic_constructors<bool>("bool", m);
@@ -498,15 +451,15 @@ namespace chaiscript
operators::equal<bool>(m);
operators::not_equal<bool>(m);
m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
m->add(fun(&Bootstrap::bool_to_string), "to_string");
m->add(fun(&unknown_assign), "=");
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
m.add(fun([](const std::string &s) { return s; }), "to_string");
m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
m.add(fun(&unknown_assign), "=");
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
m->add(fun(&to_string<char>), "to_string");
m->add(fun(&Boxed_Number::to_string), "to_string");
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
m.add(fun(&Boxed_Number::to_string), "to_string");
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<long double>("long_double", m);
bootstrap_pod_type<float>("float", m);
@@ -530,58 +483,71 @@ namespace chaiscript
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m);
opers_arithmetic_pod(m);
m.add(fun(&Build_Info::version_major), "version_major");
m.add(fun(&Build_Info::version_minor), "version_minor");
m.add(fun(&Build_Info::version_patch), "version_patch");
m.add(fun(&Build_Info::version), "version");
m.add(fun(&Build_Info::compiler_version), "compiler_version");
m.add(fun(&Build_Info::compiler_name), "compiler_name");
m.add(fun(&Build_Info::compiler_id), "compiler_id");
m.add(fun(&Build_Info::debug_build), "debug_build");
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");
m->add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
m.add(fun(&print), "print_string");
m.add(fun(&println), "println_string");
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
m->add(fun(
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
m.add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m.add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m.add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m.add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
m.add(fun(
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
t_lhs.assign(t_rhs);
}
), "="
);
m->add(fun(&Boxed_Value::type_match), "type_match");
m.add(fun(&Boxed_Value::type_match), "type_match");
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
"eval_error",
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
return retval;
})), "call_stack"} }
}), "call_stack"} }
);
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
chaiscript::utility::add_class<chaiscript::File_Position>(m,
"File_Position",
{ constructor<File_Position()>(),
constructor<File_Position(int, int)>() },
@@ -590,7 +556,7 @@ namespace chaiscript
);
chaiscript::utility::add_class<AST_Node>(*m,
chaiscript::utility::add_class<AST_Node>(m,
"AST_Node",
{ },
{ {fun(&AST_Node::text), "text"},
@@ -599,28 +565,17 @@ namespace chaiscript
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::to_string), "to_string"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
{fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_node.children.begin(), t_node.children.end(),
const auto children = t_node.get_children();
std::transform(children.begin(), children.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
return retval;
})), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}), "children"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
return m;
}
};
}

View File

@@ -37,11 +37,10 @@ namespace chaiscript
/// Bidir_Range, based on the D concept of ranges.
/// \todo Update the Range code to base its capabilities on
/// the user_typetraits of the iterator passed in
template<typename Container>
template<typename Container, typename IterType>
struct Bidir_Range
{
typedef Container container_type;
typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
Bidir_Range(Container &c)
: m_begin(c.begin()), m_end(c.end())
@@ -71,86 +70,28 @@ namespace chaiscript
--m_end;
}
reference_type front() const
decltype(auto) front() const
{
if (empty())
{
throw std::range_error("Range empty");
}
return *m_begin;
return (*m_begin);
}
reference_type back() const
decltype(auto) back() const
{
if (empty())
{
throw std::range_error("Range empty");
}
typename Container::iterator pos = m_end;
auto pos = m_end;
--pos;
return *(pos);
return (*(pos));
}
typename Container::iterator m_begin;
typename Container::iterator m_end;
};
template<typename Container>
struct Const_Bidir_Range
{
typedef const Container container_type;
typedef typename std::iterator_traits<typename Container::const_iterator>::reference const_reference_type;
Const_Bidir_Range(const Container &c)
: m_begin(c.begin()), m_end(c.end())
{
}
bool empty() const
{
return m_begin == m_end;
}
void pop_front()
{
if (empty())
{
throw std::range_error("Range empty");
}
++m_begin;
}
void pop_back()
{
if (empty())
{
throw std::range_error("Range empty");
}
--m_end;
}
const_reference_type front() const
{
if (empty())
{
throw std::range_error("Range empty");
}
return *m_begin;
}
const_reference_type back() const
{
if (empty())
{
throw std::range_error("Range empty");
}
typename Container::const_iterator pos = m_end;
--pos;
return *(pos);
}
typename Container::const_iterator m_begin;
typename Container::const_iterator m_end;
IterType m_begin;
IterType m_end;
};
namespace detail {
@@ -177,22 +118,20 @@ namespace chaiscript
/// Add Bidir_Range support for the given ContainerType
template<typename Bidir_Type>
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared<Module>())
void input_range_type_impl(const std::string &type, Module& m)
{
m->add(user_type<Bidir_Type>(), type + "_Range");
m.add(user_type<Bidir_Type>(), type + "_Range");
copy_constructor<Bidir_Type>(type + "_Range", m);
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
m.add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
m->add(fun(&Bidir_Type::empty), "empty");
m->add(fun(&Bidir_Type::pop_front), "pop_front");
m->add(fun(&Bidir_Type::front), "front");
m->add(fun(&Bidir_Type::pop_back), "pop_back");
m->add(fun(&Bidir_Type::back), "back");
return m;
}
m.add(fun(&Bidir_Type::empty), "empty");
m.add(fun(&Bidir_Type::pop_front), "pop_front");
m.add(fun(&Bidir_Type::front), "front");
m.add(fun(&Bidir_Type::pop_back), "pop_back");
m.add(fun(&Bidir_Type::back), "back");
}
/// Algorithm for inserting at a specific position into a container
@@ -230,10 +169,16 @@ namespace chaiscript
}
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void input_range_type(const std::string &type, Module& m)
{
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
detail::input_range_type_impl<Bidir_Range<ContainerType, typename ContainerType::iterator> >(type,m);
detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator> >("Const_" + type,m);
}
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type)
{
auto m = std::make_shared<Module>();
input_range_type<ContainerType>(type, *m);
return m;
}
@@ -241,11 +186,11 @@ namespace chaiscript
/// Add random_access_container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
void random_access_container_type(const std::string &/*type*/, Module& m)
{
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
//to throw an exception in an out of bounds condition.
m->add(
m.add(
fun(
[](ContainerType &c, int index) -> typename ContainerType::reference {
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
@@ -253,25 +198,71 @@ namespace chaiscript
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
m->add(
m.add(
fun(
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
}
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &type)
{
auto m = std::make_shared<Module>();
random_access_container_type<ContainerType>(type, *m);
return m;
}
/// Add assignable concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Assignable.html
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void assignable_type(const std::string &type, Module& m)
{
copy_constructor<ContainerType>(type, m);
operators::assign<ContainerType>(m);
}
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type)
{
auto m = std::make_shared<Module>();
assignable_type<ContainerType>(type, *m);
return m;
}
/// Add container resize concept to the given ContainerType
/// http://www.cplusplus.com/reference/stl/
template<typename ContainerType>
void resizable_type(const std::string &/*type*/, Module& m)
{
m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize");
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize");
}
template<typename ContainerType>
ModulePtr resizable_type(const std::string &type)
{
auto m = std::make_shared<Module>();
resizable_type<ContainerType>(type, *m);
return m;
}
/// Add container reserve concept to the given ContainerType
/// http://www.cplusplus.com/reference/stl/
template<typename ContainerType>
void reservable_type(const std::string &/*type*/, Module& m)
{
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
}
template<typename ContainerType>
ModulePtr reservable_type(const std::string &type)
{
auto m = std::make_shared<Module>();
reservable_type<ContainerType>(type, *m);
return m;
}
@@ -279,33 +270,44 @@ namespace chaiscript
/// Add container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Container.html
template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
void container_type(const std::string &/*type*/, Module& m)
{
m->add(fun([](const ContainerType *a) { return a->size(); } ), "size");
m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
m->add(fun([](ContainerType *a) { a->clear(); } ), "clear");
return m;
m.add(fun([](const ContainerType *a) { return a->size(); } ), "size");
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
}
template <typename ContainerType>
ModulePtr container_type(const std::string& type)
{
auto m = std::make_shared<Module>();
container_type<ContainerType>(type, *m);
return m;
}
/// Add default constructable concept to the given Type
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void default_constructible_type(const std::string &type, Module& m)
{
m->add(constructor<Type ()>(), type);
m.add(constructor<Type ()>(), type);
}
template <typename Type>
ModulePtr default_constructible_type(const std::string& type)
{
auto m = std::make_shared<Module>();
default_constructible_type<Type>(type, *m);
return m;
}
/// Add sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Sequence.html
template<typename ContainerType>
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
void sequence_type(const std::string &/*type*/, Module& m)
{
m->add(fun(&detail::insert_at<ContainerType>),
m.add(fun(&detail::insert_at<ContainerType>),
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "insert_ref_at";
@@ -314,27 +316,31 @@ namespace chaiscript
}
}());
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
}
template <typename ContainerType>
ModulePtr sequence_type(const std::string &type)
{
auto m = std::make_shared<Module>();
sequence_type<ContainerType>(type, *m);
return m;
}
/// Add back insertion sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void back_insertion_sequence_type(const std::string &type, Module& m)
{
typedef typename ContainerType::reference (ContainerType::*backptr)();
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
m.add(fun(static_cast<backptr>(&ContainerType::back)), "back");
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
[&]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
m->eval(
m.eval(
"# Pushes the second value onto the container while making a clone of the value\n"
"def push_back(" + type + " container, x)\n"
"{ \n"
@@ -353,7 +359,13 @@ namespace chaiscript
}
}());
m->add(fun(&ContainerType::pop_back), "pop_back");
m.add(fun(&ContainerType::pop_back), "pop_back");
}
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &type)
{
auto m = std::make_shared<Module>();
back_insertion_sequence_type<ContainerType>(type, *m);
return m;
}
@@ -362,20 +374,20 @@ namespace chaiscript
/// Front insertion sequence
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void front_insertion_sequence_type(const std::string &type, Module& m)
{
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
typedef void (ContainerType::*pop_ptr)();
m->add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
m.add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
m.add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
[&]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
m->eval(
m.eval(
"# Pushes the second value onto the front of container while making a clone of the value\n"
"def push_front(" + type + " container, x)\n"
"{ \n"
@@ -393,7 +405,13 @@ namespace chaiscript
}
}());
m->add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
}
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &type)
{
auto m = std::make_shared<Module>();
front_insertion_sequence_type<ContainerType>(type, *m);
return m;
}
@@ -401,20 +419,21 @@ namespace chaiscript
/// bootstrap a given PairType
/// http://www.sgi.com/tech/stl/pair.html
template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void pair_type(const std::string &type, Module& m)
{
m->add(user_type<PairType>(), type);
m.add(user_type<PairType>(), type);
typename PairType::first_type PairType::* f = &PairType::first;
typename PairType::second_type PairType::* s = &PairType::second;
m->add(fun(f), "first");
m->add(fun(s), "second");
m.add(fun(&PairType::first), "first");
m.add(fun(&PairType::second), "second");
basic_constructors<PairType>(type, m);
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
}
template<typename PairType>
ModulePtr pair_type(const std::string &type)
{
auto m = std::make_shared<Module>();
pair_type<PairType>(type, *m);
return m;
}
@@ -424,10 +443,15 @@ namespace chaiscript
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void pair_associative_container_type(const std::string &type, Module& m)
{
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
}
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type)
{
auto m = std::make_shared<Module>();
pair_associative_container_type<ContainerType>(type, *m);
return m;
}
@@ -435,17 +459,17 @@ namespace chaiscript
/// Add unique associative container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
void unique_associative_container_type(const std::string &/*type*/, Module& m)
{
m->add(fun(detail::count<ContainerType>), "count");
m.add(fun(detail::count<ContainerType>), "count");
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
m->add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
m->add(fun(&detail::insert<ContainerType>), "insert");
m.add(fun(&detail::insert<ContainerType>), "insert");
m->add(fun(&detail::insert_ref<ContainerType>),
m.add(fun(&detail::insert_ref<ContainerType>),
[]()->std::string{
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
return "insert_ref";
@@ -453,8 +477,12 @@ namespace chaiscript
return "insert";
}
}());
}
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &type)
{
auto m = std::make_shared<Module>();
unique_associative_container_type<ContainerType>(type, *m);
return m;
}
@@ -462,21 +490,21 @@ namespace chaiscript
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void map_type(const std::string &type, Module& m)
{
m->add(user_type<MapType>(), type);
m.add(user_type<MapType>(), type);
typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const;
m->add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
m.add(fun(static_cast<elem_access>(&MapType::at)), "at");
m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
{
m->eval(R"(
m.eval(R"(
def Map::`==`(Map rhs) {
if ( rhs.size() != this.size() ) {
return false;
@@ -504,26 +532,36 @@ namespace chaiscript
unique_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m);
input_range_type<MapType>(type, m);
}
template<typename MapType>
ModulePtr map_type(const std::string &type)
{
auto m = std::make_shared<Module>();
map_type<MapType>(type, *m);
return m;
}
/// hopefully working List type
/// http://www.sgi.com/tech/stl/List.html
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void list_type(const std::string &type, Module& m)
{
m->add(user_type<ListType>(), type);
m.add(user_type<ListType>(), type);
front_insertion_sequence_type<ListType>(type, m);
back_insertion_sequence_type<ListType>(type, m);
sequence_type<ListType>(type, m);
resizable_type<ListType>(type, m);
container_type<ListType>(type, m);
default_constructible_type<ListType>(type, m);
assignable_type<ListType>(type, m);
input_range_type<ListType>(type, m);
}
template<typename ListType>
ModulePtr list_type(const std::string &type)
{
auto m = std::make_shared<Module>();
list_type<ListType>(type, m);
return m;
}
@@ -531,20 +569,22 @@ namespace chaiscript
/// Create a vector type with associated concepts
/// http://www.sgi.com/tech/stl/Vector.html
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void vector_type(const std::string &type, Module& m)
{
m->add(user_type<VectorType>(), type);
m.add(user_type<VectorType>(), type);
typedef typename VectorType::reference (VectorType::*frontptr)();
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
m.add(fun(static_cast<frontptr>(&VectorType::front)), "front");
m.add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
back_insertion_sequence_type<VectorType>(type, m);
sequence_type<VectorType>(type, m);
random_access_container_type<VectorType>(type, m);
resizable_type<VectorType>(type, m);
reservable_type<VectorType>(type, m);
container_type<VectorType>(type, m);
default_constructible_type<VectorType>(type, m);
assignable_type<VectorType>(type, m);
@@ -552,7 +592,7 @@ namespace chaiscript
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
{
m->eval(R"(
m.eval(R"(
def Vector::`==`(Vector rhs) {
if ( rhs.size() != this.size() ) {
return false;
@@ -573,16 +613,21 @@ namespace chaiscript
} )"
);
}
}
template<typename VectorType>
ModulePtr vector_type(const std::string &type)
{
auto m = std::make_shared<Module>();
vector_type<VectorType>(type, *m);
return m;
}
/// Add a String container
/// http://www.sgi.com/tech/stl/basic_string.html
template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void string_type(const std::string &type, Module& m)
{
m->add(user_type<String>(), type);
m.add(user_type<String>(), type);
operators::addition<String>(m);
operators::assign_sum<String>(m);
opers_comparison<String>(m);
@@ -594,7 +639,7 @@ namespace chaiscript
input_range_type<String>(type, m);
//Special case: add push_back to string (which doesn't support other back_insertion operations
m->add(fun(&String::push_back),
m.add(fun(&String::push_back),
[]()->std::string{
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
return "push_back_ref";
@@ -604,21 +649,26 @@ namespace chaiscript
}());
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
m->add(fun([](String *s) { s->clear(); } ), "clear");
m->add(fun([](const String *s) { return s->empty(); } ), "empty");
m->add(fun([](const String *s) { return s->size(); } ), "size");
m->add(fun([](const String *s) { return s->c_str(); } ), "c_str");
m->add(fun([](const String *s) { return s->data(); } ), "data");
m->add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
m.add(fun([](String *s) { s->clear(); } ), "clear");
m.add(fun([](const String *s) { return s->empty(); } ), "empty");
m.add(fun([](const String *s) { return s->size(); } ), "size");
m.add(fun([](const String *s) { return s->c_str(); } ), "c_str");
m.add(fun([](const String *s) { return s->data(); } ), "data");
m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
}
template<typename String>
ModulePtr string_type(const std::string &type)
{
auto m = std::make_shared<Module>();
string_type<String>(type, *m);
return m;
}
@@ -627,14 +677,19 @@ namespace chaiscript
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
template<typename FutureType>
ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
void future_type(const std::string &type, Module& m)
{
m->add(user_type<FutureType>(), type);
m->add(fun([](const FutureType &t) { return t.valid(); }), "valid");
m->add(fun(&FutureType::get), "get");
m->add(fun(&FutureType::wait), "wait");
m.add(user_type<FutureType>(), type);
m.add(fun([](const FutureType &t) { return t.valid(); }), "valid");
m.add(fun(&FutureType::get), "get");
m.add(fun(&FutureType::wait), "wait");
}
template<typename FutureType>
ModulePtr future_type(const std::string &type)
{
auto m = std::make_shared<Module>();
future_type<FutureType>(type, *m);
return m;
}
}

View File

@@ -69,11 +69,11 @@ namespace chaiscript
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
decltype(auto) 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>())) {
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 &) {
}
}
@@ -82,21 +82,19 @@ namespace chaiscript
if (t_conversions && (*t_conversions)->convertable_type<Type>())
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions);
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
} catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
// try going the other way
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
}
} else {
// If it's not polymorphic, just throw the error, don't waste the time on the
// If it's not convertable, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}

View File

@@ -25,25 +25,54 @@ namespace chaiscript
template<typename T>
T* throw_if_null(T *t)
{
if (t) return t;
if (t) { return t; }
throw std::runtime_error("Attempted to dereference null Boxed_Value");
}
template<typename T>
static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
if (ob.get_type_info() == ti) {
return ptr;
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename T>
static T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
if (!ob.is_const() && ob.get_type_info() == ti) {
return ptr;
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename T>
static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
if (ob.get_type_info().bare_equal_type_info(ti)) {
return throw_if_null(ptr);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename T>
static T *verify_type(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) {
return throw_if_null(ptr);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
/// Generic Cast_Helper_Inner, for casting to any type
template<typename Result>
struct Cast_Helper_Inner
{
typedef typename std::add_const<Result>::type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
}
};
@@ -57,15 +86,9 @@ namespace chaiscript
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 *)
static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return static_cast<const Result *>(ob.get_const_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
}
};
@@ -73,15 +96,9 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<Result *>
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
{
return static_cast<Result *>(ob.get_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
}
};
@@ -100,17 +117,9 @@ namespace chaiscript
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 *)
static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
}
};
@@ -120,26 +129,50 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<Result &>
{
typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Result& 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)))
{
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
}
};
/// Cast_Helper_Inner for casting to a && type
template<typename Result>
struct Cast_Helper_Inner<Result &&>
{
static Result&& cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
}
};
/// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
/// \todo Fix the fact that this has to be in a shared_ptr for now
template<typename Result>
struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
{
static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
}
};
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
/// \todo Fix the fact that this has to be in a shared_ptr for now
template<typename Result>
struct Cast_Helper_Inner<std::unique_ptr<Result> &>
{
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
}
};
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
template<typename Result>
struct Cast_Helper_Inner<std::shared_ptr<Result> >
{
typedef std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob.get().cast<std::shared_ptr<Result> >();
}
@@ -149,9 +182,7 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
{
typedef std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const())
{
@@ -177,10 +208,7 @@ namespace chaiscript
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 *)
static auto 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);
@@ -204,9 +232,7 @@ namespace chaiscript
template<>
struct Cast_Helper_Inner<Boxed_Value>
{
typedef Boxed_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob;
}
@@ -216,9 +242,7 @@ namespace chaiscript
template<>
struct Cast_Helper_Inner<Boxed_Value &>
{
typedef std::reference_wrapper<Boxed_Value> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return std::ref(const_cast<Boxed_Value &>(ob));
}
@@ -272,11 +296,9 @@ namespace chaiscript
template<typename T>
struct Cast_Helper
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static decltype(auto) 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

@@ -28,9 +28,9 @@ namespace chaiscript
{
struct arithmetic_error : std::runtime_error
{
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
arithmetic_error(const arithmetic_error &) = default;
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
~arithmetic_error() noexcept override = default;
};
}
}
@@ -91,7 +91,7 @@ namespace chaiscript
{
}
static CHAISCRIPT_CONSTEXPR Common_Types get_common_type(size_t t_size, bool t_signed)
static constexpr Common_Types get_common_type(size_t t_size, bool t_signed)
{
return (t_size == 1 && t_signed)?(Common_Types::t_int8)
:(t_size == 1)?(Common_Types::t_uint8)
@@ -162,17 +162,17 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::equals:
case Operators::Opers::equals:
return const_var(t == u);
case Operators::less_than:
case Operators::Opers::less_than:
return const_var(t < u);
case Operators::greater_than:
case Operators::Opers::greater_than:
return const_var(t > u);
case Operators::less_than_equal:
case Operators::Opers::less_than_equal:
return const_var(t <= u);
case Operators::greater_than_equal:
case Operators::Opers::greater_than_equal:
return const_var(t >= u);
case Operators::not_equal:
case Operators::Opers::not_equal:
return const_var(t != u);
default:
throw chaiscript::detail::exception::bad_any_cast();
@@ -184,10 +184,10 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::pre_increment:
case Operators::Opers::pre_increment:
++t;
break;
case Operators::pre_decrement:
case Operators::Opers::pre_decrement:
--t;
break;
default:
@@ -202,20 +202,20 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::assign:
case Operators::Opers::assign:
t = u;
break;
case Operators::assign_product:
case Operators::Opers::assign_product:
t *= u;
break;
case Operators::assign_sum:
case Operators::Opers::assign_sum:
t += u;
break;
case Operators::assign_quotient:
case Operators::Opers::assign_quotient:
check_divide_by_zero(u);
t /= u;
break;
case Operators::assign_difference:
case Operators::Opers::assign_difference:
t -= u;
break;
default:
@@ -230,23 +230,23 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::assign_bitwise_and:
case Operators::Opers::assign_bitwise_and:
t &= u;
break;
case Operators::assign_bitwise_or:
case Operators::Opers::assign_bitwise_or:
t |= u;
break;
case Operators::assign_shift_left:
case Operators::Opers::assign_shift_left:
t <<= u;
break;
case Operators::assign_shift_right:
case Operators::Opers::assign_shift_right:
t >>= u;
break;
case Operators::assign_remainder:
case Operators::Opers::assign_remainder:
check_divide_by_zero(u);
t %= u;
break;
case Operators::assign_bitwise_xor:
case Operators::Opers::assign_bitwise_xor:
t ^= u;
break;
default:
@@ -260,7 +260,7 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::bitwise_complement:
case Operators::Opers::bitwise_complement:
return const_var(~t);
default:
throw chaiscript::detail::exception::bad_any_cast();
@@ -272,18 +272,18 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::shift_left:
case Operators::Opers::shift_left:
return const_var(t << u);
case Operators::shift_right:
case Operators::Opers::shift_right:
return const_var(t >> u);
case Operators::remainder:
case Operators::Opers::remainder:
check_divide_by_zero(u);
return const_var(t % u);
case Operators::bitwise_and:
case Operators::Opers::bitwise_and:
return const_var(t & u);
case Operators::bitwise_or:
case Operators::Opers::bitwise_or:
return const_var(t | u);
case Operators::bitwise_xor:
case Operators::Opers::bitwise_xor:
return const_var(t ^ u);
default:
throw chaiscript::detail::exception::bad_any_cast();
@@ -295,9 +295,9 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::unary_minus:
case Operators::Opers::unary_minus:
return const_var(-t);
case Operators::unary_plus:
case Operators::Opers::unary_plus:
return const_var(+t);
default:
throw chaiscript::detail::exception::bad_any_cast();
@@ -309,14 +309,14 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::sum:
case Operators::Opers::sum:
return const_var(t + u);
case Operators::quotient:
case Operators::Opers::quotient:
check_divide_by_zero(u);
return const_var(t / u);
case Operators::product:
case Operators::Opers::product:
return const_var(t * u);
case Operators::difference:
case Operators::Opers::difference:
return const_var(t - u);
default:
throw chaiscript::detail::exception::bad_any_cast();
@@ -328,16 +328,16 @@ namespace chaiscript
-> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
{
typedef typename std::common_type<LHS, RHS>::type common_type;
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
{
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
} else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_int_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
return const_binary_int_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@@ -349,12 +349,12 @@ namespace chaiscript
-> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
{
typedef typename std::common_type<LHS, RHS>::type common_type;
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
{
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@@ -366,11 +366,11 @@ namespace chaiscript
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
-> typename std::enable_if<!std::is_floating_point<LHS>::value, Boxed_Value>::type
{
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
return const_unary_int_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@@ -381,9 +381,9 @@ namespace chaiscript
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
-> typename std::enable_if<std::is_floating_point<LHS>::value, Boxed_Value>::type
{
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@@ -502,18 +502,15 @@ namespace chaiscript
{
}
Boxed_Number(Boxed_Value v)
explicit Boxed_Number(Boxed_Value v)
: bv(std::move(v))
{
validate_boxed_number(bv);
}
Boxed_Number(const Boxed_Number &) = default;
#if !defined(_MSC_VER) || _MSC_VER != 1800
Boxed_Number(Boxed_Number &&) = default;
Boxed_Number& operator=(Boxed_Number &&) = default;
#endif
template<typename T> explicit Boxed_Number(T t)
: bv(Boxed_Value(t))
@@ -648,71 +645,6 @@ namespace chaiscript
throw chaiscript::detail::exception::bad_any_cast();
}
bool operator==(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
}
bool operator<(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
}
bool operator>(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
}
bool operator>=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
}
bool operator<=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
}
bool operator!=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
}
Boxed_Number operator--()
{
return oper(Operators::pre_decrement, this->bv);
}
Boxed_Number operator++()
{
return oper(Operators::pre_increment, this->bv);
}
Boxed_Number operator+(const Boxed_Number &t_rhs) const
{
return oper(Operators::sum, this->bv, t_rhs.bv);
}
Boxed_Number operator+() const
{
return oper(Operators::unary_plus, this->bv);
}
Boxed_Number operator-() const
{
return oper(Operators::unary_minus, this->bv);
}
Boxed_Number operator-(const Boxed_Number &t_rhs) const
{
return oper(Operators::difference, this->bv, t_rhs.bv);
}
Boxed_Number operator&=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
}
static void validate_boxed_number(const Boxed_Value &v)
{
const Type_Info &inp_ = v.get_type_info();
@@ -727,266 +659,165 @@ namespace chaiscript
}
}
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Value &v)
{
validate_boxed_number(v);
bv = v;
return *this;
}
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Number &t_rhs) const
{
return oper(Operators::assign, this->bv, t_rhs.bv);
}
Boxed_Number operator|=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator^=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator%=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
}
Boxed_Number operator&(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator~() const
{
return oper(Operators::bitwise_complement, this->bv);
}
Boxed_Number operator^(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator|(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator*=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, this->bv, t_rhs.bv);
}
Boxed_Number operator/=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator+=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
}
Boxed_Number operator-=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
}
Boxed_Number operator/(const Boxed_Number &t_rhs) const
{
return oper(Operators::quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator*(const Boxed_Number &t_rhs) const
{
return oper(Operators::product, this->bv, t_rhs.bv);
}
Boxed_Number operator%(const Boxed_Number &t_rhs) const
{
return oper(Operators::remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_right, this->bv, t_rhs.bv);
}
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
}
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
{
return oper(Operators::pre_decrement, t_lhs.bv);
return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv));
}
static Boxed_Number pre_increment(Boxed_Number t_lhs)
{
return oper(Operators::pre_increment, t_lhs.bv);
return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv));
}
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_plus, t_lhs.bv);
return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv));
}
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_minus, t_lhs.bv);
return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv));
}
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
{
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
}
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
}
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
}
@@ -1012,9 +843,7 @@ namespace chaiscript
template<>
struct Cast_Helper<Boxed_Number>
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return Boxed_Number(ob);
}

View File

@@ -54,7 +54,7 @@ namespace chaiscript
if (rhs.m_attrs)
{
m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*rhs.m_attrs));
m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*rhs.m_attrs);
}
return *this;
@@ -62,10 +62,8 @@ namespace chaiscript
Data(const Data &) = delete;
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
Data(Data &&) = default;
Data &operator=(Data &&rhs) = default;
#endif
Type_Info m_type_info;
@@ -79,7 +77,7 @@ namespace chaiscript
struct Object_Data
{
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
static auto get(Boxed_Value::Void_Type, bool t_return_value)
{
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
@@ -91,13 +89,13 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
static auto get(const std::shared_ptr<T> *obj, bool t_return_value)
{
return get(*obj, t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
static auto get(const std::shared_ptr<T> &obj, bool t_return_value)
{
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
@@ -109,7 +107,7 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
static auto get(std::shared_ptr<T> &&obj, bool t_return_value)
{
auto ptr = obj.get();
return std::make_shared<Data>(
@@ -121,21 +119,23 @@ namespace chaiscript
);
}
template<typename T>
static std::shared_ptr<Data> get(T *t, bool t_return_value)
static auto get(T *t, bool t_return_value)
{
return get(std::ref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
static auto get(const T *t, bool t_return_value)
{
return get(std::cref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
static auto get(std::reference_wrapper<T> obj, bool t_return_value)
{
auto p = &obj.get();
return std::make_shared<Data>(
@@ -148,7 +148,20 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(T t, bool t_return_value)
static auto get(std::unique_ptr<T> &&obj, bool t_return_value)
{
auto ptr = obj.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::make_shared<std::unique_ptr<T>>(std::move(obj))),
false,
ptr,
t_return_value
);
}
template<typename T>
static auto get(T t, bool t_return_value)
{
auto p = std::make_shared<T>(std::move(t));
auto ptr = p.get();
@@ -184,16 +197,10 @@ namespace chaiscript
}
/// Unknown-type constructor
Boxed_Value()
: m_data(Object_Data::get())
{
}
Boxed_Value() = default;
#if !defined(_MSC_VER) || _MSC_VER != 1800
Boxed_Value(Boxed_Value&&) = default;
Boxed_Value& operator=(Boxed_Value&&) = default;
#endif
Boxed_Value(const Boxed_Value&) = default;
Boxed_Value& operator=(const Boxed_Value&) = default;
@@ -210,107 +217,98 @@ namespace chaiscript
return *this;
}
const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
const Type_Info &get_type_info() const noexcept
{
return m_data->m_type_info;
}
/// return true if the object is uninitialized
bool is_undef() const CHAISCRIPT_NOEXCEPT
bool is_undef() const noexcept
{
return m_data->m_type_info.is_undef();
}
bool is_const() const CHAISCRIPT_NOEXCEPT
bool is_const() const noexcept
{
return m_data->m_type_info.is_const();
}
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
bool is_type(const Type_Info &ti) const noexcept
{
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
auto pointer_sentinel(std::shared_ptr<T> &ptr) const
{
return Sentinel<T>(ptr, *(m_data.get()));
struct Sentinel {
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
: m_ptr(t_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) = default;
Sentinel(Sentinel &&s) = default;
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;
};
return Sentinel(ptr, *(m_data.get()));
}
bool is_null() const CHAISCRIPT_NOEXCEPT
bool is_null() const noexcept
{
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
}
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
const chaiscript::detail::Any & get() const noexcept
{
return m_data->m_obj;
}
bool is_ref() const CHAISCRIPT_NOEXCEPT
bool is_ref() const noexcept
{
return m_data->m_is_ref;
}
bool is_return_value() const CHAISCRIPT_NOEXCEPT
bool is_return_value() const noexcept
{
return m_data->m_return_value;
}
void reset_return_value() const CHAISCRIPT_NOEXCEPT
void reset_return_value() const noexcept
{
m_data->m_return_value = false;
}
bool is_pointer() const CHAISCRIPT_NOEXCEPT
bool is_pointer() const noexcept
{
return !is_ref();
}
void *get_ptr() const CHAISCRIPT_NOEXCEPT
void *get_ptr() const noexcept
{
return m_data->m_data_ptr;
}
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
const void *get_const_ptr() const noexcept
{
return m_data->m_const_data_ptr;
}
@@ -319,7 +317,7 @@ namespace chaiscript
{
if (!m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>());
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>();
}
auto &attr = (*m_data->m_attrs)[t_name];
@@ -336,7 +334,7 @@ namespace chaiscript
{
if (t_obj.m_data->m_attrs)
{
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*t_obj.m_data->m_attrs));
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*t_obj.m_data->m_attrs);
}
return *this;
}
@@ -350,7 +348,7 @@ namespace chaiscript
/// \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) noexcept
{
return l.get_type_info() == r.get_type_info();
}
@@ -359,11 +357,11 @@ namespace chaiscript
// necessary to avoid hitting the templated && constructor of Boxed_Value
struct Internal_Construction{};
Boxed_Value(const std::shared_ptr<Data> &t_data, Internal_Construction)
: m_data(t_data) {
Boxed_Value(std::shared_ptr<Data> t_data, Internal_Construction)
: m_data(std::move(t_data)) {
}
std::shared_ptr<Data> m_data;
std::shared_ptr<Data> m_data = Object_Data::get();
};
/// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
@@ -460,10 +458,14 @@ namespace chaiscript
return detail::const_var_impl(t);
}
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
inline Boxed_Value void_var() {
static const auto v = Boxed_Value(Boxed_Value::Void_Type());
return v;
}
inline Boxed_Value const_var(bool b) {
static auto t = detail::const_var_impl(true);
static auto f = detail::const_var_impl(false);
static const auto t = detail::const_var_impl(true);
static const auto f = detail::const_var_impl(false);
if (b) {
return t;
@@ -471,7 +473,6 @@ namespace chaiscript
return f;
}
}
#endif
}

View File

@@ -25,7 +25,7 @@ namespace chaiscript {
template<typename Ret, typename Class, typename ... Param>
struct Const_Caller
{
Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(const Class &o, Inner&& ... inner) const {
@@ -38,7 +38,7 @@ namespace chaiscript {
template<typename Ret, typename ... Param>
struct Fun_Caller
{
Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(Inner&& ... inner) const {
@@ -51,7 +51,7 @@ namespace chaiscript {
template<typename Ret, typename Class, typename ... Param>
struct Caller
{
Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(Class &o, Inner&& ... inner) const {

View File

@@ -8,7 +8,6 @@
#define CHAISCRIPT_DISPATCHKIT_HPP_
#include <algorithm>
#include <deque>
#include <iostream>
#include <list>
#include <map>
@@ -31,12 +30,16 @@
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "type_info.hpp"
#include "short_alloc.hpp"
namespace chaiscript {
class Boxed_Number;
} // namespace chaiscript
namespace chaiscript {
namespace parser {
class ChaiScript_Parser_Base;
}
namespace dispatch {
class Dynamic_Proxy_Function;
class Proxy_Function_Base;
@@ -45,6 +48,7 @@ struct Placeholder_Object;
} // namespace chaiscript
/// \namespace chaiscript::dispatch
/// \brief Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use to the end user.
@@ -56,14 +60,14 @@ namespace chaiscript
class reserved_word_error : public std::runtime_error
{
public:
reserved_word_error(const std::string &t_word) CHAISCRIPT_NOEXCEPT
explicit reserved_word_error(const std::string &t_word) noexcept
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
{
}
reserved_word_error(const reserved_word_error &) = default;
virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {}
~reserved_word_error() noexcept override = default;
std::string word() const
{
@@ -78,14 +82,14 @@ namespace chaiscript
class illegal_name_error : public std::runtime_error
{
public:
illegal_name_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
explicit illegal_name_error(const std::string &t_name) noexcept
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
{
}
illegal_name_error(const illegal_name_error &) = default;
virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {}
~illegal_name_error() noexcept override = default;
std::string name() const
{
@@ -101,14 +105,14 @@ namespace chaiscript
class name_conflict_error : public std::runtime_error
{
public:
name_conflict_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
explicit name_conflict_error(const std::string &t_name) noexcept
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
{
}
name_conflict_error(const name_conflict_error &) = default;
virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {}
~name_conflict_error() noexcept override = default;
std::string name() const
{
@@ -125,13 +129,13 @@ namespace chaiscript
class global_non_const : public std::runtime_error
{
public:
global_non_const() CHAISCRIPT_NOEXCEPT
global_non_const() noexcept
: std::runtime_error("a global object must be const")
{
}
global_non_const(const global_non_const &) = default;
virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {}
~global_non_const() noexcept override = default;
};
}
@@ -143,7 +147,7 @@ namespace chaiscript
public:
Module &add(Type_Info ti, std::string name)
{
m_typeinfos.emplace_back(std::move(ti), std::move(name));
m_typeinfos.emplace_back(ti, std::move(name));
return *this;
}
@@ -178,12 +182,6 @@ namespace chaiscript
return *this;
}
Module &add(const std::shared_ptr<Module> &m)
{
m->apply(*this, *this);
return *m;
}
template<typename Eval, typename Engine>
void apply(Eval &t_eval, Engine &t_engine) const
{
@@ -194,30 +192,28 @@ namespace chaiscript
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
}
~Module()
{
}
bool has_function(const Proxy_Function &new_f, const std::string &name)
{
return std::any_of(m_funcs.begin(), m_funcs.end(), [&](const std::pair<Proxy_Function, std::string> &existing_f) {
return existing_f.second == name && *(existing_f.first) == *(new_f);
});
return std::any_of(m_funcs.begin(), m_funcs.end(),
[&](const std::pair<Proxy_Function, std::string> &existing_f) {
return existing_f.second == name && *(existing_f.first) == *(new_f);
}
);
}
private:
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
std::vector<std::pair<Boxed_Value, std::string> > m_globals;
std::vector<std::pair<Type_Info, std::string>> m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string>> m_funcs;
std::vector<std::pair<Boxed_Value, std::string>> m_globals;
std::vector<std::string> m_evals;
std::vector<Type_Conversion> m_conversions;
template<typename T, typename InItr>
static void apply(InItr begin, const InItr end, T &t)
{
for_each(begin, end, [&t](typename std::iterator_traits<InItr>::reference obj)
{
for_each(begin, end,
[&t](const auto &obj) {
try {
t.add(obj.first, obj.second);
} catch (const chaiscript::exception::name_conflict_error &) {
@@ -267,16 +263,16 @@ namespace chaiscript
/// A Proxy_Function implementation that is able to take
/// a vector of Proxy_Functions and perform a dispatch on them. It is
/// used specifically in the case of dealing with Function object variables
class Dispatch_Function : public dispatch::Proxy_Function_Base
class Dispatch_Function final : public dispatch::Proxy_Function_Base
{
public:
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
explicit Dispatch_Function(std::vector<Proxy_Function> t_funcs)
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
m_funcs(std::move(t_funcs))
{
}
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
bool operator==(const dispatch::Proxy_Function_Base &rhs) const override
{
try {
const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
@@ -286,9 +282,7 @@ namespace chaiscript
}
}
virtual ~Dispatch_Function() {}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
std::vector<Const_Proxy_Function> get_contained_functions() const override
{
return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
}
@@ -314,19 +308,14 @@ namespace chaiscript
return arity;
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
return std::any_of(std::begin(m_funcs), std::end(m_funcs),
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "Multiple method dispatch function wrapper.";
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return dispatch::dispatch(m_funcs, params, t_conversions);
}
@@ -367,7 +356,7 @@ namespace chaiscript
++begin;
}
assert(type_infos.size() > 0 && " type_info vector size is < 0, this is only possible if something else is broken");
assert(!type_infos.empty() && " type_info vector size is < 0, this is only possible if something else is broken");
if (size_mismatch)
{
@@ -387,22 +376,56 @@ namespace chaiscript
{
struct Stack_Holder
{
typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
typedef std::vector<Scope> StackData;
//template <class T, std::size_t BufSize = sizeof(T)*20000>
// using SmallVector = std::vector<T, short_alloc<T, BufSize>>;
template <class T>
using SmallVector = std::vector<T>;
typedef SmallVector<std::pair<std::string, Boxed_Value>> Scope;
typedef SmallVector<Scope> StackData;
typedef SmallVector<StackData> Stacks;
typedef SmallVector<Boxed_Value> Call_Param_List;
typedef SmallVector<Call_Param_List> Call_Params;
Stack_Holder()
: call_depth(0)
{
stacks.reserve(2);
stacks.emplace_back(1);
call_params.emplace_back();
call_params.back().reserve(2);
push_stack();
push_call_params();
}
std::vector<StackData> stacks;
void push_stack_data()
{
stacks.back().emplace_back();
// stacks.back().emplace_back(Scope(scope_allocator));
}
std::vector<std::vector<Boxed_Value>> call_params;
int call_depth;
void push_stack()
{
stacks.emplace_back(1);
// stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator));
}
void push_call_params()
{
call_params.emplace_back();
// call_params.emplace_back(Call_Param_List(call_param_list_allocator));
}
//Scope::allocator_type::arena_type scope_allocator;
//StackData::allocator_type::arena_type stack_data_allocator;
//Stacks::allocator_type::arena_type stacks_allocator;
//Call_Param_List::allocator_type::arena_type call_param_list_allocator;
//Call_Params::allocator_type::arena_type call_params_allocator;
// Stacks stacks = Stacks(stacks_allocator);
// Call_Params call_params = Call_Params(call_params_allocator);
Stacks stacks;
Call_Params call_params;
int call_depth = 0;
};
/// Main class for the dispatchkit. Handles management
@@ -413,7 +436,7 @@ namespace chaiscript
public:
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
typedef std::vector<Scope> StackData;
typedef Stack_Holder::StackData StackData;
struct State
{
@@ -422,29 +445,20 @@ namespace chaiscript
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
State &operator=(const State &) = default;
State() = default;
State(const State &) = default;
};
Dispatch_Engine()
explicit Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
: m_stack_holder(this),
m_method_missing_loc(0)
{
}
~Dispatch_Engine()
m_parser(parser)
{
}
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
decltype(auto) boxed_cast(const Boxed_Value &bv) const
{
Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
return chaiscript::boxed_cast<Type>(bv, &state);
return(chaiscript::boxed_cast<Type>(bv, &state));
}
/// Add a new conversion for upcasting to a base class
@@ -456,7 +470,6 @@ namespace chaiscript
/// Add a new named Proxy_Function to the system
void add(const Proxy_Function &f, const std::string &name)
{
validate_object_name(name);
add_function(f, name);
}
@@ -464,7 +477,6 @@ namespace chaiscript
/// is not available in the current scope it is created
void add(Boxed_Value obj, const std::string &name)
{
validate_object_name(name);
auto &stack = get_stack_data();
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
@@ -484,6 +496,26 @@ namespace chaiscript
add_object(name, std::move(obj));
}
/// Adds a named object to the current scope
/// \warning This version does not check the validity of the name
/// it is meant for internal use only
Boxed_Value &add_get_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);
}
stack_elem.emplace_back(t_name, std::move(obj));
return stack_elem.back().second;
}
/// 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
@@ -499,7 +531,7 @@ namespace chaiscript
throw chaiscript::exception::name_conflict_error(t_name);
}
get_stack_data(t_holder).back().emplace_back(t_name, std::move(obj));
stack_elem.emplace_back(t_name, std::move(obj));
}
@@ -514,7 +546,6 @@ namespace chaiscript
/// Adds a new global shared object, between all the threads
void add_global_const(const Boxed_Value &obj, const std::string &name)
{
validate_object_name(name);
if (!obj.is_const())
{
throw chaiscript::exception::global_non_const();
@@ -533,8 +564,6 @@ namespace chaiscript
/// Adds a new global (non-const) shared object, between all the threads
Boxed_Value add_global_no_throw(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);
@@ -551,8 +580,6 @@ namespace chaiscript
/// Adds a new global (non-const) shared object, between all the threads
void add_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);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
@@ -566,8 +593,6 @@ 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);
@@ -594,8 +619,8 @@ namespace chaiscript
/// Adds a new scope to the stack
static void new_scope(Stack_Holder &t_holder)
{
get_stack_data(t_holder).emplace_back();
t_holder.call_params.emplace_back();
t_holder.push_stack_data();
t_holder.push_call_params();
}
/// Pops the current scope from the stack
@@ -603,12 +628,10 @@ namespace chaiscript
{
t_holder.call_params.pop_back();
StackData &stack = get_stack_data(t_holder);
if (stack.size() > 1)
{
stack.pop_back();
} else {
throw std::range_error("Unable to pop global stack");
}
assert(!stack.empty());
stack.pop_back();
}
@@ -616,7 +639,7 @@ namespace chaiscript
static void new_stack(Stack_Holder &t_holder)
{
// add a new Stack with 1 element
t_holder.stacks.emplace_back(1);
t_holder.push_stack();
}
static void pop_stack(Stack_Holder &t_holder)
@@ -627,7 +650,7 @@ namespace chaiscript
/// Searches the current stack for an object of the given name
/// includes a special overload for the _ place holder object to
/// ensure that it is always in scope.
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc) const
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
{
enum class Loc : uint_fast32_t {
located = 0x80000000,
@@ -640,7 +663,7 @@ namespace chaiscript
if (loc == 0)
{
auto &stack = get_stack_data();
auto &stack = get_stack_data(t_holder);
// Is it in the stack?
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
@@ -658,8 +681,8 @@ namespace chaiscript
}
t_loc = static_cast<uint_fast32_t>(Loc::located);
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
auto &stack = get_stack_data();
} else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) {
auto &stack = get_stack_data(t_holder);
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;
}
@@ -675,9 +698,9 @@ namespace chaiscript
// no? is it a function object?
auto obj = get_function_object_int(name, loc);
if (obj.first != loc) t_loc = uint_fast32_t(obj.first);
return obj.second;
if (obj.first != loc) { t_loc = uint_fast32_t(obj.first); }
return obj.second;
}
@@ -740,7 +763,10 @@ namespace chaiscript
{
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);
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);
}
@@ -828,7 +854,7 @@ namespace chaiscript
{
auto &stack = get_stack_data();
auto &scope = stack.front();
scope = std::vector<std::pair<std::string, Boxed_Value>>(t_locals.begin(), t_locals.end());
scope.assign(t_locals.begin(), t_locals.end());
}
@@ -899,12 +925,6 @@ namespace chaiscript
return rets;
}
void add_reserved_word(const std::string &name)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_state.m_reserved_words.insert(name);
}
const Type_Conversions &conversions() const
{
@@ -918,15 +938,12 @@ namespace chaiscript
return false;
}
for (const auto &fun : t_funs) {
if (fun->is_attribute_function()) {
if (fun->compare_first_type(t_params[0], t_conversions)) {
return true;
return std::any_of(std::begin(t_funs), std::end(t_funs),
[&](const auto &fun) {
return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions);
}
}
}
);
return false;
}
#ifdef CHAISCRIPT_MSVC
@@ -940,7 +957,7 @@ namespace chaiscript
{
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);
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first); }
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_State &l_conversions)->Boxed_Value
@@ -963,14 +980,21 @@ namespace chaiscript
This_Foist fi(*this, l_params.front());
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);
auto func = boxed_cast<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>{boxed_cast<Const_Proxy_Function>(bv)});
} catch (const chaiscript::exception::bad_boxed_cast &) {
} catch (const chaiscript::exception::arity_error &) {
} catch (const chaiscript::exception::guard_error &) {
// unable to convert bv into a Proxy_Function_Base
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({l_params.begin() + l_num_params, l_params.end()}, std::vector<Const_Proxy_Function>{func});
} else {
return bv;
}
@@ -1053,7 +1077,8 @@ namespace chaiscript
{
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);
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first);
}
return dispatch::dispatch(*funs.second, params, t_conversions);
}
@@ -1074,27 +1099,31 @@ namespace chaiscript
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
{
std::vector<Type_Info> params = f.second->get_param_types();
std::string annotation = f.second->annotation();
if (annotation.size() > 0) {
std::cout << annotation;
std::vector<std::pair<std::string, Type_Info>> typed_params;
auto func(std::dynamic_pointer_cast<const dispatch::Dynamic_Function_Interface>(f.second));
if (func) {
typed_params = func->get_dynamic_param_types().types();
}
dump_type(params.front());
std::cout << " " << f.first << "(";
for (std::vector<Type_Info>::const_iterator itr = params.begin() + 1;
itr != params.end();
)
for (size_t i = 1; i < params.size(); ++i)
{
dump_type(*itr);
++itr;
if (!typed_params.empty() && !typed_params[i-1].first.empty()) {
std::cout << typed_params[i-1].first;
} else {
dump_type(params[i]);
}
if (itr != params.end())
{
if (i != params.size() - 1) {
std::cout << ", ";
}
}
std::cout << ") \n";
}
@@ -1110,7 +1139,7 @@ namespace chaiscript
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves());
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
return const_var(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
}
/// Dump all system info to stdout
@@ -1181,7 +1210,7 @@ namespace chaiscript
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(), t_params);
}
static void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
@@ -1199,7 +1228,7 @@ namespace chaiscript
void save_function_params(std::initializer_list<Boxed_Value> t_params)
{
save_function_params(*m_stack_holder, std::move(t_params));
save_function_params(*m_stack_holder, t_params);
}
void save_function_params(std::vector<Boxed_Value> &&t_params)
@@ -1269,6 +1298,11 @@ namespace chaiscript
return m_stack_holder->stacks.back();
}
parser::ChaiScript_Parser_Base &get_parser()
{
return m_parser.get();
}
private:
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
@@ -1301,115 +1335,160 @@ namespace chaiscript
return m_state.m_functions;
}
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
static std::vector<Type_Info> param_types(const Proxy_Function &t_f)
{
assert(t_f);
return t_f->get_param_types();
}
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
static std::vector<std::pair<std::string, Type_Info>> param_types(const std::shared_ptr<const dispatch::Dynamic_Function_Interface> &t_f)
{
assert(t_f);
const auto types = t_f->get_dynamic_param_types().types();
std::vector<std::pair<std::string, Type_Info>> ret(1);
ret.insert(ret.end(), types.begin(), types.end());
return ret;
}
if (dynamic_lhs && dynamic_rhs)
static Type_Info type_info(const std::pair<std::string, Type_Info> &t_ti)
{
return t_ti.second;
}
static Type_Info type_info(const Type_Info &t_ti)
{
return t_ti;
}
static std::string dynamic_type_name(const std::pair<std::string, Type_Info> &t_ti)
{
return t_ti.first.empty()?t_ti.second.name():t_ti.first;
}
static std::string dynamic_type_name(const Type_Info &ti)
{
return ti.name();
}
template<typename LHS, typename RHS>
static bool params_less_than(const LHS &t_lhs, const RHS &t_rhs)
{
if (dynamic_lhs->get_guard())
assert(t_lhs);
assert(t_rhs);
const auto lhsparamtypes = param_types(t_lhs);
const auto rhsparamtypes = param_types(t_rhs);
const auto lhssize = lhsparamtypes.size();
const auto rhssize = rhsparamtypes.size();
constexpr auto boxed_type = user_type<Boxed_Value>();
constexpr auto boxed_pod_type = user_type<Boxed_Number>();
constexpr auto dynamic_type = user_type<dispatch::Dynamic_Object>();
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
{
return dynamic_rhs->get_guard() ? false : true;
} else {
return false;
}
}
const Type_Info lt = type_info(lhsparamtypes[i]);
const Type_Info rt = type_info(rhsparamtypes[i]);
const std::string ln = dynamic_type_name(lhsparamtypes[i]);
const std::string rn = dynamic_type_name(rhsparamtypes[i]);
if (dynamic_lhs && !dynamic_rhs)
{
return false;
}
if ( (lt.bare_equal(dynamic_type) || lt.is_undef())
&& (rt.bare_equal(dynamic_type) || rt.is_undef()))
{
if (!dynamic_lhs && dynamic_rhs)
{
return true;
}
if (!ln.empty() && rn.empty()) {
return true;
} else if (ln.empty() && !rn.empty()) {
return false;
} else if (!ln.empty() && !rn.empty()) {
if (ln < rn) {
return true;
} else if (rn < ln) {
return false;
}
const auto &lhsparamtypes = lhs->get_param_types();
const auto &rhsparamtypes = rhs->get_param_types();
// the remaining cases are handled by the is_const rules below
}
}
const auto lhssize = lhsparamtypes.size();
const auto rhssize = rhsparamtypes.size();
if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
{
continue; // The first two types are essentially the same, next iteration
}
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
static auto boxed_type = user_type<Boxed_Value>();
static auto boxed_pod_type = user_type<Boxed_Number>();
#else
auto boxed_type = user_type<Boxed_Value>();
auto boxed_pod_type = user_type<Boxed_Number>();
#endif
// const is after non-const for the same type
if (lt.bare_equal(rt) && lt.is_const() && !rt.is_const())
{
return false;
}
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
{
const Type_Info &lt = lhsparamtypes[i];
const Type_Info &rt = rhsparamtypes[i];
if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
{
continue; // The first two types are essentially the same, next iteration
}
// const is after non-const for the same type
if (lt.bare_equal(rt) && lt.is_const() && !rt.is_const())
{
return false;
}
if (lt.bare_equal(rt) && !lt.is_const())
{
return true;
}
// boxed_values are sorted last
if (lt.bare_equal(boxed_type))
{
return false;
}
if (rt.bare_equal(boxed_type))
{
if (lt.bare_equal(boxed_pod_type))
if (lt.bare_equal(rt) && !lt.is_const())
{
return true;
}
return true;
// boxed_values are sorted last
if (lt.bare_equal(boxed_type))
{
return false;
}
if (rt.bare_equal(boxed_type))
{
return true;
}
if (lt.bare_equal(boxed_pod_type))
{
return false;
}
if (rt.bare_equal(boxed_pod_type))
{
return true;
}
// otherwise, we want to sort by typeid
return lt < rt;
}
if (lt.bare_equal(boxed_pod_type))
{
return false;
// if everything else checks out, sort on guard
//
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_lhs));
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_rhs));
if (dynamic_lhs && dynamic_rhs) {
if (dynamic_lhs->get_guard() && !dynamic_rhs->get_guard()) {
return true;
} else if (dynamic_rhs->get_guard()) {
return false;
}
}
if (rt.bare_equal(boxed_pod_type))
{
return true;
}
// otherwise, we want to sort by typeid
return lt < rt;
return false;
}
return false;
}
/// Throw a reserved_word exception if the name is not allowed
void validate_object_name(const std::string &name) const
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
{
if (name.find("::") != std::string::npos) {
throw chaiscript::exception::illegal_name_error(name);
}
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Function_Interface>(lhs));
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Function_Interface>(rhs));
if (dynamic_lhs && dynamic_rhs)
{
throw chaiscript::exception::reserved_word_error(name);
return params_less_than(dynamic_lhs, dynamic_rhs);
} else if (dynamic_lhs) {
return params_less_than(dynamic_lhs, rhs);
} else if (dynamic_rhs) {
return params_less_than(lhs, dynamic_rhs);
} else {
return params_less_than(lhs, rhs);
}
}
template<typename Container, typename Key, typename Value>
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
{
@@ -1446,7 +1525,7 @@ namespace chaiscript
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);
return std::next(t_c.begin(), static_cast<typename std::iterator_traits<typename Container::const_iterator>::difference_type>(t_hint));
} else {
return find_keyed_value(t_c, t_key);
}
@@ -1503,8 +1582,9 @@ namespace chaiscript
Type_Conversions m_conversions;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
std::reference_wrapper<parser::ChaiScript_Parser_Base> m_parser;
mutable std::atomic_uint_fast32_t m_method_missing_loc;
mutable std::atomic_uint_fast32_t m_method_missing_loc = {0};
State m_state;
};
@@ -1512,7 +1592,7 @@ namespace chaiscript
class Dispatch_State
{
public:
Dispatch_State(Dispatch_Engine &t_engine)
explicit Dispatch_State(Dispatch_Engine &t_engine)
: m_engine(t_engine),
m_stack_holder(t_engine.get_stack_holder()),
m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves())
@@ -1539,8 +1619,16 @@ namespace chaiscript
return m_conversions.saves();
}
Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj) const {
return m_engine.get().add_get_object(t_name, std::move(obj), m_stack_holder.get());
}
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());
return m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
}
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const {
return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get());
}
private:
@@ -1553,3 +1641,4 @@ namespace chaiscript
#endif

View File

@@ -25,7 +25,7 @@ namespace chaiscript
namespace dispatch
{
struct option_explicit_set : std::runtime_error {
option_explicit_set(const std::string &t_param_name)
explicit option_explicit_set(const std::string &t_param_name)
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
{
@@ -33,20 +33,18 @@ namespace chaiscript
option_explicit_set(const option_explicit_set &) = default;
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
~option_explicit_set() noexcept override = default;
};
class Dynamic_Object
{
public:
Dynamic_Object(std::string t_type_name)
explicit Dynamic_Object(std::string t_type_name)
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
{
}
Dynamic_Object() : m_type_name(""), m_option_explicit(false)
{
}
Dynamic_Object() = default;
bool is_explicit() const
{
@@ -84,6 +82,10 @@ namespace chaiscript
}
}
bool has_attr(const std::string &t_attr_name) const {
return m_attrs.find(t_attr_name) != m_attrs.end();
}
Boxed_Value &get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
@@ -107,15 +109,14 @@ namespace chaiscript
return get_attr(t_method_name);
}
std::map<std::string, Boxed_Value> get_attrs() const
{
return m_attrs;
}
private:
std::string m_type_name;
bool m_option_explicit;
const std::string m_type_name = "";
bool m_option_explicit = false;
std::map<std::string, Boxed_Value> m_attrs;
};

View File

@@ -39,7 +39,7 @@ namespace chaiscript
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function : public Proxy_Function_Base
class Dynamic_Object_Function : public Proxy_Function_Base, public Dynamic_Function_Interface
{
public:
Dynamic_Object_Function(
@@ -67,12 +67,22 @@ namespace chaiscript
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
Param_Types get_dynamic_param_types() const override {
auto dynamic(std::dynamic_pointer_cast<dispatch::Dynamic_Function_Interface>(m_func));
if (dynamic) {
return dynamic->get_dynamic_param_types();
} else {
return Param_Types(get_param_types());
}
}
bool operator==(const Proxy_Function_Base &f) const override
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
{
@@ -82,9 +92,9 @@ namespace chaiscript
}
}
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
bool is_attribute_function() const override { return m_is_attribute; }
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
@@ -94,19 +104,13 @@ namespace chaiscript
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
std::vector<Const_Proxy_Function> get_contained_functions() const override
{
return {m_func};
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
@@ -116,7 +120,7 @@ namespace chaiscript
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
}
@@ -158,7 +162,7 @@ namespace chaiscript
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
{
if (bvs.size() > 0)
if (!bvs.empty())
{
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
} else {
@@ -170,9 +174,7 @@ namespace chaiscript
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
bool m_is_attribute;
const bool m_is_attribute;
};
@@ -182,7 +184,7 @@ namespace chaiscript
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
class Dynamic_Object_Constructor final : public Proxy_Function_Base, public Dynamic_Function_Interface
{
public:
Dynamic_Object_Constructor(
@@ -191,6 +193,7 @@ namespace chaiscript
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
m_type_name(std::move(t_type_name)), m_func(t_func)
{
assert( t_func );
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
@@ -208,29 +211,34 @@ namespace chaiscript
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
Param_Types get_dynamic_param_types() const override {
auto dynamic(std::dynamic_pointer_cast<dispatch::Dynamic_Function_Interface>(m_func));
if (dynamic) {
return dynamic->get_dynamic_param_types();
} else {
return Param_Types(get_param_types());
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool operator==(const Proxy_Function_Base &f) const override
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
std::vector<Boxed_Value> new_params{bv};
@@ -242,8 +250,8 @@ namespace chaiscript
}
private:
std::string m_type_name;
Proxy_Function m_func;
const std::string m_type_name;
const Proxy_Function m_func;
};
}

View File

@@ -23,12 +23,11 @@ namespace chaiscript
{
namespace detail
{
/// \todo make this a variadic template
struct Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
virtual ~Exception_Handler_Base() {}
virtual ~Exception_Handler_Base() = default;
protected:
template<typename T>
@@ -38,65 +37,12 @@ namespace chaiscript
}
};
template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base
template<typename ... T>
struct Exception_Handler_Impl : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl1() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
{
throw_type<T1>(bv, t_engine);
}
};
template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl2() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl3() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl4() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl5() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
throw_type<T5>(bv, t_engine);
(void)std::initializer_list<int>{(throw_type<T>(bv, t_engine), 0)...};
}
};
}
@@ -155,42 +101,10 @@ namespace chaiscript
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions
template<typename T1>
template<typename ... T>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
}
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
}
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
}
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
}
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
}
}

View File

@@ -35,8 +35,7 @@ namespace chaiscript
/// \returns A std::function object for dispatching
/// \param[in] funcs the set of functions to dispatch on.
template<typename FunctionType>
std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
std::function<FunctionType> 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) {
@@ -63,8 +62,7 @@ namespace chaiscript
/// \returns A std::function object for dispatching
/// \param[in] func A function to execute.
template<typename FunctionType>
std::function<FunctionType>
functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
}
@@ -72,8 +70,7 @@ namespace chaiscript
/// Helper for automatically unboxing a Boxed_Value that contains a function object
/// and creating a typesafe C++ function caller from it.
template<typename FunctionType>
std::function<FunctionType>
functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
}
@@ -84,9 +81,7 @@ namespace chaiscript
template<typename Signature>
struct Cast_Helper<const std::function<Signature> &>
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@@ -101,9 +96,7 @@ namespace chaiscript
template<typename Signature>
struct Cast_Helper<std::function<Signature> >
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@@ -118,9 +111,7 @@ namespace chaiscript
template<typename Signature>
struct Cast_Helper<const std::function<Signature> >
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{

View File

@@ -33,7 +33,7 @@ namespace chaiscript
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
if (t_conversions) {
if (t_conversions != nullptr) {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
} else {
Type_Conversions conv;
@@ -52,7 +52,7 @@ namespace chaiscript
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
if (t_conversions) {
if (t_conversions != nullptr) {
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
} else {
Type_Conversions conv;
@@ -72,7 +72,7 @@ namespace chaiscript
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
if (t_conversions) {
if (t_conversions != nullptr) {
dispatch::dispatch(t_funcs, params, *t_conversions);
} else {
Type_Conversions conv;

View File

@@ -59,13 +59,8 @@ namespace chaiscript
};
template<typename Ret>
struct Handle_Return<std::function<Ret>>
struct Handle_Return<std::function<Ret>> : Handle_Return<const std::function<Ret> &>
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
);
}
};
template<typename Ret>
@@ -79,23 +74,13 @@ namespace chaiscript
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
};
template<typename Ret>
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
struct Handle_Return<std::shared_ptr<std::function<Ret>>> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
};
template<typename Ret>
@@ -161,21 +146,13 @@ namespace chaiscript
};
template<typename Ret>
struct Handle_Return<std::shared_ptr<Ret> >
struct Handle_Return<std::shared_ptr<Ret>> : Handle_Return<std::shared_ptr<Ret> &>
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<Ret> &>
struct Handle_Return<const std::shared_ptr<Ret> &> : Handle_Return<std::shared_ptr<Ret> &>
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
}
};
template<typename Ret>
@@ -187,10 +164,15 @@ namespace chaiscript
}
};
template<typename Ret>
struct Handle_Return<const Ret>
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return<Ret &>
{
@@ -198,16 +180,8 @@ namespace chaiscript
{
return Boxed_Value(std::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value>
{
@@ -217,40 +191,19 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value>
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value &>
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value &>
struct Handle_Return<const Boxed_Value &> : Handle_Return<Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
@@ -265,16 +218,9 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Number>
struct Handle_Return<const Boxed_Number> : Handle_Return<Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
@@ -286,7 +232,7 @@ namespace chaiscript
{
static Boxed_Value handle()
{
return Boxed_Value(Boxed_Value::Void_Type());
return void_var();
}
};
}

View File

@@ -16,447 +16,202 @@ namespace chaiscript
{
namespace operators
{
namespace detail
{
/// \todo make this return a decltype once we drop gcc 4.6
template<typename L, typename R>
auto assign(L l, R r) -> L&
{
return (l = r);
}
template<typename L, typename R>
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
{
return (l &= r);
}
template<typename L, typename R>
auto assign_xor(L l, R r) -> decltype((l^=r))
{
return (l ^= r);
}
template<typename L, typename R>
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
{
return (l |= r);
}
template<typename L, typename R>
auto assign_difference(L l, R r) -> decltype(( l -= r))
{
return (l -= r);
}
template<typename L, typename R>
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
{
return (l <<= r);
}
template<typename L, typename R>
auto assign_product(L l, R r) -> decltype(( l *= r ))
{
return (l *= r);
}
template<typename L, typename R>
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
{
return (l /= r);
}
template<typename L, typename R>
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
{
return (l %= r);
}
template<typename L, typename R>
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
{
return (l >>= r);
}
/// \todo make this return a decltype once we drop gcc 4.6
template<typename L, typename R>
auto assign_sum(L l, R r) -> L&
{
return (l += r);
}
template<typename L>
auto prefix_decrement(L l) -> decltype(( --l ))
{
return (--l);
}
template<typename L>
auto prefix_increment(L l) -> decltype(( ++l ))
{
return (++l);
}
template<typename L, typename R>
auto equal(L l, R r) -> decltype(( l == r ))
{
return (l == r);
}
template<typename L, typename R>
auto greater_than(L l, R r) -> decltype(( l > r ))
{
return (l > r);
}
template<typename L, typename R>
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
{
return (l >= r);
}
template<typename L, typename R>
auto less_than(L l, R r) -> decltype(( l < r ))
{
return (l < r);
}
template<typename L, typename R>
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
{
return (l <= r);
}
template<typename L>
auto logical_compliment(L l) -> decltype(( !l ))
{
return (!l);
}
template<typename L, typename R>
auto not_equal(L l, R r) -> decltype(( l != r ))
{
return (l != r);
}
template<typename L, typename R>
auto addition(L l, R r) -> decltype(( l + r ))
{
return (l + r);
}
template<typename L>
auto unary_plus(L l) -> decltype(( +l ))
{
return (+l);
}
template<typename L, typename R>
auto subtraction(L l, R r) -> decltype(( l - r ))
{
return (l - r);
}
template<typename L>
auto unary_minus(L l) -> decltype(( -l ))
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4146)
return (-l);
#pragma warning(pop)
#else
return (-l);
#endif
}
template<typename L, typename R>
auto bitwise_and(L l, R r) -> decltype(( l & r ))
{
return (l & r);
}
template<typename L>
auto bitwise_compliment(L l) -> decltype(( ~l ))
{
return (~l);
}
template<typename L, typename R>
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
{
return (l ^ r);
}
template<typename L, typename R>
auto bitwise_or(L l, R r) -> decltype(( l | r ))
{
return (l | r);
}
template<typename L, typename R>
auto division(L l, R r) -> decltype(( l / r ))
{
return (l / r);
}
template<typename L, typename R>
auto left_shift(L l, R r) -> decltype(( l << r ))
{
return l << r;
}
template<typename L, typename R>
auto multiplication(L l, R r) -> decltype(( l * r ))
{
return l * r;
}
template<typename L, typename R>
auto remainder(L l, R r) -> decltype(( l % r ))
{
return (l % r);
}
template<typename L, typename R>
auto right_shift(L l, R r) -> decltype(( l >> r ))
{
return (l >> r);
}
}
template<typename T>
ModulePtr assign(ModulePtr m = std::make_shared<Module>())
void assign(Module& m)
{
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
}
template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared<Module>())
void assign_bitwise_and(Module& m)
{
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
}
template<typename T>
ModulePtr assign_xor(ModulePtr m = std::make_shared<Module>())
void assign_xor(Module& m)
{
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
}
template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared<Module>())
void assign_bitwise_or(Module& m)
{
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
}
template<typename T>
ModulePtr assign_difference(ModulePtr m = std::make_shared<Module>())
void assign_difference(Module& m)
{
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
}
template<typename T>
ModulePtr assign_left_shift(ModulePtr m = std::make_shared<Module>())
void assign_left_shift(Module& m)
{
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
}
template<typename T>
ModulePtr assign_product(ModulePtr m = std::make_shared<Module>())
void assign_product(Module& m)
{
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
}
template<typename T>
ModulePtr assign_quotient(ModulePtr m = std::make_shared<Module>())
void assign_quotient(Module& m)
{
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
}
template<typename T>
ModulePtr assign_remainder(ModulePtr m = std::make_shared<Module>())
void assign_remainder(Module& m)
{
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
}
template<typename T>
ModulePtr assign_right_shift(ModulePtr m = std::make_shared<Module>())
void assign_right_shift(Module& m)
{
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
}
template<typename T>
ModulePtr assign_sum(ModulePtr m = std::make_shared<Module>())
void assign_sum(Module& m)
{
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
return m;
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
}
template<typename T>
ModulePtr prefix_decrement(ModulePtr m = std::make_shared<Module>())
void prefix_decrement(Module& m)
{
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
return m;
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
}
template<typename T>
ModulePtr prefix_increment(ModulePtr m = std::make_shared<Module>())
void prefix_increment(Module& m)
{
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
return m;
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
}
template<typename T>
ModulePtr equal(ModulePtr m = std::make_shared<Module>())
void equal(Module& m)
{
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
}
template<typename T>
ModulePtr greater_than(ModulePtr m = std::make_shared<Module>())
void greater_than(Module& m)
{
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
}
template<typename T>
ModulePtr greater_than_equal(ModulePtr m = std::make_shared<Module>())
void greater_than_equal(Module& m)
{
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
}
template<typename T>
ModulePtr less_than(ModulePtr m = std::make_shared<Module>())
void less_than(Module& m)
{
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
}
template<typename T>
ModulePtr less_than_equal(ModulePtr m = std::make_shared<Module>())
void less_than_equal(Module& m)
{
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
}
template<typename T>
ModulePtr logical_compliment(ModulePtr m = std::make_shared<Module>())
void logical_compliment(Module& m)
{
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
return m;
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
}
template<typename T>
ModulePtr not_equal(ModulePtr m = std::make_shared<Module>())
void not_equal(Module& m)
{
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
}
template<typename T>
ModulePtr addition(ModulePtr m = std::make_shared<Module>())
void addition(Module& m)
{
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
}
template<typename T>
ModulePtr unary_plus(ModulePtr m = std::make_shared<Module>())
void unary_plus(Module& m)
{
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
return m;
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
}
template<typename T>
ModulePtr subtraction(ModulePtr m = std::make_shared<Module>())
void subtraction(Module& m)
{
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
}
template<typename T>
ModulePtr unary_minus(ModulePtr m = std::make_shared<Module>())
void unary_minus(Module& m)
{
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
return m;
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
}
template<typename T>
ModulePtr bitwise_and(ModulePtr m = std::make_shared<Module>())
void bitwise_and(Module& m)
{
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
}
template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = std::make_shared<Module>())
void bitwise_compliment(Module& m)
{
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
return m;
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
}
template<typename T>
ModulePtr bitwise_xor(ModulePtr m = std::make_shared<Module>())
void bitwise_xor(Module& m)
{
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
}
template<typename T>
ModulePtr bitwise_or(ModulePtr m = std::make_shared<Module>())
void bitwise_or(Module& m)
{
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
}
template<typename T>
ModulePtr division(ModulePtr m = std::make_shared<Module>())
void division(Module& m)
{
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
}
template<typename T>
ModulePtr left_shift(ModulePtr m = std::make_shared<Module>())
void left_shift(Module& m)
{
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
}
template<typename T>
ModulePtr multiplication(ModulePtr m = std::make_shared<Module>())
void multiplication(Module& m)
{
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
}
template<typename T>
ModulePtr remainder(ModulePtr m = std::make_shared<Module>())
void remainder(Module& m)
{
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
}
template<typename T>
ModulePtr right_shift(ModulePtr m = std::make_shared<Module>())
void right_shift(Module& m)
{
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
return m;
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
}
}
}

View File

@@ -53,7 +53,14 @@ namespace chaiscript
m_doti(user_type<Dynamic_Object>())
{}
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
explicit Param_Types(const std::vector<Type_Info> &t_types)
: m_types(build_param_types(t_types)),
m_has_types(false),
m_doti(user_type<Dynamic_Object>())
{
}
explicit Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
: m_types(std::move(t_types)),
m_has_types(false),
m_doti(user_type<Dynamic_Object>())
@@ -61,9 +68,21 @@ namespace chaiscript
update_has_types();
}
static std::vector<std::pair<std::string, Type_Info>> build_param_types(const std::vector<Type_Info> &t_types)
{
std::vector<std::pair<std::string, Type_Info>> retval;
std::transform(t_types.begin(), t_types.end(), std::back_inserter(retval),
[](const Type_Info &ti){
return std::make_pair(std::string(), ti);
}
);
return retval;
}
void push_front(std::string t_name, Type_Info t_ti)
{
m_types.emplace(m_types.begin(), std::move(t_name), std::move(t_ti));
m_types.emplace(m_types.begin(), std::move(t_name), t_ti);
update_has_types();
}
@@ -74,8 +93,8 @@ namespace chaiscript
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
{
if (!m_has_types) return true;
if (vals.size() != m_types.size()) return false;
if (!m_has_types) { return true; }
if (vals.size() != m_types.size()) { return false; }
for (size_t i = 0; i < vals.size(); ++i)
{
@@ -145,7 +164,7 @@ namespace chaiscript
class Proxy_Function_Base
{
public:
virtual ~Proxy_Function_Base() {}
virtual ~Proxy_Function_Base() = default;
Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Type_Conversions_State &t_conversions) const
{
@@ -181,20 +200,15 @@ namespace chaiscript
//! to the passed in values
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
{
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
if (m_arity < 0)
{
return true;
} else if (static_cast<size_t>(m_arity) == vals.size()) {
if (m_arity == 0)
{
return true;
} else if (m_arity > 1) {
return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
} else {
return compare_type_to_param(m_types[1], vals[0], t_conversions);
}
} else if (m_arity > 1) {
return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
} else {
return false;
return compare_type_to_param(m_types[1], vals[0], t_conversions);
}
}
@@ -204,8 +218,6 @@ namespace chaiscript
return m_arity;
}
virtual std::string annotation() const = 0;
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
{
if (ti.is_undef()
@@ -248,7 +260,8 @@ namespace chaiscript
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs, const Type_Conversions_State &t_conversions)
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())
{
@@ -282,52 +295,56 @@ namespace chaiscript
class guard_error : public std::runtime_error
{
public:
guard_error() CHAISCRIPT_NOEXCEPT
guard_error() noexcept
: std::runtime_error("Guard evaluation failed")
{ }
guard_error(const guard_error &) = default;
virtual ~guard_error() CHAISCRIPT_NOEXCEPT
{ }
~guard_error() noexcept override = default;
};
}
namespace dispatch
{
class Dynamic_Function_Interface
{
public:
virtual ~Dynamic_Function_Interface() {}
virtual Param_Types get_dynamic_param_types() const = 0;
};
/**
* A Proxy_Function implementation that is not type safe, the called function
* is expecting a vector<Boxed_Value> that it works with how it chooses.
*/
class Dynamic_Proxy_Function : public Proxy_Function_Base
class Dynamic_Proxy_Function : public Proxy_Function_Base, public Dynamic_Function_Interface
{
public:
Dynamic_Proxy_Function(
int t_arity=-1,
AST_NodePtr t_parsenode = AST_NodePtr(),
Param_Types t_param_types = Param_Types(),
std::string t_description = "",
Proxy_Function t_guard = Proxy_Function())
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
m_param_types(std::move(t_param_types)),
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description))
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
{
}
virtual ~Dynamic_Proxy_Function() {}
virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
bool operator==(const Proxy_Function_Base &rhs) const override
{
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
return this == &rhs
|| (prhs
|| ((prhs != nullptr)
&& this->m_arity == prhs->m_arity
&& !this->m_guard && !prhs->m_guard
&& this->m_param_types == prhs->m_param_types);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
&& test_guard(vals, t_conversions);
@@ -344,12 +361,10 @@ namespace chaiscript
return m_parsenode;
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_description;
Param_Types get_dynamic_param_types() const override {
return m_param_types;
}
protected:
bool test_guard(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const
{
@@ -367,6 +382,8 @@ namespace chaiscript
}
}
private:
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
{
@@ -388,13 +405,12 @@ namespace chaiscript
Param_Types m_param_types;
Proxy_Function m_guard;
AST_NodePtr m_parsenode;
std::string m_description;
};
template<typename Callable>
class Dynamic_Proxy_Function_Impl : public Dynamic_Proxy_Function
class Dynamic_Proxy_Function_Impl final : public Dynamic_Proxy_Function
{
public:
Dynamic_Proxy_Function_Impl(
@@ -402,24 +418,20 @@ namespace chaiscript
int t_arity=-1,
AST_NodePtr t_parsenode = AST_NodePtr(),
Param_Types t_param_types = Param_Types(),
std::string t_description = "",
Proxy_Function t_guard = Proxy_Function())
: Dynamic_Proxy_Function(
t_arity,
std::move(t_parsenode),
std::move(t_param_types),
std::move(t_description),
std::move(t_guard)
),
m_f(std::move(t_f))
{
}
virtual ~Dynamic_Proxy_Function_Impl() {}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
{
@@ -430,7 +442,6 @@ namespace chaiscript
}
private:
Callable m_f;
};
@@ -451,7 +462,7 @@ namespace chaiscript
/// and substitutes bound parameters into the parameter list
/// at runtime, when call() is executed.
/// it is used for bind(function, param1, _, param2) style calls
class Bound_Function : public Proxy_Function_Base
class Bound_Function final : public Proxy_Function_Base
{
public:
Bound_Function(const Const_Proxy_Function &t_f,
@@ -462,19 +473,18 @@ namespace chaiscript
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
}
virtual bool operator==(const Proxy_Function_Base &t_f) const CHAISCRIPT_OVERRIDE
bool operator==(const Proxy_Function_Base &t_f) const override
{
return &t_f == this;
}
virtual ~Bound_Function() {}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return m_f->call_match(build_param_list(vals), t_conversions);
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
std::vector<Const_Proxy_Function> get_contained_functions() const override
{
return std::vector<Const_Proxy_Function>{m_f};
}
@@ -511,10 +521,6 @@ namespace chaiscript
return args;
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "Bound: " + m_f->annotation();
}
protected:
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
@@ -524,18 +530,11 @@ namespace chaiscript
if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }
std::vector<Type_Info> types = t_f->get_param_types();
const auto types = t_f->get_param_types();
assert(types.size() == t_args.size() + 1);
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(push)
#pragma warning(disable : 6011)
#endif
// this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14
std::vector<Type_Info> retval{types[0]};
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(pop)
#endif
for (size_t i = 0; i < types.size() - 1; ++i)
{
@@ -548,7 +547,7 @@ namespace chaiscript
return retval;
}
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return (*m_f)(build_param_list(params), t_conversions);
}
@@ -561,21 +560,15 @@ namespace chaiscript
class Proxy_Function_Impl_Base : public Proxy_Function_Base
{
public:
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
explicit Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
{
}
virtual ~Proxy_Function_Impl_Base() {}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return "";
}
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, t_conversions) && 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_State &t_conversions) const = 0;
@@ -585,33 +578,30 @@ namespace chaiscript
/// For any callable object
template<typename Func, typename Callable>
class Proxy_Function_Callable_Impl : public Proxy_Function_Impl_Base
class Proxy_Function_Callable_Impl final : public Proxy_Function_Impl_Base
{
public:
Proxy_Function_Callable_Impl(Callable f)
explicit Proxy_Function_Callable_Impl(Callable f)
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
m_f(std::move(f))
{
}
virtual ~Proxy_Function_Callable_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
bool operator==(const Proxy_Function_Base &t_func) const override
{
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
typedef typename detail::Function_Signature<Func>::Return_Type Return_Type;
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
return detail::call_func(detail::Function_Signature<Func>(), m_f, params, t_conversions);
}
private:
@@ -622,21 +612,16 @@ namespace chaiscript
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
{
public:
Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
explicit Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
: Proxy_Function_Impl_Base(t_types)
{
}
virtual ~Assignable_Proxy_Function() {}
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
};
template<typename Func>
class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function
class Assignable_Proxy_Function_Impl final : public Assignable_Proxy_Function
{
public:
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
@@ -646,14 +631,12 @@ namespace chaiscript
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
}
virtual ~Assignable_Proxy_Function_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
bool operator==(const Proxy_Function_Base &t_func) const override
{
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
}
@@ -663,14 +646,14 @@ namespace chaiscript
return m_f.get();
}
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) CHAISCRIPT_OVERRIDE {
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return detail::Do_Call<typename std::function<Func>::result_type>::template go<Func>(m_f.get(), params, t_conversions);
return detail::call_func(detail::Function_Signature<Func>(), m_f.get(), params, t_conversions);
}
@@ -678,22 +661,22 @@ namespace chaiscript
std::reference_wrapper<std::function<Func>> m_f;
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
};
/// Attribute getter Proxy_Function implementation
template<typename T, typename Class>
class Attribute_Access : public Proxy_Function_Base
class Attribute_Access final : public Proxy_Function_Base
{
public:
Attribute_Access(T Class::* t_attr)
explicit Attribute_Access(T Class::* t_attr)
: Proxy_Function_Base(param_types(), 1),
m_attr(t_attr)
{
}
virtual ~Attribute_Access() {}
bool is_attribute_function() const override { return true; }
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; }
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
bool operator==(const Proxy_Function_Base &t_func) const override
{
const Attribute_Access<T, Class> * aa
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
@@ -705,7 +688,7 @@ namespace chaiscript
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const CHAISCRIPT_OVERRIDE
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const override
{
if (vals.size() != 1)
{
@@ -715,26 +698,47 @@ namespace chaiscript
return vals[0].get_type_info().bare_equal(user_type<Class>());
}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "";
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
return do_call_impl<T>(o);
} else {
Class *o = boxed_cast<Class *>(bv, &t_conversions);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
return do_call_impl<T>(o);
}
}
private:
template<typename Type>
auto do_call_impl(Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<Type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(const Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<const Type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(const Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
}
static std::vector<Type_Info> param_types()
{
return {user_type<T>(), user_type<Class>()};
@@ -769,7 +773,7 @@ namespace chaiscript
dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
~dispatch_error() noexcept override = default;
std::vector<Boxed_Value> parameters;
std::vector<Const_Proxy_Function> functions;
@@ -786,7 +790,7 @@ namespace chaiscript
{
const std::vector<Type_Info> &types = t_func->get_param_types();
if (t_func->get_arity() == -1) return false;
if (t_func->get_arity() == -1) { return false; }
assert(plist.size() == types.size() - 1);
@@ -882,6 +886,9 @@ namespace chaiscript
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
ordered_funcs.reserve(funcs.size());
const constexpr auto boxed_type = user_type<Boxed_Value>();
const constexpr auto dynamic_type = user_type<Dynamic_Object>();
for (const auto &func : funcs)
{
const auto arity = func->get_arity();
@@ -893,7 +900,10 @@ namespace chaiscript
size_t numdiffs = 0;
for (size_t i = 0; i < plist.size(); ++i)
{
if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info()))
const auto &p_type = plist[i].get_type_info();
const auto &f_type = func->get_param_types()[i+1];
if (!(f_type.bare_equal(boxed_type) && p_type.bare_equal(dynamic_type)) && !f_type.bare_equal(p_type))
{
++numdiffs;
}
@@ -908,7 +918,7 @@ namespace chaiscript
for (const auto &func : ordered_funcs )
{
try {
if (func.first == i && func.second->filter(plist, t_conversions))
if (func.first == i && (i == 0 || func.second->filter(plist, t_conversions)))
{
return (*(func.second))(plist, t_conversions);
}

View File

@@ -10,6 +10,7 @@
#include <functional>
#include <stdexcept>
#include <vector>
#include <array>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
@@ -43,7 +44,7 @@ namespace chaiscript
arity_error(const arity_error &) = default;
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
~arity_error() noexcept override = default;
int got;
int expected;
@@ -66,34 +67,6 @@ namespace chaiscript
}
#ifdef CHAISCRIPT_GCC_4_6
/// \todo REMOVE THIS WHEN WE DROP G++4.6
// Forward declaration
template<typename ... Rest>
struct Try_Cast;
template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...>
{
static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions_State &t_conversions)
{
boxed_cast<Param>(params[generation], &t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
}
};
// 0th case
template<>
struct Try_Cast<>
{
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions_State &)
{
}
};
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarily used to prevent
@@ -104,137 +77,54 @@ namespace chaiscript
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
Try_Cast<Params...>::do_try(params, 0, t_conversions);
} catch (const exception::bad_boxed_cast &) {
return false;
}
return true;
}
template<typename Ret, int count, typename ... Params>
struct Call_Func
{
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
}
};
template<typename Ret, typename ... Params>
struct Call_Func<Ret, 0, Params...>
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this
#endif
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
};
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each parameter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
if (params.size() == sizeof...(Params))
{
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params, t_conversions);
}
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
}
#else
template<size_t ... I>
struct Indexes
{
};
template<size_t S, size_t ... I>
struct Make_Indexes
{
typedef typename Make_Indexes<S-1, I..., sizeof...(I)>::indexes indexes;
};
template<size_t ... I>
struct Make_Indexes<0, I...>
{
typedef Indexes<I...> indexes;
};
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarily used to prevent
* registration of two functions with the exact same signatures
*/
template<typename Ret, typename ... Params, size_t ... I>
bool compare_types_cast(Indexes<I...>, Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
std::vector<Boxed_Value>::size_type i = 0;
(void)i;
(void)params; (void)t_conversions;
(void)std::initializer_list<int>{(boxed_cast<Params>(params[I], &t_conversions), 0)...};
// this is ok because the order of evaluation of initializer lists is well defined
(void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};
return true;
} catch (const exception::bad_boxed_cast &) {
return false;
}
}
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*f)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return compare_types_cast(indexes(), f, params, t_conversions);
}
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
std::index_sequence<I...>, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
(void)params; (void)t_conversions;
return f(boxed_cast<Params>(params[I], &t_conversions)...);
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each parameter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
/// The function attempts to unbox each parameter to the expected type.
/// if any unboxing fails the execution of the function fails and
/// the bad_boxed_cast is passed up to the caller.
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return call_func(sig, indexes(), f, params, t_conversions);
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
}
template<typename Callable, typename ... Params>
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4702)
#endif
// MSVC is reporting that this is unreachable code - and it's wrong.
return Handle_Return<void>::handle();
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
}
}
@@ -242,34 +132,4 @@ namespace chaiscript
}
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
}
};
template<>
struct Do_Call<void>
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};
}
}
}
#endif

View File

@@ -0,0 +1,159 @@
#ifndef SHORT_ALLOC_H
#define SHORT_ALLOC_H
// The MIT License (MIT)
//
// Copyright (c) 2015 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <cstddef>
#include <cassert>
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
class arena
{
alignas(alignment) char buf_[N];
char* ptr_;
public:
~arena() {ptr_ = nullptr;}
arena() noexcept : ptr_(buf_) {}
arena(const arena&) = delete;
arena& operator=(const arena&) = delete;
template <std::size_t ReqAlign> char* allocate(std::size_t n);
void deallocate(char* p, std::size_t n) noexcept;
static constexpr std::size_t size() noexcept {return N;}
std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
void reset() noexcept {ptr_ = buf_;}
private:
static
std::size_t
align_up(std::size_t n) noexcept
{return (n + (alignment-1)) & ~(alignment-1);}
bool
pointer_in_buffer(char* p) noexcept
{return buf_ <= p && p <= buf_ + N;}
};
template <std::size_t N, std::size_t alignment>
template <std::size_t ReqAlign>
char*
arena<N, alignment>::allocate(std::size_t n)
{
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
auto const aligned_n = align_up(n);
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
{
char* r = ptr_;
ptr_ += aligned_n;
return r;
}
static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
"alignment that is larger than alignof(std::max_align_t), and "
"cannot be guaranteed by normal operator new");
return static_cast<char*>(::operator new(n));
}
template <std::size_t N, std::size_t alignment>
void
arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
{
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
if (pointer_in_buffer(p))
{
n = align_up(n);
if (p + n == ptr_) {
ptr_ = p;
}
}
else {
::operator delete(p);
}
}
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
class short_alloc
{
public:
using value_type = T;
static auto constexpr alignment = Align;
static auto constexpr size = N;
using arena_type = arena<size, alignment>;
private:
arena_type& a_;
public:
short_alloc(const short_alloc&) = default;
short_alloc& operator=(const short_alloc&) = delete;
explicit short_alloc(arena_type& a) noexcept : a_(a)
{
static_assert(size % alignment == 0,
"size N needs to be a multiple of alignment Align");
}
template <class U>
explicit short_alloc(const short_alloc<U, N, alignment>& a) noexcept
: a_(a.a_) {}
template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
T* allocate(std::size_t n)
{
return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
}
void deallocate(T* p, std::size_t n) noexcept
{
a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
}
template <class T1, std::size_t N1, std::size_t A1,
class U, std::size_t M, std::size_t A2>
friend
bool
operator==(const short_alloc<T1, N1, A1>& x, const short_alloc<U, M, A2>& y) noexcept;
template <class U, std::size_t M, std::size_t A> friend class short_alloc;
};
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
inline
bool
operator==(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
{
return N == M && A1 == A2 && &x.a_ == &y.a_;
}
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
inline
bool
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
{
return !(x == y);
}
#endif // SHORT_ALLOC_HPP

View File

@@ -29,48 +29,48 @@ namespace chaiscript
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_NOEXCEPT
const std::string &t_what) noexcept
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
explicit bad_boxed_dynamic_cast(const std::string &w) noexcept
: bad_boxed_cast(w)
{
}
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
~bad_boxed_dynamic_cast() noexcept override = default;
};
class bad_boxed_type_cast : public bad_boxed_cast
{
public:
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) CHAISCRIPT_NOEXCEPT
const std::string &t_what) noexcept
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
explicit bad_boxed_type_cast(const std::string &w) noexcept
: bad_boxed_cast(w)
{
}
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
~bad_boxed_type_cast() noexcept override = default;
};
}
@@ -97,18 +97,18 @@ namespace chaiscript
return true;
}
virtual ~Type_Conversion_Base() {}
virtual ~Type_Conversion_Base() = default;
protected:
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
: m_to(t_to), m_from(t_from)
Type_Conversion_Base(Type_Info t_to, Type_Info t_from)
: m_to(std::move(t_to)), m_from(std::move(t_from))
{
}
private:
Type_Info m_to;
Type_Info m_from;
const Type_Info m_to;
const Type_Info m_from;
};
@@ -126,7 +126,7 @@ namespace chaiscript
if (t_from.is_const())
{
return Boxed_Value(
[&]()->std::shared_ptr<const To>{
[&](){
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
@@ -137,7 +137,7 @@ namespace chaiscript
);
} else {
return Boxed_Value(
[&]()->std::shared_ptr<To>{
[&](){
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
@@ -182,7 +182,7 @@ namespace chaiscript
if (t_from.is_const())
{
return Boxed_Value(
[&]()->std::shared_ptr<const To>{
[&](){
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
@@ -193,7 +193,7 @@ namespace chaiscript
);
} else {
return Boxed_Value(
[&]()->std::shared_ptr<To>{
[&](){
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
@@ -242,12 +242,12 @@ namespace chaiscript
{
}
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
Boxed_Value convert_down(const Boxed_Value &t_base) const override
{
return Dynamic_Caster<Base, Derived>::cast(t_base);
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
Boxed_Value convert(const Boxed_Value &t_derived) const override
{
return Static_Caster<Derived, Base>::cast(t_derived);
}
@@ -262,17 +262,18 @@ namespace chaiscript
{
}
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
Boxed_Value convert_down(const Boxed_Value &t_base) const override
{
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types");
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived),
"Unable to cast down inheritance hierarchy with non-polymorphic types");
}
virtual bool bidir() const CHAISCRIPT_OVERRIDE
bool bidir() const override
{
return false;
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
Boxed_Value convert(const Boxed_Value &t_derived) const override
{
return Static_Caster<Derived, Base>::cast(t_derived);
}
@@ -285,23 +286,23 @@ namespace chaiscript
{
public:
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
: Type_Conversion_Base(t_to, t_from),
m_func(std::move(t_func))
{
}
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
Boxed_Value convert_down(const Boxed_Value &) const override
{
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
}
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
Boxed_Value convert(const Boxed_Value &t_from) const override
{
/// \todo better handling of errors from the conversion function
return m_func(t_from);
}
virtual bool bidir() const CHAISCRIPT_OVERRIDE
bool bidir() const override
{
return false;
}
@@ -317,11 +318,7 @@ namespace chaiscript
public:
struct Conversion_Saves
{
Conversion_Saves()
: enabled(false)
{}
bool enabled;
bool enabled = false;
std::vector<Boxed_Value> saves;
};
@@ -350,7 +347,6 @@ namespace chaiscript
m_num_types(m_conversions.size()),
m_thread_cache(this),
m_conversion_saves(this)
{
}
@@ -403,7 +399,7 @@ namespace chaiscript
{
try {
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
if (t_saves.enabled) t_saves.saves.push_back(ret);
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
@@ -417,7 +413,7 @@ namespace chaiscript
{
try {
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
if (t_saves.enabled) t_saves.saves.push_back(ret);
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
@@ -448,7 +444,7 @@ namespace chaiscript
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
auto itr = find(to, from);
const auto itr = find(to, from);
if (itr != m_conversions.end())
{

View File

@@ -29,8 +29,8 @@ namespace chaiscript
class Type_Info
{
public:
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
@@ -40,69 +40,55 @@ namespace chaiscript
{
}
CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(nullptr), m_bare_type_info(nullptr),
m_flags(1 << is_undef_flag)
{
}
constexpr Type_Info() = default;
#if !defined(_MSC_VER) || _MSC_VER != 1800
Type_Info(Type_Info&&) = default;
Type_Info& operator=(Type_Info&&) = default;
#endif
Type_Info(const Type_Info&) = default;
Type_Info& operator=(const Type_Info&) = default;
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool operator<(const Type_Info &ti) const noexcept
{
return m_type_info < ti.m_type_info;
}
CHAISCRIPT_CONSTEXPR bool operator!=(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool operator!=(const Type_Info &ti) const noexcept
{
return !(operator==(ti));
}
CHAISCRIPT_CONSTEXPR bool operator!=(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool operator!=(const std::type_info &ti) const noexcept
{
return !(operator==(ti));
}
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool operator==(const Type_Info &ti) const noexcept
{
return ti.m_type_info == m_type_info
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
|| *ti.m_type_info == *m_type_info;
}
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool operator==(const std::type_info &ti) const noexcept
{
return m_type_info != nullptr && (*m_type_info) == ti;
return !is_undef() && (*m_type_info) == ti;
}
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool bare_equal(const Type_Info &ti) const noexcept
{
return ti.m_bare_type_info == m_bare_type_info
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
return ti.m_bare_type_info == m_bare_type_info
|| *ti.m_bare_type_info == *m_bare_type_info;
}
CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
{
return m_bare_type_info != nullptr
&& (*m_bare_type_info) == ti;
return !is_undef() && (*m_bare_type_info) == ti;
}
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_const_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_reference_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_void_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_undef_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_pointer_flag)) != 0; }
constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
std::string name() const
{
if (m_type_info)
if (!is_undef())
{
return m_type_info->name();
} else {
@@ -112,7 +98,7 @@ namespace chaiscript
std::string bare_name() const
{
if (m_bare_type_info)
if (!is_undef())
{
return m_bare_type_info->name();
} else {
@@ -120,21 +106,23 @@ namespace chaiscript
}
}
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
constexpr const std::type_info *bare_type_info() const
{
return m_bare_type_info;
}
private:
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
unsigned int m_flags;
struct Unknown_Type {};
const std::type_info *m_type_info = &typeid(Unknown_Type);
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
static const int is_const_flag = 0;
static const int is_reference_flag = 1;
static const int is_pointer_flag = 2;
static const int is_void_flag = 3;
static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5;
unsigned int m_flags = (1 << is_undef_flag);
};
namespace detail
@@ -143,9 +131,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
std::is_reference<T>::value, std::is_pointer<T>::value,
@@ -160,9 +146,9 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<std::shared_ptr<T> >
{
typedef T type;
// typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@@ -180,9 +166,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<const std::shared_ptr<T> &>
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@@ -195,9 +179,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<std::reference_wrapper<T> >
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@@ -210,9 +192,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<const std::reference_wrapper<T> &>
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@@ -234,7 +214,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode
template<typename T>
Type_Info user_type(const T &/*t*/)
constexpr Type_Info user_type(const T &/*t*/)
{
return detail::Get_Type_Info<T>::get();
}
@@ -249,7 +229,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \endcode
template<typename T>
Type_Info user_type()
constexpr Type_Info user_type()
{
return detail::Get_Type_Info<T>::get();
}

View File

@@ -7,13 +7,15 @@
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#include "../utility/fnv1a.hpp"
#include <string>
namespace chaiscript
{
struct Operators {
enum Opers
enum class Opers
{
boolean_flag,
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
@@ -31,7 +33,7 @@ namespace chaiscript
};
static const char *to_string(Opers t_oper) {
const char *opers[] = {
static const char *opers[] = {
"",
"==", "<", ">", "<=", ">=", "!=",
"",
@@ -46,81 +48,44 @@ namespace chaiscript
"+", "/", "*", "-", "+", "-",
""
};
return opers[t_oper];
return opers[static_cast<int>(t_oper)];
}
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{
if (t_str == "==")
{
return equals;
} else if (t_str == "<") {
return less_than;
} else if (t_str == ">") {
return greater_than;
} else if (t_str == "<=") {
return less_than_equal;
} else if (t_str == ">=") {
return greater_than_equal;
} else if (t_str == "!=") {
return not_equal;
} else if (t_str == "=") {
return assign;
} else if (t_str == "++") {
return pre_increment;
} else if (t_str == "--") {
return pre_decrement;
} else if (t_str == "*=") {
return assign_product;
} else if (t_str == "+=") {
return assign_sum;
} else if (t_str == "-=") {
return assign_difference;
} else if (t_str == "&=") {
return assign_bitwise_and;
} else if (t_str == "|=") {
return assign_bitwise_or;
} else if (t_str == "<<=") {
return assign_shift_left;
} else if (t_str == ">>=") {
return assign_shift_right;
} else if (t_str == "%=") {
return assign_remainder;
} else if (t_str == "^=") {
return assign_bitwise_xor;
} else if (t_str == "<<") {
return shift_left;
} else if (t_str == ">>") {
return shift_right;
} else if (t_str == "%") {
return remainder;
} else if (t_str == "&") {
return bitwise_and;
} else if (t_str == "|") {
return bitwise_or;
} else if (t_str == "^") {
return bitwise_xor;
} else if (t_str == "~") {
return bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return unary_plus;
} else {
return sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return unary_minus;
} else {
return difference;
}
} else if (t_str == "/") {
return quotient;
} else if (t_str == "*") {
return product;
} else {
return invalid;
}
const auto op_hash = utility::fnv1a_32(t_str.c_str());
switch (op_hash) {
case utility::fnv1a_32("=="): { return Opers::equals; }
case utility::fnv1a_32("<"): { return Opers::less_than; }
case utility::fnv1a_32(">"): { return Opers::greater_than; }
case utility::fnv1a_32("<="): { return Opers::less_than_equal; }
case utility::fnv1a_32(">="): { return Opers::greater_than_equal; }
case utility::fnv1a_32("!="): { return Opers::not_equal; }
case utility::fnv1a_32("="): { return Opers::assign; }
case utility::fnv1a_32("++"): { return Opers::pre_increment; }
case utility::fnv1a_32("--"): { return Opers::pre_decrement; }
case utility::fnv1a_32("*="): { return Opers::assign_product; }
case utility::fnv1a_32("+="): { return Opers::assign_sum; }
case utility::fnv1a_32("-="): { return Opers::assign_difference; }
case utility::fnv1a_32("&="): { return Opers::assign_bitwise_and; }
case utility::fnv1a_32("|="): { return Opers::assign_bitwise_or; }
case utility::fnv1a_32("<<="): { return Opers::assign_shift_left; }
case utility::fnv1a_32(">>="): { return Opers::assign_shift_right; }
case utility::fnv1a_32("%="): { return Opers::assign_remainder; }
case utility::fnv1a_32("^="): { return Opers::assign_bitwise_xor; }
case utility::fnv1a_32("<<"): { return Opers::shift_left; }
case utility::fnv1a_32(">>"): { return Opers::shift_right; }
case utility::fnv1a_32("%"): { return Opers::remainder; }
case utility::fnv1a_32("&"): { return Opers::bitwise_and; }
case utility::fnv1a_32("|"): { return Opers::bitwise_or; }
case utility::fnv1a_32("^"): { return Opers::bitwise_xor; }
case utility::fnv1a_32("~"): { return Opers::bitwise_complement; }
case utility::fnv1a_32("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
case utility::fnv1a_32("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
case utility::fnv1a_32("/"): { return Opers::quotient; }
case utility::fnv1a_32("*"): { return Opers::product; }
default: { return Opers::invalid; }
}
}
};

View File

@@ -26,34 +26,60 @@ struct AST_Node;
namespace chaiscript
{
struct Name_Validator {
static bool is_reserved_word(const std::string &name)
{
static const std::set<std::string> m_reserved_words
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_",
"__LINE__", "__FILE__", "__FUNC__", "__CLASS__"};
return m_reserved_words.count(name) > 0;
}
static bool valid_object_name(const std::string &name)
{
return name.find("::") == std::string::npos && !is_reserved_word(name);
}
static void validate_object_name(const std::string &name)
{
if (is_reserved_word(name)) {
throw exception::reserved_word_error(name);
}
if (name.find("::") != std::string::npos) {
throw exception::illegal_name_error(name);
}
}
};
/// Signature of module entry point that all binary loadable modules must implement.
typedef ModulePtr (*Create_Module_Func)();
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
};
enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl,
Array_Call, Dot_Access,
Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
};
enum class Operator_Precidence { Ternary_Cond, Logical_Or,
Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And,
Equality, Comparison, Shift, Addition, Multiplication, Prefix };
namespace
{
/// Helper lookup to get the name of each node type
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
inline const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl",
"Array_Call", "Dot_Access",
"Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
return ast_node_types[ast_node_type];
return ast_node_types[static_cast<int>(ast_node_type)];
}
}
@@ -101,6 +127,36 @@ namespace chaiscript
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
namespace exception
{
/// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error
{
explicit load_module_error(const std::string &t_reason) noexcept
: std::runtime_error(t_reason)
{
}
load_module_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
: std::runtime_error(format_error(t_name, t_errors))
{
}
load_module_error(const load_module_error &) = default;
~load_module_error() noexcept override = default;
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
{
std::stringstream ss;
ss << "Error loading module '" << t_name << "'\n"
<< " The following locations were searched:\n";
for (const auto &err : t_errors) {
ss << " " << err.what() << "\n";
}
return ss.str();
}
};
/// Errors generated during parsing or evaluation
struct eval_error : std::runtime_error {
@@ -113,7 +169,7 @@ namespace chaiscript
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
@@ -121,18 +177,18 @@ namespace chaiscript
eval_error(const std::string &t_why,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
std::runtime_error(format(t_why, t_where, t_fname)),
reason(t_why), start_position(t_where), filename(t_fname)
{}
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
explicit eval_error(const std::string &t_why) noexcept
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
@@ -144,7 +200,7 @@ namespace chaiscript
std::ostringstream ss;
ss << what();
if (call_stack.size() > 0) {
if (!call_stack.empty()) {
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
ss << '\n' << detail << '\n';
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
@@ -161,12 +217,12 @@ namespace chaiscript
return ss.str();
}
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
~eval_error() noexcept override = default;
private:
template<typename T>
static int id(const T& t)
static AST_Node_Type id(const T& t)
{
return t->identifier;
}
@@ -420,12 +476,12 @@ namespace chaiscript
/// Errors generated when loading a file
struct file_not_found_error : std::runtime_error {
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
explicit file_not_found_error(const std::string &t_filename) noexcept
: std::runtime_error("File Not Found: " + t_filename)
{ }
file_not_found_error(const file_not_found_error &) = default;
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
~file_not_found_error() noexcept override = default;
};
}
@@ -434,11 +490,9 @@ namespace chaiscript
/// \brief Struct that doubles as both a parser ast_node and an AST node.
struct AST_Node : std::enable_shared_from_this<AST_Node> {
public:
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
const AST_Node_Type identifier;
const std::string text;
Parse_Location location;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
const std::string &filename() const {
return *location.filename;
@@ -452,19 +506,22 @@ namespace chaiscript
return location.end;
}
virtual std::string pretty_print() const
std::string pretty_print() const
{
std::ostringstream oss;
oss << text;
for (auto & elem : this->children) {
oss << elem->pretty_print();
for (auto & elem : this->get_children()) {
oss << elem->pretty_print() << ' ';
}
return oss.str();
}
virtual std::vector<AST_NodePtr> get_children() const = 0;
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
/// Prints the contents of an AST node, including its children, recursively
std::string to_string(const std::string &t_prepend = "") const {
@@ -473,25 +530,16 @@ namespace chaiscript
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
for (auto & elem : this->children) {
for (auto & elem : this->get_children()) {
oss << elem->to_string(t_prepend + " ");
}
return oss.str();
}
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const
{
try {
return eval_internal(t_e);
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this());
throw;
}
}
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 {
return boxed_cast<bool>(t_bv);
return t_ss->boxed_cast<bool>(t_bv);
}
catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("Condition not boolean");
@@ -499,33 +547,47 @@ namespace chaiscript
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
virtual ~AST_Node() {}
protected:
AST_Node(std::string t_ast_node_text, int t_id, Parse_Location t_loc,
std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
identifier(t_id), text(std::move(t_ast_node_text)),
location(std::move(t_loc)),
children(std::move(t_children))
{
}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const
{
throw std::runtime_error("Undispatched ast_node (internal error)");
}
private:
// Copy and assignment explicitly unimplemented
virtual ~AST_Node() = default;
AST_Node(AST_Node &&) = default;
AST_Node &operator=(AST_Node &&) = default;
AST_Node(const AST_Node &) = delete;
AST_Node& operator=(const AST_Node &) = delete;
protected:
AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc)
: identifier(t_id), text(std::move(t_ast_node_text)),
location(std::move(t_loc))
{
}
};
namespace parser {
class ChaiScript_Parser_Base
{
public:
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0;
virtual void *get_tracer_ptr() = 0;
virtual ~ChaiScript_Parser_Base() = default;
ChaiScript_Parser_Base() = default;
ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
template<typename T>
T &get_tracer()
{
// to do type check this somehow?
return *static_cast<T*>(get_tracer_ptr());
}
protected:
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
};
}
namespace eval
{
@@ -535,96 +597,102 @@ namespace chaiscript
struct Return_Value {
Boxed_Value retval;
Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
explicit Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
};
/// Special type indicating a call to 'break'
struct Break_Loop {
Break_Loop() { }
Break_Loop() = default;
};
/// Special type indicating a call to 'continue'
struct Continue_Loop {
Continue_Loop() { }
Continue_Loop() = default;
};
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(Scope_Push_Pop &&) = default;
Scope_Push_Pop& operator=(Scope_Push_Pop &&) = default;
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
explicit Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_scope(m_ds.get().stack_holder());
m_ds->new_scope(m_ds.stack_holder());
}
~Scope_Push_Pop()
{
m_ds.get()->pop_scope(m_ds.get().stack_holder());
m_ds->pop_scope(m_ds.stack_holder());
}
private:
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
const chaiscript::detail::Dispatch_State &m_ds;
};
/// Creates a new function call and pops it on destruction
struct Function_Push_Pop
{
Function_Push_Pop(Function_Push_Pop &&) = default;
Function_Push_Pop& operator=(Function_Push_Pop &&) = default;
Function_Push_Pop(const Function_Push_Pop &) = delete;
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
explicit Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
}
~Function_Push_Pop()
{
m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
}
void save_params(const std::vector<Boxed_Value> &t_params)
{
m_ds.get()->save_function_params(t_params);
m_ds->save_function_params(t_params);
}
void save_params(std::initializer_list<Boxed_Value> t_params)
{
m_ds.get()->save_function_params(std::move(t_params));
m_ds->save_function_params(t_params);
}
private:
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
const chaiscript::detail::Dispatch_State &m_ds;
};
/// Creates a new scope then pops it on destruction
struct Stack_Push_Pop
{
Stack_Push_Pop(Stack_Push_Pop &&) = default;
Stack_Push_Pop& operator=(Stack_Push_Pop &&) = default;
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
explicit Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_stack(m_ds.get().stack_holder());
m_ds->new_stack(m_ds.stack_holder());
}
~Stack_Push_Pop()
{
m_ds.get()->pop_stack(m_ds.get().stack_holder());
m_ds->pop_stack(m_ds.stack_holder());
}
private:
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
const chaiscript::detail::Dispatch_State &m_ds;
};
}
}

View File

@@ -17,6 +17,7 @@
#include <set>
#include <stdexcept>
#include <vector>
#include <cstring>
#include "../chaiscript_defines.hpp"
#include "../chaiscript_threading.hpp"
@@ -33,227 +34,31 @@
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
#include <dlfcn.h>
#else
#endif
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#include "chaiscript_windows.hpp"
#elif _POSIX_VERSION
#include "chaiscript_posix.hpp"
#else
#include "chaiscript_unknown.hpp"
#endif
#include "../dispatchkit/exception_specification.hpp"
#include "chaiscript_parser.hpp"
namespace chaiscript
{
namespace exception
{
/// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error
{
load_module_error(const std::string &t_reason) CHAISCRIPT_NOEXCEPT
: std::runtime_error(t_reason)
{
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
};
}
namespace detail
{
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
struct Loadable_Module
{
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
~DLModule()
{
dlclose(m_data);
}
void *m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
static T cast_symbol(void *p)
{
union cast_union
{
T func_ptr;
void *in_ptr;
};
cast_union c;
c.in_ptr = p;
return c.func_ptr;
}
T m_symbol;
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
#ifdef WIN32
struct Loadable_Module
{
template<typename T>
static std::wstring to_wstring(const T &t_str)
{
return std::wstring(t_str.begin(), t_str.end());
}
template<typename T>
static std::string to_string(const T &t_str)
{
return std::string(t_str.begin(), t_str.end());
}
#if defined(_UNICODE) || defined(UNICODE)
template<typename T>
static std::wstring to_proper_string(const T &t_str)
{
return to_wstring(t_str);
}
#else
template<typename T>
static std::string to_proper_string(const T &t_str)
{
return to_string(t_str);
}
#endif
static std::string get_error_message(DWORD t_err)
{
typedef LPTSTR StringType;
#if defined(_UNICODE) || defined(UNICODE)
std::wstring retval = L"Unknown Error";
#else
std::string retval = "Unknown Error";
#endif
StringType lpMsgBuf = nullptr;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<StringType>(&lpMsgBuf),
0, nullptr ) != 0 && lpMsgBuf)
{
retval = lpMsgBuf;
LocalFree(lpMsgBuf);
}
return to_string(retval);
}
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
~DLModule()
{
FreeLibrary(m_data);
}
HMODULE m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
T m_symbol;
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
struct Loadable_Module
{
Loadable_Module(const std::string &, const std::string &)
{
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
}
ModulePtr m_moduleptr;
};
#endif
#endif
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
}
/// \brief The main object that the ChaiScript user will use.
class ChaiScript {
class ChaiScript_Basic {
mutable chaiscript::detail::threading::shared_mutex m_mutex;
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
@@ -265,19 +70,16 @@ namespace chaiscript
std::vector<std::string> m_module_paths;
std::vector<std::string> m_use_paths;
std::unique_ptr<parser::ChaiScript_Parser_Base> m_parser;
chaiscript::detail::Dispatch_Engine m_engine;
/// Evaluates the given string in by parsing it and running the results through the evaluator
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
{
try {
parser::ChaiScript_Parser parser;
if (parser.parse(t_input, t_filename)) {
//parser.show_match_stack();
return parser.optimized_ast()->eval(m_engine);
} else {
return Boxed_Value();
}
const auto p = m_parser->parse(t_input, t_filename);
return p->eval(chaiscript::detail::Dispatch_State(m_engine));
}
catch (chaiscript::eval::detail::Return_Value &rv) {
return rv.retval;
@@ -286,8 +88,6 @@ namespace chaiscript
/// Evaluates the given file and looks in the 'use' paths
const Boxed_Value internal_eval_file(const std::string &t_filename) {
for (const auto &path : m_use_paths)
@@ -324,28 +124,7 @@ namespace chaiscript
}
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
void build_eval_system(const ModulePtr &t_lib) {
m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while");
m_engine.add_reserved_word("for");
m_engine.add_reserved_word("if");
m_engine.add_reserved_word("else");
m_engine.add_reserved_word("&&");
m_engine.add_reserved_word("||");
m_engine.add_reserved_word(",");
m_engine.add_reserved_word("auto");
m_engine.add_reserved_word("return");
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("class");
m_engine.add_reserved_word("attr");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("global");
m_engine.add_reserved_word("GLOBAL");
m_engine.add_reserved_word("_");
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
if (t_lib)
{
add(t_lib);
@@ -390,23 +169,26 @@ namespace chaiscript
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end()
&& std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end())
{
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
}
if (std::find(t_opts.begin(), t_opts.end(), Options::No_External_Scripts) == t_opts.end()
&& std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end())
{
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 use(t_file); }), "use");
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
m_engine.add(fun(&parse), "parse");
m_engine.add(fun(&ChaiScript::version_major), "version_major");
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
m_engine.add(fun(&ChaiScript::version), "version");
m_engine.add(fun(&ChaiScript::compiler_version), "compiler_version");
m_engine.add(fun(&ChaiScript::compiler_name), "compiler_name");
m_engine.add(fun(&ChaiScript::compiler_id), "compiler_id");
m_engine.add(fun(&ChaiScript::debug_build), "debug_build");
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
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");
@@ -437,65 +219,43 @@ namespace chaiscript
}
}
std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths)
{
if (paths.empty()) { return {""}; }
else { return paths; }
}
public:
/// \brief Constructor for ChaiScript
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript(const ModulePtr &t_lib,
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
ChaiScript_Basic(const ModulePtr &t_lib,
std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
std::vector<std::string> t_module_paths = {},
std::vector<std::string> t_use_paths = {},
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))),
m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths))),
m_parser(std::move(parser)),
m_engine(*m_parser)
{
if (m_module_paths.empty())
{
m_module_paths.push_back("");
}
if (m_use_paths.empty())
{
m_use_paths.push_back("");
}
build_eval_system(t_lib);
}
/// \brief Constructor for ChaiScript.
///
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
/// at runtime generates an error if it cannot be found.
///
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
{
if (m_module_paths.empty())
{
m_module_paths.push_back("");
}
if (m_use_paths.empty())
{
m_use_paths.push_back("");
}
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
// If on Unix, add the path of the current executable to the module search path
// as windows would do
union cast_union
{
Boxed_Value (ChaiScript::*in_ptr)(const std::string&);
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&);
void *out_ptr;
};
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
cast_union u;
u.in_ptr = &ChaiScript::use;
if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
u.in_ptr = &ChaiScript_Basic::use;
if ( (dladdr(static_cast<void*>(u.out_ptr), &rInfo) != 0) && (rInfo.dli_fname != nullptr) ) {
std::string dllpath(rInfo.dli_fname);
const size_t lastslash = dllpath.rfind('/');
if (lastslash != std::string::npos)
@@ -514,83 +274,63 @@ namespace chaiscript
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
}
#endif
// attempt to load the stdlib
load_module("chaiscript_stdlib-" + version());
build_eval_system(ModulePtr());
build_eval_system(t_lib, t_opts);
}
/// \brief Constructor for ChaiScript.
///
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
/// at runtime generates an error if it cannot be found.
///
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
std::vector<std::string> t_module_paths = {},
std::vector<std::string> t_use_paths = {},
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
: ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts)
{
try {
// attempt to load the stdlib
load_module("chaiscript_stdlib-" + Build_Info::version());
} catch (const exception::load_module_error &t_err) {
std::cout << "An error occured while trying to load the chaiscript standard library.\n"
<< "\n"
<< "You must either provide a standard library, or compile it in.\n"
<< "For an example of compiling the standard library in,\n"
<< "see: https://gist.github.com/lefticus/9456197\n"
<< "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
<< "\n"
<< "\n"
<< t_err.what();
throw;
}
}
parser::ChaiScript_Parser_Base &get_parser()
{
return *m_parser;
}
const Boxed_Value eval(const AST_NodePtr &t_ast)
{
try {
return t_ast->eval(m_engine);
return t_ast->eval(chaiscript::detail::Dispatch_State(m_engine));
} catch (const exception::eval_error &t_ee) {
throw Boxed_Value(t_ee);
}
}
static AST_NodePtr parse(const std::string &t_input)
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
{
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");
const auto ast = m_parser->parse(t_input, "PARSE");
if (t_debug_print) {
m_parser->debug_print(ast);
}
return ast;
}
static int version_major()
{
return chaiscript::version_major;
}
static int version_minor()
{
return chaiscript::version_minor;
}
static int version_patch()
{
return chaiscript::version_patch;
}
static std::string version()
{
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
{
return chaiscript::compiler_name;
}
static bool debug_build()
{
return chaiscript::debug_build;
}
std::string get_type_name(const Type_Info &ti) const
{
return m_engine.get_type_name(ti);
@@ -643,8 +383,9 @@ namespace chaiscript
/// \param[in] t_name Name of the value to add
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
/// \sa Boxed_Value::is_const
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
ChaiScript_Basic &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
{
Name_Validator::validate_object_name(t_name);
m_engine.add_global_const(t_bv, t_name);
return *this;
}
@@ -654,14 +395,16 @@ namespace chaiscript
/// \param[in] t_name Name of the value to add
/// \warning The user is responsible for making sure the object is thread-safe if necessary
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
ChaiScript_Basic &add_global(const Boxed_Value &t_bv, const std::string &t_name)
{
Name_Validator::validate_object_name(t_name);
m_engine.add_global(t_bv, t_name);
return *this;
}
ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name)
ChaiScript_Basic &set_global(const Boxed_Value &t_bv, const std::string &t_name)
{
Name_Validator::validate_object_name(t_name);
m_engine.set_global(t_bv, t_name);
return *this;
}
@@ -759,8 +502,9 @@ namespace chaiscript
///
/// \sa \ref adding_items
template<typename T>
ChaiScript &add(const T &t_t, const std::string &t_name)
ChaiScript_Basic &add(const T &t_t, const std::string &t_name)
{
Name_Validator::validate_object_name(t_name);
m_engine.add(t_t, t_name);
return *this;
}
@@ -774,7 +518,7 @@ namespace chaiscript
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
/// \endcode
ChaiScript &add(const Type_Conversion &d)
ChaiScript_Basic &add(const Type_Conversion &d)
{
m_engine.add(d);
return *this;
@@ -783,7 +527,7 @@ namespace chaiscript
/// \brief Adds all elements of a module to ChaiScript runtime
/// \param[in] t_p The module to add.
/// \sa chaiscript::Module
ChaiScript &add(const ModulePtr &t_p)
ChaiScript_Basic &add(const ModulePtr &t_p)
{
t_p->apply(*this, this->get_eval_engine());
return *this;
@@ -805,7 +549,7 @@ namespace chaiscript
{
std::vector<exception::load_module_error> errors;
std::string version_stripped_name = t_module_name;
size_t version_pos = version_stripped_name.find("-"+version());
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
if (version_pos != std::string::npos)
{
version_stripped_name.erase(version_pos);
@@ -835,21 +579,7 @@ namespace chaiscript
}
}
std::string errstring;
for (std::vector<exception::load_module_error>::const_iterator itr = errors.begin();
itr != errors.end();
++itr)
{
if (!errstring.empty())
{
errstring += "; ";
}
errstring += itr->what();
}
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
throw chaiscript::exception::load_module_error(t_module_name, errors);
}
/// \brief Load a binary module from a dynamic library. Works on platforms that support
@@ -886,14 +616,7 @@ namespace chaiscript
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
{
try {
return do_eval(t_script);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return eval(t_script, t_handler);
}
/// \brief Evaluates a string and returns a typesafe result.
@@ -912,21 +635,14 @@ namespace chaiscript
template<typename T>
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
{
try {
return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
}
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
decltype(auto) boxed_cast(const Boxed_Value &bv) const
{
return m_engine.boxed_cast<Type>(bv);
return(m_engine.boxed_cast<Type>(bv));
}
@@ -958,14 +674,7 @@ namespace chaiscript
/// \return result of the script execution
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return do_eval(load_file(t_filename), t_filename);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return eval(load_file(t_filename), t_handler, t_filename);
}
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
@@ -978,14 +687,7 @@ namespace chaiscript
/// to the requested type.
template<typename T>
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,427 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
#define CHAISCRIPT_OPTIMIZER_HPP_
#include "chaiscript_eval.hpp"
namespace chaiscript {
namespace optimizer {
template<typename ... T>
struct Optimizer : T...
{
Optimizer() = default;
explicit Optimizer(T ... t)
: T(std::move(t))...
{
}
template<typename Tracer>
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(p), 0)... };
return p;
}
};
template<typename T>
auto child_at(const eval::AST_Node_Impl_Ptr<T> &node, const size_t offset) {
if (node->children[offset]->identifier == AST_Node_Type::Compiled) {
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node->children[offset]).m_original_node;
} else {
return node->children[offset];
}
/*
if (node->identifier == AST_Node_Type::Compiled) {
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
} else {
return node->children[offset];
}
*/
}
template<typename T>
auto child_count(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Compiled) {
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children.size();
} else {
return node->children.size();
}
}
template<typename T, typename Callable>
auto make_compiled_node(const eval::AST_Node_Impl_Ptr<T> &original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
{
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(original_node, std::move(children), std::move(callable));
}
struct Return {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
{
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
&& !p->children.empty())
{
auto &last_child = p->children.back();
if (last_child->identifier == AST_Node_Type::Block) {
auto &block_last_child = last_child->children.back();
if (block_last_child->identifier == AST_Node_Type::Return) {
if (block_last_child->children.size() == 1) {
last_child->children.back() = block_last_child->children[0];
}
}
}
}
return p;
}
};
template<typename T>
bool contains_var_decl_in_scope(const T &node)
{
if (node->identifier == AST_Node_Type::Var_Decl) {
return true;
}
const auto num = child_count(node);
for (size_t i = 0; i < num; ++i) {
const auto &child = child_at(node, i);
if (child->identifier != AST_Node_Type::Block
&& child->identifier != AST_Node_Type::For
&& contains_var_decl_in_scope(child)) {
return true;
}
}
return false;
}
struct Block {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Block)
{
if (!contains_var_decl_in_scope(node))
{
if (node->children.size() == 1) {
return node->children[0];
} else {
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location, node->children);
}
}
}
return node;
}
};
struct Dead_Code {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Block)
{
std::vector<size_t> keepers;
const auto num_children = node->children.size();
keepers.reserve(num_children);
for (size_t i = 0; i < num_children; ++i) {
auto child = node->children[i];
if ( (child->identifier != AST_Node_Type::Id
&& child->identifier != AST_Node_Type::Constant
&& child->identifier != AST_Node_Type::Noop)
|| i == num_children - 1) {
keepers.push_back(i);
}
}
if (keepers.size() == num_children) {
return node;
} else {
std::vector<eval::AST_Node_Impl_Ptr<T>> new_children;
for (const auto x : keepers)
{
new_children.push_back(node->children[x]);
}
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children);
}
} else {
return node;
}
}
};
struct Unused_Return {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if ((node->identifier == AST_Node_Type::Block
|| node->identifier == AST_Node_Type::Scopeless_Block)
&& !node->children.empty())
{
for (size_t i = 0; i < node->children.size()-1; ++i) {
auto child = node->children[i];
if (child->identifier == AST_Node_Type::Fun_Call) {
node->children[i] = chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text, child->location, std::move(child->children));
}
}
} else if ((node->identifier == AST_Node_Type::For
|| node->identifier == AST_Node_Type::While)
&& child_count(node) > 0) {
auto child = child_at(node, child_count(node) - 1);
if (child->identifier == AST_Node_Type::Block
|| child->identifier == AST_Node_Type::Scopeless_Block)
{
auto num_sub_children = child_count(child);
for (size_t i = 0; i < num_sub_children; ++i) {
auto sub_child = child_at(child, i);
if (sub_child->identifier == AST_Node_Type::Fun_Call) {
child->children[i] = chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child->text, sub_child->location, std::move(sub_child->children));
}
}
}
}
return node;
}
};
struct If {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if ((node->identifier == AST_Node_Type::If)
&& node->children.size() >= 2
&& node->children[0]->identifier == AST_Node_Type::Constant)
{
const auto condition = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
if (boxed_cast<bool>(condition)) {
return node->children[1];
} else if (node->children.size() == 3) {
return node->children[2];
}
}
}
return node;
}
};
struct Partial_Fold {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
// Fold right side
if (node->identifier == AST_Node_Type::Binary
&& node->children.size() == 2
&& node->children[0]->identifier != AST_Node_Type::Constant
&& node->children[1]->identifier == AST_Node_Type::Constant)
{
try {
const auto &oper = node->text;
const auto parsed = Operators::to_operator(oper);
if (parsed != Operators::Opers::invalid) {
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
if (rhs.get_type_info().is_arithmetic()) {
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location, node->children, rhs);
}
}
} catch (const std::exception &) {
//failure to fold, that's OK
}
}
return node;
}
};
struct Constant_Fold {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Prefix
&& node->children.size() == 1
&& node->children[0]->identifier == AST_Node_Type::Constant)
{
try {
const auto &oper = node->text;
const auto parsed = Operators::to_operator(oper, true);
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
const auto match = oper + node->children[0]->text;
if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
const auto val = Boxed_Number::do_oper(parsed, lhs);
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
} else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") {
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(!boxed_cast<bool>(lhs)));
}
} catch (const std::exception &) {
//failure to fold, that's OK
}
} else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or)
&& node->children.size() == 2
&& node->children[0]->identifier == AST_Node_Type::Constant
&& node->children[1]->identifier == AST_Node_Type::Constant)
{
try {
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) {
const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text;
const auto val = [lhs_val = boxed_cast<bool>(lhs), rhs_val = boxed_cast<bool>(rhs), id = node->identifier] {
if (id == AST_Node_Type::Logical_And) { return Boxed_Value(lhs_val && rhs_val); }
else { return Boxed_Value(lhs_val || rhs_val); }
}();
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
}
} catch (const std::exception &) {
//failure to fold, that's OK
}
} else if (node->identifier == AST_Node_Type::Binary
&& node->children.size() == 2
&& node->children[0]->identifier == AST_Node_Type::Constant
&& node->children[1]->identifier == AST_Node_Type::Constant)
{
try {
const auto &oper = node->text;
const auto parsed = Operators::to_operator(oper);
if (parsed != Operators::Opers::invalid) {
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
}
}
} catch (const std::exception &) {
//failure to fold, that's OK
}
} else if (node->identifier == AST_Node_Type::Fun_Call
&& node->children.size() == 2
&& node->children[0]->identifier == AST_Node_Type::Id
&& node->children[1]->identifier == AST_Node_Type::Arg_List
&& node->children[1]->children.size() == 1
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
const auto arg = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1]->children[0])->m_value;
if (arg.get_type_info().is_arithmetic()) {
const auto &fun_name = node->children[0]->text;
const auto make_constant = [&node, &fun_name](auto val){
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
};
if (fun_name == "double") {
return make_constant(Boxed_Number(arg).get_as<double>());
} else if (fun_name == "int") {
return make_constant(Boxed_Number(arg).get_as<int>());
} else if (fun_name == "float") {
return make_constant(Boxed_Number(arg).get_as<float>());
} else if (fun_name == "long") {
return make_constant(Boxed_Number(arg).get_as<long>());
} else if (fun_name == "size_t") {
return make_constant(Boxed_Number(arg).get_as<size_t>());
}
}
}
return node;
}
};
struct For_Loop {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &for_node) {
if (for_node->identifier != AST_Node_Type::For) {
return for_node;
}
const auto eq_node = child_at(for_node, 0);
const auto binary_node = child_at(for_node, 1);
const auto prefix_node = child_at(for_node, 2);
if (eq_node->identifier == AST_Node_Type::Equation
&& child_count(eq_node) == 2
&& child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl
&& child_at(eq_node, 1)->identifier == AST_Node_Type::Constant
&& binary_node->identifier == AST_Node_Type::Binary
&& binary_node->text == "<"
&& child_count(binary_node) == 2
&& child_at(binary_node, 0)->identifier == AST_Node_Type::Id
&& child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text
&& child_at(binary_node, 1)->identifier == AST_Node_Type::Constant
&& prefix_node->identifier == AST_Node_Type::Prefix
&& prefix_node->text == "++"
&& child_count(prefix_node) == 1
&& child_at(prefix_node, 0)->identifier == AST_Node_Type::Id
&& child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text)
{
const Boxed_Value &begin = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(eq_node, 1))->m_value;
const Boxed_Value &end = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(binary_node, 1))->m_value;
const std::string &id = child_at(prefix_node, 0)->text;
if (begin.get_type_info().bare_equal(user_type<int>())
&& end.get_type_info().bare_equal(user_type<int>())) {
const auto start_int = boxed_cast<int>(begin);
const auto end_int = boxed_cast<int>(end);
const auto body = child_at(for_node, 3);
return make_compiled_node(for_node, {body},
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
assert(children.size() == 1);
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
int i = start_int;
t_ss.add_object(id, var(&i));
try {
for (; i < end_int; ++i) {
try {
// Body of Loop
children[0]->eval(t_ss);
} catch (eval::detail::Continue_Loop &) {
// we got a continue exception, which means all of the remaining
// loop implementation is skipped and we just need to continue to
// the next iteration step
}
}
} catch (eval::detail::Break_Loop &) {
// loop broken
}
return void_var();
}
);
} else {
return for_node;
}
} else {
return for_node;
}
}
};
typedef Optimizer<optimizer::Partial_Fold, optimizer::Unused_Return, optimizer::Constant_Fold,
optimizer::If, optimizer::Return, optimizer::Dead_Code, optimizer::Block, optimizer::For_Loop> Optimizer_Default;
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,81 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_POSIX_HPP_
#define CHAISCRIPT_POSIX_HPP_
namespace chaiscript
{
namespace detail
{
struct Loadable_Module
{
struct DLModule
{
explicit DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
{
if (m_data == nullptr)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
DLModule(DLModule &&) = default;
DLModule &operator=(DLModule &&) = default;
DLModule(const DLModule &) = delete;
DLModule &operator=(const DLModule &) = delete;
~DLModule()
{
dlclose(m_data);
}
void *m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
static T cast_symbol(void *p)
{
union cast_union
{
T func_ptr;
void *in_ptr;
};
cast_union c;
c.in_ptr = p;
return c.func_ptr;
}
T m_symbol;
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
}
}
#endif

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// and 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_
@@ -9,7 +9,7 @@
namespace chaiscript {
struct ChaiScript_Prelude {
static std::string chaiscript_prelude() { return R""(
static std::string chaiscript_prelude() { return R"chaiscript(
def lt(l, r) {
if (call_exists(`<`, l, r)) {
@@ -215,6 +215,29 @@ def for_each(container, func) : call_exists(range, container) {
}
}
def any_of(container, func) : call_exists(range, container) {
var t_range := range(container);
while (!t_range.empty()) {
if (func(t_range.front())) {
return true;
}
t_range.pop_front();
}
false;
}
def all_of(container, func) : call_exists(range, container) {
var t_range := range(container);
while (!t_range.empty()) {
if (!func(t_range.front())) {
return false;
}
t_range.pop_front();
}
true;
}
def back_inserter(container) {
bind(push_back, container, _);
}
@@ -530,7 +553,7 @@ def find(container, value) {
}
)"";
)chaiscript";
}
};

View File

@@ -505,7 +505,7 @@ class Function
/// \endcode
Vector get_contained_functions() const;
/// \brief Returns a vector of the contained functions
/// \brief Returns a function guard as function
///
/// Example:
/// \code

View File

@@ -0,0 +1,46 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_TRACER_HPP_
#define CHAISCRIPT_TRACER_HPP_
namespace chaiscript {
namespace eval {
struct Noop_Tracer_Detail
{
template<typename T>
void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
{
}
};
template<typename ... T>
struct Tracer : T...
{
Tracer() = default;
explicit Tracer(T ... t)
: T(std::move(t))...
{
}
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
(void)std::initializer_list<int>{ (static_cast<T&>(*this).trace(ds, node), 0)... };
}
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
}
};
typedef Tracer<Noop_Tracer_Detail> Noop_Tracer;
}
}
#endif

View File

@@ -0,0 +1,27 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UNKNOWN_HPP_
#define CHAISCRIPT_UNKNOWN_HPP_
namespace chaiscript
{
namespace detail
{
struct Loadable_Module
{
Loadable_Module(const std::string &, const std::string &)
{
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
}
ModulePtr m_moduleptr;
};
}
}
#endif

View File

@@ -0,0 +1,133 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_WINDOWS_HPP_
#define CHAISCRIPT_WINDOWS_HPP_
#include <string>
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
namespace chaiscript
{
namespace detail
{
struct Loadable_Module
{
template<typename T>
static std::wstring to_wstring(const T &t_str)
{
return std::wstring(t_str.begin(), t_str.end());
}
template<typename T>
static std::string to_string(const T &t_str)
{
return std::string(t_str.begin(), t_str.end());
}
#if defined(_UNICODE) || defined(UNICODE)
template<typename T>
static std::wstring to_proper_string(const T &t_str)
{
return to_wstring(t_str);
}
#else
template<typename T>
static std::string to_proper_string(const T &t_str)
{
return to_string(t_str);
}
#endif
static std::string get_error_message(DWORD t_err)
{
typedef LPTSTR StringType;
#if defined(_UNICODE) || defined(UNICODE)
std::wstring retval = L"Unknown Error";
#else
std::string retval = "Unknown Error";
#endif
StringType lpMsgBuf = nullptr;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<StringType>(&lpMsgBuf),
0, nullptr ) != 0 && lpMsgBuf)
{
retval = lpMsgBuf;
LocalFree(lpMsgBuf);
}
return to_string(retval);
}
struct DLModule
{
explicit DLModule(const std::string &t_filename)
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
DLModule(DLModule &&) = default;
DLModule &operator=(DLModule &&) = default;
DLModule(const DLModule &) = delete;
DLModule &operator=(const DLModule &) = delete;
~DLModule()
{
FreeLibrary(m_data);
}
HMODULE m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
T m_symbol;
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
}
}
#endif

View File

@@ -0,0 +1,22 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
#include <cstdint>
namespace chaiscript
{
namespace utility
{
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193));
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -9,11 +9,11 @@ namespace chaiscript
{
public:
static ModulePtr library(ModulePtr m = std::make_shared<Module>())
static Module& library(Module& m)
{
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");
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;
@@ -30,7 +30,7 @@ namespace chaiscript
{
std::map<std::string, Boxed_Value> m;
for (const auto &p : t_json.ObjectRange())
for (const auto &p : t_json.object_range())
{
m.insert(std::make_pair(p.first, from_json(p.second)));
}
@@ -41,7 +41,7 @@ namespace chaiscript
{
std::vector<Boxed_Value> vec;
for (const auto &p : t_json.ArrayRange())
for (const auto &p : t_json.array_range())
{
vec.emplace_back(from_json(p));
}
@@ -49,13 +49,13 @@ namespace chaiscript
return Boxed_Value(vec);
}
case json::JSON::Class::String:
return Boxed_Value(t_json.ToString());
return Boxed_Value(t_json.to_string());
case json::JSON::Class::Floating:
return Boxed_Value(t_json.ToFloat());
return Boxed_Value(t_json.to_float());
case json::JSON::Class::Integral:
return Boxed_Value(t_json.ToInt());
return Boxed_Value(t_json.to_int());
case json::JSON::Class::Boolean:
return Boxed_Value(t_json.ToBool());
return Boxed_Value(t_json.to_bool());
}
throw std::runtime_error("Unknown JSON type");
@@ -102,32 +102,24 @@ namespace chaiscript
try {
Boxed_Number bn(t_bv);
json::JSON obj;
if (Boxed_Number::is_floating_point(t_bv))
{
obj = bn.get_as<double>();
return json::JSON(bn.get_as<double>());
} else {
obj = bn.get_as<long>();
return json::JSON(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;
return json::JSON(boxed_cast<bool>(t_bv));
} 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;
return json::JSON(boxed_cast<std::string>(t_bv));
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a string
}

View File

@@ -0,0 +1,37 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
#define CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
namespace chaiscript
{
namespace utility
{
struct Static_String
{
template<size_t N>
constexpr Static_String(const char (&str)[N])
: m_size(N-1), data(&str[0])
{
}
constexpr size_t size() const {
return m_size;
}
constexpr const char *c_str() const {
return data;
}
const size_t m_size;
const char *data = nullptr;
};
}
}
#endif

View File

@@ -12,9 +12,8 @@
#include <utility>
#include <vector>
#include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
#include "../language/chaiscript_common.hpp"
#include "../dispatchkit/register_function.hpp"
#include "../dispatchkit/operators.hpp"
@@ -69,11 +68,7 @@ namespace chaiscript
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);
@@ -82,24 +77,41 @@ namespace chaiscript
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>()));
}());
equal<Enum>(t_module);
not_equal<Enum>(t_module);
assign<Enum>(t_module);
#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);
}
}
template<typename EnumClass, typename ModuleType>
typename std::enable_if<std::is_enum<EnumClass>::value, void>::type
add_class(ModuleType &t_module,
const std::string &t_class_name,
const std::vector<std::pair<EnumClass, std::string>> &t_constants
)
{
t_module.add(chaiscript::user_type<EnumClass>(), t_class_name);
t_module.add(chaiscript::constructor<EnumClass()>(), t_class_name);
t_module.add(chaiscript::constructor<EnumClass(const EnumClass &)>(), t_class_name);
using namespace chaiscript::bootstrap::operators;
equal<EnumClass>(t_module);
not_equal<EnumClass>(t_module);
assign<EnumClass>(t_module);
for (const auto &constant : t_constants)
{
t_module.add_global_const(chaiscript::const_var(EnumClass(constant.first)), constant.second);
}
}
}
}

View File

@@ -1,3 +1,8 @@
<a href="https://www.patreon.com/bePatron?u=2977989&redirect_uri=https%3A%2F%2Fwww.patreon.com%2Flefticus">
<img height="40" width="204" src="https://s3-us-west-1.amazonaws.com/widget-images/become-patron-widget-medium%402x.png">
</a>
Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=master)](http://codecov.io/github/ChaiScript/ChaiScript?branch=master)
Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=develop)](http://codecov.io/github/ChaiScript/ChaiScript?branch=develop)
@@ -38,10 +43,9 @@ languages:
Requirements
============
ChaiScript requires a C++11 compiler to build with support for variadic
templates. It has been tested with gcc 4.6 and clang 3.1 (with libcxx). MacOS
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
clang 4.0. MSVC 2013 or newer is supports also. For more information see the build
ChaiScript requires a C++14 compiler to build with support for variadic
templates. It has been tested with gcc 4.9 and clang 3.6 (with libcxx).
For more information see the build
[dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html).
Usage

View File

@@ -1,6 +1,54 @@
Notes:
=======
Current Version: 5.8.5
Current Version: 6.0.0
### Changes since 5.8.6
*6.0.0 is a massive rework compared to 5.x. It now requires a C++14 enabled compiler*
#### Compiler Requirements
* MSVC 2015 or greater
* g++ 4.9 or greater
* clang 3.6 or greater
#### Breaking Changes
* Instantiating a ChaiScript object now, by default, builds the stdlib in
* This was done to address the most common support issues of loading stdlib dynamically at runtime
* If you want the old behavior, use include/chaiscript/chaiscript_basic.hpp
* Headers have been reorganized to fully separate stdlib/parser/engine from each other (some faster builds)
* Bootstrap functions no longer return a reference to the module added to (compile time savings)
* It's now no longer possible modify AST_Nodes (compile time, runtime efficiency)
* Function annotations no longer exist (simplifies code, reduces compile time, compile size)
#### New Features Added
* Modular optimization system; this can be accessed via the ChaiScript_Basic interface
* Execution tracing capability; also accessed via ChaiScript_Basic interface
* range-based for loops `for( id : container ) { }`
* If-init expressions (ala C++17)
* Support for passing r-value references to functions
* Support for containing unique_ptr
* Add helpers for exposing enum classes to ChaiScript
#### Improvements
* Compile time improvements
* Compile size improvements
* Significant runtime improvements (see "Modular optimization system")
* Significant parser improvements, both with parse-time and parser initialization time (Thanks @niXman)
#### Improvements Still Need To Be Made
* File location tracking has been rewritten; this currently means error location reporting is not as good as it was
* Tracing capability needs to be tested and vetted
### 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

View File

@@ -73,7 +73,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//Create a new system object and share it with the chaiscript engine
System system;
chai.add(var(&system), "system");
chai.add_global(var(&system), "system");
//Add a bound callback method
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");

View File

@@ -1,5 +1,4 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
class Entity
{
@@ -57,7 +56,7 @@ class Factory
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&Entity::width), "width");
chai.add(chaiscript::fun(&Entity::height), "height");

View File

@@ -13,7 +13,6 @@
#endif
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
@@ -291,7 +290,7 @@ int main(int argc, char *argv[])
}
//chaiscript::ChaiScript chai(modulepaths, usepaths);
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths);
chaiscript::ChaiScript chai(usepaths);
chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit");

View File

@@ -1,5 +1,4 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
class BaseClass
{
@@ -44,14 +43,14 @@ class ChaiScriptDerived : public BaseClass
tie(t_funcs.at(1), m_validateValueImpl);
}
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
std::string doSomething(float f, double d) const override
{
assert(m_doSomethingImpl);
return m_doSomethingImpl(*this, f, d);
}
protected:
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
bool validateValue(const std::string &t_val) override
{
assert(m_validateValueImpl);
return m_validateValueImpl(*this, t_val);
@@ -70,7 +69,7 @@ class ChaiScriptDerived : public BaseClass
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");

View File

@@ -1,7 +1,6 @@
#include <iostream>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
@@ -32,16 +31,9 @@ void function(void)
class test
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript::State backupState;
chaiscript::ChaiScript::State backupState = chai.get_state();
public:
test()
: chai(chaiscript::Std_Lib::library())
{
backupState = chai.get_state();
}
~test(){}
void ResetState()
{
chai.set_state(backupState);

View File

@@ -1,11 +1,10 @@
#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( ) );
chaiscript::ChaiScript ch;
try

View File

@@ -12,7 +12,10 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
@@ -22,7 +25,7 @@
char *mystrdup (const char *s) {
size_t len = strlen(s); // Space for length plus nul
char *d = static_cast<char*>(malloc (len+1));
if (d == nullptr) return nullptr; // No memory
if (d == nullptr) { return nullptr; } // No memory
#ifdef CHAISCRIPT_MSVC
strcpy_s(d, len+1, s); // Copy the characters
#else
@@ -41,7 +44,7 @@ char* readline(const char* p)
}
void add_history(const char*){}
void add_history(const char* /*unused*/){}
void using_history(){}
#endif
@@ -113,7 +116,7 @@ std::vector<std::string> default_search_paths()
{
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
if ( !dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname ) {
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
return paths;
}
@@ -125,7 +128,7 @@ std::vector<std::string> default_search_paths()
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
if (lastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, lastslash));
paths.push_back(exepath.substr(0, lastslash+1));
}
if (secondtolastslash != std::string::npos)
@@ -181,7 +184,7 @@ std::string get_next_command() {
std::string retval("quit");
if ( ! std::cin.eof() ) {
char *input_raw = readline("eval> ");
if ( input_raw ) {
if ( input_raw != nullptr ) {
add_history(input_raw);
std::string val(input_raw);
@@ -217,7 +220,7 @@ void myexit(int return_val) {
exit(return_val);
}
void interactive(chaiscript::ChaiScript& chai)
void interactive(chaiscript::ChaiScript_Basic& chai)
{
using_history();
@@ -237,7 +240,7 @@ void interactive(chaiscript::ChaiScript& chai)
}
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what();
if (ee.call_stack.size() > 0) {
if ( !ee.call_stack.empty() ) {
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
}
std::cout << '\n';
@@ -274,7 +277,7 @@ int main(int argc, char *argv[])
std::vector<std::string> usepaths;
usepaths.push_back("");
if (usepath)
if (usepath != nullptr)
{
usepaths.push_back(usepath);
}
@@ -283,12 +286,12 @@ int main(int argc, char *argv[])
std::vector<std::string> searchpaths = default_search_paths();
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
modulepaths.push_back("");
if (modulepath)
if (modulepath != nullptr)
{
modulepaths.push_back(modulepath);
}
chaiscript::ChaiScript chai(modulepaths,usepaths);
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(),modulepaths,usepaths);
chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit");
@@ -305,7 +308,7 @@ int main(int argc, char *argv[])
++i;
}
std::string arg( i ? argv[i] : "--interactive" );
std::string arg( i != 0 ? argv[i] : "--interactive" );
enum { eInteractive
, eCommand
@@ -316,9 +319,9 @@ int main(int argc, char *argv[])
if ( (i+1) >= argc ) {
std::cout << "insufficient input following " << arg << '\n';
return EXIT_FAILURE;
} else {
}
arg = argv[++i];
}
} else if ( arg == "-" || arg == "--stdin" ) {
arg = "" ;
std::string line;
@@ -371,6 +374,9 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
}
catch (const chaiscript::exception::load_module_error &e) {
std::cout << "Unhandled module load error\n" << e.what() << '\n';
}
// catch (std::exception &e) {
// std::cout << e.what() << '\n';

View File

@@ -4,7 +4,7 @@
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <list>
#include <string>
@@ -23,9 +23,9 @@
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
{
auto module = chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
module->add(chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector"));
auto module = std::make_shared<chaiscript::Module>();
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List", *module);
chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector", *module);
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
return module;
}

View File

@@ -1,5 +1,5 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <string>
@@ -8,18 +8,10 @@
class TestBaseType
{
public:
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(push)
#pragma warning(disable : 4351)
#endif
// MSVC 12 warns that we are using new (correct) behavior
TestBaseType() : val(10), const_val(15), mdarray{} { }
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(pop)
#endif
TestBaseType(const TestBaseType &) = default;
virtual ~TestBaseType() {}
virtual int func() { return 0; }
@@ -30,6 +22,11 @@ class TestBaseType
int val;
const int const_val;
const int *const_val_ptr = &const_val;
const int *get_const_val_ptr() {
return const_val_ptr;
}
int mdarray[2][3][5];
std::function<int (int)> func_member;
@@ -84,7 +81,7 @@ class TestDerivedType : public TestBaseType
virtual ~TestDerivedType() {}
TestDerivedType(const TestDerivedType &) = default;
TestDerivedType() = default;
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
virtual int func() override { return 1; }
int derived_only_func() { return 19; }
private:
@@ -186,19 +183,15 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&TestBaseType::func), "func");
m->add(chaiscript::fun(&TestBaseType::val), "val");
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
m->add(chaiscript::fun(&TestBaseType::const_val_ptr), "const_val_ptr");
m->add(chaiscript::fun(&TestBaseType::get_const_val_ptr), "get_const_val_ptr");
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
#ifndef CHAISCRIPT_MSVC_12
// we cannot support these in MSVC_12 because of a bug in the implementation of
// std::reference_wrapper
// Array types
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
m->add(chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5"));
m->add(chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5"));
m->add(chaiscript::bootstrap::array<int[5]>("IntArray_5"));
// end array types
#endif
chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5", *m);
chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5", *m);
chaiscript::bootstrap::array<int[5]>("IntArray_5", *m);
// member that is a function
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");

View File

@@ -0,0 +1,8 @@
#include "../include/chaiscript/language/chaiscript_parser.hpp"
#include "chaiscript_parser.hpp"
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser()
{
return std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>();
}

View File

@@ -0,0 +1,13 @@
#ifndef CHAISCRIPT_PARSER_LIB
#define CHAISCRIPT_PARSER_LIB
namespace chaiscript {
namespace parser {
class ChaiScript_Parser_Base;
}
}
std::unique_ptr<chaiscript::parser::ChaiScript_Parser_Base> create_chaiscript_parser();
#endif

View File

@@ -0,0 +1,8 @@
#include "../include/chaiscript/chaiscript_stdlib.hpp"
#include "chaiscript_stdlib.hpp"
std::shared_ptr<chaiscript::Module> create_chaiscript_stdlib()
{
return chaiscript::Std_Lib::library();
}

View File

@@ -0,0 +1,11 @@
#ifndef CHAISCRIPT_STDLIB
#define CHAISCRIPT_STDLIB
namespace chaiscript {
class Module;
}
std::shared_ptr<chaiscript::Module> create_chaiscript_stdlib();
#endif

1
supporters.md Normal file
View File

@@ -0,0 +1 @@

View File

@@ -1,7 +1,6 @@
assert_equal(`==`, `==`);
assert_not_equal(`==`, `<`);
assert_equal(`<`.get_arity(), 2);
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
assert_equal(get_arity.get_contained_functions().size(), 0);
assert_equal(get_arity.get_arity(), 1);
assert_equal(get_arity.get_param_types().size(), 2);

View File

@@ -35,4 +35,4 @@ def while_doing()
var f = fun() { while_doing(); }
assert_equal(get_eval_error(f).call_stack.size(), 16)
assert_true(get_eval_error(f).call_stack.size() <= 16)

View File

@@ -10,7 +10,6 @@ def test_function(a)
// test_function tests
assert_equal(test_function.get_arity(), 1);
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
assert_equal(test_function.get_contained_functions().size(), 0);
assert_equal(test_function.get_param_types().size(), 2);

View File

@@ -1,36 +0,0 @@
var parser := ChaiScript_Parser()
var parse_success = parser.parse("3 + 4", "INPUT")
var a := parser.ast()
assert_equal(eval(a), 7)
var childs := a.children.front().children
var node := childs[0]
var parser2 := ChaiScript_Parser()
parser2.parse("9", "INPUT")
a.children.front().replace_child(childs[0], parser2.ast())
assert_equal(eval(a), 13)
assert_equal(node.filename, "INPUT")
def my_fun()
{
return 1;
}
assert_equal(true, my_fun.has_parse_tree());
assert_equal(false, `+`.has_parse_tree());
assert_throws("Function does not have a parse tree", fun() { `+`.get_parse_tree(); } );
var parsetree := my_fun.get_parse_tree();
assert_equal(1, eval(parsetree));
print(parsetree.text());

View File

@@ -206,7 +206,7 @@ bool built_in_type_test(const T &initial, bool ispod)
/** shared_ptr tests **/
std::shared_ptr<T> ip(new T(initial));
auto ip = std::make_shared<T>(initial);
passed &= do_test<T>(var(ip), true, true, true, true, true,
true, true, true, true, true,
@@ -221,7 +221,7 @@ bool built_in_type_test(const T &initial, bool ispod)
ispod, ispod, ispod, false, true);
/** const shared_ptr tests **/
std::shared_ptr<const T> ipc(new T(initial));
auto ipc = std::make_shared<const T>(T(initial));
passed &= do_test<T>(var(ipc), true, true, false, true, false,
true, false, true, false, true,

View File

@@ -1,4 +1,6 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"
extern "C"
@@ -11,8 +13,7 @@ extern "C"
int main()
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&do_something), "do_something");
return chai.eval<int>("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;

View File

@@ -1,6 +1,6 @@
/*
* Catch v1.3.5
* Generated: 2016-02-29 08:16:42.342094
* Catch v1.5.7
* Generated: 2016-09-27 10:45:46.824849
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -62,7 +62,11 @@
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#ifdef CATCH_CONFIG_COUNTER
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
#else
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#endif
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
@@ -89,7 +93,7 @@
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// ****************
// Note to maintainers: if new toggles are added please document them
// in configuration.md, too
@@ -102,8 +106,16 @@
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
#if defined(__cplusplus) && __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
#ifdef __cplusplus
# if __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
# endif
# if __cplusplus >= 201402L
# define CATCH_CPP14_OR_GREATER
# endif
#endif
#ifdef __clang__
@@ -185,6 +197,15 @@
#endif
// Use __COUNTER__ if the compiler supports it
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
( defined __clang__ && __clang_major__ >= 3 )
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
@@ -256,6 +277,9 @@
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
#endif
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -686,24 +710,28 @@ void registerTestCaseFunction
#ifdef CATCH_CONFIG_VARIADIC_MACROS
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void TestName()
#define INTERNAL_CATCH_TESTCASE( ... ) \
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
namespace{ \
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
struct TestName : ClassName{ \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
} \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
void TestName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
@@ -711,24 +739,28 @@ void registerTestCaseFunction
#else
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
static void TestName(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void TestName()
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
namespace{ \
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
struct TestCaseName : ClassName{ \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
} \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
void TestCaseName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
@@ -2041,7 +2073,7 @@ namespace Catch {
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
} \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::isTrue( false && static_cast<bool>(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
} while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
@@ -2578,10 +2610,12 @@ namespace Catch {
}
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
static std::string translatorName( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
static std::string translatorName( signature )
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
// #included from: internal/catch_approx.hpp
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
@@ -3189,10 +3223,11 @@ namespace Catch {
bool matches( TestCaseInfo const& testCase ) const {
// All patterns in a filter must match for the filter to be a match
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
if( !(*it)->matches( testCase ) )
return false;
return true;
}
return true;
}
};
@@ -3424,7 +3459,7 @@ namespace Catch {
};
class DebugOutStream : public IStream {
std::auto_ptr<StreamBufBase> m_streamBuf;
CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
mutable std::ostream m_os;
public:
DebugOutStream();
@@ -3572,7 +3607,7 @@ namespace Catch {
}
ConfigData m_data;
std::auto_ptr<IStream const> m_stream;
CATCH_AUTO_PTR( IStream const ) m_stream;
TestSpec m_testSpec;
};
@@ -3592,7 +3627,7 @@ namespace Catch {
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
// #included from: ../external/clara.h
// Version 0.0.1.1
// Version 0.0.2.4
// Only use header guard if we are not using an outer namespace
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
@@ -3908,6 +3943,10 @@ namespace Tbc {
#include <stdexcept>
#include <memory>
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#define CLARA_PLATFORM_WINDOWS
#endif
// Use optional outer namespace
#ifdef STITCH_CLARA_OPEN_NAMESPACE
STITCH_CLARA_OPEN_NAMESPACE
@@ -3931,9 +3970,6 @@ namespace Clara {
const unsigned int consoleWidth = 80;
#endif
// Use this to try and stop compiler from warning about unreachable code
inline bool isTrue( bool value ) { return value; }
using namespace Tbc;
inline bool startsWith( std::string const& str, std::string const& prefix ) {
@@ -3969,14 +4005,6 @@ namespace Clara {
else
throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
}
inline void convertInto( bool _source, bool& _dest ) {
_dest = _source;
}
template<typename T>
inline void convertInto( bool, T& ) {
if( isTrue( true ) )
throw std::runtime_error( "Invalid conversion" );
}
template<typename ConfigT>
struct IArgFunction {
@@ -3986,7 +4014,6 @@ namespace Clara {
IArgFunction( IArgFunction const& ) = default;
#endif
virtual void set( ConfigT& config, std::string const& value ) const = 0;
virtual void setFlag( ConfigT& config ) const = 0;
virtual bool takesArg() const = 0;
virtual IArgFunction* clone() const = 0;
};
@@ -4008,9 +4035,6 @@ namespace Clara {
void set( ConfigT& config, std::string const& value ) const {
functionObj->set( config, value );
}
void setFlag( ConfigT& config ) const {
functionObj->setFlag( config );
}
bool takesArg() const { return functionObj->takesArg(); }
bool isSet() const {
@@ -4023,7 +4047,6 @@ namespace Clara {
template<typename C>
struct NullBinder : IArgFunction<C>{
virtual void set( C&, std::string const& ) const {}
virtual void setFlag( C& ) const {}
virtual bool takesArg() const { return true; }
virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
};
@@ -4034,9 +4057,6 @@ namespace Clara {
virtual void set( C& p, std::string const& stringValue ) const {
convertInto( stringValue, p.*member );
}
virtual void setFlag( C& p ) const {
convertInto( true, p.*member );
}
virtual bool takesArg() const { return !IsBool<M>::value; }
virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
M C::* member;
@@ -4049,11 +4069,6 @@ namespace Clara {
convertInto( stringValue, value );
(p.*member)( value );
}
virtual void setFlag( C& p ) const {
typename RemoveConstRef<M>::type value;
convertInto( true, value );
(p.*member)( value );
}
virtual bool takesArg() const { return !IsBool<M>::value; }
virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
void (C::*member)( M );
@@ -4067,9 +4082,6 @@ namespace Clara {
if( value )
(p.*member)();
}
virtual void setFlag( C& p ) const {
(p.*member)();
}
virtual bool takesArg() const { return false; }
virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
void (C::*member)();
@@ -4084,9 +4096,6 @@ namespace Clara {
if( value )
function( obj );
}
virtual void setFlag( C& p ) const {
function( p );
}
virtual bool takesArg() const { return false; }
virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
void (*function)( C& );
@@ -4100,11 +4109,6 @@ namespace Clara {
convertInto( stringValue, value );
function( obj, value );
}
virtual void setFlag( C& obj ) const {
typename RemoveConstRef<T>::type value;
convertInto( true, value );
function( obj, value );
}
virtual bool takesArg() const { return !IsBool<T>::value; }
virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
void (*function)( C&, T );
@@ -4112,8 +4116,20 @@ namespace Clara {
} // namespace Detail
struct Parser {
Parser() : separators( " \t=:" ) {}
inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
std::vector<std::string> args( static_cast<std::size_t>( argc ) );
for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
args[i] = argv[i];
return args;
}
class Parser {
enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
Mode mode;
std::size_t from;
bool inQuotes;
public:
struct Token {
enum Type { Positional, ShortOpt, LongOpt };
@@ -4122,38 +4138,75 @@ namespace Clara {
std::string data;
};
void parseIntoTokens( int argc, char const* const argv[], std::vector<Parser::Token>& tokens ) const {
Parser() : mode( None ), from( 0 ), inQuotes( false ){}
void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
const std::string doubleDash = "--";
for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
parseIntoTokens( argv[i] , tokens);
for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
parseIntoTokens( args[i], tokens);
}
void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
while( !arg.empty() ) {
Parser::Token token( Parser::Token::Positional, arg );
arg = "";
if( token.data[0] == '-' ) {
if( token.data.size() > 1 && token.data[1] == '-' ) {
token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
}
else {
token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
arg = "-" + token.data.substr( 1 );
token.data = token.data.substr( 0, 1 );
}
}
}
if( token.type != Parser::Token::Positional ) {
std::size_t pos = token.data.find_first_of( separators );
if( pos != std::string::npos ) {
arg = token.data.substr( pos+1 );
token.data = token.data.substr( 0, pos );
}
}
tokens.push_back( token );
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
for( std::size_t i = 0; i <= arg.size(); ++i ) {
char c = arg[i];
if( c == '"' )
inQuotes = !inQuotes;
mode = handleMode( i, c, arg, tokens );
}
}
std::string separators;
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
switch( mode ) {
case None: return handleNone( i, c );
case MaybeShortOpt: return handleMaybeShortOpt( i, c );
case ShortOpt:
case LongOpt:
case SlashOpt: return handleOpt( i, c, arg, tokens );
case Positional: return handlePositional( i, c, arg, tokens );
default: throw std::logic_error( "Unknown mode" );
}
}
Mode handleNone( std::size_t i, char c ) {
if( inQuotes ) {
from = i;
return Positional;
}
switch( c ) {
case '-': return MaybeShortOpt;
#ifdef CLARA_PLATFORM_WINDOWS
case '/': from = i+1; return SlashOpt;
#endif
default: from = i; return Positional;
}
}
Mode handleMaybeShortOpt( std::size_t i, char c ) {
switch( c ) {
case '-': from = i+1; return LongOpt;
default: from = i; return ShortOpt;
}
}
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
return mode;
std::string optName = arg.substr( from, i-from );
if( mode == ShortOpt )
for( std::size_t j = 0; j < optName.size(); ++j )
tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
else if( mode == SlashOpt && optName.size() == 1 )
tokens.push_back( Token( Token::ShortOpt, optName ) );
else
tokens.push_back( Token( Token::LongOpt, optName ) );
return None;
}
Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
return mode;
std::string data = arg.substr( from, i-from );
tokens.push_back( Token( Token::Positional, data ) );
return None;
}
};
template<typename ConfigT>
@@ -4456,21 +4509,21 @@ namespace Clara {
return oss.str();
}
ConfigT parse( int argc, char const* const argv[] ) const {
ConfigT parse( std::vector<std::string> const& args ) const {
ConfigT config;
parseInto( argc, argv, config );
parseInto( args, config );
return config;
}
std::vector<Parser::Token> parseInto( int argc, char const* argv[], ConfigT& config ) const {
std::string processName = argv[0];
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
std::string processName = args[0];
std::size_t lastSlash = processName.find_last_of( "/\\" );
if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 );
m_boundProcessName.set( config, processName );
std::vector<Parser::Token> tokens;
Parser parser;
parser.parseIntoTokens( argc, argv, tokens );
parser.parseIntoTokens( args, tokens );
return populate( tokens, config );
}
@@ -4501,7 +4554,7 @@ namespace Clara {
arg.boundField.set( config, tokens[++i].data );
}
else {
arg.boundField.setFlag( config );
arg.boundField.set( config, "true" );
}
break;
}
@@ -4667,8 +4720,11 @@ namespace Catch {
std::string line;
while( std::getline( f, line ) ) {
line = trim(line);
if( !line.empty() && !startsWith( line, "#" ) )
addTestOrTags( config, "\"" + line + "\"," );
if( !line.empty() && !startsWith( line, "#" ) ) {
if( !startsWith( line, "\"" ) )
line = "\"" + line + "\"";
addTestOrTags( config, line + "," );
}
}
}
@@ -5209,6 +5265,8 @@ namespace Catch
bool aborting;
};
class MultipleReporters;
struct IStreamingReporter : IShared {
virtual ~IStreamingReporter();
@@ -5236,6 +5294,8 @@ namespace Catch
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
};
struct IReporterFactory : IShared {
@@ -5312,7 +5372,10 @@ namespace Catch {
++it ) {
matchedTests++;
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Catch::cout() << testCaseInfo.name << std::endl;
if( startsWith( testCaseInfo.name, "#" ) )
Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
else
Catch::cout() << testCaseInfo.name << std::endl;
}
return matchedTests;
}
@@ -5453,6 +5516,10 @@ namespace TestCaseTracking {
virtual void addChild( Ptr<ITracker> const& child ) = 0;
virtual ITracker* findChild( std::string const& name ) = 0;
virtual void openChild() = 0;
// Debug/ checking
virtual bool isSectionTracker() const = 0;
virtual bool isIndexTracker() const = 0;
};
class TrackerContext {
@@ -5577,6 +5644,10 @@ namespace TestCaseTracking {
m_parent->openChild();
}
}
virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
void open() {
m_runState = Executing;
moveToThis();
@@ -5640,13 +5711,16 @@ namespace TestCaseTracking {
{}
virtual ~SectionTracker();
virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
SectionTracker* section = CATCH_NULL;
ITracker& currentTracker = ctx.currentTracker();
if( ITracker* childTracker = currentTracker.findChild( name ) ) {
section = dynamic_cast<SectionTracker*>( childTracker );
assert( section );
assert( childTracker );
assert( childTracker->isSectionTracker() );
section = static_cast<SectionTracker*>( childTracker );
}
else {
section = new SectionTracker( name, ctx, &currentTracker );
@@ -5671,13 +5745,16 @@ namespace TestCaseTracking {
{}
virtual ~IndexTracker();
virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
IndexTracker* tracker = CATCH_NULL;
ITracker& currentTracker = ctx.currentTracker();
if( ITracker* childTracker = currentTracker.findChild( name ) ) {
tracker = dynamic_cast<IndexTracker*>( childTracker );
assert( tracker );
assert( childTracker );
assert( childTracker->isIndexTracker() );
tracker = static_cast<IndexTracker*>( childTracker );
}
else {
tracker = new IndexTracker( name, ctx, &currentTracker, size );
@@ -5884,6 +5961,11 @@ namespace Catch {
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
Totals deltaTotals = m_totals.delta( prevTotals );
if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
deltaTotals.assertions.failed++;
deltaTotals.testCases.passed--;
deltaTotals.testCases.failed++;
}
m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( testInfo,
deltaTotals,
@@ -6275,10 +6357,10 @@ namespace Catch {
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
}
int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try {
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
if( m_configData.showHelp )
showHelp( m_configData.processName );
m_config.reset();
@@ -6302,16 +6384,13 @@ namespace Catch {
m_config.reset();
}
int run( int argc, char const* argv[] ) {
int run( int argc, char const* const* const argv ) {
int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 )
returnCode = run();
return returnCode;
}
int run( int argc, char* argv[] ) {
return run( argc, const_cast<char const**>( argv ) );
}
int run() {
if( m_configData.showHelp )
@@ -6375,13 +6454,31 @@ namespace Catch {
#include <iostream>
#include <algorithm>
#ifdef CATCH_CPP14_OR_GREATER
#include <random>
#endif
namespace Catch {
struct LexSort {
bool operator() (TestCase i,TestCase j) const { return (i<j);}
};
struct RandomNumberGenerator {
int operator()( int n ) const { return std::rand() % n; }
typedef int result_type;
result_type operator()( result_type n ) const { return std::rand() % n; }
#ifdef CATCH_CPP14_OR_GREATER
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return 1000000; }
result_type operator()() const { return std::rand() % max(); }
#endif
template<typename V>
static void shuffle( V& vector ) {
RandomNumberGenerator rng;
#ifdef CATCH_CPP14_OR_GREATER
std::shuffle( vector.begin(), vector.end(), rng );
#else
std::random_shuffle( vector.begin(), vector.end(), rng );
#endif
}
};
inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
@@ -6390,14 +6487,12 @@ namespace Catch {
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( sorted.begin(), sorted.end(), LexSort() );
std::sort( sorted.begin(), sorted.end() );
break;
case RunTests::InRandomOrder:
{
seedRng( config );
RandomNumberGenerator rng;
std::random_shuffle( sorted.begin(), sorted.end(), rng );
RandomNumberGenerator::shuffle( sorted );
}
break;
case RunTests::InDeclarationOrder:
@@ -6416,13 +6511,15 @@ namespace Catch {
it != itEnd;
++it ) {
std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
if( !prev.second ){
Catch::cerr()
<< Colour( Colour::Red )
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
exit(1);
if( !prev.second ) {
std::ostringstream ss;
ss << Colour( Colour::Red )
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
throw std::runtime_error(ss.str());
}
}
}
@@ -7481,7 +7578,7 @@ namespace Catch {
return os;
}
Version libraryVersion( 1, 3, 5, "", 0 );
Version libraryVersion( 1, 5, 7, "", 0 );
}
@@ -8460,13 +8557,18 @@ public: // IStreamingReporter
++it )
(*it)->skipTest( testInfo );
}
virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
return this;
}
};
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
Ptr<IStreamingReporter> resultingReporter;
if( existingReporter ) {
MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() );
MultipleReporters* multi = existingReporter->tryAsMulti();
if( !multi ) {
multi = new MultipleReporters;
resultingReporter = Ptr<IStreamingReporter>( multi );
@@ -8646,7 +8748,7 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
assert( !m_sectionStack.empty() );
SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back( assertionStats );
@@ -8856,9 +8958,10 @@ namespace Catch {
break;
default:
// Escape control chars - based on contribution by @espenalb in PR #465
// Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
else
os << c;
}
@@ -8913,13 +9016,20 @@ namespace Catch {
: m_tagIsOpen( false ),
m_needsNewline( false ),
m_os( &Catch::cout() )
{}
{
// We encode control characters, which requires
// XML 1.1
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
}
XmlWriter( std::ostream& os )
: m_tagIsOpen( false ),
m_needsNewline( false ),
m_os( &os )
{}
{
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
}
~XmlWriter() {
while( !m_tags.empty() )
@@ -9086,7 +9196,7 @@ namespace Catch {
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseStarting(testInfo);
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
if ( m_config->showDurations() == ShowDurations::Always )
m_testCaseTimer.start();
@@ -9777,7 +9887,7 @@ namespace Catch {
if( totals.testCases.total() == 0 ) {
stream << Colour( Colour::Warning ) << "No tests ran\n";
}
else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
stream << Colour( Colour::ResultSuccess ) << "All tests passed";
stream << " ("
<< pluralise( totals.assertions.passed, "assertion" ) << " in "

View File

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

View File

@@ -0,0 +1,38 @@
GLOBAL clone_count = 0;
class Cloneable
{
def Cloneable() {
}
}
def clone(Cloneable c)
{
print("Clone called");
++clone_count;
return c;
}
class MyObject
{
def MyObject() {
this.data = Cloneable();
}
var data;
}
assert_equal(0, clone_count);
var o = MyObject();
assert_equal(0, clone_count);
var p = o;
assert_equal(1, clone_count);

View File

@@ -16,9 +16,12 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/utility/utility.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"
@@ -34,7 +37,7 @@ TEST_CASE("C++11 Lambdas Can Be Registered")
// We cannot deduce the type of a lambda expression, you must either wrap it
// in an std::function or provide the signature
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun([]()->std::string { return "hello"; } ), "f1");
@@ -49,7 +52,7 @@ TEST_CASE("C++11 Lambdas Can Be Registered")
// dynamic_object tests
TEST_CASE("Dynamic_Object attributes can be shared with C++")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai("attr bob::z; def bob::bob() { this.z = 10 }; auto x = bob()");
@@ -77,7 +80,7 @@ TEST_CASE("Dynamic_Object attributes can be shared with C++")
TEST_CASE("Function objects can be created from chaiscript functions")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.eval("def func() { print(\"Hello World\"); } ");
@@ -91,7 +94,7 @@ TEST_CASE("Function objects can be created from chaiscript functions")
TEST_CASE("ChaiScript can be created and destroyed on heap")
{
chaiscript::ChaiScript *chai = new chaiscript::ChaiScript();
auto *chai = new chaiscript::ChaiScript_Basic(create_chaiscript_stdlib(),create_chaiscript_parser());
delete chai;
}
@@ -123,7 +126,7 @@ void arithmetic_conversions_f_func_return(const std::function<unsigned int (unsi
TEST_CASE("Test automatic arithmetic conversions")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&arithmetic_conversions_f1), "f1");
chai.add(chaiscript::fun(&arithmetic_conversions_f2), "f2");
@@ -164,7 +167,7 @@ TEST_CASE("Test automatic arithmetic conversions")
TEST_CASE("Generic exception handling with C++")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
try {
chai.eval("throw(runtime_error(\"error\"));");
@@ -177,7 +180,7 @@ TEST_CASE("Generic exception handling with C++")
TEST_CASE("Throw an int")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
try {
chai.eval("throw(1)", chaiscript::exception_specification<int>());
@@ -189,7 +192,7 @@ TEST_CASE("Throw an int")
TEST_CASE("Throw int or double")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
try {
chai.eval("throw(1.0)", chaiscript::exception_specification<int, double>());
@@ -201,7 +204,7 @@ TEST_CASE("Throw int or double")
TEST_CASE("Throw a runtime_error")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
try {
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
@@ -221,7 +224,7 @@ TEST_CASE("Throw a runtime_error")
TEST_CASE("Throw unhandled type")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
try {
chai.eval("throw(\"error\")", chaiscript::exception_specification<int, double, float, const std::exception &>());
@@ -250,7 +253,7 @@ int expected_eval_errors_test_one(const int &)
TEST_CASE("No unexpected exceptions leak")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&expected_eval_errors_test_one), "test_fun");
chai.eval("def guard_fun(i) : i.get_type_info().is_type_arithmetic() {} ");
@@ -313,10 +316,11 @@ int function_ordering_test_two(int &)
TEST_CASE("Function ordering")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.eval("def test_fun(x) { return 3; }");
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
// chai.eval("def test_fun(x) { return 5; }");
chai.eval("def test_fun(double d) { return 5; }");
chai.add(chaiscript::fun(&function_ordering_test_one), "test_fun");
chai.add(chaiscript::fun(&function_ordering_test_two), "test_fun");
@@ -324,6 +328,7 @@ TEST_CASE("Function ordering")
CHECK(chai.eval<int>("auto i = 1; test_fun(i)") == 2);
CHECK(chai.eval<int>("test_fun(\"bob\")") == 3);
CHECK(chai.eval<int>("test_fun(\"hi\")") == 4);
CHECK(chai.eval<int>("test_fun(5.0)") == 5);
}
@@ -337,7 +342,7 @@ int functor_cast_test_call(const std::function<int (int)> &f, int val)
TEST_CASE("Functor cast")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&functor_cast_test_call), "test_call");
@@ -356,10 +361,10 @@ int set_state_test_myfun()
TEST_CASE("Set and restore chai state")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
// save the initial state of globals and locals
chaiscript::ChaiScript::State firststate = chai.get_state();
auto firststate = chai.get_state();
std::map<std::string, chaiscript::Boxed_Value> locals = chai.get_locals();
// add some new globals and locals
@@ -402,7 +407,7 @@ class Short_Comparison_Test {
TEST_CASE("Short comparison with int")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::user_type<Short_Comparison_Test>(), "Test");
chai.add(chaiscript::constructor<Short_Comparison_Test()>(), "Test");
@@ -425,7 +430,7 @@ class Type_Name_MyClass
TEST_CASE("Test lookup of type names")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
auto type = chaiscript::user_type<Type_Name_MyClass>();
chai.add(type, "MyClass");
@@ -451,13 +456,13 @@ int simultaneous_chaiscript_do_something_else(int i)
TEST_CASE("Simultaneous ChaiScript tests")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&simultaneous_chaiscript_do_something), "do_something");
chai.add(chaiscript::var(1), "i");
for (int i = 0; i < 10; ++i)
{
chaiscript::ChaiScript chai2;
chaiscript::ChaiScript_Basic chai2(create_chaiscript_stdlib(),create_chaiscript_parser());
chai2.add(chaiscript::fun(&simultaneous_chaiscript_do_something_else), "do_something_else");
CHECK(chai.eval<int>("do_something(" + std::to_string(i) + ")") == i + 2);
@@ -506,7 +511,7 @@ TEST_CASE("Utility_Test utility class wrapper")
);
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(m);
CHECK(chai.eval<std::string>("auto t = Utility_Test(); t.function2(); ") == "Function2");
@@ -549,7 +554,7 @@ TEST_CASE("Utility_Test utility class wrapper for enum")
);
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(m);
CHECK(chai.eval<Utility_Test_Numbers>("ONE ") == 0);
@@ -644,7 +649,7 @@ TEST_CASE("Object copy counts")
m->add(chaiscript::constructor<Object_Copy_Count_Test(const Object_Copy_Count_Test &)>(), "Object_Copy_Count_Test");
m->add(chaiscript::fun(&object_copy_count_create), "create");
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(m);
chai.eval(" { auto i = create(); } ");
@@ -700,7 +705,7 @@ TEST_CASE("Object lifetime tests")
m->add(chaiscript::constructor<Object_Lifetime_Test(const Object_Lifetime_Test &)>(), "Object_Lifetime_Test");
m->add(chaiscript::fun(&Object_Lifetime_Test::count), "count");
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(m);
CHECK(chai.eval<int>("count()") == 0);
@@ -753,7 +758,7 @@ Object_Lifetime_Vector2<float> Object_Lifetime_Vector2_GetValue()
TEST_CASE("Object lifetime test 2")
{
chaiscript::ChaiScript _script;
chaiscript::ChaiScript_Basic _script(create_chaiscript_stdlib(),create_chaiscript_parser());
//Registering stuff
_script.add(chaiscript::user_type<Object_Lifetime_Vector2<float>>(), "Object_Lifetime_Vector2f");
@@ -794,7 +799,7 @@ int myfunction(Non_Poly_Base *)
TEST_CASE("Test Derived->Base with non-polymorphic classes")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::base_class<Non_Poly_Base, Non_Poly_Derived>());
Non_Poly_Derived d;
chai.add(chaiscript::var(&d), "d");
@@ -813,7 +818,7 @@ struct TestCppVariableScope
TEST_CASE("Variable Scope When Calling From C++")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::user_type<TestCppVariableScope>(), "Test");
chai.add(chaiscript::constructor<TestCppVariableScope()>(), "Test");
chai.add(chaiscript::fun(&TestCppVariableScope::print), "print");
@@ -836,7 +841,7 @@ TEST_CASE("Variable Scope When Calling From C++")
TEST_CASE("Variable Scope When Calling From C++ 2")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.eval("var obj = 2;");
auto func = chai.eval<std::function<void()>>("fun(){ return obj; }");
CHECK_THROWS(func());
@@ -853,7 +858,7 @@ void longlong(long long i) {
TEST_CASE("Test long long dispatch")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&longlong), "longlong");
chai.add(chaiscript::fun(&ulonglong), "ulonglong");
chai.eval("longlong(15)");
@@ -873,7 +878,7 @@ struct Returned_Converted_Config
TEST_CASE("Return of converted type from script")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::constructor<Returned_Converted_Config ()>(), "Returned_Converted_Config");
chai.add(chaiscript::fun(&Returned_Converted_Config::num_iterations), "num_iterations");
@@ -921,7 +926,7 @@ int get_value_a(const std::map<std::string, int> &t_m)
TEST_CASE("Map conversions")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
chai.add(chaiscript::fun(&get_value_a), "get_value_a");
@@ -941,7 +946,7 @@ TEST_CASE("Parse floats with non-posix locale")
#else
std::setlocale(LC_ALL, "en_ZA.utf8");
#endif
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
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)");
@@ -958,7 +963,7 @@ bool FindBitmap(int &ox, int &oy, long) {
TEST_CASE("Mismatched numeric types only convert necessary params")
{
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&FindBitmap), "FindBitmap");
int x = 0;
@@ -980,4 +985,149 @@ TEST_CASE("type_conversion to bool")
module->add(chaiscript::type_conversion<T, bool>());
}
TEST_CASE("Make sure ChaiScript object still compiles / executes")
{
chaiscript::ChaiScript chai;
}
struct Count_Tracer
{
int count = 0;
template<typename T>
void trace(const chaiscript::detail::Dispatch_State &, const chaiscript::eval::AST_Node_Impl<T> *)
{
++count;
}
};
TEST_CASE("Test count tracer")
{
typedef chaiscript::parser::ChaiScript_Parser< chaiscript::eval::Tracer<Count_Tracer>, chaiscript::optimizer::Optimizer_Default > Parser_Type;
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library(),
std::make_unique<Parser_Type>());
Parser_Type &parser = dynamic_cast<Parser_Type &>(chai.get_parser());
const auto count = parser.get_tracer().count;
chai.eval("");
CHECK(parser.get_tracer().count > count);
}
TEST_CASE("Test stdlib options")
{
const auto test_has_external_scripts = [](chaiscript::ChaiScript_Basic &chai) {
CHECK_NOTHROW(chai.eval("`use`"));
CHECK_NOTHROW(chai.eval("`eval_file`"));
};
const auto test_no_external_scripts = [](chaiscript::ChaiScript_Basic &chai) {
CHECK_THROWS(chai.eval("`use`"));
CHECK_THROWS(chai.eval("`eval_file`"));
};
const auto test_has_load_modules = [](chaiscript::ChaiScript_Basic &chai) {
CHECK_NOTHROW(chai.eval("`load_module`"));
};
const auto test_no_load_modules = [](chaiscript::ChaiScript_Basic &chai) {
CHECK_THROWS(chai.eval("`load_module`"));
};
SECTION( "Defaults" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
test_has_external_scripts(chai);
test_has_load_modules(chai);
}
SECTION( "Load_Modules, External_Scripts" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
{chaiscript::Options::Load_Modules, chaiscript::Options::External_Scripts} );
test_has_external_scripts(chai);
test_has_load_modules(chai);
}
SECTION( "No_Load_Modules, No_External_Scripts" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts} );
test_no_external_scripts(chai);
test_no_load_modules(chai);
}
SECTION( "No_Load_Modules, Load_Modules" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::Load_Modules} );
test_no_external_scripts(chai);
test_no_load_modules(chai);
}
SECTION( "No_External_Scripts, External_Scripts" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
{chaiscript::Options::No_External_Scripts, chaiscript::Options::External_Scripts} );
test_no_external_scripts(chai);
test_no_load_modules(chai);
}
SECTION( "No_External_Scripts, Load_Modules" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
{chaiscript::Options::No_External_Scripts, chaiscript::Options::Load_Modules} );
test_no_external_scripts(chai);
test_has_load_modules(chai);
}
SECTION( "External_Scripts, No_Load_Modules" ) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
{chaiscript::Options::External_Scripts, chaiscript::Options::No_Load_Modules} );
test_has_external_scripts(chai);
test_no_load_modules(chai);
}
}
void uservalueref(int &&)
{
}
void usemoveonlytype(std::unique_ptr<int> &&)
{
}
TEST_CASE("Pass r-value reference to func")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&uservalueref), "uservalueref");
chai.add(chaiscript::fun(&usemoveonlytype), "usemoveonlytype");
chai.add(chaiscript::var(std::make_unique<int>(1)), "iptr");
chai.eval("usemoveonlytype(iptr)");
}
TEST_CASE("Use unique_ptr")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun([](int &i){ ++i; }), "inci");
chai.add(chaiscript::fun([](int i){ ++i; }), "copyi");
chai.add(chaiscript::fun([](int *i){ ++(*i); }), "derefi");
chai.add(chaiscript::var(std::make_unique<int>(1)), "iptr");
CHECK(chai.eval<int>("iptr") == 1);
chai.eval("inci(iptr)");
CHECK(chai.eval<int>("iptr") == 2);
chai.eval("copyi(iptr)");
CHECK(chai.eval<int>("iptr") == 2);
chai.eval("derefi(iptr)");
CHECK(chai.eval<int>("iptr") == 3);
}

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

@@ -1,7 +1,6 @@
assert_equal(`==`, `==`);
assert_not_equal(`==`, `<`);
assert_equal(`<`.get_arity(), 2);
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
assert_equal(get_arity.get_contained_functions().size(), 0);
assert_equal(get_arity.get_arity(), 1);
assert_equal(get_arity.get_param_types().size(), 2);

View File

@@ -0,0 +1,26 @@
class MyClass
{
def MyClass()
{
this.x = 2;
}
var x;
}
var o = MyClass();
var o2 = MyClass();
o2.x = 5;
o = o2;
assert_true(o.x == 5)
assert_true(o == o2)
o2.x = 3;
print(o2.x);
print(o.x);
assert_true(o != o2)

View File

@@ -35,4 +35,4 @@ def while_doing()
auto f = fun() { while_doing(); }
assert_equal(get_eval_error(f).call_stack.size(), 16)
assert_true(get_eval_error(f).call_stack.size() <= 16)

View File

@@ -0,0 +1,42 @@
assert_equal(__LINE__, 3)
def f() {
[__LINE__, __CLASS__, __FUNC__]
}
var res = f()
assert_equal(res[0], 6)
assert_equal(res[1], "NOT_IN_CLASS")
assert_equal(res[2], "f")
assert_equal(__CLASS__, "NOT_IN_CLASS")
assert_equal(__FUNC__, "NOT_IN_FUNCTION")
class C
{
def C() {}
def member() { [__LINE__, __CLASS__, __FUNC__]; }
}
var c = C();
var res2 = c.member();
assert_equal(res2[0], 21)
assert_equal(res2[1], "C")
assert_equal(res2[2], "member")
def C::member2() { [__LINE__, __CLASS__, __FUNC__]; }
var res3 = c.member2();
assert_equal(res3[0], 32)
assert_equal(res3[1], "C")
assert_equal(res3[2], "member2")
assert_true(__FILE__.find("execution_context.chai") != -1)

View File

@@ -10,7 +10,6 @@ def test_function(a)
// test_function tests
assert_equal(test_function.get_arity(), 1);
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
assert_equal(test_function.get_contained_functions().size(), 0);
assert_equal(test_function.get_param_types().size(), 2);

Binary file not shown.

View File

@@ -16,3 +16,8 @@ def f() {
f();
global &h = v;
assert_true(h == v)
v = 3;
assert_true(h == 3)

7
unittests/init_if.chai Normal file
View File

@@ -0,0 +1,7 @@
if (var x = 2; x == 3) {
assert_true(false);
} else if (var y = 3; y == 6) {
assert_true(false);
} else {
assert_equal(5, y + x);
}

View File

@@ -1,4 +1,7 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"
#define TEST_LITERAL(v) test_literal(v, #v)
@@ -6,7 +9,7 @@ template<typename T>
bool test_literal(T val, const std::string &str)
{
std::cout << "Comparing : " << val;
chaiscript::ChaiScript chai;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
T val2 = chai.eval<T>(str);
std::cout << " " << val2 << '\n';
return val == val2;

View File

@@ -0,0 +1,13 @@
load_module("stl_extra");
auto list = List();
list.resize(2);
assert_equal(list.size(), 2);
list.resize(6, "AAA");
assert_equal(list.back(), "AAA");
list.resize(0);
assert_equal(list.size(), 0);

View File

@@ -8,4 +8,6 @@ assert_equal(13, t0.val)
assert_equal(15, t0.constMe().const_val)
assert_equal(13, t0.constMe().val)
assert_equal(15, t0.get_const_val_ptr())
assert_equal(15, t0.const_val_ptr)

View File

@@ -1,14 +1,16 @@
#include "multifile_test_chai.hpp"
#include <chaiscript/chaiscript_stdlib.hpp>
#include <chaiscript/language/chaiscript_parser.hpp>
Multi_Test_Chai::Multi_Test_Chai()
: m_chai(new chaiscript::ChaiScript(chaiscript::Std_Lib::library()))
: m_chai(new chaiscript::ChaiScript_Basic(chaiscript::Std_Lib::library(),
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>()))
{
}
std::shared_ptr<chaiscript::ChaiScript> Multi_Test_Chai::get_chai()
std::shared_ptr<chaiscript::ChaiScript_Basic> Multi_Test_Chai::get_chai()
{
return m_chai;
}

View File

@@ -1,14 +1,14 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
class Multi_Test_Chai
{
public:
Multi_Test_Chai();
std::shared_ptr<chaiscript::ChaiScript> get_chai();
std::shared_ptr<chaiscript::ChaiScript_Basic> get_chai();
private:
std::shared_ptr<chaiscript::ChaiScript> m_chai;
std::shared_ptr<chaiscript::ChaiScript_Basic> m_chai;
};

View File

@@ -1,14 +1,14 @@
#include "multifile_test_chai.hpp"
#include "multifile_test_module.hpp"
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
int main()
{
Multi_Test_Chai chaitest;
Multi_Test_Module chaimodule;
std::shared_ptr<chaiscript::ChaiScript> chai = chaitest.get_chai();
std::shared_ptr<chaiscript::ChaiScript_Basic> chai = chaitest.get_chai();
chai->add(chaimodule.get_module());
return chai->eval<int>("get_module_value()");
}

View File

@@ -1,4 +1,4 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include "multifile_test_module.hpp"

View File

@@ -1,4 +1,4 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
class Multi_Test_Module
{

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