Compare commits

..

154 Commits

Author SHA1 Message Date
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 83b7973cb8.
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
Hristo Petrov
fd57bec676 Update cheatsheet.md
Added missing parameters to the examples of "Adding Method / Member"
2016-04-15 16:11:36 +01:00
93 changed files with 3562 additions and 1865 deletions

View File

@@ -1,33 +1,56 @@
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="5"
compiler: gcc
- os: osx
compiler: clang
osx_image: xcode8
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
- if [ "${GCC_VER}" == "5" ]; then export CPPCHECK=1 COVERAGE=1 FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE" ; 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
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD .
- cmake --build . -- -j2
- ctest
- 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 +65,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

@@ -249,27 +249,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 +298,7 @@ if (RUN_FUZZY_TESTS)
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
)
@@ -421,7 +424,7 @@ if(BUILD_TESTING)
if(NOT UNIT_TEST_LIGHT)
add_executable(compiled_tests unittests/compiled_tests.cpp)
target_link_libraries(compiled_tests ${LIBS})
target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS})
ADD_CATCH_TESTS(compiled_tests)
@@ -434,11 +437,11 @@ if(BUILD_TESTING)
add_test(NAME Type_Info_Test COMMAND type_info_test)
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
target_link_libraries(c_linkage_test ${LIBS})
target_link_libraries(c_linkage_test ${LIBS} ${CHAISCRIPT_LIBS})
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
target_link_libraries(integer_literal_test ${LIBS})
target_link_libraries(integer_literal_test ${LIBS} ${CHAISCRIPT_LIBS})
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
if(MULTITHREAD_SUPPORT_ENABLED)

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);");
/// }
@@ -816,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
@@ -137,18 +141,11 @@ namespace chaiscript {
};
template<typename Iter, typename Distance>
Iter advance_copy(Iter iter, Distance distance) {
std::advance(iter, static_cast<typename std::iterator_traits<Iter>::difference_type>(distance));
return iter;
}
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
{
T t = 0;
for (char c = *t_str; (c = *t_str); ++t_str) {
for (char c = *t_str; (c = *t_str) != 0; ++t_str) {
if (c < '0' || c > '9') {
return t;
}
@@ -209,6 +206,18 @@ namespace chaiscript {
return parse_num<T>(t_str.c_str());
}
enum class Options
{
No_Load_Modules,
Load_Modules,
No_External_Scripts,
External_Scripts
};
static inline std::vector<Options> default_options()
{
return {Options::Load_Modules, Options::External_Scripts};
}
}
#endif

View File

@@ -16,6 +16,8 @@
#include "chaiscript_defines.hpp"
#include "language/chaiscript_common.hpp"
#include "dispatchkit/function_call.hpp"
//#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/operators.hpp"
#include "dispatchkit/bootstrap.hpp"
@@ -42,8 +44,6 @@ namespace chaiscript
static ModulePtr library()
{
// using namespace bootstrap;
auto lib = std::make_shared<Module>();
bootstrap::Bootstrap::bootstrap(*lib);

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,7 +61,6 @@ 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>
@@ -106,69 +109,6 @@ namespace chaiscript
}
};
#else
#pragma message ("Threading without thread_local support is not well supported.")
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// 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_

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_BOOTSTRAP_HPP_
#define CHAISCRIPT_BOOTSTRAP_HPP_
@@ -15,18 +19,6 @@ 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)
{
@@ -110,7 +102,7 @@ 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);
}
@@ -161,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);
}

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_

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,7 +29,7 @@ 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");
}
@@ -135,6 +139,50 @@ namespace chaiscript
}
};
/// 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> >

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;
};
}
}
@@ -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)) {

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,7 +81,7 @@ namespace chaiscript
struct Object_Data
{
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
static auto get(Boxed_Value::Void_Type, bool t_return_value)
{
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
@@ -89,13 +93,13 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
static auto get(const std::shared_ptr<T> *obj, bool t_return_value)
{
return get(*obj, t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
static auto get(const std::shared_ptr<T> &obj, bool t_return_value)
{
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
@@ -107,7 +111,7 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
static auto get(std::shared_ptr<T> &&obj, bool t_return_value)
{
auto ptr = obj.get();
return std::make_shared<Data>(
@@ -119,21 +123,23 @@ namespace chaiscript
);
}
template<typename T>
static std::shared_ptr<Data> get(T *t, bool t_return_value)
static auto get(T *t, bool t_return_value)
{
return get(std::ref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
static auto get(const T *t, bool t_return_value)
{
return get(std::cref(*t), t_return_value);
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
static auto get(std::reference_wrapper<T> obj, bool t_return_value)
{
auto p = &obj.get();
return std::make_shared<Data>(
@@ -146,7 +152,20 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(T t, bool t_return_value)
static auto get(std::unique_ptr<T> &&obj, bool t_return_value)
{
auto ptr = obj.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::make_shared<std::unique_ptr<T>>(std::move(obj))),
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();
@@ -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;
@@ -239,8 +255,9 @@ namespace chaiscript
~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();
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;
@@ -305,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];
@@ -322,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;
}
@@ -345,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,6 +34,7 @@
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "type_info.hpp"
#include "short_alloc.hpp"
namespace chaiscript {
class Boxed_Number;
@@ -67,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
{
@@ -89,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
{
@@ -112,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
{
@@ -135,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;
};
}
@@ -147,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;
}
@@ -266,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))
{
@@ -356,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)
{
@@ -376,20 +380,55 @@ 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()
{
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));
}
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;
std::vector<std::vector<Boxed_Value>> call_params;
int call_depth = 0;
};
@@ -401,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
{
@@ -410,15 +449,11 @@ 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
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"};
};
Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
explicit Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
: m_stack_holder(this),
m_parser(parser)
{
}
@@ -439,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);
}
@@ -447,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)
@@ -467,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
@@ -482,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));
}
@@ -497,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();
@@ -516,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);
@@ -534,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())
@@ -549,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);
@@ -577,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
@@ -597,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)
@@ -639,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;
@@ -656,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;
}
@@ -721,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);
}
@@ -809,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());
}
@@ -912,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
@@ -935,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;
}
@@ -1025,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);
}
@@ -1149,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)
@@ -1167,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)
@@ -1359,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)
@@ -1410,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);
}
@@ -1469,7 +1512,7 @@ namespace chaiscript
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;
};
@@ -1477,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())
@@ -1504,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 {

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_
@@ -99,7 +99,7 @@ namespace chaiscript
}
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))
{
@@ -109,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);
}
@@ -151,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 {
@@ -202,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

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_

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
{
@@ -155,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 &>
{

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_

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
@@ -282,7 +332,7 @@ namespace chaiscript
guard_error(const guard_error &) = default;
virtual ~guard_error() noexcept = default;
~guard_error() noexcept override = default;
};
}
@@ -307,21 +357,20 @@ namespace chaiscript
}
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;
}
@@ -353,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)
{
@@ -371,7 +440,10 @@ namespace chaiscript
return types;
}
protected:
Param_Types m_param_types;
private:
Proxy_Function m_guard;
AST_NodePtr m_parsenode;
};
@@ -402,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();
}
@@ -516,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);
}
@@ -529,7 +606,7 @@ 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)
{
}
@@ -550,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))
{
@@ -581,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)
{
}
@@ -637,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)
{
@@ -742,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;
@@ -759,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);
@@ -819,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;
@@ -827,8 +905,6 @@ namespace chaiscript
}
);
try {
return (*(matching_func->second))(newplist, t_conversions);
} catch (const exception::bad_boxed_cast &) {
@@ -844,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)

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;
@@ -115,7 +119,15 @@ namespace chaiscript
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
}
}

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;
}
@@ -340,15 +344,11 @@ namespace chaiscript
{
}
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 +397,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_
@@ -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

