Compare commits

...

228 Commits

Author SHA1 Message Date
Jason Turner
0f9d9cae4a Merge pull request #332 from ftk/develop
Ability to disable module loading support at compile time
2017-03-21 12:55:30 -07:00
Jason Turner
468d65a661 Merge pull request #336 from totalgee/from_json_fix
Handle negative numbers in JSONParse::parse_number
2017-03-21 12:21:26 -07:00
Jason Turner
9847618cf3 Fix use after move during parsing
closes #337
2017-03-21 12:17:30 -07:00
Jason Turner
a281d9571e Add workaround for chaiscript used as static
closes #338
2017-03-21 11:58:33 -07:00
Jason Turner
204faa82c1 Add failing static chaiscript test 2017-03-21 11:58:21 -07:00
Jason Turner
be2fec02d9 Simplify usage of Thread_Specific object 2017-03-21 10:44:53 -07:00
Glen Fraser
491b95099d In JSONParser::parse_number(), only allow a single '-' at start
- also, don't allow multiple '.' decimal points. Add unit tests to
  cover these cases.
2017-03-14 13:01:09 +01:00
Glen Fraser
561c5bc981 Handle negative numbers in JSONParse::parse_number
- fix issue #334, where negative numbers loaded from JSON were being
  parsed as 0.
- add unit tests to cover these cases.
2017-03-14 12:01:51 +01:00
ftk
12829ee5d2 Simplified travis.yml 2017-03-11 15:42:24 +03:00
ftk
f53a1ed951 Fix compilation of multithreaded_test 2017-03-11 15:09:55 +03:00
ftk
12100cce99 Updated travis.yml 2017-03-11 15:09:54 +03:00
ftk
d22c27b627 Added option to disable dynload in cmakelists.txt 2017-03-08 12:31:30 +03:00
ftk
60c43233c6 More clear error message in load_module 2017-03-05 21:55:01 +03:00
ftk
c2f7ca3aa2 Using runtime stdlib constructor will result in compilation error 2017-03-05 21:48:59 +03:00
ftk
72cb9bd940 Compile out module path search code when module support is disabled 2017-03-05 21:26:01 +03:00
ftk
84f9c44ab6 Do not register load_module by default when dynamic loading is disabled 2017-03-05 21:23:05 +03:00
ftk
698dfb06db Loadable module support can be disabled by defining CHAISCRIPT_NO_DYNLOAD 2017-03-05 20:54:01 +03:00
Jason Turner
244b5b224b Merge pull request #330 from IonoclastBrigham/patch-1
Fixes path reference and code formatting in readme.
2017-03-03 09:55:27 -08:00
Ionoclast Laboratories
534897d835 Fixes path reference and code formatting in readme.
Changes Example.cpp's directory "src" => "samples" to match repo.
Change code example from indented quote to highlighted code block.
2017-03-02 11:27:10 -08:00
Jason Turner
fac5a39066 Update readme.md for 6.0.0 2017-02-23 17:54:59 -07:00
Jason Turner
064a385a64 Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2017-02-22 15:56:04 -07:00
Jason Turner
e342243193 Update release notes for 6.0.0 2017-02-22 15:33:42 -07:00
Jason Turner
283785faaf Add PVS Studio and address some issues it found 2017-02-22 15:18:56 -07:00
Jason Turner
c0c0bd3172 Address warning from MSVC /analyze 2017-02-22 14:04:56 -07:00
Jason Turner
40fb8d257e Fix warnings from MSVC 2017-02-22 13:55:02 -07:00
Jason Turner
f5f6ddf219 Disable tests on MSVC for broken literal handling 2017-02-20 13:28:31 -07:00
Jason Turner
87f1242ed4 Update copyrights to 2017 2017-02-15 15:55:40 -07:00
Jason Turner
faba0f1317 Require thread_local support, move to xcode8 2017-02-15 15:38:44 -07:00
Jason Turner
077c93ab27 Fix/enhance unique_ptr support 2017-02-04 09:14:07 -08:00
Jason Turner
914bca6295 Merge pull request #324 from Dalzhim/uniquePtrTests
Add test to call base class methods through std::unique_ptr<derived>.
2017-02-04 09:18:39 -07:00
Gabriel Aubut-Lussier
2549b4e983 Add test to call base class methods through std::unique_ptr<derived>. 2017-02-03 23:19:25 -05:00
Jason Turner
1cb15d8b22 Handle return of std::unique_ptr objects 2017-02-03 19:34:12 -08:00
Jason Turner
2ce155237d Add test for unique_ptr returned from function 2017-02-03 18:55:58 -08:00
Jason Turner
dca3ce4ea6 Enhance testing of integer literals
* enable the ability to check a boxed_number conversion
 * fix integer_literal_test to pass on MacOS
2017-02-02 15:07:37 -07:00
Jason Turner
ca7d4ab734 Add test for calling method of unique_ptr var 2017-02-02 13:17:59 -08:00
Jason Turner
f5ced799cf Hopefully find balance with gcc/clang for static_string 2017-02-02 08:10:47 -08:00
Jason Turner
1499061f86 Add check for negate conversion to bool
Check for #321
2017-02-02 08:06:41 -08:00
Jason Turner
24352c62e8 Some clang specific fixes / warnings 2017-02-02 08:00:57 -08:00
Jason Turner
6b4c47c5ba Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2017-02-01 20:03:17 -08:00
Jason Turner
396d43a13f sublime now at ChaiScript/sublimetext-chaiscript 2017-02-01 20:01:30 -08:00
Jason Turner
18cf09b512 Merge pull request #319 from Tw1ddle/patch-1
Add double stringize trick so _MSC_FULL_VER macro gets expanded
2017-02-01 20:12:04 -07:00
Jason Turner
2782cdd33b Remove 2-value bind in favor of lambdas
closes #320
2017-02-01 15:42:32 -08:00
Jason Turner
d8d7bc79b7 Enhance number parsing tests 2017-02-01 09:07:40 -08:00
Jason Turner
3e04210027 Add more integer literal tests / fix neg test
Addresses #322
2017-02-01 07:02:18 -08:00
Jason Turner
c82c9ccb6e Revert "Fix parsing of negative numbers"
This reverts commit 83b7973cb885af928e36195a7cbc6ab8f04a93b6.
2017-02-01 06:18:14 -08:00
Jason Turner
efd37a7071 Add some more integer literal tests 2017-01-31 17:05:53 -08:00
Jason Turner
83b7973cb8 Fix parsing of negative numbers 2017-01-31 15:41:21 -08:00
Jason Turner
e7a6b2306c Add tests for parsing of neg numbers 2017-01-31 15:30:38 -08:00
Jason Turner
0a18f0a809 Remove unnecessary params 2017-01-31 13:40:16 -08:00
Jason Turner
8efba903c3 use std::end instead of end because of MSVC 2017-01-31 13:28:40 -08:00
Jason Turner
ca87c05cd4 Don't add 'this' if it was explicitly captured 2017-01-31 13:25:26 -08:00
Jason Turner
94fb7c2453 Add test for explicitly capturing "this" 2017-01-31 13:24:53 -08:00
Jason Turner
c54d84fae6 Don't force compiler when building cppcheck 2017-01-31 10:11:28 -08:00
Sam Twidale
574f4a9664 Add double stringize trick so _MSC_FULL_VER macro gets expanded
This fixes CHAISCRIPT_COMPILER_VERSION, so it gets the compiler version number instead of the string "_MSC_FULL_VER".

This means, for example, build ids read like msvc-190023918-Debug, not msvc-_MSC_FULL_VER-Debug.
2017-01-09 18:38:19 +00:00
Jason Turner
b7e8897a43 Merge pull request #317 from ChaiScript/add_osx_travis
Add osx travis
2016-12-29 12:32:19 -07:00
Jason Turner
7a588ed5cf Disable cppcheck runs 2016-12-27 17:56:10 -07:00
Jason Turner
89f373d21c Clean up ENV and addons 2016-12-27 16:10:08 -07:00
Jason Turner
037335a0ea Don't require sudu on linux for travis.yml 2016-12-27 16:02:55 -07:00
Jason Turner
2431362e54 Simplify OS types for travis 2016-12-27 15:50:53 -07:00
Jason Turner
9c59600b9f Add OSX to OS matrix 2016-12-27 15:23:58 -07:00
Jason Turner
51663df1ba Demonstrate workaround for pointer to ref member
closes #302
2016-12-06 14:51:00 -07:00
Jason Turner
624c7c435b Add unit test for #302 2016-12-06 14:26:10 -07:00
Jason Turner
cf89bdd804 Update release notes, add chai type fun conversion test 2016-12-06 14:15:39 -07:00
Jason Turner
a8e70a4cfe Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop 2016-12-06 13:43:53 -07:00
Jason Turner
f79de06e0b Change comment format 2016-12-06 13:42:58 -07:00
Jason Turner
cee57f998a Allow conversions while calling chaiscript funcs
* This puts ChaiScript funcs more on even footings with
   C++ defined funcs
 * Minor performance hit (0.5%)
2016-12-06 13:05:17 -07:00
Jason Turner
ce62706fea Clean up warnings
* msvc
 * pvs-studio
2016-12-06 10:31:36 -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
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
7339ff2c2f Update release notes for 5.8.5 2016-10-09 19:59:48 -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
665125665a Bump to 5.8.5
- remove parsing of unary &, it was unused
2016-10-06 22:32:55 -06:00
Jason Turner
d1c7645a4e Backport inits for g++4.6 2016-10-06 15:19:47 -06:00
Jason Turner
58faea1cf2 Add conversion to bool compile test
Re: #275
2016-10-06 14:52:34 -06:00
Jason Turner
8b7fe33bf1 Fix order of operations for prefix and '*', '/'
The problem is that Prefix did not properly participate in
operator precedence. I've fixed this, at least for the moment,
by adding a final depth of precedence that can be called when
the depth gets to the bottom.