View File

@@ -1,12 +1,18 @@
// 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
@@ -51,76 +57,48 @@ namespace chaiscript
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{
if (t_str == "==")
{
return Opers::equals;
} else if (t_str == "<") {
return Opers::less_than;
} else if (t_str == ">") {
return Opers::greater_than;
} else if (t_str == "<=") {
return Opers::less_than_equal;
} else if (t_str == ">=") {
return Opers::greater_than_equal;
} else if (t_str == "!=") {
return Opers::not_equal;
} else if (t_str == "=") {
return Opers::assign;
} else if (t_str == "++") {
return Opers::pre_increment;
} else if (t_str == "--") {
return Opers::pre_decrement;
} else if (t_str == "*=") {
return Opers::assign_product;
} else if (t_str == "+=") {
return Opers::assign_sum;
} else if (t_str == "-=") {
return Opers::assign_difference;
} else if (t_str == "&=") {
return Opers::assign_bitwise_and;
} else if (t_str == "|=") {
return Opers::assign_bitwise_or;
} else if (t_str == "<<=") {
return Opers::assign_shift_left;
} else if (t_str == ">>=") {
return Opers::assign_shift_right;
} else if (t_str == "%=") {
return Opers::assign_remainder;
} else if (t_str == "^=") {
return Opers::assign_bitwise_xor;
} else if (t_str == "<<") {
return Opers::shift_left;
} else if (t_str == ">>") {
return Opers::shift_right;
} else if (t_str == "%") {
return Opers::remainder;
} else if (t_str == "&") {
return Opers::bitwise_and;
} else if (t_str == "|") {
return Opers::bitwise_or;
} else if (t_str == "^") {
return Opers::bitwise_xor;
} else if (t_str == "~") {
return Opers::bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return Opers::unary_plus;
} else {
return Opers::sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return Opers::unary_minus;
} else {
return Opers::difference;
}
} else if (t_str == "/") {
return Opers::quotient;
} else if (t_str == "*") {
return Opers::product;
} else {
return Opers::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,30 +30,58 @@ 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
enum class AST_Node_Type { Id, Caching_Id, Fun_Call, Arg_List, Equation, Var_Decl,
enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl,
Array_Call, Dot_Access,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
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 };
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(AST_Node_Type ast_node_type) {
static const char * const ast_node_types[] = { "Id", "Caching_Id", "Fun_Call", "Arg_List", "Equation", "Var_Decl",
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", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
return ast_node_types[static_cast<int>(ast_node_type)];
}
@@ -102,7 +134,7 @@ namespace chaiscript
/// \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
explicit load_module_error(const std::string &t_reason) noexcept
: std::runtime_error(t_reason)
{
}
@@ -113,7 +145,7 @@ namespace chaiscript
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() noexcept = 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)
{
@@ -160,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)
{}
@@ -172,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]) << "'";
@@ -189,7 +221,7 @@ namespace chaiscript
return ss.str();
}
virtual ~eval_error() noexcept = default;
~eval_error() noexcept override = default;
private:
@@ -448,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;
};
}
@@ -509,9 +541,9 @@ namespace chaiscript
}
static bool get_bool_condition(const Boxed_Value &t_bv) {
static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
try {
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");
@@ -569,19 +601,19 @@ 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;
};
@@ -593,7 +625,7 @@ namespace chaiscript
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->new_scope(m_ds.stack_holder());
@@ -617,7 +649,7 @@ namespace chaiscript
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->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
@@ -635,7 +667,7 @@ namespace chaiscript
void save_params(std::initializer_list<Boxed_Value> t_params)
{
m_ds->save_function_params(std::move(t_params));
m_ds->save_function_params(t_params);
}
@@ -651,7 +683,7 @@ namespace chaiscript
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->new_stack(m_ds.stack_holder());

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"
@@ -46,7 +51,6 @@
#include "../dispatchkit/exception_specification.hpp"
#include "chaiscript_parser.hpp"
namespace chaiscript
{
@@ -58,7 +62,7 @@ namespace chaiscript
/// \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;
@@ -79,7 +83,7 @@ namespace chaiscript
{
try {
const auto p = m_parser->parse(t_input, t_filename);
return p->eval(m_engine);
return p->eval(chaiscript::detail::Dispatch_State(m_engine));
}
catch (chaiscript::eval::detail::Return_Value &rv) {
return rv.retval;
@@ -124,7 +128,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) {
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
if (t_lib)
{
add(t_lib);
@@ -145,9 +149,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 {
@@ -169,11 +170,20 @@ 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");
@@ -210,70 +220,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)),
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Caching_Id, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
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)),
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Caching_Id, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
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("");
}
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
// If on Unix, add the path of the current executable to the module search path
// as windows would do
union cast_union
{
Boxed_Value (ChaiScript::*in_ptr)(const std::string&);
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&);
void *out_ptr;
};
Dl_info rInfo;
memset( &rInfo, 0, sizeof(rInfo) );
cast_union u;
u.in_ptr = &ChaiScript::use;
if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
u.in_ptr = &ChaiScript_Basic::use;
if ( (dladdr(static_cast<void*>(u.out_ptr), &rInfo) != 0) && (rInfo.dli_fname != nullptr) ) {
std::string dllpath(rInfo.dli_fname);
const size_t lastslash = dllpath.rfind('/');
if (lastslash != std::string::npos)
@@ -292,8 +275,22 @@ namespace chaiscript
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
}
#endif
build_eval_system(t_lib, t_opts);
}
/// \brief Constructor for ChaiScript.
///
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
/// at runtime generates an error if it cannot be found.
///
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
std::vector<std::string> t_module_paths = {},
std::vector<std::string> t_use_paths = {},
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
: ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts)
{
try {
// attempt to load the stdlib
load_module("chaiscript_stdlib-" + Build_Info::version());
@@ -309,15 +306,17 @@ namespace chaiscript
<< t_err.what();
throw;
}
build_eval_system(ModulePtr());
}
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);
}
@@ -385,8 +384,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;
}
@@ -396,14 +396,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;
}
@@ -501,8 +503,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;
}
@@ -516,7 +519,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;
@@ -525,7 +528,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;

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_EVAL_HPP_
#define CHAISCRIPT_EVAL_HPP_
@@ -49,7 +53,7 @@ namespace chaiscript
{
/// Helper function that will set up the scope around a function call, including handling the named function parameters
template<typename T>
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr) {
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
chaiscript::detail::Dispatch_State state(t_ss);
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
@@ -64,7 +68,7 @@ namespace chaiscript
}();
chaiscript::eval::detail::Stack_Push_Pop tpp(state);
if (thisobj) state.add_object("this", *thisobj);
if (thisobj && !has_this_capture) { state.add_object("this", *thisobj); }
if (t_locals) {
for (const auto &local : *t_locals) {
@@ -86,18 +90,21 @@ namespace chaiscript
}
}
template<typename T>
struct AST_Node_Impl : AST_Node
{
AST_Node_Impl(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc,
std::vector<AST_Node_Impl_Ptr<T>> t_children = std::vector<AST_Node_Impl_Ptr<T>>())
: AST_Node(std::move(t_ast_node_text), std::move(t_id), std::move(t_loc)),
: AST_Node(std::move(t_ast_node_text), t_id, std::move(t_loc)),
children(std::move(t_children))
{
}
static bool get_scoped_bool_condition(const AST_Node_Impl<T> &node, const chaiscript::detail::Dispatch_State &t_ss) {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
return get_bool_condition(node.eval(t_ss), t_ss);
}
std::vector<AST_NodePtr> get_children() const final {
return {children.begin(), children.end()};
@@ -141,6 +148,52 @@ namespace chaiscript
AST_Node_Impl_Ptr<T> m_original_node;
};
template<typename T>
struct Fold_Right_Binary_Operator_AST_Node : AST_Node_Impl<T> {
Fold_Right_Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children, Boxed_Value t_rhs) :
AST_Node_Impl<T>(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(t_oper)),
m_rhs(std::move(t_rhs))
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
return do_oper(t_ss, this->text, this->children[0]->eval(t_ss));
}
protected:
Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss,
const std::string &t_oper_string, const Boxed_Value &t_lhs) const
{
try {
if (t_lhs.get_type_info().is_arithmetic())
{
// If it's an arithmetic operation we want to short circuit dispatch
try{
return Boxed_Number::do_oper(m_oper, t_lhs, m_rhs);
} catch (const chaiscript::exception::arithmetic_error &) {
throw;
} catch (...) {
throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
}
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({t_lhs, m_rhs});
return t_ss->call_function(t_oper_string, m_loc, {t_lhs, m_rhs}, t_ss.conversions());
}
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, *t_ss);
}
}
private:
Operators::Opers m_oper;
Boxed_Value m_rhs;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
struct Binary_Operator_AST_Node : AST_Node_Impl<T> {
Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
@@ -182,7 +235,7 @@ namespace chaiscript
private:
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
@@ -194,6 +247,12 @@ namespace chaiscript
{
}
explicit Constant_AST_Node(Boxed_Value t_value)
: AST_Node_Impl<T>("", AST_Node_Type::Constant, Parse_Location()),
m_value(std::move(t_value))
{
}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
return m_value;
}
@@ -201,45 +260,10 @@ namespace chaiscript
Boxed_Value m_value;
};
template<typename T>
struct Caching_Id_AST_Node final : AST_Node_Impl<T> {
Caching_Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Caching_Id, std::move(t_loc)),
m_loc(0),
m_cache(this)
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
try {
const uint32_t loc = m_loc;
if (loc == 0) {
Boxed_Value bv = t_ss.get_object(this->text, m_loc);
if ((m_loc & 0x40000000) == 0) {
*m_cache = bv;
}
return bv;
} else if ((loc & 0x40000000) != 0) {
/// \todo this is a magic number now to see if it's a local - we shouldn't be doing this
return t_ss.get_object(this->text, m_loc);
} else {
return *m_cache;
}
}
catch (std::exception &) {
throw exception::eval_error("Can not find object: " + this->text);
}
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable chaiscript::detail::threading::Thread_Storage<Boxed_Value> m_cache;
};
template<typename T>
struct Id_AST_Node final : AST_Node_Impl<T> {
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)),
m_loc(0)
AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc))
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
@@ -252,17 +276,16 @@ namespace chaiscript
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
struct Fun_Call_AST_Node final : AST_Node_Impl<T> {
struct Fun_Call_AST_Node : AST_Node_Impl<T> {
Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
template<bool Save_Params>
Boxed_Value do_eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const
{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
@@ -273,12 +296,14 @@ namespace chaiscript
params.push_back(child->eval(t_ss));
}
fpp.save_params(params);
if (Save_Params) {
fpp.save_params(params);
}
Boxed_Value fn(this->children[0]->eval(t_ss));
try {
return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss.conversions());
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(params, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@@ -303,10 +328,28 @@ namespace chaiscript
}
}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
return do_eval_internal<true>(t_ss);
}
};
template<typename T>
struct Unused_Return_Fun_Call_AST_Node final : Fun_Call_AST_Node<T> {
Unused_Return_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
Fun_Call_AST_Node<T>(std::move(t_ast_node_text), std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
return this->template do_eval_internal<false>(t_ss);
}
};
template<typename T>
struct Arg_AST_Node final : AST_Node_Impl<T> {
@@ -370,7 +413,7 @@ namespace chaiscript
Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(this->text))
{ assert(children.size() == 2); }
{ assert(this->children.size() == 2); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
@@ -394,13 +437,13 @@ namespace chaiscript
try {
if (lhs.is_undef()) {
if ((!this->children.empty()
if (!this->children.empty()
&& ((this->children[0]->identifier == AST_Node_Type::Reference)
|| (!this->children[0]->children.empty()
&& this->children[0]->children[0]->identifier == AST_Node_Type::Reference)
)
)
)
{
/// \todo This does not handle the case of an unassigned reference variable
/// being assigned outside of its declaration
@@ -448,8 +491,8 @@ namespace chaiscript
private:
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_clone_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
mutable std::atomic_uint_fast32_t m_clone_loc = {0};
};
template<typename T>
@@ -467,12 +510,7 @@ namespace chaiscript
}
}();
try {
return t_ss->add_global_no_throw(Boxed_Value(), idname);
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as global '" + idname + "'");
}
return t_ss->add_global_no_throw(Boxed_Value(), idname);
}
};
@@ -490,9 +528,6 @@ namespace chaiscript
Boxed_Value bv;
t_ss.add_object(idname, bv);
return bv;
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as variable '" + idname + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Variable redefined '" + e.name() + "'");
}
@@ -521,7 +556,7 @@ namespace chaiscript
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
@@ -577,8 +612,8 @@ namespace chaiscript
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_array_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
mutable std::atomic_uint_fast32_t m_array_loc = {0};
const std::string m_fun_name;
};
@@ -587,7 +622,9 @@ namespace chaiscript
struct Lambda_AST_Node final : AST_Node_Impl<T> {
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)),
m_param_names(Arg_List_AST_Node<T>::get_arg_names(this->children[1])) { }
m_param_names(Arg_List_AST_Node<T>::get_arg_names(this->children[1])),
m_this_capture(has_this_capture(this->children[0]->children))
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
@@ -607,20 +644,43 @@ namespace chaiscript
return Boxed_Value(
dispatch::make_dynamic_proxy_function(
[engine, lambda_node, param_names = this->m_param_names, captures](const std::vector<Boxed_Value> &t_params)
[engine, lambda_node, param_names = this->m_param_names, captures, this_capture = this->m_this_capture](const std::vector<Boxed_Value> &t_params)
{
return detail::eval_function(engine, lambda_node, param_names, t_params, &captures);
return detail::eval_function(engine, lambda_node, param_names, t_params, &captures, this_capture);
},
static_cast<int>(numparams), lambda_node, param_types
)
);
}
static bool has_this_capture(const std::vector<AST_Node_Impl_Ptr<T>> &children) {
return std::any_of(std::begin(children), std::end(children),
[](const auto &child){
return child->children[0]->text == "this";
}
);
}
private:
const std::vector<std::string> m_param_names;
const bool m_this_capture = false;
};
template<typename T>
struct Scopeless_Block_AST_Node final : AST_Node_Impl<T> {
Scopeless_Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Scopeless_Block, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
const auto num_children = this->children.size();
for (size_t i = 0; i < num_children-1; ++i) {
this->children[i]->eval(t_ss);
}
return this->children.back()->eval(t_ss);
}
};
template<typename T>
struct Block_AST_Node final : AST_Node_Impl<T> {
Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
@@ -689,9 +749,6 @@ namespace chaiscript
},
static_cast<int>(numparams), this->children.back(),
param_types, guard), l_function_name);
}
catch (const exception::reserved_word_error &e) {
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Function redefined '" + e.name() + "'");
}
@@ -709,7 +766,7 @@ namespace chaiscript
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
try {
while (this->get_bool_condition(this->children[0]->eval(t_ss))) {
while (this->get_scoped_bool_condition(*this->children[0], t_ss)) {
try {
this->children[1]->eval(t_ss);
} catch (detail::Continue_Loop &) {
@@ -750,22 +807,96 @@ namespace chaiscript
If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children))
{
assert(this->children.size() == 2 || this->children.size() == 3);
assert(this->children.size() == 3);
}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
if (this->get_bool_condition(this->children[0]->eval(t_ss))) {
if (this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)) {
return this->children[1]->eval(t_ss);
} else {
if (this->children.size() == 3) {
return this->children[2]->eval(t_ss);
} else {
return void_var();
}
return this->children[2]->eval(t_ss);
}
}
};
template<typename T>
struct Ranged_For_AST_Node final : AST_Node_Impl<T> {
Ranged_For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Ranged_For, std::move(t_loc), std::move(t_children))
{ assert(this->children.size() == 3); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
const auto get_function = [&t_ss](const std::string &t_name, auto &t_hint){
uint_fast32_t hint = t_hint;
auto funs = t_ss->get_function(t_name, hint);
if (funs.first != hint) { t_hint = uint_fast32_t(funs.first); }
return std::move(funs.second);
};
const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) {
return dispatch::dispatch(*t_funcs, {t_param}, t_ss.conversions());
};
const std::string &loop_var_name = this->children[0]->text;
Boxed_Value range_expression_result = this->children[1]->eval(t_ss);
const auto do_loop = [&loop_var_name, &t_ss, this](const auto &ranged_thing){
try {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
Boxed_Value &obj = t_ss.add_get_object(loop_var_name, void_var());
for (auto loop_var : ranged_thing) {
obj = Boxed_Value(std::move(loop_var));
try {
this->children[2]->eval(t_ss);
} catch (detail::Continue_Loop &) {
}
}
} catch (detail::Break_Loop &) {
// loop broken
}
return void_var();
};
if (range_expression_result.get_type_info().bare_equal_type_info(typeid(std::vector<Boxed_Value>))) {
return do_loop(boxed_cast<const std::vector<Boxed_Value> &>(range_expression_result));
} else if (range_expression_result.get_type_info().bare_equal_type_info(typeid(std::map<std::string, Boxed_Value>))) {
return do_loop(boxed_cast<const std::map<std::string, Boxed_Value> &>(range_expression_result));
} else {
const auto range_funcs = get_function("range", m_range_loc);
const auto empty_funcs = get_function("empty", m_empty_loc);
const auto front_funcs = get_function("front", m_front_loc);
const auto pop_front_funcs = get_function("pop_front", m_pop_front_loc);
try {
const auto range_obj = call_function(range_funcs, range_expression_result);
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
Boxed_Value &obj = t_ss.add_get_object(loop_var_name, void_var());
while (!boxed_cast<bool>(call_function(empty_funcs, range_obj))) {
obj = call_function(front_funcs, range_obj);
try {
this->children[2]->eval(t_ss);
} catch (detail::Continue_Loop &) {
}
call_function(pop_front_funcs, range_obj);
}
} catch (detail::Break_Loop &) {
// loop broken
}
return void_var();
}
}
private:
mutable std::atomic_uint_fast32_t m_range_loc = {0};
mutable std::atomic_uint_fast32_t m_empty_loc = {0};
mutable std::atomic_uint_fast32_t m_front_loc = {0};
mutable std::atomic_uint_fast32_t m_pop_front_loc = {0};
};
template<typename T>
struct For_AST_Node final : AST_Node_Impl<T> {
For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
@@ -778,7 +909,7 @@ namespace chaiscript
try {
for (
this->children[0]->eval(t_ss);
this->get_bool_condition(this->children[1]->eval(t_ss));
this->get_scoped_bool_condition(*this->children[1], t_ss);
this->children[2]->eval(t_ss)
) {
try {
@@ -840,14 +971,14 @@ namespace chaiscript
return void_var();
}
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
struct Case_AST_Node final : AST_Node_Impl<T> {
Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 2); /* how many children does it have? */ }
{ assert(this->children.size() == 2); /* how many children does it have? */ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
@@ -862,7 +993,7 @@ namespace chaiscript
struct Default_AST_Node final : AST_Node_Impl<T> {
Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 1); }
{ assert(this->children.size() == 1); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
@@ -901,7 +1032,7 @@ namespace chaiscript
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
@@ -909,7 +1040,8 @@ namespace chaiscript
Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
try {
std::map<std::string, Boxed_Value> retval;
@@ -930,7 +1062,7 @@ namespace chaiscript
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
@@ -977,17 +1109,12 @@ namespace chaiscript
struct Reference_AST_Node final : AST_Node_Impl<T> {
Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 1); }
{ assert(this->children.size() == 1); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
try {
Boxed_Value bv;
t_ss.add_object(this->children[0]->text, bv);
return bv;
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'");
}
Boxed_Value bv;
t_ss.add_object(this->children[0]->text, bv);
return bv;
}
};
@@ -1017,15 +1144,15 @@ namespace chaiscript
}
private:
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
Operators::Opers m_oper = Operators::Opers::invalid;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
struct Break_AST_Node final : AST_Node_Impl<T> {
Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
throw detail::Break_Loop();
}
@@ -1048,10 +1175,11 @@ namespace chaiscript
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
// It's a no-op, that evaluates to "true"
// the magic-static version of const_var(true) helps us here
return const_var(true);
// It's a no-op, that evaluates to "void"
return val;
}
Boxed_Value val = void_var();
};
template<typename T>
@@ -1083,7 +1211,7 @@ namespace chaiscript
}
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
@@ -1113,7 +1241,7 @@ namespace chaiscript
if (dispatch::Param_Types(
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(catch_block->children[0], t_ss)}
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()))
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()).first)
{
t_ss.add_object(name, t_except);
@@ -1161,11 +1289,8 @@ namespace chaiscript
try {
retval = this->children[0]->eval(t_ss);
}
catch (exception::eval_error &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw;
catch (const exception::eval_error &e) {
retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
}
catch (const std::runtime_error &e) {
retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
@@ -1217,30 +1342,27 @@ namespace chaiscript
AST_Node_Impl_Ptr<T> guardnode;
const auto d = t_ss->get_parent_locals();
const auto itr = d.find("_current_class_name");
const auto class_offset = (itr != d.end())?-1:0;
const std::string & class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
const std::string & class_name = this->children[0]->text;
//The first param of a method is always the implied this ptr.
std::vector<std::string> t_param_names{"this"};
dispatch::Param_Types param_types;
if ((this->children.size() > static_cast<size_t>(3 + class_offset))
&& (this->children[static_cast<size_t>(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) {
auto args = Arg_List_AST_Node<T>::get_arg_names(this->children[static_cast<size_t>(2 + class_offset)]);
if ((this->children.size() > 3)
&& (this->children[2]->identifier == AST_Node_Type::Arg_List)) {
auto args = Arg_List_AST_Node<T>::get_arg_names(this->children[2]);
t_param_names.insert(t_param_names.end(), args.begin(), args.end());
param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[static_cast<size_t>(2 + class_offset)], t_ss);
param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[2], t_ss);
if (this->children.size() > static_cast<size_t>(4 + class_offset)) {
guardnode = this->children[static_cast<size_t>(3 + class_offset)];
if (this->children.size() > 4) {
guardnode = this->children[3];
}
}
else {
//no parameters
if (this->children.size() > static_cast<size_t>(3 + class_offset)) {
guardnode = this->children[static_cast<size_t>(2 + class_offset)];
if (this->children.size() > 3) {
guardnode = this->children[2];
}
}
@@ -1257,7 +1379,7 @@ namespace chaiscript
}
try {
const std::string & function_name = this->children[static_cast<size_t>(1 + class_offset)]->text;
const std::string & function_name = this->children[1]->text;
auto node = this->children.back();
if (function_name == class_name) {
@@ -1288,9 +1410,6 @@ namespace chaiscript
static_cast<int>(numparams), node, param_types, guard), type),
function_name);
}
}
catch (const exception::reserved_word_error &e) {
throw exception::eval_error("Reserved word used as method name '" + e.word() + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Method redefined '" + e.name() + "'");
}
@@ -1306,13 +1425,10 @@ namespace chaiscript
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
const auto &d = t_ss->get_parent_locals();
const auto itr = d.find("_current_class_name");
const auto class_offset = (itr != d.end())?-1:0;
std::string class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
std::string class_name = this->children[0]->text;
try {
std::string attr_name = this->children[static_cast<size_t>(1 + class_offset)]->text;
std::string attr_name = this->children[1]->text;
t_ss->add(
std::make_shared<dispatch::detail::Dynamic_Object_Function>(
@@ -1322,11 +1438,7 @@ namespace chaiscript
}),
true
), this->children[static_cast<size_t>(1 + class_offset)]->text);
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as attribute '" + this->children[static_cast<size_t>(1 + class_offset)]->text + "'");
), this->children[1]->text);
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
}
@@ -1344,8 +1456,8 @@ namespace chaiscript
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss))
&& this->get_bool_condition(this->children[1]->eval(t_ss)));
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)
&& this->get_bool_condition(this->children[1]->eval(t_ss), t_ss));
}
};
@@ -1358,8 +1470,8 @@ namespace chaiscript
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss))
|| this->get_bool_condition(this->children[1]->eval(t_ss)));
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)
|| this->get_bool_condition(this->children[1]->eval(t_ss), t_ss));
}
};
}

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_OPTIMIZER_HPP_
@@ -17,25 +17,34 @@ namespace chaiscript {
struct Optimizer : T...
{
Optimizer() = default;
Optimizer(T ... t)
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 = T::optimize(p), 0)... };
(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>
@@ -58,7 +67,7 @@ namespace chaiscript {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
{
if (p->identifier == AST_Node_Type::Def
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
&& !p->children.empty())
{
auto &last_child = p->children.back();
@@ -88,6 +97,7 @@ namespace chaiscript {
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;
}
@@ -99,21 +109,94 @@ namespace chaiscript {
struct Block {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Block
&& node->children.size() == 1
&& !contains_var_decl_in_scope(node))
if (node->identifier == AST_Node_Type::Block)
{
return node->children[0];
} else {
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
if ((node->identifier == AST_Node_Type::If)
&& node->children.size() >= 2
&& node->children[0]->identifier == AST_Node_Type::Constant)
{
@@ -131,15 +214,31 @@ namespace chaiscript {
}
};
struct Caching_Id {
struct Partial_Fold {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Id)
// 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)
{
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Caching_Id_AST_Node<T>>(node->text, node->location);
} else {
return node;
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;
}
};
@@ -147,7 +246,46 @@ namespace chaiscript {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Binary
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)
@@ -191,8 +329,11 @@ namespace chaiscript {
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>());
}
}
}
@@ -276,6 +417,8 @@ namespace chaiscript {
}
};
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;
}
}