closes #285
2016-10-06 14:44:30 -06:00
Jason Turner
7cc100e3d7 Make ChaiScript constructor public... 2016-10-06 09:36:43 -06:00
Jason Turner
21495ebb40 Make sure atomics are initialized 2016-10-06 09:09:50 -06:00
Jason Turner
b2907fc608 Merge branch 'release-5.x' into develop 2016-10-05 15:14:58 -06:00
Jason Turner
bec1b91b7b Increment to 5.8.4 2016-09-24 17:17:40 -06:00
Jason Turner
4b81a24a0a Fix numeric mixed-convesion operations 2016-09-24 17:15:17 -06:00
Jason Turner
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
cefb4d3c78 Update release notes for 5.x 2016-09-16 12:33:07 -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
41c1c490c8 Add support for *& return types 2016-04-29 08:31:59 -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
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 5a947b5035dc99d2dbef35a220340036886e189c.
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
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
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
104 changed files with 5316 additions and 3940 deletions

View File

@ -1,33 +1,62 @@
language: cpp
compiler:
- gcc
env:
matrix:
- GCC_VER="4.9"
- GCC_VER="5"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- g++-5
coverity_scan:
project:
name: "ChaiScript/ChaiScript"
description: "Build submitted via Travis CI"
notification_email: jason@emptycrate.com
build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . "
build_command: "cmake --build . -- -j2"
branch_pattern: coverity_scan
matrix:
include:
- os: linux
sudo: false
env: GCC_VER="4.9"
compiler: gcc
- os: linux
sudo: false
env: GCC_VER="4.9" CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1
compiler: gcc
- os: linux
sudo: false
env: GCC_VER="5" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
compiler: gcc
- os: osx
compiler: clang
osx_image: xcode8
- os: osx
compiler: clang
osx_image: xcode8
env: CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1
env:
global:
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
- secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM="
before_install:
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
- if [ "$GCC_VER" = "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
- sudo apt-get update
- sudo apt-get install -qq g++-$GCC_VER
- if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi
- pip install --user cpp-coveralls
script:
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi
- make test
- if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $CMAKE_OPTIONS .
- cmake --build . -- -j2
- if [ "${BUILD_ONLY}" != "1" ]; then ctest; fi
- if [ "${COVERAGE}" = "1" ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
after_script:
- if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
#after_script:
# - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
notifications:
@ -42,15 +71,3 @@ notifications:
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
addons:
coverity_scan:
project:
name: "ChaiScript/ChaiScript"
description: "Build submitted via Travis CI"
notification_email: jason@emptycrate.com
build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . "
build_command: "cmake --build . -- -j2"
branch_pattern: coverity_scan

View File

@ -14,6 +14,7 @@ ELSE()
project(chaiscript)
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
option(DYNLOAD_ENABLED "Dynamic Loading Support Enabled" TRUE)
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
@ -221,9 +222,15 @@ if(NOT MULTITHREAD_SUPPORT_ENABLED)
add_definitions(-DCHAISCRIPT_NO_THREADS)
endif()
if(NOT DYNLOAD_ENABLED)
add_definitions(-DCHAISCRIPT_NO_DYNLOAD)
endif()
if(CMAKE_HOST_UNIX)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
list(APPEND LIBS "dl")
if(DYNLOAD_ENABLED)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
list(APPEND LIBS "dl")
endif()
endif()
if(MULTITHREAD_SUPPORT_ENABLED)
@ -249,27 +256,30 @@ 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()
@ -295,7 +305,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
)
@ -421,9 +431,12 @@ 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)
add_executable(static_chaiscript_test unittests/static_chaiscript.cpp)
target_link_libraries(static_chaiscript_test ${LIBS})
add_test(NAME Static_ChaiScript_Test COMMAND static_chaiscript_test)
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
target_link_libraries(boxed_cast_test ${LIBS})
@ -434,11 +447,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)

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

@ -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

@ -4,7 +4,7 @@ pushd ..
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
tar -xvf cppcheck-1.66.tar.bz2
cd cppcheck-1.66
CXX=g++-4.8 make -j2
make -j2
popd
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output

View File

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

View File

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

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_HPP_
#define CHAISCRIPT_HPP_
@ -65,7 +69,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 +699,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 +820,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-2017, 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

@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DEFINES_HPP_
@ -9,9 +9,13 @@
#ifdef _MSC_VER
#define CHAISCRIPT_STRINGIZE(x) "" #x
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
#define CHAISCRIPT_STRINGIZE_EXPANDED(x) CHAISCRIPT_STRINGIZE(x)
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE_EXPANDED(_MSC_FULL_VER)
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEC
static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later required");
#else
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
#endif
@ -44,10 +48,6 @@
#endif
#endif
#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(__llvm__)
#define CHAISCRIPT_CLANG
@ -60,6 +60,10 @@
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(CHAISCRIPT_CLANG)
#define CHAISCRIPT_UTF16_UTF32
#endif
#ifdef _DEBUG
#define CHAISCRIPT_DEBUG true
#else
@ -89,18 +93,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;
}
@ -161,6 +206,22 @@ 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()
{
#ifdef CHAISCRIPT_NO_DYNLOAD
return {Options::No_Load_Modules, Options::External_Scripts};
#else
return {Options::Load_Modules, Options::External_Scripts};
#endif
}
}
#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 "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.hpp"
#include "dispatchkit/register_function.hpp"
#include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS
@ -38,18 +44,16 @@ namespace chaiscript
static ModulePtr library()
{
using namespace bootstrap;
auto lib = std::make_shared<Module>();
Bootstrap::bootstrap(*lib);
bootstrap::Bootstrap::bootstrap(*lib);
standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
standard_library::string_type<std::string>("string", *lib);
standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
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
standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);
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

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_THREADING_HPP_
#define CHAISCRIPT_THREADING_HPP_
@ -57,115 +61,71 @@ namespace chaiscript
using std::recursive_mutex;
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
template<typename T>
class Thread_Storage
{
public:
explicit Thread_Storage(void *t_key)
: m_key(t_key)
{
}
Thread_Storage() = default;
Thread_Storage(const Thread_Storage &) = delete;
Thread_Storage(Thread_Storage &&) = delete;
Thread_Storage &operator=(const Thread_Storage &) = delete;
Thread_Storage &operator=(Thread_Storage &&) = delete;
~Thread_Storage()
{
t().erase(m_key);
if (!destroyed) {
t().erase(this);
}
}
inline const T *operator->() const
{
return &(t()[m_key]);
return &(t()[const_cast<Thread_Storage *>(this)]);
}
inline const T &operator*() const
{
return t()[m_key];
return t()[const_cast<Thread_Storage *>(this)];
}
inline T *operator->()
{
return &(t()[m_key]);
return &(t()[this]);
}
inline T &operator*()
{
return t()[m_key];
return t()[this];
}
void *m_key;
private:
static std::unordered_map<void*, T> &t()
struct Map_Holder {
std::unordered_map<Thread_Storage<T> *, T> map;
Map_Holder() = default;
Map_Holder(const Map_Holder &) = delete;
Map_Holder(Map_Holder &&) = delete;
Map_Holder& operator=(Map_Holder &&) = delete;
Map_Holder& operator=(const Map_Holder &&) = delete;
~Map_Holder() {
// here is the theory:
// * If the Map_Holder is destroyed before the Thread_Storage, a flag will get set
// * If destroyed after the Thread_Storage, the * will have been removed from `map` and nothing will happen
for(auto &elem : map) { elem.first->destroyed = true; }
}
};
static std::unordered_map<Thread_Storage<T> *, T> &t()
{
thread_local static std::unordered_map<void *, T> my_t;
return my_t;
thread_local Map_Holder my_map;
return my_map.map;
}
bool destroyed{false};
};
#else
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// This version is used if the compiler does not support thread_local
template<typename T>
class Thread_Storage
{
public:
explicit Thread_Storage(void *)
{
}
inline const T *operator->() const
{
return get_tls().get();
}
inline const T &operator*() const
{
return *get_tls();
}
inline T *operator->()
{
return get_tls().get();
}
inline T &operator*()
{
return *get_tls();
}
private:
/// \todo this leaks thread instances. It needs to be culled from time to time
std::shared_ptr<T> get_tls() const
{
unique_lock<mutex> lock(m_mutex);
const auto id = std::this_thread::get_id();
auto itr = m_instances.find(id);
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(std::make_shared<T>());
m_instances.insert(std::make_pair(id, new_instance));
return new_instance;
}
mutable mutex m_mutex;
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
};
#endif // threading enabled but no tls
#else // threading disabled
template<typename T>
class unique_lock

View File

@ -21,10 +21,7 @@ namespace chaiscript {
class bad_any_cast : public std::bad_cast
{
public:
bad_any_cast() noexcept
: m_what("bad any cast")
{
}
bad_any_cast() = default;
bad_any_cast(const bad_any_cast &) = default;
@ -37,7 +34,7 @@ namespace chaiscript {
}
private:
std::string m_what;
std::string m_what = "bad any cast";
};
}
@ -75,7 +72,7 @@ namespace chaiscript {
{
}
virtual void *data() override
void *data() override
{
return &m_data;
}
@ -151,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
@ -31,31 +35,31 @@ namespace chaiscript
public:
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
std::string t_what) noexcept
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
: 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) noexcept
: to(nullptr), m_what(std::move(t_what))
: m_what(std::move(t_what))
{
}
bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() noexcept = default;
~bad_boxed_cast() noexcept override = default;
/// \brief Description of what error occurred
virtual const char * what() const noexcept 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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
#define CHAISCRIPT_BIND_FIRST_HPP_
@ -27,45 +31,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

@ -1,56 +1,24 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#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 >
void array(const std::string &type, Module& m)
{
@ -134,19 +102,10 @@ namespace chaiscript
template<typename T>
void construct_pod(const std::string &type, Module& m)
{
m.add(fun(&detail::construct_pod<T>), type);
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>
@ -194,15 +153,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);
}
@ -288,8 +246,6 @@ namespace chaiscript
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
@ -329,26 +285,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)
@ -384,7 +320,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);
@ -407,13 +343,13 @@ namespace chaiscript
m.add(user_type<std::exception>(), "exception");
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m.add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m.add(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");
@ -425,7 +361,6 @@ namespace chaiscript
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(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
@ -520,15 +455,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([](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(&throw_exception), "throw");
m.add(fun(&what), "what");
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
m.add(fun(&to_string<char>), "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);
@ -552,10 +487,21 @@ 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");
@ -580,9 +526,11 @@ namespace chaiscript
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::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::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);
@ -593,13 +541,13 @@ namespace chaiscript
{ },
{ {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"} }
);
@ -621,24 +569,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"} }
);
}
};
}

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
/// \file
/// This file contains utility functions for registration of STL container
/// classes. The methodology used is based on the SGI STL concepts.
@ -37,11 +41,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 +74,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 {
@ -230,8 +175,8 @@ namespace chaiscript
template<typename ContainerType>
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)
@ -482,12 +427,8 @@ namespace chaiscript
{
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);
@ -605,7 +546,6 @@ namespace chaiscript
}
/// hopefully working List type
/// http://www.sgi.com/tech/stl/List.html
template<typename ListType>
void list_type(const std::string &type, Module& m)

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
#define CHAISCRIPT_BOXED_CAST_HPP_
@ -69,11 +73,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 &) {
}
}
@ -84,11 +88,11 @@ namespace chaiscript
try {
// 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 {
// try going the other way
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
@ -25,25 +29,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 +90,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 +100,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 +121,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 +133,61 @@ 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::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<const 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 +197,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 +223,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 +247,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 +257,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 +311,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

@ -1,9 +1,12 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
@ -28,9 +31,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() noexcept = default;
~arithmetic_error() noexcept override = default;
};
}
}
@ -162,17 +165,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 +187,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 +205,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 +233,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 +263,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 +275,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 +298,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 +312,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 +331,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 +352,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 +369,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 +384,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,7 +505,7 @@ namespace chaiscript
{
}
Boxed_Number(Boxed_Value v)
explicit Boxed_Number(Boxed_Value v)
: bv(std::move(v))
{
validate_boxed_number(bv);
@ -585,6 +588,67 @@ namespace chaiscript
}
template<typename Source, typename Target>
static void check_type()
{
#ifdef CHAISCRIPT_MSVC
// MSVC complains about this being redundant / tautologica l
#pragma warning(push)
#pragma warning(disable : 4127 6287)
#endif
if (sizeof(Source) != sizeof(Target)
|| std::is_signed<Source>() != std::is_signed<Target>()
|| std::is_floating_point<Source>() != std::is_floating_point<Target>())
{
throw chaiscript::detail::exception::bad_any_cast();
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
template<typename Target> Target get_as_checked() const
{
switch (get_common_type(bv)) {
case Common_Types::t_int32:
check_type<int32_t, Target>();
return get_as_aux<Target, int32_t>(bv);
case Common_Types::t_uint8:
check_type<uint8_t, Target>();
return get_as_aux<Target, uint8_t>(bv);
case Common_Types::t_int8:
check_type<int8_t, Target>();
return get_as_aux<Target, int8_t>(bv);
case Common_Types::t_uint16:
check_type<uint16_t, Target>();
return get_as_aux<Target, uint16_t>(bv);
case Common_Types::t_int16:
check_type<int16_t, Target>();
return get_as_aux<Target, int16_t>(bv);
case Common_Types::t_uint32:
check_type<uint32_t, Target>();
return get_as_aux<Target, uint32_t>(bv);
case Common_Types::t_uint64:
check_type<uint64_t, Target>();
return get_as_aux<Target, uint64_t>(bv);
case Common_Types::t_int64:
check_type<int64_t, Target>();
return get_as_aux<Target, int64_t>(bv);
case Common_Types::t_double:
check_type<double, Target>();
return get_as_aux<Target, double>(bv);
case Common_Types::t_float:
check_type<float, Target>();
return get_as_aux<Target, float>(bv);
case Common_Types::t_long_double:
check_type<long double, Target>();
return get_as_aux<Target, long double>(bv);
}
throw chaiscript::detail::exception::bad_any_cast();
}
template<typename Target> Target get_as() const
{
switch (get_common_type(bv)) {
@ -645,71 +709,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();
@ -724,266 +723,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));
}
@ -1009,9 +907,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
#define CHAISCRIPT_BOXED_VALUE_HPP_
@ -35,11 +39,11 @@ namespace chaiscript
{
Data(const Type_Info &ti,
chaiscript::detail::Any to,
bool tr,
bool is_ref,
const void *t_void_ptr,
bool t_return_value)
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
m_is_ref(tr), m_return_value(t_return_value)
m_is_ref(is_ref), m_return_value(t_return_value)
{
}
@ -54,7 +58,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;
@ -77,9 +81,9 @@ namespace chaiscript
struct Object_Data
{
static std::unique_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_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
chaiscript::detail::Any(),
false,
@ -89,15 +93,15 @@ namespace chaiscript
}
template<typename T>
static std::unique_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::unique_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_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(obj),
false,
@ -107,10 +111,10 @@ namespace chaiscript
}
template<typename T>
static std::unique_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_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
false,
@ -119,24 +123,26 @@ namespace chaiscript
);
}
template<typename T>
static std::unique_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::unique_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::unique_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_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
true,
@ -146,11 +152,24 @@ namespace chaiscript
}
template<typename T>
static std::unique_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))),
true,
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();
return std::make_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(p)),
false,
@ -159,9 +178,9 @@ namespace chaiscript
);
}
static std::unique_ptr<Data> get()
static std::shared_ptr<Data> get()
{
return std::make_unique<Data>(
return std::make_shared<Data>(
Type_Info(),
chaiscript::detail::Any(),
false,
@ -182,10 +201,7 @@ namespace chaiscript
}
/// Unknown-type constructor
Boxed_Value()
: m_data(Object_Data::get())
{
}
Boxed_Value() = default;
Boxed_Value(Boxed_Value&&) = default;
Boxed_Value& operator=(Boxed_Value&&) = default;
@ -226,48 +242,40 @@ namespace chaiscript
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
const auto ptr_ = m_ptr.get().get();
m_data.get().m_data_ptr = ptr_;
m_data.get().m_const_data_ptr = ptr_;
}
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 noexcept
@ -314,7 +322,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];
@ -331,7 +339,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;
}
@ -354,11 +362,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

View File

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