File diff suppressed because it is too large Load Diff

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_POSIX_HPP_
@@ -15,10 +15,10 @@ namespace chaiscript
{
struct DLModule
{
DLModule(const std::string &t_filename)
explicit DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
{
if (!m_data)
if (m_data == nullptr)
{
throw chaiscript::exception::load_module_error(dlerror());
}

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

@@ -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_TRACER_HPP_
@@ -10,10 +10,11 @@
namespace chaiscript {
namespace eval {
struct Noop_Tracer
struct Noop_Tracer_Detail
{
template<typename T>
static void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
{
}
};
@@ -22,13 +23,13 @@ namespace chaiscript {
struct Tracer : T...
{
Tracer() = default;
Tracer(T ... t)
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>{ (T::trace(ds, node), 0)... };
(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) {
@@ -36,6 +37,8 @@ namespace chaiscript {
}
};
typedef Tracer<Noop_Tracer_Detail> Noop_Tracer;
}
}

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_UNKNOWN_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_WINDOWS_HPP_
@@ -80,7 +80,7 @@ namespace chaiscript
struct DLModule
{
DLModule(const std::string &t_filename)
explicit DLModule(const std::string &t_filename)
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
{
if (!m_data)

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);
@@ -496,30 +570,35 @@ struct JSONParser {
long exp = 0;
for (; offset < str.size() ;) {
c = str[offset++];
if( (c == '-') || (c >= '0' && c <= '9') )
if( (c == '-') || (c >= '0' && c <= '9') ) {
val += c;
else if( c == '.' ) {
} else if( c == '.' ) {
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 );
}
@@ -570,8 +649,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_
@@ -89,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

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>
@@ -291,7 +294,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
@@ -113,7 +120,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 +132,7 @@ std::vector<std::string> default_search_paths()
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
if (lastslash != std::string::npos)
{
paths.push_back(exepath.substr(0, lastslash));
paths.push_back(exepath.substr(0, lastslash+1));
}
if (secondtolastslash != std::string::npos)
@@ -181,7 +188,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 +224,7 @@ void myexit(int return_val) {
exit(return_val);
}
void interactive(chaiscript::ChaiScript& chai)
void interactive(chaiscript::ChaiScript_Basic& chai)
{
using_history();
@@ -237,7 +244,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 +281,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 +290,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 +312,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 +323,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

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

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

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

Binary file not shown.

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,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,8 @@
#include <algorithm>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_basic.hpp>
#include <chaiscript/language/chaiscript_parser.hpp>
int expected_value(int num_iters)
{
@@ -15,7 +16,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;
@@ -62,7 +63,12 @@ int main()
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);
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

@@ -0,0 +1,8 @@
assert_equal('\u0020', ' ')
assert_equal('\u0021', '!')
assert_equal('\u0030', '0')
assert_equal('\u0040', '@')
assert_equal('\u005B', '[')
assert_equal('\u005d', ']')
assert_equal('\u0061', 'a')
assert_equal('\u007e', '~')

View File

@@ -0,0 +1,11 @@
assert_equal('\u00aa', '\u00AA')
assert_equal('\u00bb', '\uBB')
assert_equal('\ucc', '\u00CC')
assert_equal('\udd', '\uDD')
assert_equal('\u0ee', '\uEE')
assert_equal('\ue', '\u000E')
assert_equal("\u30\u31\u32", "012")
assert_equal("\u33Test", "3Test")
assert_equal("Test\u0040", "Test@")

View File

@@ -0,0 +1,5 @@
assert_equal("\uc39c", "Ü")
assert_equal("U for \uc39cmlauts", "U for Ümlauts")
assert_equal("More \uc39cml\uc3a4\uc3bcts", "More Ümläüts")
assert_equal("Thorn \uc3be sign", "Thorn þ sign")