@ -1,14 +1,17 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
#define CHAISCRIPT_DISPATCHKIT_HPP_
#include <algorithm>
#include <deque>
#include <iostream>
#include <list>
#include <map>
@ -31,12 +34,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 +52,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.
@ -63,7 +71,7 @@ namespace chaiscript
reserved_word_error(const reserved_word_error &) = default;
virtual ~reserved_word_error() noexcept = default;
~reserved_word_error() noexcept override = default;
std::string word() const
{
@ -85,7 +93,7 @@ namespace chaiscript
illegal_name_error(const illegal_name_error &) = default;
virtual ~illegal_name_error() noexcept = default;
~illegal_name_error() noexcept override = default;
std::string name() const
{
@ -108,7 +116,7 @@ namespace chaiscript
name_conflict_error(const name_conflict_error &) = default;
virtual ~name_conflict_error() noexcept = default;
~name_conflict_error() noexcept override = default;
std::string name() const
{
@ -131,7 +139,7 @@ namespace chaiscript
}
global_non_const(const global_non_const &) = default;
virtual ~global_non_const() noexcept = default;
~global_non_const() noexcept override = default;
};
}
@ -143,7 +151,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;
}
@ -262,7 +270,7 @@ namespace chaiscript
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))
{
@ -310,11 +318,6 @@ namespace chaiscript
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
}
std::string annotation() const override
{
return "Multiple method dispatch function wrapper.";
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
@ -357,7 +360,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)
{
@ -377,22 +380,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
@ -403,7 +440,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
{
@ -412,28 +449,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()
: m_stack_holder(this)
{
}
~Dispatch_Engine()
explicit Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
: m_stack_holder(),
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
@ -445,7 +474,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);
}
@ -453,7 +481,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)
@ -473,6 +500,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
@ -488,7 +535,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));
}
@ -503,7 +550,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();
@ -522,8 +568,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);
@ -540,8 +584,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())
@ -555,8 +597,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);
@ -583,8 +623,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,7 +643,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)
@ -645,7 +685,7 @@ namespace chaiscript
}
t_loc = static_cast<uint_fast32_t>(Loc::located);
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
} else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 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;
@ -662,9 +702,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;
}
@ -727,7 +767,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);
}
@ -815,7 +858,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());
}
@ -886,12 +929,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
{
@ -924,7 +961,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
@ -947,14 +984,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;
}
@ -1037,7 +1081,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);
}
@ -1058,11 +1103,7 @@ 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;
}
dump_type(params.front());
std::cout << " " << f.first << "(";
@ -1165,7 +1206,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)
@ -1183,7 +1224,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)
@ -1253,6 +1294,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
@ -1349,10 +1395,6 @@ namespace chaiscript
if (rt.bare_equal(boxed_type))
{
if (lt.bare_equal(boxed_pod_type))
{
return true;
}
return true;
}
@ -1374,20 +1416,6 @@ namespace chaiscript
}
/// Throw a reserved_word exception if the name is not allowed
void validate_object_name(const std::string &name) const
{
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())
{
throw chaiscript::exception::reserved_word_error(name);
}
}
template<typename Container, typename Key, typename Value>
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
@ -1425,7 +1453,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);
}
@ -1482,8 +1510,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;
};
@ -1491,7 +1520,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())
@ -1518,8 +1547,12 @@ 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 {
@ -1536,3 +1569,4 @@ namespace chaiscript
#endif

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
@ -25,7 +29,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,13 +37,13 @@ namespace chaiscript
option_explicit_set(const option_explicit_set &) = default;
virtual ~option_explicit_set() noexcept = default;
~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)
{
}

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
@ -98,14 +98,8 @@ namespace chaiscript
return {m_func};
}
std::string annotation() const override
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const 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))
{
@ -115,7 +109,7 @@ namespace chaiscript
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const 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);
}
@ -157,7 +151,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 {
@ -208,7 +202,7 @@ namespace chaiscript
bool operator==(const Proxy_Function_Base &f) const 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);
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
@ -219,11 +213,6 @@ namespace chaiscript
return m_func->call_match(new_vals, t_conversions);
}
std::string annotation() const override
{
return m_func->annotation();
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_HPP_
@ -81,9 +85,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>()))
{
@ -98,9 +100,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>()))
{
@ -115,9 +115,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
@ -33,7 +37,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 +56,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 +76,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
#define CHAISCRIPT_HANDLE_RETURN_HPP_
@ -27,9 +31,7 @@ namespace chaiscript
namespace detail
{
/**
* Used internally for handling a return value from a Proxy_Function call
*/
/// Used internally for handling a return value from a Proxy_Function call
template<typename Ret>
struct Handle_Return
{
@ -100,6 +102,24 @@ namespace chaiscript
}
};
template<typename Ret>
struct Handle_Return<Ret *&>
{
static Boxed_Value handle(Ret *p)
{
return Boxed_Value(p, true);
}
};
template<typename Ret>
struct Handle_Return<const Ret *&>
{
static Boxed_Value handle(const Ret *p)
{
return Boxed_Value(p, true);
}
};
template<typename Ret>
struct Handle_Return<Ret *>
{
@ -137,6 +157,18 @@ namespace chaiscript
{
};
template<typename Ret>
struct Handle_Return<std::unique_ptr<Ret>> : Handle_Return<std::unique_ptr<Ret> &>
{
static Boxed_Value handle(std::unique_ptr<Ret> &&r)
{
return Boxed_Value(std::move(r), true);
}
};
template<typename Ret>
struct Handle_Return<const Ret &>
{
@ -146,6 +178,14 @@ namespace chaiscript
}
};
template<typename Ret>
struct Handle_Return<const Ret>
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
template<typename Ret>
struct Handle_Return<Ret &>
@ -154,11 +194,6 @@ namespace chaiscript
{
return Boxed_Value(std::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
template<>

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_OPERATORS_HPP_
#define CHAISCRIPT_OPERATORS_HPP_
@ -16,414 +20,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>
void assign(Module& m)
{
m.add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
}
template<typename T>
void assign_bitwise_and(Module& m)
{
m.add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
}
template<typename T>
void assign_xor(Module& m)
{
m.add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
}
template<typename T>
void assign_bitwise_or(Module& m)
{
m.add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
}
template<typename T>
void assign_difference(Module& m)
{
m.add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
}
template<typename T>
void assign_left_shift(Module& m)
{
m.add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
}
template<typename T>
void assign_product(Module& m)
{
m.add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
}
template<typename T>
void assign_quotient(Module& m)
{
m.add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
}
template<typename T>
void assign_remainder(Module& m)
{
m.add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
}
template<typename T>
void assign_right_shift(Module& m)
{
m.add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
}
template<typename T>
void assign_sum(Module& m)
{
m.add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
}
template<typename T>
void prefix_decrement(Module& m)
{
m.add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
}
template<typename T>
void prefix_increment(Module& m)
{
m.add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
}
template<typename T>
void equal(Module& m)
{
m.add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
}
template<typename T>
void greater_than(Module& m)
{
m.add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
}
template<typename T>
void greater_than_equal(Module& m)
{
m.add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
}
template<typename T>
void less_than(Module& m)
{
m.add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
}
template<typename T>
void less_than_equal(Module& m)
{
m.add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
}
template<typename T>
void logical_compliment(Module& m)
{
m.add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
}
template<typename T>
void not_equal(Module& m)
{
m.add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
}
template<typename T>
void addition(Module& m)
{
m.add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
}
template<typename T>
void unary_plus(Module& m)
{
m.add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
}
template<typename T>
void subtraction(Module& m)
{
m.add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
}
template<typename T>
void unary_minus(Module& m)
{
m.add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
}
template<typename T>
void bitwise_and(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
}
template<typename T>
void bitwise_compliment(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
}
template<typename T>
void bitwise_xor(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
}
template<typename T>
void bitwise_or(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
}
template<typename T>
void division(Module& m)
{
m.add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
}
template<typename T>
void left_shift(Module& m)
{
m.add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
}
template<typename T>
void multiplication(Module& m)
{
m.add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
}
template<typename T>
void remainder(Module& m)
{
m.add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
}
template<typename T>
void right_shift(Module& m)
{
m.add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
}
}
}

View File

@ -1,9 +1,12 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_

View File

@ -1,9 +1,12 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
@ -53,7 +56,7 @@ namespace chaiscript
m_doti(user_type<Dynamic_Object>())
{}
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
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>())
@ -63,7 +66,7 @@ namespace chaiscript
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();
}
@ -72,10 +75,51 @@ namespace chaiscript
return m_types == t_rhs.m_types;
}
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
std::vector<Boxed_Value> convert(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;
for (size_t i = 0; i < vals.size(); ++i)
{
const auto &name = m_types[i].first;
if (!name.empty()) {
const auto &bv = vals[i];
if (!bv.get_type_info().bare_equal(m_doti))
{
const auto &ti = m_types[i].second;
if (!ti.is_undef())
{
if (!bv.get_type_info().bare_equal(ti)) {
if (t_conversions->converts(ti, bv.get_type_info())) {
try {
// 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
vals[i] = t_conversions->boxed_type_conversion(m_types[i].second, t_conversions.saves(), vals[i]);
} catch (...) {
try {
// try going the other way
vals[i] = t_conversions->boxed_type_down_conversion(m_types[i].second, t_conversions.saves(), vals[i]);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), *m_types[i].second.bare_type_info());
}
}
}
}
}
}
}
}
return vals;
}
// first result: is a match
// second result: needs conversions
std::pair<bool, bool> match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
{
bool needs_conversion = false;
if (!m_has_types) { return std::make_pair(true, needs_conversion); }
if (vals.size() != m_types.size()) { return std::make_pair(false, needs_conversion); }
for (size_t i = 0; i < vals.size(); ++i)
{
@ -87,25 +131,31 @@ namespace chaiscript
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
return name == "Dynamic_Object" || d.get_type_name() == name;
if (!(name == "Dynamic_Object" || d.get_type_name() == name)) {
return std::make_pair(false, false);
}
} catch (const std::bad_cast &) {
return false;
return std::make_pair(false, false);
}
} else {
const auto &ti = m_types[i].second;
if (!ti.is_undef())
{
if (!bv.get_type_info().bare_equal(ti)) {
return false;
if (!t_conversions->converts(ti, bv.get_type_info())) {
return std::make_pair(false, false);
} else {
needs_conversion = true;
}
}
} else {
return false;
return std::make_pair(false, false);
}
}
}
}
return true;
return std::make_pair(true, needs_conversion);
}
const std::vector<std::pair<std::string, Type_Info>> &types() const
@ -181,20 +231,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 +249,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()
@ -289,7 +332,7 @@ namespace chaiscript
guard_error(const guard_error &) = default;
virtual ~guard_error() noexcept = default;
~guard_error() noexcept override = default;
};
}
@ -306,30 +349,28 @@ 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())
: 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 bool operator==(const Proxy_Function_Base &rhs) const 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 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);
return call_match_internal(vals, t_conversions).first;
}
@ -343,11 +384,6 @@ namespace chaiscript
return m_parsenode;
}
virtual std::string annotation() const override
{
return m_description;
}
protected:
bool test_guard(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const
@ -366,6 +402,26 @@ namespace chaiscript
}
}
// first result: is a match
// second result: needs conversions
std::pair<bool, bool> call_match_internal(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
{
const auto comparison_result = [&](){
if (m_arity < 0) {
return std::make_pair(true, false);
} else if (vals.size() == size_t(m_arity)) {
return m_param_types.match(vals, t_conversions);
} else {
return std::make_pair(false, false);
}
}();
return std::make_pair(
comparison_result.first && test_guard(vals, t_conversions),
comparison_result.second
);
}
private:
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
{
@ -384,10 +440,12 @@ namespace chaiscript
return types;
}
protected:
Param_Types m_param_types;
private:
Proxy_Function m_guard;
AST_NodePtr m_parsenode;
std::string m_description;
};
@ -401,13 +459,11 @@ 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))
@ -418,9 +474,14 @@ namespace chaiscript
protected:
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))
const auto match_results = call_match_internal(params, t_conversions);
if (match_results.first)
{
return m_f(params);
if (match_results.second) {
return m_f(m_param_types.convert(params, t_conversions));
} else {
return m_f(params);
}
} else {
throw exception::guard_error();
}
@ -506,10 +567,6 @@ namespace chaiscript
return args;
}
virtual std::string annotation() const override
{
return "Bound: " + m_f->annotation();
}
protected:
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
@ -536,7 +593,7 @@ namespace chaiscript
return retval;
}
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const 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);
}
@ -549,16 +606,11 @@ 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)
{
}
std::string annotation() const override
{
return "";
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return static_cast<int>(vals.size()) == get_arity()
@ -575,7 +627,7 @@ namespace chaiscript
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))
{
@ -595,8 +647,7 @@ namespace chaiscript
protected:
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:
@ -607,7 +658,7 @@ 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)
{
}
@ -648,7 +699,7 @@ namespace chaiscript
protected:
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);
}
@ -663,7 +714,7 @@ namespace chaiscript
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)
{
@ -693,11 +744,6 @@ namespace chaiscript
return vals[0].get_type_info().bare_equal(user_type<Class>());
}
std::string annotation() const override
{
return "";
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
@ -728,13 +774,13 @@ namespace chaiscript
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<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
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<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
}
@ -773,7 +819,7 @@ namespace chaiscript
dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() noexcept = default;
~dispatch_error() noexcept override = default;
std::vector<Boxed_Value> parameters;
std::vector<Const_Proxy_Function> functions;
@ -790,7 +836,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);
@ -850,7 +896,8 @@ namespace chaiscript
plist.begin(),
std::back_inserter(newplist),
[](const Type_Info &ti, const Boxed_Value &param) -> Boxed_Value {
if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()) {
if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()
&& param.get_type_info() != ti) {
return Boxed_Number(param).get_as(ti).bv;
} else {
return param;
@ -858,8 +905,6 @@ namespace chaiscript
}
);
try {
return (*(matching_func->second))(newplist, t_conversions);
} catch (const exception::bad_boxed_cast &) {
@ -875,11 +920,9 @@ namespace chaiscript
}
}
/**
* Take a vector of functions and a vector of parameters. Attempt to execute
* each function against the set of parameters, in order, until a matching
* function is found or throw dispatch_error if no matching function is found
*/
/// Take a vector of functions and a vector of parameters. Attempt to execute
/// each function against the set of parameters, in order, until a matching
/// function is found or throw dispatch_error if no matching function is found
template<typename Funcs>
Boxed_Value dispatch(const Funcs &funcs,
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
@ -913,7 +956,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
@ -44,7 +48,7 @@ namespace chaiscript
arity_error(const arity_error &) = default;
virtual ~arity_error() noexcept {}
~arity_error() noexcept override = default;
int got;
int expected;
@ -99,17 +103,31 @@ namespace chaiscript
}
/**
* 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)
{
return call_func(sig, std::index_sequence_for<Params...>{}, 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
}
}
@ -118,34 +136,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
@ -107,31 +111,6 @@ namespace chaiscript
return fun(detail::bind_first(std::forward<T>(t), q));
}
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
/// \param[in] t Function / member to expose
/// \param[in] q Value to bind to first parameter
/// \param[in] r Value to bind to second parameter
///
/// \b Example:
/// \code
/// struct MyClass
/// {
/// void memberfunction(int);
/// };
///
/// MyClass obj;
/// chaiscript::ChaiScript chai;
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
/// // memberfunction() will be equivalent to obj.memberfunction(1)
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
/// \endcode
///
/// \sa \ref adding_functions
template<typename T, typename Q, typename R>
Proxy_Function fun(T &&t, Q &&q, R &&r)
{
return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
}
}

View File

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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
@ -39,14 +43,14 @@ namespace chaiscript
{
}
bad_boxed_dynamic_cast(const std::string &w) 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() noexcept = default;
~bad_boxed_dynamic_cast() noexcept override = default;
};
class bad_boxed_type_cast : public bad_boxed_cast
@ -63,14 +67,14 @@ namespace chaiscript
{
}
bad_boxed_type_cast(const std::string &w) 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() noexcept = default;
~bad_boxed_type_cast() noexcept override = default;
};
}
@ -100,8 +104,8 @@ namespace chaiscript
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))
{
}
@ -286,7 +290,7 @@ 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))
{
}
@ -302,7 +306,7 @@ namespace chaiscript
return m_func(t_from);
}
virtual bool bidir() const override
bool bidir() const override
{
return false;
}
@ -334,21 +338,15 @@ namespace chaiscript
: m_mutex(),
m_conversions(),
m_convertableTypes(),
m_num_types(0),
m_thread_cache(this),
m_conversion_saves(this)
m_num_types(0)
{
}
Type_Conversions(const Type_Conversions &t_other)
: m_mutex(),
m_conversions(t_other.get_conversions()),
m_convertableTypes(t_other.m_convertableTypes),
m_num_types(m_conversions.size()),
m_thread_cache(this),
m_conversion_saves(this)
{
}
Type_Conversions(const Type_Conversions &t_other) = delete;
Type_Conversions(Type_Conversions &&) = default;
Type_Conversions &operator=(const Type_Conversions &) = delete;
Type_Conversions &operator=(Type_Conversions &&) = default;
const std::set<const std::type_info *, Less_Than> &thread_cache() const
{
@ -397,28 +395,39 @@ namespace chaiscript
template<typename To>
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
{
try {
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
if (t_saves.enabled) t_saves.saves.push_back(ret);
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
}
return boxed_type_conversion(user_type<To>(), t_saves, from);
}
template<typename From>
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
{
return boxed_type_down_conversion(user_type<From>(), t_saves, to);
}
Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const
{
try {
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
if (t_saves.enabled) t_saves.saves.push_back(ret);
Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from);
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "Unable to perform dynamic_cast operation");
}
}
Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const
{
try {
Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to);
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "Unable to perform dynamic_cast operation");
}
}

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
#define CHAISCRIPT_TYPE_INFO_HPP_
@ -29,8 +33,8 @@ namespace chaiscript
class Type_Info
{
public:
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)
@ -47,6 +51,16 @@ namespace chaiscript
return m_type_info < ti.m_type_info;
}
constexpr bool operator!=(const Type_Info &ti) const noexcept
{
return !(operator==(ti));
}
constexpr bool operator!=(const std::type_info &ti) const noexcept
{
return !(operator==(ti));
}
constexpr bool operator==(const Type_Info &ti) const noexcept
{
return ti.m_type_info == m_type_info
@ -121,9 +135,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,
@ -138,9 +150,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,
@ -158,9 +170,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,
@ -173,9 +183,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,
@ -188,9 +196,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,
@ -212,7 +218,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();
}
@ -227,7 +233,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

@ -1,19 +1,25 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#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 +37,7 @@ namespace chaiscript
};
static const char *to_string(Opers t_oper) {
const char *opers[] = {
static const char *opers[] = {
"",
"==", "<", ">", "<=", ">=", "!=",
"",
@ -46,81 +52,53 @@ 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;
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4307)
#endif
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; }
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
};

View File

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_COMMON_HPP_
#define CHAISCRIPT_COMMON_HPP_
@ -26,34 +30,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", "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 +131,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 {
@ -132,7 +192,7 @@ namespace chaiscript
reason(t_why), start_position(t_where), filename(t_fname)
{}
eval_error(const std::string &t_why) noexcept
explicit eval_error(const std::string &t_why) noexcept
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
@ -144,7 +204,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 +221,12 @@ namespace chaiscript
return ss.str();
}
virtual ~eval_error() 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 +480,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) 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() noexcept {}
~file_not_found_error() noexcept override = default;
};
}
@ -434,11 +494,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 +510,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 +534,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 +551,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 +601,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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_ENGINE_HPP_
#define CHAISCRIPT_ENGINE_HPP_
@ -17,6 +21,7 @@
#include <set>
#include <stdexcept>
#include <vector>
#include <cstring>
#include "../chaiscript_defines.hpp"
#include "../chaiscript_threading.hpp"
@ -31,229 +36,34 @@
#include <unistd.h>
#endif
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
#include <dlfcn.h>
#endif
#if defined(CHAISCRIPT_NO_DYNLOAD)
#include "chaiscript_unknown.hpp"
#elif defined(CHAISCRIPT_WINDOWS)
#include "chaiscript_windows.hpp"
#elif _POSIX_VERSION
#include "chaiscript_posix.hpp"
#else
#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_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) noexcept
: std::runtime_error(t_reason)
{
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() 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 +75,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 +93,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 +129,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);
@ -366,9 +150,6 @@ namespace chaiscript
})
, "call_exists");
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
//
//
m_engine.add(fun(
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
@ -390,23 +171,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 +221,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 !defined(CHAISCRIPT_NO_DYNLOAD) && 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 +276,70 @@ 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);
}
#ifndef CHAISCRIPT_NO_DYNLOAD
/// \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;
}
}
#else // CHAISCRIPT_NO_DYNLOAD
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()) = delete;
#endif
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 +392,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 +404,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 +511,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 +527,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 +536,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;
@ -803,9 +556,13 @@ namespace chaiscript
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
std::string load_module(const std::string &t_module_name)
{
#ifdef CHAISCRIPT_NO_DYNLOAD
(void)t_module_name; // -Wunused-parameter
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
#else
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 +592,8 @@ 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);
#endif
}
/// \brief Load a binary module from a dynamic library. Works on platforms that support
@ -886,14 +630,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 +649,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 +688,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 +701,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-2017, 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-2017, 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 2009-2016, Jason Turner (jason@emptycrate.com)
// and 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_

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-2017, 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,31 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2017, 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 &)
{
#ifdef CHAISCRIPT_NO_DYNLOAD
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
#else
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
#endif
}
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-2017, 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,50 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
#include <cstdint>
#include "../chaiscript_defines.hpp"
namespace chaiscript
{
namespace utility
{
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4307)
#endif
return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193));
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
}
}
#endif

View File

@ -47,6 +47,79 @@ class JSON
};
private:
struct QuickFlatMap
{
auto find(const std::string &s) {
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
}
auto find(const std::string &s) const {
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
}
auto size() const {
return data.size();
}
auto begin() const {
return data.begin();
}
auto end() const {
return data.end();
}
auto begin() {
return data.begin();
}
auto end() {
return data.end();
}
JSON &operator[](const std::string &s) {
const auto itr = find(s);
if (itr != data.end()) {
return itr->second;
} else {
data.emplace_back(s, JSON());
return data.back().second;
}
}
JSON &at(const std::string &s) {
const auto itr = find(s);
if (itr != data.end()) {
return itr->second;
} else {
throw std::out_of_range("Unknown key: " + s);
}
}
const JSON &at(const std::string &s) const {
const auto itr = find(s);
if (itr != data.end()) {
return itr->second;
} else {
throw std::out_of_range("Unknown key: " + s);
}
}
size_t count(const std::string &s) const {
return (find(s) != data.end())?1:0;
}
std::vector<std::pair<std::string, JSON>> data;
using iterator = decltype(data)::iterator;
using const_iterator = decltype(data)::const_iterator;
};
struct Internal {
template<typename T>
auto clone(const std::unique_ptr<T> &ptr) {
@ -100,7 +173,7 @@ class JSON
String.reset();
switch( type ) {
case Class::Object: Map = std::make_unique<std::map<std::string,JSON>>(); break;
case Class::Object: Map = std::make_unique<QuickFlatMap>(); break;
case Class::Array: List = std::make_unique<std::vector<JSON>>(); break;
case Class::String: String = std::make_unique<std::string>(); break;
case Class::Floating: Float = 0.0; break;
@ -116,7 +189,7 @@ class JSON
Internal &operator=(Internal &&) = default;
std::unique_ptr<std::vector<JSON>> List;
std::unique_ptr<std::map<std::string,JSON>> Map;
std::unique_ptr<QuickFlatMap> Map;
std::unique_ptr<std::string> String;
double Float = 0;
long Int = 0;
@ -229,7 +302,7 @@ class JSON
bool has_key( const std::string &key ) const {
if( internal.Type == Class::Object ) {
return internal.Map->find( key ) != internal.Map->end();
return internal.Map->count(key) != 0;
}
return false;
@ -274,11 +347,11 @@ class JSON
return ok ? internal.Bool : false;
}
JSONWrapper<std::map<std::string,JSON>> object_range() {
JSONWrapper<QuickFlatMap> object_range() {
if( internal.Type == Class::Object ) {
return JSONWrapper<std::map<std::string,JSON>>( internal.Map.get() );
return JSONWrapper<QuickFlatMap>( internal.Map.get() );
} else {
return JSONWrapper<std::map<std::string,JSON>>( nullptr );
return JSONWrapper<QuickFlatMap>( nullptr );
}
}
@ -290,11 +363,11 @@ class JSON
}
}
JSONConstWrapper<std::map<std::string,JSON>> object_range() const {
JSONConstWrapper<QuickFlatMap> object_range() const {
if( internal.Type == Class::Object ) {
return JSONConstWrapper<std::map<std::string,JSON>>( internal.Map.get() );
return JSONConstWrapper<QuickFlatMap>( internal.Map.get() );
} else {
return JSONConstWrapper<std::map<std::string,JSON>>( nullptr );
return JSONConstWrapper<QuickFlatMap>( nullptr );
}
}
@ -313,12 +386,12 @@ class JSON
return "null";
case Class::Object: {
std::string pad = "";
for( long i = 0; i < depth; ++i, pad += tab );
for( long i = 0; i < depth; ++i, pad += tab ) { }
std::string s = "{\n";
bool skip = true;
for( auto &p : *internal.Map ) {
if( !skip ) s += ",\n";
if( !skip ) { s += ",\n"; }
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
skip = false;
}
@ -329,7 +402,7 @@ class JSON
std::string s = "[";
bool skip = true;
for( auto &p : *internal.List ) {
if( !skip ) s += ", ";
if( !skip ) { s += ", "; }
s += p.dump( depth + 1, tab );
skip = false;
}
@ -353,8 +426,8 @@ class JSON
private:
static std::string json_escape( const std::string &str ) {
std::string output;
for( size_t i = 0; i < str.length(); ++i )
switch( str[i] ) {
for(char i : str) {
switch( i ) {
case '\"': output += "\\\""; break;
case '\\': output += "\\\\"; break;
case '\b': output += "\\b"; break;
@ -362,8 +435,9 @@ class JSON
case '\n': output += "\\n"; break;
case '\r': output += "\\r"; break;
case '\t': output += "\\t"; break;
default : output += str[i]; break;
default : output += i; break;
}
}
return output;
}
@ -389,7 +463,7 @@ struct JSONParser {
}
static void consume_ws( const std::string &str, size_t &offset ) {
while( isspace( str[offset] ) && offset <= str.size() ) ++offset;
while( isspace( str[offset] ) && offset <= str.size() ) { ++offset; }
}
static JSON parse_object( const std::string &str, size_t &offset ) {
@ -471,9 +545,9 @@ struct JSONParser {
val += "\\u" ;
for( size_t i = 1; i <= 4; ++i ) {
c = str[offset+i];
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) {
val += c;
else {
} else {
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
}
}
@ -481,9 +555,9 @@ struct JSONParser {
} break;
default : val += '\\'; break;
}
}
else
} else {
val += c;
}
}
++offset;
return JSON(val);
@ -493,33 +567,43 @@ struct JSONParser {
std::string val, exp_str;
char c = '\0';
bool isDouble = false;
bool isNegative = false;
long exp = 0;
if( offset < str.size() && str[offset] == '-' ) {
isNegative = true;
++offset;
}
for (; offset < str.size() ;) {
c = str[offset++];
if( (c == '-') || (c >= '0' && c <= '9') )
if( c >= '0' && c <= '9' ) {
val += c;
else if( c == '.' ) {
} else if( c == '.' && !isDouble ) {
val += c;
isDouble = true;
}
else
} else {
break;
}
}
if( offset < str.size() && (c == 'E' || c == 'e' )) {
c = str[ offset++ ];
if( c == '-' ) { exp_str += '-';}
else if( c == '+' ) { }
else --offset;
if( c == '-' ) {
exp_str += '-';
} else if( c == '+' ) {
// do nothing
} else {
--offset;
}
for (; offset < str.size() ;) {
c = str[ offset++ ];
if( c >= '0' && c <= '9' )
if( c >= '0' && c <= '9' ) {
exp_str += c;
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
} else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
}
else
else {
break;
}
}
exp = chaiscript::parse_num<long>( exp_str );
}
@ -529,12 +613,12 @@ struct JSONParser {
--offset;
if( isDouble ) {
return JSON(chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
} else {
if( !exp_str.empty() ) {
return JSON(static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp ));
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp ));
} else {
return JSON(chaiscript::parse_num<long>( val ));
return JSON((isNegative?-1:1) * chaiscript::parse_num<long>( val ));
}
}
}
@ -570,8 +654,9 @@ struct JSONParser {
case 't' :
case 'f' : return parse_bool( str, offset );
case 'n' : return parse_null( str, offset );
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
default : if( ( value <= '9' && value >= '0' ) || value == '-' ) {
return parse_number( str, offset );
}
}
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
}

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-2017, 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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
@ -12,9 +16,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"
@ -90,6 +93,29 @@ namespace chaiscript
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

@ -17,7 +17,7 @@ ChaiScript
http://www.chaiscript.com
(c) 2009-2012 Jonathan Turner
(c) 2009-2016 Jason Turner
(c) 2009-2017 Jason Turner
Release under the BSD license, see "license.txt" for details.
@ -43,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
@ -80,7 +79,7 @@ directory, and for more in-depth look at the language, the unit tests in the
"unittests" directory cover the most ground.
For examples of how to register parts of your C++ application, see
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
"example.cpp" in the "samples" directory. Example.cpp is verbose and shows every
possible way of working with the library. For further documentation generate
the doxygen documentation in the build folder or see the website
http://www.chaiscript.com.
@ -88,44 +87,21 @@ http://www.chaiscript.com.
The shortest complete example possible follows:
/// main.cpp
```C++
/// main.cpp
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}
Or, if you want to compile the std lib into your code, which reduces
runtime requirements.
/// main.cpp
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}
double function(int i, double j)
{
return i * j;
}
int main()
{
chaiscript::ChaiScript chai;
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}
```

View File

@ -1,6 +1,67 @@
Notes:
=======
Current Version: 5.8.2
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 ) { }` (much better performance than other loop types)
* 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
* Allow typed ChaiScript defined functions to perform conversions on call #303
#### 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)
* Fix type conversion to bool in conditionals
#### 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
* Make sure atomics are initialized properly
* Remove parsing of unused prefix `&` operator
### Changes since 5.8.3
* Fix case with some numeric conversions mixed with numerics that do not need conversion
### Changes since 5.8.2
* Add support for reference of pointer return types
### Changes since 5.8.1
* Allow casting to non-const & std::shared_ptr<T>

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");
@ -108,9 +108,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
// A shortcut to using eval is just to use the chai operator()
chai("log(\"Test Module\", \"Test Message\");");
//Finally, it is possible to register any std::function as a system function, in this
//Finally, it is possible to register a lambda as a system function, in this
//way, we can, for instance add a bound member function to the system
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
chai.add(fun([&system](){ return system.do_callbacks("Bound Test"); }), "do_callbacks");
//Call bound version of do_callbacks
chai("do_callbacks()");

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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <iostream>
#include <list>
#include <regex>
@ -13,7 +17,6 @@
#endif
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#ifdef READLINE_AVAILABLE
#include <readline/readline.h>
@ -65,6 +68,7 @@ std::vector<std::string> default_search_paths()
{
std::vector<std::string> paths;
#ifndef CHAISCRIPT_NO_DYNLOAD
#ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
@ -134,6 +138,7 @@ std::vector<std::string> default_search_paths()
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
}
#endif
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
return paths;
}
@ -291,7 +296,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
{
@ -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

@ -1,9 +1,13 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <iostream>
#include <list>
#include <regex>
@ -12,7 +16,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 +29,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 +48,7 @@ char* readline(const char* p)
}
void add_history(const char*){}
void add_history(const char* /*unused*/){}
void using_history(){}
#endif
@ -64,6 +71,7 @@ std::vector<std::string> default_search_paths()
{
std::vector<std::string> paths;
#ifndef CHAISCRIPT_NO_DYNLOAD
#ifdef CHAISCRIPT_WINDOWS // force no unicode
CHAR path[4096];
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
@ -113,7 +121,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 +133,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)
@ -133,6 +141,7 @@ std::vector<std::string> default_search_paths()
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
}
#endif
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
return paths;
}
@ -181,7 +190,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 +226,7 @@ void myexit(int return_val) {
exit(return_val);
}
void interactive(chaiscript::ChaiScript& chai)
void interactive(chaiscript::ChaiScript_Basic& chai)
{
using_history();
@ -237,7 +246,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 +283,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 +292,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 +314,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 +325,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;

View File

@ -1,10 +1,14 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <chaiscript/chaiscript.hpp>
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
#include <list>
#include <string>

View File

@ -1,5 +1,5 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <string>

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

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

@ -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

@ -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,19 +192,19 @@ 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>());
REQUIRE(false);
} catch (const double e) {
CHECK(e == 1.0);
CHECK(e == Approx(1.0));
}
}
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,7 +316,7 @@ 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; }");
@ -337,7 +340,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 +359,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 +405,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 +428,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 +454,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 +509,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 +552,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 +647,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 +703,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 +756,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 +797,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 +816,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 +839,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 +856,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 +876,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 +924,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 +944,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)");
@ -950,4 +953,320 @@ TEST_CASE("Parse floats with non-posix locale")
bool FindBitmap(int &ox, int &oy, long) {
ox = 1;
oy = 2;
return true;
}
TEST_CASE("Mismatched numeric types only convert necessary params")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::fun(&FindBitmap), "FindBitmap");
int x = 0;
int y = 0;
chai.add(chaiscript::var(&x), "x");
chai.add(chaiscript::var(&y), "y");
chai.eval( "if ( FindBitmap ( x, y, 0) ) { print(\"found at \" + to_string(x) + \", \" + to_string(y))}" );
CHECK(x == 1);
CHECK(y == 2);
}
TEST_CASE("type_conversion to bool")
{
auto module = std::make_shared<chaiscript::Module>();
struct T {
operator bool() const { return true; }
};
module->add(chaiscript::type_conversion<T, bool>());
}
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::fun([](const std::unique_ptr<int> &i){ ++(*i); }), "constrefuniqptri");
chai.add(chaiscript::fun([](std::unique_ptr<int> &i){ ++(*i); }), "refuniqptri");
chai.add(chaiscript::fun([](std::unique_ptr<int> &&i){ ++(*i); }), "rvaluniqptri");
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);
chai.eval("constrefuniqptri(iptr)");
CHECK(chai.eval<int>("iptr") == 4);
chai.eval("refuniqptri(iptr)");
CHECK(chai.eval<int>("iptr") == 5);
chai.eval("rvaluniqptri(iptr)");
CHECK(chai.eval<int>("iptr") == 6);
}
class Unique_Ptr_Test_Class
{
public:
Unique_Ptr_Test_Class() = default;
Unique_Ptr_Test_Class(const Unique_Ptr_Test_Class&) = default;
Unique_Ptr_Test_Class(Unique_Ptr_Test_Class &&) = default;
Unique_Ptr_Test_Class &operator=(const Unique_Ptr_Test_Class&) = default;
Unique_Ptr_Test_Class &operator=(Unique_Ptr_Test_Class&&) = default;
virtual ~Unique_Ptr_Test_Class() = default;
int getI() const {return 5;}
};
std::unique_ptr<Unique_Ptr_Test_Class> make_Unique_Ptr_Test_Class()
{
return std::make_unique<Unique_Ptr_Test_Class>();
}
TEST_CASE("Call methods through unique_ptr")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::var(std::make_unique<Unique_Ptr_Test_Class>()), "uptr");
chai.add(chaiscript::fun(make_Unique_Ptr_Test_Class), "make_Unique_Ptr_Test_Class");
chai.add(chaiscript::fun(&Unique_Ptr_Test_Class::getI), "getI");
CHECK(chai.eval<int>("uptr.getI()") == 5);
CHECK(chai.eval<int>("var uptr2 = make_Unique_Ptr_Test_Class(); uptr2.getI()") == 5);
}
class Unique_Ptr_Test_Base_Class
{
public:
int getI() const {return 5;}
};
class Unique_Ptr_Test_Derived_Class : public Unique_Ptr_Test_Base_Class
{};
std::unique_ptr<Unique_Ptr_Test_Derived_Class> make_Unique_Ptr_Test_Derived_Class()
{
return std::make_unique<Unique_Ptr_Test_Derived_Class>();
}
TEST_CASE("Call methods on base class through unique_ptr<derived>")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
chai.add(chaiscript::var(std::make_unique<Unique_Ptr_Test_Derived_Class>()), "uptr");
chai.add(chaiscript::fun(make_Unique_Ptr_Test_Derived_Class), "make_Unique_Ptr_Test_Derived_Class");
chai.add(chaiscript::fun(&Unique_Ptr_Test_Base_Class::getI), "getI");
chai.add(chaiscript::base_class<Unique_Ptr_Test_Base_Class, Unique_Ptr_Test_Derived_Class>());
CHECK(chai.eval<int>("uptr.getI()") == 5);
CHECK(chai.eval<int>("var uptr2 = make_Unique_Ptr_Test_Derived_Class(); uptr2.getI()") == 5);
}
class A
{
public:
A() = default;
A(const A&) = default;
A(A &&) = default;
A &operator=(const A&) = default;
A &operator=(A&&) = default;
virtual ~A() = default;
};
class B : public A
{
public:
B() = default;
};
TEST_CASE("Test typed chaiscript functions to perform conversions")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
//-------------------------------------------------------------------------
chai.add(chaiscript::user_type<A>(), "A");
chai.add(chaiscript::user_type<B>(), "B");
chai.add(chaiscript::base_class<A, B>());
chai.add(chaiscript::fun([](const B &)
{
}), "CppFunctWithBArg");
chai.add(chaiscript::fun([]() -> std::shared_ptr<A>
{
return (std::shared_ptr<A>(new B()));
}), "Create");
chai.eval(R"(
var inst = Create() // A*
// it prints "A"
inst.type_name().print()
// Ok it is casted using conversion
CppFunctWithBArg(inst)
// Define a function with B as argument
def ChaiFuncWithBArg(B inst)
{
print("ok")
}
// don't work
ChaiFuncWithBArg(inst)
)");
}
struct Reference_MyClass
{
Reference_MyClass(double& t_x) : x(t_x) {}
double& x;
};
TEST_CASE("Test reference member being registered")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
// Note, C++ will not allow us to do this:
// chai.add(chaiscript::fun(&Reference_MyClass::x) , "x");
chai.add(chaiscript::fun([](Reference_MyClass &r) -> decltype(auto) { return (r.x); }), "x");
chai.add(chaiscript::fun([](const Reference_MyClass &r) -> decltype(auto) { return (r.x); }), "x");
double d;
chai.add(chaiscript::var(Reference_MyClass(d)), "ref");
chai.eval("ref.x = 2.3");
CHECK(d == Approx(2.3));
}

View File

@ -0,0 +1,23 @@
// 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);
}
if (!0) {
assert_true(true);
} else {
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

@ -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

@ -0,0 +1,26 @@
class Test
{
def Test()
{}
def a(Function f)
{
f("test");
// f();
}
def b()
{
var l = fun [this](x) { this.thing(); }
this.a(l)
}
def thing()
{
print("hello world");
}
}
var t = Test()
t.b()

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,122 +1,284 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"
#ifdef CHAISCRIPT_MSVC
// ignore errors about negative unsigned integer literals
#pragma warning(push)
#pragma warning(disable : 4146)
#endif
#define TEST_LITERAL(v) test_literal(v, #v)
#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true)
template<typename T>
bool test_literal(T val, const std::string &str)
bool test_literal(T val, const std::string &str, bool use_boxed_number = false)
{
std::cout << "Comparing : " << val;
chaiscript::ChaiScript chai;
T val2 = chai.eval<T>(str);
std::cout << " " << val2 << '\n';
std::cout << '(' << str << ") Comparing : C++ '" << val;
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
// Note, after applying the `-` it's possible that chaiscript has internally converted
// between two equivalently sized types (ie, unsigned long and unsigned long long on a 64bit system)
// so we're going to allow some leeway with the signed tests
T val2 = [&](){
if (!use_boxed_number) {
return chai.eval<T>(str);
} else {
return chai.eval<chaiscript::Boxed_Number>(str).get_as_checked<T>();
}
}();
std::cout << "' chai '" << val2 << "'\n";
return val == val2;
}
int main()
{
if( TEST_LITERAL(0xF)
&& TEST_LITERAL(0xFF)
&& TEST_LITERAL(0xFFF)
&& TEST_LITERAL(0xFFFF)
&& TEST_LITERAL(0xFFFFF)
&& TEST_LITERAL(0xFFFFFF)
&& TEST_LITERAL(0xFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
&& TEST_LITERAL(01)
&& TEST_LITERAL(017)
&& TEST_LITERAL(0177)
&& TEST_LITERAL(01777)
&& TEST_LITERAL(017777)
&& TEST_LITERAL(0177777)
&& TEST_LITERAL(01777777)
&& TEST_LITERAL(017777777)
&& TEST_LITERAL(0177777777)
&& TEST_LITERAL(01777777777)
&& TEST_LITERAL(017777777777)
&& TEST_LITERAL(0177777777777)
&& TEST_LITERAL(01777777777777)
&& TEST_LITERAL(017777777777777)
&& TEST_LITERAL(0177777777777777)
&& TEST_LITERAL(01777777777777777)
&& TEST_LITERAL(017777777777777777)
&& TEST_LITERAL(0177777777777777777)
&& TEST_LITERAL(01777777777777777777)
&& TEST_LITERAL(017777777777777777777)
&& TEST_LITERAL(0177777777777777777777)
&& TEST_LITERAL(01777777777777777777777)
if(
TEST_LITERAL(0xF)
&& TEST_LITERAL(0xFF)
&& TEST_LITERAL(0xFFF)
&& TEST_LITERAL(0xFFFF)
&& TEST_LITERAL(0xFFFFF)
&& TEST_LITERAL(0xFFFFFF)
&& TEST_LITERAL(0xFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
&& TEST_LITERAL(1)
&& TEST_LITERAL(17)
&& TEST_LITERAL(177)
&& TEST_LITERAL(1777)
&& TEST_LITERAL(17777)
&& TEST_LITERAL(177777)
&& TEST_LITERAL(1777777)
&& TEST_LITERAL(17777777)
&& TEST_LITERAL(177777777)
&& TEST_LITERAL(1777777777)
&& TEST_LITERAL(17777777777)
&& TEST_LITERAL(177777777777)
&& TEST_LITERAL(1777777777777)
&& TEST_LITERAL(17777777777777)
&& TEST_LITERAL(177777777777777)
&& TEST_LITERAL(1777777777777777)
&& TEST_LITERAL(17777777777777777)
&& TEST_LITERAL(177777777777777777)
&& TEST_LITERAL(1777777777777777777)
&& test_literal(0xF, "0b1111")
&& test_literal(0xFF, "0b11111111")
&& test_literal(0xFFF, "0b111111111111")
&& test_literal(0xFFFF, "0b1111111111111111")
&& test_literal(0xFFFFF, "0b11111111111111111111")
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
&& TEST_LITERAL(01)
&& TEST_LITERAL(017)
&& TEST_LITERAL(0177)
&& TEST_LITERAL(01777)
&& TEST_LITERAL(017777)
&& TEST_LITERAL(0177777)
&& TEST_LITERAL(01777777)
&& TEST_LITERAL(017777777)
&& TEST_LITERAL(0177777777)
&& TEST_LITERAL(01777777777)
&& TEST_LITERAL(017777777777)
&& TEST_LITERAL(0177777777777)
&& TEST_LITERAL(01777777777777)
&& TEST_LITERAL(017777777777777)
&& TEST_LITERAL(0177777777777777)
&& TEST_LITERAL(01777777777777777)
&& TEST_LITERAL(017777777777777777)
&& TEST_LITERAL(0177777777777777777)
&& TEST_LITERAL(01777777777777777777)
&& TEST_LITERAL(017777777777777777777)
&& TEST_LITERAL(0177777777777777777777)
&& TEST_LITERAL(01777777777777777777777)
&& test_literal(0x7, "0b111")
&& test_literal(0x7F, "0b1111111")
&& test_literal(0x7FF, "0b11111111111")
&& test_literal(0x7FFF, "0b111111111111111")
&& test_literal(0x7FFFF, "0b1111111111111111111")
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
)
&& TEST_LITERAL(1)
&& TEST_LITERAL(17)
&& TEST_LITERAL(177)
&& TEST_LITERAL(1777)
&& TEST_LITERAL(17777)
&& TEST_LITERAL(177777)
&& TEST_LITERAL(1777777)
&& TEST_LITERAL(17777777)
&& TEST_LITERAL(177777777)
&& TEST_LITERAL(1777777777)
&& TEST_LITERAL(17777777777)
&& TEST_LITERAL(177777777777)
&& TEST_LITERAL(1777777777777)
&& TEST_LITERAL(17777777777777)
&& TEST_LITERAL(177777777777777)
&& TEST_LITERAL(1777777777777777)
&& TEST_LITERAL(17777777777777777)
&& TEST_LITERAL(177777777777777777)
&& TEST_LITERAL(1777777777777777777)
&& test_literal(0xF, "0b1111")
&& test_literal(0xFF, "0b11111111")
&& test_literal(0xFFF, "0b111111111111")
&& test_literal(0xFFFF, "0b1111111111111111")
&& test_literal(0xFFFFF, "0b11111111111111111111")
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7, "0b111")
&& test_literal(0x7F, "0b1111111")
&& test_literal(0x7FF, "0b11111111111")
&& test_literal(0x7FFF, "0b111111111111111")
&& test_literal(0x7FFFF, "0b1111111111111111111")
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
&& TEST_LITERAL_SIGNED(-0xF)
&& TEST_LITERAL_SIGNED(-0xFF)
&& TEST_LITERAL_SIGNED(-0xFFF)
&& TEST_LITERAL_SIGNED(-0xFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFFF)
&& TEST_LITERAL_SIGNED(-01)
&& TEST_LITERAL_SIGNED(-017)
&& TEST_LITERAL_SIGNED(-0177)
&& TEST_LITERAL_SIGNED(-01777)
&& TEST_LITERAL_SIGNED(-017777)
&& TEST_LITERAL_SIGNED(-0177777)
&& TEST_LITERAL_SIGNED(-01777777)
&& TEST_LITERAL_SIGNED(-017777777)
&& TEST_LITERAL_SIGNED(-0177777777)
&& TEST_LITERAL_SIGNED(-01777777777)
&& TEST_LITERAL_SIGNED(-017777777777)
&& TEST_LITERAL_SIGNED(-0177777777777)
&& TEST_LITERAL_SIGNED(-01777777777777)
&& TEST_LITERAL_SIGNED(-017777777777777)
&& TEST_LITERAL_SIGNED(-0177777777777777)
&& TEST_LITERAL_SIGNED(-01777777777777777)
&& TEST_LITERAL_SIGNED(-017777777777777777)
&& TEST_LITERAL_SIGNED(-0177777777777777777)
&& TEST_LITERAL_SIGNED(-01777777777777777777)
&& TEST_LITERAL_SIGNED(-017777777777777777777)
&& TEST_LITERAL_SIGNED(-0177777777777777777777)
&& TEST_LITERAL_SIGNED(-01777777777777777777777)
&& TEST_LITERAL_SIGNED(-1)
&& TEST_LITERAL_SIGNED(-17)
&& TEST_LITERAL_SIGNED(-177)
&& TEST_LITERAL_SIGNED(-1777)
&& TEST_LITERAL_SIGNED(-17777)
&& TEST_LITERAL_SIGNED(-177777)
&& TEST_LITERAL_SIGNED(-1777777)
&& TEST_LITERAL_SIGNED(-17777777)
&& TEST_LITERAL_SIGNED(-177777777)
&& TEST_LITERAL_SIGNED(-1777777777)
&& TEST_LITERAL_SIGNED(-17777777777)
&& TEST_LITERAL_SIGNED(-177777777777)
&& TEST_LITERAL_SIGNED(-1777777777777)
&& TEST_LITERAL_SIGNED(-17777777777777)
&& TEST_LITERAL_SIGNED(-177777777777777)
&& TEST_LITERAL_SIGNED(-1777777777777777)
&& TEST_LITERAL_SIGNED(-17777777777777777)
&& TEST_LITERAL_SIGNED(-177777777777777777)
&& TEST_LITERAL_SIGNED(-1777777777777777777)
// Test 8/16/24/32 bit boundaries for various types
&& TEST_LITERAL(255)
&& TEST_LITERAL(65535)
&& TEST_LITERAL(16777215)
#ifndef CHAISCRIPT_MSVC
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
&& TEST_LITERAL(4294967295)
#endif
&& TEST_LITERAL_SIGNED(-255)
&& TEST_LITERAL_SIGNED(-65535)
&& TEST_LITERAL_SIGNED(-16777215)
#ifndef CHAISCRIPT_MSVC
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
&& TEST_LITERAL_SIGNED(-4294967295)
#endif
&& TEST_LITERAL(255u)
&& TEST_LITERAL(65535u)
&& TEST_LITERAL(16777215u)
&& TEST_LITERAL(4294967295u)
&& TEST_LITERAL_SIGNED(-255u)
&& TEST_LITERAL_SIGNED(-65535u)
&& TEST_LITERAL_SIGNED(-16777215u)
&& TEST_LITERAL_SIGNED(-4294967295u)
&& TEST_LITERAL(255l)
&& TEST_LITERAL(65535l)
&& TEST_LITERAL(16777215l)
#ifndef CHAISCRIPT_MSVC
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
&& TEST_LITERAL(4294967295l)
#endif
&& TEST_LITERAL_SIGNED(-255l)
&& TEST_LITERAL_SIGNED(-65535l)
&& TEST_LITERAL_SIGNED(-16777215l)
#ifndef CHAISCRIPT_MSVC
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
&& TEST_LITERAL_SIGNED(-4294967295l)
#endif
&& TEST_LITERAL(255ul)
&& TEST_LITERAL(65535ul)
&& TEST_LITERAL(16777215ul)
&& TEST_LITERAL(4294967295ul)
&& TEST_LITERAL_SIGNED(-255ul)
&& TEST_LITERAL_SIGNED(-65535ul)
&& TEST_LITERAL_SIGNED(-16777215ul)
&& TEST_LITERAL_SIGNED(-4294967295ul)
&& TEST_LITERAL(255ull)
&& TEST_LITERAL(65535ull)
&& TEST_LITERAL(16777215ull)
&& TEST_LITERAL(4294967295ull)
&& TEST_LITERAL_SIGNED(-255ull)
&& TEST_LITERAL_SIGNED(-65535ull)
&& TEST_LITERAL_SIGNED(-16777215ull)
&& TEST_LITERAL_SIGNED(-4294967295ull)
&& TEST_LITERAL(255ll)
&& TEST_LITERAL(65535ll)
&& TEST_LITERAL(16777215ll)
&& TEST_LITERAL(4294967295ll)
&& TEST_LITERAL_SIGNED(-255ll)
&& TEST_LITERAL_SIGNED(-65535ll)
&& TEST_LITERAL_SIGNED(-16777215ll)
&& TEST_LITERAL_SIGNED(-4294967295ll)
)
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif

View File

@ -1 +1,2 @@
assert_equal(from_json("100"), 100)
assert_equal(from_json("-100"), -100)

View File

@ -1 +1,22 @@
assert_equal(from_json("1.234"), 1.234)
assert_equal(from_json("-1.234"), -1.234)
auto caught = false;
try {
from_json("-1-5.3");
}
catch(e) {
assert_equal("JSON ERROR: Number: unexpected character '-'", e.what());
caught = true;
}
assert_equal(caught, true);
caught = false;
try {
from_json("-15.3.2");
}
catch(e) {
assert_equal("JSON ERROR: Number: unexpected character '.'", e.what());
caught = true;
}
assert_equal(caught, true);

View File

@ -1,2 +1,2 @@
assert_equal(from_json("[1,2,3]"), [1,2,3])
assert_equal(from_json("[1,-2,3]"), [1,-2,3])

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
{

View File

@ -2,7 +2,11 @@
#include <algorithm>
#ifdef CHAISCRIPT_NO_DYNLOAD
#include <chaiscript/chaiscript.hpp>
#endif
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/language/chaiscript_parser.hpp>
int expected_value(int num_iters)
{
@ -15,7 +19,7 @@ int expected_value(int num_iters)
return i;
}
void do_work(chaiscript::ChaiScript &c, const size_t id)
void do_work(chaiscript::ChaiScript_Basic &c, const size_t id)
{
try{
std::stringstream ss;
@ -56,13 +60,22 @@ int main()
}
std::vector<std::string> modulepaths;
#ifdef CHAISCRIPT_NO_DYNLOAD
chaiscript::ChaiScript chai(/* unused */modulepaths, usepaths);
#else
modulepaths.push_back("");
if (modulepath)
{
modulepaths.push_back(modulepath);
}
chaiscript::ChaiScript chai(modulepaths,usepaths);
// For this test we are going to load the dynamic stdlib
// to make sure it continues to work
chaiscript::ChaiScript_Basic chai(
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>(),
modulepaths,usepaths);
#endif
std::vector<std::shared_ptr<std::thread> > threads;

View File

@ -0,0 +1,12 @@
def numFunc(x)
{
return x + 10;
}
// Note that unary prefix `-` has lower precedence than `.`
// this is why these values are correct, even if counterintuitive
assert_true(-5.numFunc() == -15);
assert_true((-5).numFunc() == 5);

View File

@ -0,0 +1,4 @@
var i = 2;
assert_equal(++i * i, 9)

21
unittests/ranged_for.chai Normal file
View File

@ -0,0 +1,21 @@
var sum = 0;
for (x : [1,2,3,4]) {
sum += x;
}
assert_equal(sum, 10)
var result = 0.0;
for (x : retro(range([1,2,3,4]))) {
if (result == 0.0) {
result = x;
} else {
result /= x;
}
}
assert_true(result > .6 && result < .7);

View File

@ -1,22 +1,9 @@
auto& parser = ChaiScript_Parser()
auto parse_success = parser.parse("3 + 4", "INPUT")
auto& a = parser.ast()
auto a = parse("3 + 4")
assert_equal(eval(a), 7)
auto& childs = a.children.front().children
auto& node = childs[0]
auto& 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")
assert_equal(1, a.children.size());
assert_equal("3 + 4", a.children[0].text());
def my_fun()
{

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