Compare commits
311 Commits
v5.7.1
...
attempt_gl
Author | SHA1 | Date | |
---|---|---|---|
![]() |
caf2b39995 | ||
![]() |
9a526bc1ec | ||
![]() |
03803ee4c4 | ||
![]() |
dcedd64032 | ||
![]() |
d34d74205c | ||
![]() |
41c1c490c8 | ||
![]() |
70cdbef693 | ||
![]() |
f6c69f2826 | ||
![]() |
184ca7f7b2 | ||
![]() |
71caf5006f | ||
![]() |
4dbf1ee2bd | ||
![]() |
4324a700ad | ||
![]() |
5b78d5a898 | ||
![]() |
ff2ab6bb8d | ||
![]() |
25575564c0 | ||
![]() |
683164650a | ||
![]() |
647f8842fd | ||
![]() |
6d6f79b1a4 | ||
![]() |
06b2893bfb | ||
![]() |
7ab6bce7fa | ||
![]() |
f9294c8cbe | ||
![]() |
80cc18bf2f | ||
![]() |
c68488388e | ||
![]() |
7d5a97aa2f | ||
![]() |
83c6df11f0 | ||
![]() |
10b984556d | ||
![]() |
cf2fa09d6c | ||
![]() |
f3f84594ee | ||
![]() |
57aa874c6e | ||
![]() |
32bd936a18 | ||
![]() |
498339c202 | ||
![]() |
56b4f465a1 | ||
![]() |
1a42614441 | ||
![]() |
6fa83bca85 | ||
![]() |
14307194e9 | ||
![]() |
62e34c097c | ||
![]() |
cdb9dcc154 | ||
![]() |
14d429853b | ||
![]() |
e8ff1f9d7e | ||
![]() |
49ef5306a9 | ||
![]() |
7d9dbc3d86 | ||
![]() |
49dfdfd15a | ||
![]() |
720395e47a | ||
![]() |
5e0a882b18 | ||
![]() |
9603d3910a | ||
![]() |
6f0d02f158 | ||
![]() |
8d808f75c0 | ||
![]() |
2a1632f213 | ||
![]() |
e57f11fcf4 | ||
![]() |
2fe794fcae | ||
![]() |
b594043eef | ||
![]() |
fe8f8a89a7 | ||
![]() |
40694c798c | ||
![]() |
443828fa23 | ||
![]() |
866db4ee8b | ||
![]() |
5e97f459d8 | ||
![]() |
e02ac78195 | ||
![]() |
62cd8031ac | ||
![]() |
61dfcb00c0 | ||
![]() |
4bf619c80f | ||
![]() |
08a68f310a | ||
![]() |
641ac1a1ae | ||
![]() |
2400c64c82 | ||
![]() |
1e584048ce | ||
![]() |
7865f8e7f2 | ||
![]() |
5ff97979fd | ||
![]() |
5567e767a3 | ||
![]() |
5a947b5035 | ||
![]() |
6ecbaab2fe | ||
![]() |
dd6b38cafb | ||
![]() |
1e62eb4e12 | ||
![]() |
6e6795e914 | ||
![]() |
33c966b8d6 | ||
![]() |
c07c2a9cc2 | ||
![]() |
46c45e8fc7 | ||
![]() |
91a3ae1f14 | ||
![]() |
328aef10d7 | ||
![]() |
f7b52f6c39 | ||
![]() |
2f2f789f48 | ||
![]() |
06783b7f65 | ||
![]() |
a45c76721f | ||
![]() |
3627efe03b | ||
![]() |
1cd7a1b972 | ||
![]() |
df9466e2a7 | ||
![]() |
dc8aa372c1 | ||
![]() |
bcc25222dd | ||
![]() |
6507a6e68e | ||
![]() |
5872b020fa | ||
![]() |
c57ea79d0d | ||
![]() |
b424d1f9cb | ||
![]() |
7dcd6b8447 | ||
![]() |
de63529887 | ||
![]() |
d95f59fa97 | ||
![]() |
d5ae30191d | ||
![]() |
16ffbca6d6 | ||
![]() |
afa3f2249c | ||
![]() |
c5f4a4dfd8 | ||
![]() |
34a2001a7b | ||
![]() |
16c4a11990 | ||
![]() |
6f01568a9a | ||
![]() |
a363ef5e0e | ||
![]() |
a3365a9c4a | ||
![]() |
9a5ef38d4a | ||
![]() |
5247de7d1b | ||
![]() |
cd1b3f8887 | ||
![]() |
11ee71ba27 | ||
![]() |
91ba9e25c0 | ||
![]() |
978f80751f | ||
![]() |
0ac5657661 | ||
![]() |
cfc8a3d214 | ||
![]() |
85163e08cc | ||
![]() |
019c6b2830 | ||
![]() |
c71dd8051b | ||
![]() |
fe8f571f47 | ||
![]() |
947d7c2591 | ||
![]() |
6f6227879a | ||
![]() |
e014308154 | ||
![]() |
467392e17d | ||
![]() |
cf5913f890 | ||
![]() |
71c67bc763 | ||
![]() |
539ee3c84f | ||
![]() |
594958ea8b | ||
![]() |
83b966df47 | ||
![]() |
c24004c70e | ||
![]() |
a0ee8d1137 | ||
![]() |
765e6ed8df | ||
![]() |
0cb4c18638 | ||
![]() |
ad7e2138d9 | ||
![]() |
0eee23109e | ||
![]() |
b663654a6d | ||
![]() |
2a8c248167 | ||
![]() |
457367ea7b | ||
![]() |
33e27b4f85 | ||
![]() |
b5b6e5a5a3 | ||
![]() |
a0f3eafe30 | ||
![]() |
8feff5bc76 | ||
![]() |
463f688978 | ||
![]() |
70c6ed713b | ||
![]() |
a6dcbb1f1c | ||
![]() |
d4f02b5e67 | ||
![]() |
645377e191 | ||
![]() |
5a03c88ee3 | ||
![]() |
abc30ba573 | ||
![]() |
f36b1fc5eb | ||
![]() |
feb7775d21 | ||
![]() |
8d50160cd9 | ||
![]() |
871ad10e0e | ||
![]() |
649edf1dd1 | ||
![]() |
c0664d778c | ||
![]() |
6c483bd6f6 | ||
![]() |
7f8a6f24f9 | ||
![]() |
07fa8010e4 | ||
![]() |
e024b99b36 | ||
![]() |
ed65ad72d0 | ||
![]() |
bc0eaa5d15 | ||
![]() |
e0827634bb | ||
![]() |
08ba646200 | ||
![]() |
caf0a8b5d1 | ||
![]() |
357df5c8ec | ||
![]() |
d0630d5edd | ||
![]() |
c562d0d78b | ||
![]() |
bff30278e1 | ||
![]() |
b104b26f11 | ||
![]() |
03ef44f415 | ||
![]() |
1a06e53c58 | ||
![]() |
c438a388d7 | ||
![]() |
7923c3e0c7 | ||
![]() |
872f16e45a | ||
![]() |
7688c14d43 | ||
![]() |
bde2a45384 | ||
![]() |
7f4ef8d8fd | ||
![]() |
0dab950ebf | ||
![]() |
485482b2be | ||
![]() |
b2ae317877 | ||
![]() |
5b1b1dbcb4 | ||
![]() |
7222390c96 | ||
![]() |
b33f0a08bc | ||
![]() |
140a90f72a | ||
![]() |
f697384028 | ||
![]() |
dfd04c8291 | ||
![]() |
209d6ed2e4 | ||
![]() |
d8fa6061a2 | ||
![]() |
651eed8d7a | ||
![]() |
af1eba1b0e | ||
![]() |
f82f6c2068 | ||
![]() |
fcca453223 | ||
![]() |
7ed5c18a86 | ||
![]() |
c067575ac4 | ||
![]() |
52c96de6a8 | ||
![]() |
907e6d74e0 | ||
![]() |
12cbbd2097 | ||
![]() |
4aa370fbfd | ||
![]() |
3587c3e165 | ||
![]() |
acc4345b65 | ||
![]() |
43def57852 | ||
![]() |
561b47e463 | ||
![]() |
9885534b5b | ||
![]() |
ad3f111e13 | ||
![]() |
452f71b51f | ||
![]() |
a97cb1530d | ||
![]() |
21048b9e65 | ||
![]() |
d73e715997 | ||
![]() |
353a077c6b | ||
![]() |
373a3688c9 | ||
![]() |
208107fd7e | ||
![]() |
e19a8e31ea | ||
![]() |
b55eff95cf | ||
![]() |
b6287a194c | ||
![]() |
888d897a3e | ||
![]() |
e32714c456 | ||
![]() |
e1c40f3e8f | ||
![]() |
d7489358f3 | ||
![]() |
316ba45e3c | ||
![]() |
f0796b51c8 | ||
![]() |
e638d450ed | ||
![]() |
e60eabbeb2 | ||
![]() |
c249bef27d | ||
![]() |
4e69e5a3d2 | ||
![]() |
49c89a3b88 | ||
![]() |
7507223c8b | ||
![]() |
681b7db727 | ||
![]() |
4826bddb5b | ||
![]() |
49436e5740 | ||
![]() |
202204a82a | ||
![]() |
34c6b17215 | ||
![]() |
6fe7f5ce98 | ||
![]() |
d9f86a96f0 | ||
![]() |
da1511a092 | ||
![]() |
8bd7ccfa9f | ||
![]() |
0806df11d2 | ||
![]() |
40b1549b3b | ||
![]() |
c9a5bf6f83 | ||
![]() |
8496a86043 | ||
![]() |
bc388e59da | ||
![]() |
09748275db | ||
![]() |
eec0299cbc | ||
![]() |
19ecfdfec5 | ||
![]() |
7ba7b81a5c | ||
![]() |
882cbf2dfb | ||
![]() |
38b98c55cc | ||
![]() |
3a675bf379 | ||
![]() |
985b62705f | ||
![]() |
5aecb7f17b | ||
![]() |
ad69bf7d38 | ||
![]() |
84554ed0a5 | ||
![]() |
36765df3c0 | ||
![]() |
b11ebf9e8f | ||
![]() |
84e2d449b9 | ||
![]() |
3e62a99f82 | ||
![]() |
64dd349e32 | ||
![]() |
1add4c4b0f | ||
![]() |
14b3870efb | ||
![]() |
d2cf12f948 | ||
![]() |
e221ceaa4c | ||
![]() |
beedf13d01 | ||
![]() |
9d18360333 | ||
![]() |
18e5ee0ba2 | ||
![]() |
41e9027d9a | ||
![]() |
8d9dc2b0a3 | ||
![]() |
6a4647af43 | ||
![]() |
5a651e2b8a | ||
![]() |
d9fa5605ac | ||
![]() |
3a8cb581cc | ||
![]() |
b434d26a5d | ||
![]() |
ba30d4f483 | ||
![]() |
b4ffcd594d | ||
![]() |
ca35128503 | ||
![]() |
681f18ee62 | ||
![]() |
e62a38b39f | ||
![]() |
85ac1052dd | ||
![]() |
8024edeadf | ||
![]() |
f9f1d5807a | ||
![]() |
14227475b2 | ||
![]() |
e1a80fb5ce | ||
![]() |
aabe53c934 | ||
![]() |
f3dbb7ed87 | ||
![]() |
52e11bf001 | ||
![]() |
f06e5cdcd6 | ||
![]() |
15eb78bd8f | ||
![]() |
9f362608b7 | ||
![]() |
e21c8f87b4 | ||
![]() |
0a143d1cd3 | ||
![]() |
08935beaf3 | ||
![]() |
c9625b09b0 | ||
![]() |
800c7fb37b | ||
![]() |
179eaefafe | ||
![]() |
28f5a74e98 | ||
![]() |
781d62d3a5 | ||
![]() |
8ed2158709 | ||
![]() |
8f98e16e5e | ||
![]() |
3a595ef912 | ||
![]() |
5aa0bfcea4 | ||
![]() |
04e2256c92 | ||
![]() |
38ba00e55c | ||
![]() |
8931346230 | ||
![]() |
8bdd2deb19 | ||
![]() |
535055eff8 | ||
![]() |
913d2fd20f | ||
![]() |
0c4951d742 | ||
![]() |
9d17b18f26 | ||
![]() |
31b3195c17 | ||
![]() |
0d4e4090a0 | ||
![]() |
b946af42cc | ||
![]() |
22339d10db | ||
![]() |
b3d2350f33 | ||
![]() |
3cae2aed1d | ||
![]() |
c6f262c675 | ||
![]() |
8239206ec5 | ||
![]() |
a2ff672b34 | ||
![]() |
9a0a12d230 | ||
![]() |
7d3c23fc22 |
@@ -1,30 +1,53 @@
|
||||
compilers:
|
||||
- name: "clang"
|
||||
version: "3.5"
|
||||
version: "3.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
|
||||
collect_performance_results: true
|
||||
- name: "clang"
|
||||
build_tag: "LibC++"
|
||||
version: "3.5"
|
||||
version: "3.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: AddressSanitizer
|
||||
version: "3.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
||||
cmake_extra_flags: -DRUN_FUZZY_TESTS:BOOL=TRUE -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: ThreadSanitizer
|
||||
version: "3.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.8"
|
||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.6"
|
||||
- name: "clang"
|
||||
version: "3.7"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
|
||||
collect_performance_results: true
|
||||
- name: "clang"
|
||||
build_tag: "LibC++"
|
||||
version: "3.7"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.9"
|
||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
|
||||
collect_performance_results: true
|
||||
- name: "gcc"
|
||||
version: "4.9"
|
||||
skip_packaging: true
|
||||
build_tag: "NoThreads"
|
||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF
|
||||
collect_performance_results: true
|
||||
- name: "gcc"
|
||||
version: "5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
|
||||
collect_performance_results: true
|
||||
- name: cppcheck
|
||||
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:cmake*" --suppress="*:unittests/catch.hpp" --force
|
||||
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:unittests/catch.hpp" --force --suppress="unusedFunction:*"
|
||||
- name: custom_check
|
||||
commands:
|
||||
- ./contrib/check_for_tabs.rb
|
||||
- ./contrib/check_for_todos.rb
|
||||
|
||||
|
@@ -2,8 +2,4 @@ compilers:
|
||||
- name: clang
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
build_package_generator: TBZ2
|
||||
- name: clang
|
||||
build_type: Debug
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
skip_packaging: true
|
||||
|
||||
|
@@ -11,10 +11,11 @@ compilers:
|
||||
compiler_extra_flags: /analyze
|
||||
skip_packaging: true
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
version: 14
|
||||
build_type: Debug
|
||||
architecture: Win64
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /analyze
|
||||
skip_packaging: true
|
||||
|
||||
|
||||
|
41
.github/CONTRIBUTING.md
vendored
Normal file
41
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# Contributing to ChaiScript
|
||||
|
||||
Thank you for contributing!
|
||||
|
||||
# Pull Requests
|
||||
|
||||
Please follow the existing style in the code you are patching.
|
||||
|
||||
- two space indent
|
||||
- no tabs EVER
|
||||
- match the existing indentation level
|
||||
|
||||
All ChaiScript commits are run through a large set of builds and analysis on all supported platforms. Those results are posted on the
|
||||
[build dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html). No PR will be accepted until all tests pass.
|
||||
|
||||
The build system has full integration with GitHub and you will be notified automatically if all tests have passed.
|
||||
|
||||
# Issues
|
||||
|
||||
Please do not post a "chaiscript is too slow", "chaiscript compiles too slowly", or "chaiscript needs more documentation" issue
|
||||
without first reading the following notes.
|
||||
|
||||
## ChaiScript is Too Slow
|
||||
|
||||
We are actively working on constently improving the runtime performance of ChaiScript. With the performance being
|
||||
[monitored with each commit](http://chaiscript.com/ChaiScript-BuildResults/performance.html).
|
||||
|
||||
If you feel you *must* post an issue about performance, please post a complete example that illustrates the exact case you
|
||||
feel should be better optimized.
|
||||
|
||||
Any issue request regarding performance without a complete example of the issue experienced will be closed.
|
||||
|
||||
## ChaiScript Compiles Too Slowly
|
||||
|
||||
This is also something we are actively working on. If you need highly optimized build times, please see [this discussion
|
||||
on the discourse site](http://discourse.chaiscript.com/t/slow-build-times/94).
|
||||
|
||||
## ChaiScript Needs More Documentation
|
||||
|
||||
If you have a question that is not addressed in the [cheatsheet](https://github.com/ChaiScript/ChaiScript/blob/develop/cheatsheet.md)
|
||||
please open an issue so we can get the Cheatsheet updated.
|
10
.github/ISSUE_TEMPLATE.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
* Compiler Used:
|
||||
* Operating System:
|
||||
* Architecture (ARM/x86/32bit/64bit/etc):
|
||||
|
||||
|
||||
### Expected Behavior
|
||||
|
||||
### Actual Behavior
|
||||
|
||||
### Minimal Example to Reproduce Behavior
|
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
Issue this pull request references: #
|
||||
|
||||
Changes proposed in this pull request
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
|
@@ -3,8 +3,8 @@ compiler:
|
||||
- gcc
|
||||
env:
|
||||
matrix:
|
||||
- GCC_VER="4.6"
|
||||
- GCC_VER="4.8"
|
||||
- GCC_VER="4.9"
|
||||
- GCC_VER="5"
|
||||
|
||||
global:
|
||||
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
|
||||
@@ -13,7 +13,7 @@ env:
|
||||
|
||||
before_install:
|
||||
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
|
||||
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
|
||||
- if [ "$GCC_VER" = "5" ]; then export COVERAGE=1 CPPCHECK=1; fi
|
||||
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
|
||||
- sudo pip install cpp-coveralls
|
||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||
|
@@ -20,6 +20,7 @@ option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
||||
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
|
||||
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
||||
option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE)
|
||||
|
||||
mark_as_advanced(USE_STD_MAKE_SHARED)
|
||||
|
||||
@@ -68,6 +69,13 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
|
||||
endif()
|
||||
|
||||
option(GPROF_OUTPUT "Generate profile data" FALSE)
|
||||
if (GPROF_OUTPUT)
|
||||
add_definitions(-pg)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -pg")
|
||||
endif()
|
||||
|
||||
|
||||
option(PROFILE_GENERATE "Generate profile data" FALSE)
|
||||
if (PROFILE_GENERATE)
|
||||
add_definitions(-fprofile-generate)
|
||||
@@ -93,9 +101,9 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 7)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 1)
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 6)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||
@@ -115,16 +123,12 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
||||
include(CTest)
|
||||
include(CPack)
|
||||
|
||||
include(cmake/CheckCXX11Features.cmake)
|
||||
|
||||
if(NOT MINGW)
|
||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||
endif()
|
||||
|
||||
if(HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
message(STATUS "Variadic Template support detected")
|
||||
else()
|
||||
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_program(VALGRIND NAMES valgrind PATH /usr/bin /usr/local/bin)
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
@@ -144,21 +148,24 @@ endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
|
||||
if(GCC_VERSION VERSION_LESS 4.8)
|
||||
set(CPP11_FLAG "-std=c++0x")
|
||||
if(GCC_VERSION VERSION_LESS 4.9)
|
||||
set(CPP11_FLAG "-std=c++1y")
|
||||
else()
|
||||
set(CPP11_FLAG "-std=c++11")
|
||||
set(CPP11_FLAG "-std=c++14")
|
||||
endif()
|
||||
else()
|
||||
set(CPP11_FLAG "-std=c++11")
|
||||
set(CPP11_FLAG "-std=c++14")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(/W4)
|
||||
add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
|
||||
|
||||
# VS2013 doesn't have magic statics
|
||||
if (MSVC_VERSION STREQUAL "1800")
|
||||
# VS2013 doesn't have magic statics
|
||||
add_definitions(/w44640)
|
||||
else()
|
||||
# enum warnings are too noisy on MSVC2013
|
||||
add_definitions(/w34062)
|
||||
endif()
|
||||
|
||||
add_definitions(/bigobj)
|
||||
@@ -171,10 +178,10 @@ if(MSVC)
|
||||
# how to workaround or fix the error. So I'm disabling it globally.
|
||||
add_definitions(/wd4503)
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
|
||||
add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
add_definitions(-Weverything -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors)
|
||||
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
|
||||
else()
|
||||
add_definitions(-Wnoexcept)
|
||||
endif()
|
||||
@@ -206,7 +213,7 @@ endif()
|
||||
include_directories(include)
|
||||
|
||||
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
@@ -253,16 +260,23 @@ add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
|
||||
if(BUILD_SAMPLES)
|
||||
add_executable(example samples/example.cpp)
|
||||
target_link_libraries(example ${LIBS})
|
||||
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
|
||||
target_link_libraries(test_num_exceptions ${LIBS})
|
||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
add_executable(inheritance samples/inheritance.cpp)
|
||||
target_link_libraries(inheritance ${LIBS})
|
||||
add_executable(factory samples/factory.cpp)
|
||||
target_link_libraries(factory ${LIBS})
|
||||
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
||||
target_link_libraries(fun_call_performance ${LIBS})
|
||||
endif()
|
||||
|
||||
|
||||
if(BUILD_MODULES)
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${LIBS})
|
||||
|
||||
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||
target_link_libraries(stl_extra ${LIBS})
|
||||
|
||||
@@ -272,6 +286,9 @@ endif()
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||
list(SORT UNIT_TESTS)
|
||||
|
||||
file(GLOB PERFORMANCE_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/ ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/*.chai)
|
||||
list(SORT PERFORMANCE_TESTS)
|
||||
|
||||
|
||||
if (RUN_FUZZY_TESTS)
|
||||
|
||||
@@ -336,8 +353,8 @@ if(BUILD_TESTING)
|
||||
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
|
||||
foreach(hit ${found_tests})
|
||||
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
|
||||
add_test(${test_name} "${executable}" ${test_name})
|
||||
set_tests_properties(${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
|
||||
add_test(compiled.${test_name} "${executable}" ${test_name})
|
||||
set_tests_properties(compiled.${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
@@ -371,12 +388,32 @@ if(BUILD_TESTING)
|
||||
)
|
||||
|
||||
|
||||
set(TESTS "")
|
||||
|
||||
foreach(filename ${UNIT_TESTS})
|
||||
message(STATUS "Adding test ${filename}")
|
||||
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
||||
message(STATUS "Adding unit test ${filename}")
|
||||
add_test(unit.${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
||||
list(APPEND TESTS unit.${filename})
|
||||
endforeach()
|
||||
|
||||
set_property(TEST ${UNIT_TESTS}
|
||||
if (RUN_PERFORMANCE_TESTS)
|
||||
foreach(filename ${PERFORMANCE_TESTS})
|
||||
message(STATUS "Adding performance test ${filename}")
|
||||
|
||||
add_test(NAME performance.${filename} COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.${filename} $<TARGET_FILE:chai> ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/${filename})
|
||||
list(APPEND TESTS performance.${filename})
|
||||
endforeach()
|
||||
|
||||
add_executable(profile_cpp_calls_2 performance_tests/profile_cpp_calls_2.cpp)
|
||||
target_link_libraries(profile_cpp_calls_2 ${LIBS})
|
||||
add_test(NAME performance.profile_cpp_calls_2 COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_cpp_calls_2 $<TARGET_FILE:profile_cpp_calls_2>)
|
||||
|
||||
add_executable(profile_fun_wrappers performance_tests/profile_fun_wrappers.cpp)
|
||||
target_link_libraries(profile_fun_wrappers ${LIBS})
|
||||
add_test(NAME performance.profile_fun_wrappers COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_fun_wrappers $<TARGET_FILE:profile_fun_wrappers>)
|
||||
endif()
|
||||
|
||||
set_property(TEST ${TESTS}
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
@@ -425,9 +462,6 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(multifile_test ${LIBS})
|
||||
add_test(NAME MultiFile_Test COMMAND multifile_test)
|
||||
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${LIBS})
|
||||
|
||||
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||
endif()
|
||||
endif()
|
||||
|
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2015 Jason Turner
|
||||
Copyright 2009-2016 Jason Turner
|
||||
Copyright 2009-2012 Jonathan Turner.
|
||||
|
||||
All Rights Reserved.
|
||||
|
22
appveyor.yml
Normal file
22
appveyor.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
version: 5.8.x.{build}
|
||||
os: Visual Studio 2015
|
||||
environment:
|
||||
matrix:
|
||||
- {}
|
||||
build_script:
|
||||
- cmd: >-
|
||||
mkdir build
|
||||
|
||||
cd build
|
||||
|
||||
cmake c:\Projects\chaiscript -G "Visual Studio 14"
|
||||
|
||||
cmake --build . --config Debug
|
||||
test_script:
|
||||
- cmd: ctest -C Debug
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://webhooks.gitter.im/e/9ff725a985b5679d1d5d
|
||||
on_build_success: true
|
||||
on_build_failure: true
|
||||
on_build_status_changed: false
|
@@ -77,7 +77,7 @@ chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
|
||||
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
|
||||
|
||||
```
|
||||
chai.add(chaiscript::user_type<MyClass>, "MyClass");
|
||||
chai.add(chaiscript::user_type<MyClass>(), "MyClass");
|
||||
```
|
||||
|
||||
## Adding Type Conversions
|
||||
@@ -90,6 +90,13 @@ A helper function exists for strongly typed and ChaiScript `Vector` function con
|
||||
chai.add(chaiscript::vector_conversion<std::vector<int>>());
|
||||
```
|
||||
|
||||
A helper function also exists for strongly typed and ChaiScript `Map` function conversion definition:
|
||||
|
||||
```
|
||||
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
|
||||
```
|
||||
|
||||
|
||||
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
|
||||
|
||||
## Adding Objects
|
||||
@@ -100,8 +107,9 @@ chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared
|
||||
auto shareddouble = std::make_shared<double>(4.3);
|
||||
chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai
|
||||
chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const
|
||||
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const
|
||||
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const
|
||||
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const, throws if object exists
|
||||
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, 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.
|
||||
@@ -155,6 +163,28 @@ chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with an
|
||||
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
|
||||
```
|
||||
|
||||
### Conversion Caveats
|
||||
|
||||
Conversion to `std::shared_ptr<T> &` is supported for function calls, but if you attempt to keep a reference to a `shared_ptr<>` you might invoke undefined behavior
|
||||
|
||||
```cpp
|
||||
// ok this is supported, you can register it with chaiscript engine
|
||||
void nullify_shared_ptr(std::shared_ptr<int> &t) {
|
||||
t == nullptr
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
int main()
|
||||
{
|
||||
// do some stuff and create a chaiscript instance
|
||||
std::shared_ptr<int> &ptr = chai.eval<std::shared_ptr<int> &>(somevalue);
|
||||
// DO NOT do this. Taking a non-const reference to a shared_ptr is not
|
||||
// supported and causes undefined behavior in the chaiscript engine
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Sharing Values
|
||||
|
||||
```
|
||||
@@ -221,11 +251,13 @@ var k = 5; // initialized to 5 (integer)
|
||||
var l := k; // reference to k
|
||||
auto &m = k; // reference to k
|
||||
|
||||
GLOBAL g = 5; // creates a global variable. If global already exists, it is not re-added
|
||||
GLOBAL g = 2; // global 'g' now equals 2
|
||||
global g = 5; // creates a global variable. If global already exists, it is not re-added
|
||||
global g = 2; // global 'g' now equals 2
|
||||
|
||||
GLOBAL g2;
|
||||
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once
|
||||
global g2;
|
||||
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hit more than once
|
||||
|
||||
GLOBAL g3; // all upper case version also accepted
|
||||
```
|
||||
|
||||
## Built in Types
|
||||
@@ -354,6 +386,19 @@ o.f = fun(y) { print(this.x + y); }
|
||||
o.f(10); // prints 13
|
||||
```
|
||||
|
||||
### Option Explicit
|
||||
|
||||
If you want to disable dynamic parameter definitions, you can `set_explicit`.
|
||||
|
||||
```
|
||||
class My_Class {
|
||||
def My_Class() {
|
||||
this.set_explicit(true);
|
||||
this.x = 2; // this would fail with explicit set to true
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## method_missing
|
||||
|
||||
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate
|
||||
|
@@ -1,103 +0,0 @@
|
||||
# Checks for C++11 features
|
||||
# CXX11_FEATURE_LIST - a list containing all supported features
|
||||
# HAS_CXX11_AUTO - auto keyword
|
||||
# HAS_CXX11_NULLPTR - nullptr
|
||||
# HAS_CXX11_LAMBDA - lambdas
|
||||
# HAS_CXX11_STATIC_ASSERT - static_assert()
|
||||
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
|
||||
# HAS_CXX11_DECLTYPE - decltype keyword
|
||||
# HAS_CXX11_CSTDINT_H - cstdint header
|
||||
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
|
||||
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
|
||||
# HAS_CXX11_CONSTEXPR - constexpr keyword
|
||||
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
|
||||
# HAS_CXX11_FUNC - __func__ preprocessor constant
|
||||
#
|
||||
# Original script by Rolf Eike Beer
|
||||
# Modifications by Andreas Weis
|
||||
#
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
|
||||
SET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_CXX_FLAGS "-std=c++0x")
|
||||
endif()
|
||||
|
||||
MACRO(CXX11_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
|
||||
IF (NOT DEFINED ${RESULT_VAR})
|
||||
SET(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11/cxx11_${FEATURE_NAME}")
|
||||
|
||||
IF (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
|
||||
ELSE (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\"")
|
||||
ENDIF (${FEATURE_NUMBER})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME}")
|
||||
|
||||
SET(_SRCFILE "${_SRCFILE_BASE}.cpp")
|
||||
SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
IF (CROSS_COMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ELSE (CROSS_COMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}")
|
||||
IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ENDIF (CROSS_COMPILING)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
|
||||
IF (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ELSE (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ENDIF (_TMP_RESULT)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
|
||||
IF (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- works")
|
||||
LIST(APPEND CXX11_FEATURE_LIST ${RESULT_VAR})
|
||||
ELSE (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- not supported")
|
||||
ENDIF (${RESULT_VAR})
|
||||
SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
|
||||
ENDIF (NOT DEFINED ${RESULT_VAR})
|
||||
ENDMACRO(CXX11_CHECK_FEATURE)
|
||||
|
||||
CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)
|
||||
CXX11_CHECK_FEATURE("nullptr" 2431 HAS_CXX11_NULLPTR)
|
||||
CXX11_CHECK_FEATURE("lambda" 2927 HAS_CXX11_LAMBDA)
|
||||
CXX11_CHECK_FEATURE("static_assert" 1720 HAS_CXX11_STATIC_ASSERT)
|
||||
CXX11_CHECK_FEATURE("rvalue_references" 2118 HAS_CXX11_RVALUE_REFERENCES)
|
||||
CXX11_CHECK_FEATURE("decltype" 2343 HAS_CXX11_DECLTYPE)
|
||||
CXX11_CHECK_FEATURE("cstdint" "" HAS_CXX11_CSTDINT_H)
|
||||
CXX11_CHECK_FEATURE("long_long" 1811 HAS_CXX11_LONG_LONG)
|
||||
CXX11_CHECK_FEATURE("variadic_templates" 2555 HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
CXX11_CHECK_FEATURE("constexpr" 2235 HAS_CXX11_CONSTEXPR)
|
||||
CXX11_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX11_SIZEOF_MEMBER)
|
||||
CXX11_CHECK_FEATURE("__func__" 2340 HAS_CXX11_FUNC)
|
||||
|
||||
SET(CXX11_FEATURE_LIST ${CXX11_FEATURE_LIST} CACHE STRING "C++11 feature support list")
|
||||
MARK_AS_ADVANCED(FORCE CXX11_FEATURE_LIST)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS ${CHECK_CXX11_OLD_CMAKE_CXX_FLAGS})
|
||||
UNSET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS)
|
||||
|
@@ -1,8 +0,0 @@
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!__func__) { return 1; }
|
||||
if(std::strlen(__func__) <= 0) { return 1; }
|
||||
return 0;
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
auto i = 5;
|
||||
auto f = 3.14159f;
|
||||
auto d = 3.14159;
|
||||
bool ret = (
|
||||
(sizeof(f) < sizeof(d)) &&
|
||||
(sizeof(i) == sizeof(int))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
constexpr int square(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
constexpr int the_answer()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int test_arr[square(3)];
|
||||
bool ret = (
|
||||
(square(the_answer()) == 1764) &&
|
||||
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
#include <cstdint>
|
||||
int main()
|
||||
{
|
||||
bool test =
|
||||
(sizeof(int8_t) == 1) &&
|
||||
(sizeof(int16_t) == 2) &&
|
||||
(sizeof(int32_t) == 4) &&
|
||||
(sizeof(int64_t) == 8);
|
||||
return test ? 0 : 1;
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
|
||||
bool check_size(int i)
|
||||
{
|
||||
return sizeof(int) == sizeof(decltype(i));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool ret = check_size(42);
|
||||
return ret ? 0 : 1;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
return ([&ret]() -> int { return ret; })();
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
long long l;
|
||||
unsigned long long ul;
|
||||
|
||||
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
int main()
|
||||
{
|
||||
int* test = nullptr;
|
||||
return test ? 1 : 0;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
int main()
|
||||
{
|
||||
int i = nullptr;
|
||||
return 1;
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
int foo(int& lvalue)
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int foo(int&& rvalue)
|
||||
{
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 42;
|
||||
return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1;
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
struct foo {
|
||||
char bar;
|
||||
int baz;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool ret = (
|
||||
(sizeof(foo::bar) == 1) &&
|
||||
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
|
||||
(sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(0 < 1, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(1 < 0, "this should fail");
|
||||
return 0;
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
int Accumulate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
int Accumulate(T v, Ts... vs)
|
||||
{
|
||||
return v + Accumulate(vs...);
|
||||
}
|
||||
|
||||
template<int... Is>
|
||||
int CountElements()
|
||||
{
|
||||
return sizeof...(Is);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int acc = Accumulate(1, 2, 3, 4, -5);
|
||||
int count = CountElements<1,2,3,4,5>();
|
||||
return ((acc == 5) && (count == 5)) ? 0 : 1;
|
||||
}
|
11
contrib/check_for_tabs.rb
Executable file
11
contrib/check_for_tabs.rb
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'json'
|
||||
|
||||
`grep -rPIHn '\t' src/* include/* samples/*`.lines { |line|
|
||||
if /(?<filename>.+(hpp|cpp|chai)):(?<linenumber>[0-9]+):(?<restofline>.+)/ =~ line
|
||||
puts(JSON.dump({:line => linenumber, :filename => filename, :tool => "tab_checker", :message => "Source Code Line Contains Tabs", :messagetype => "warning"}))
|
||||
end
|
||||
}
|
||||
|
||||
|
11
contrib/check_for_todos.rb
Executable file
11
contrib/check_for_todos.rb
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'json'
|
||||
|
||||
`grep -rPIHni 'todo' src/* include/* samples/*`.lines { |line|
|
||||
if /(?<filename>.+(hpp|cpp|chai)):(?<linenumber>[0-9]+):(?<restofline>.+)/ =~ line
|
||||
puts(JSON.dump({:line => linenumber, :filename => filename, :tool => "todo_checker", :message => "todo: #{restofline.strip}", :messagetype => "info"}))
|
||||
end
|
||||
}
|
||||
|
||||
|
61
contrib/codeanalysis/fuzzy_tests/chaiscript.dict
Normal file
61
contrib/codeanalysis/fuzzy_tests/chaiscript.dict
Normal file
@@ -0,0 +1,61 @@
|
||||
# My dict
|
||||
|
||||
|
||||
for="for"
|
||||
while="while"
|
||||
def="def"
|
||||
fun="fun"
|
||||
if="if"
|
||||
else="else"
|
||||
and="&&"
|
||||
or="||"
|
||||
auto="auto"
|
||||
var="var"
|
||||
begin_block="{"
|
||||
end_block="}"
|
||||
empty_vec="[]"
|
||||
string="string"
|
||||
vector="Vector"
|
||||
map="Map"
|
||||
return="return"
|
||||
break="break"
|
||||
true="true"
|
||||
false="false"
|
||||
class="class"
|
||||
attr="attr"
|
||||
var="var"
|
||||
global="global"
|
||||
empty_lambda=" fun(){} "
|
||||
empty_fun=" def empty_fun() {} "
|
||||
continue="continue"
|
||||
float=" 1.1f "
|
||||
double=" 2.2 "
|
||||
long_double=" 2.2ll "
|
||||
unsigned=" 3u "
|
||||
unsigned_long=" 4ul "
|
||||
unsigned_long_long=" 4ull "
|
||||
long_long=" 5ll "
|
||||
attr="attr"
|
||||
reference_del="auto &"
|
||||
int8=" int8_t(1) "
|
||||
int16=" int16_t(2) "
|
||||
int32=" int32_t(3) "
|
||||
int64=" int64_t(4) "
|
||||
uint8=" uint8_t(1) "
|
||||
uint16=" uint16_t(2) "
|
||||
uint32=" uint32_t(3) "
|
||||
uint64=" uint64_t(4) "
|
||||
int8t="int8_t"
|
||||
int16t="int16_t"
|
||||
int32t="int32_t"
|
||||
int64t="int64_t"
|
||||
uint8t="uint8_t"
|
||||
uint16t="uint16_t"
|
||||
uint32t="uint32_t"
|
||||
uint64t="uint64_t"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
17
contrib/codeanalysis/fuzzy_tests/notes.txt
Normal file
17
contrib/codeanalysis/fuzzy_tests/notes.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
Command line used to find this crash:
|
||||
|
||||
../../Downloads/afl-1.80b/afl-fuzz -i- -o findings -x chaiscript.dict -- ../a.out unit_test.inc @@
|
||||
|
||||
If you can't reproduce a bug outside of afl-fuzz, be sure to set the same
|
||||
memory limit. The limit used for this fuzzing session was 50.0 MB.
|
||||
|
||||
Need a tool to minimize test cases before investigating the crashes or sending
|
||||
them to a vendor? Check out the afl-tmin that comes with the fuzzer!
|
||||
|
||||
Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop
|
||||
me a mail at <lcamtuf@coredump.cx> once the issues are fixed - I'd love to
|
||||
add your finds to the gallery at:
|
||||
|
||||
http://lcamtuf.coredump.cx/afl/
|
||||
|
||||
Thanks :-)
|
5
contrib/codeanalysis/fuzzy_tests/use.inc
Normal file
5
contrib/codeanalysis/fuzzy_tests/use.inc
Normal file
@@ -0,0 +1,5 @@
|
||||
def greet {
|
||||
return("hello")
|
||||
}
|
||||
|
||||
fun(){ "world" }
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_HPP_
|
||||
@@ -695,11 +695,10 @@
|
||||
/// Begins a function or method definition
|
||||
///
|
||||
/// ~~~~~~~~
|
||||
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// annotation: meta-annotation on function, currently used as documentation. Optional.
|
||||
/// identifier: name of function. Required.
|
||||
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
||||
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
||||
|
@@ -1,22 +1,19 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||
#define CHAISCRIPT_DEFINES_HPP_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CHAISCRIPT_STRINGIZE(x) "" #x
|
||||
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
|
||||
#define CHAISCRIPT_MSVC _MSC_VER
|
||||
#define CHAISCRIPT_HAS_DECLSPEC
|
||||
#if _MSC_VER <= 1800
|
||||
#define CHAISCRIPT_MSVC_12
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CHAISCRIPT_MSVC_12
|
||||
#define CHAISCRIPT_HAS_MAGIC_STATICS
|
||||
#else
|
||||
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
@@ -29,20 +26,31 @@
|
||||
#define CHAISCRIPT_WINDOWS
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
||||
/// Currently only g++>=4.8 supports this natively
|
||||
#if defined(_WIN32)
|
||||
#if defined(__llvm__)
|
||||
#define CHAISCRIPT_COMPILER_NAME "clang(windows)"
|
||||
#elif defined(__GNUC__)
|
||||
#define CHAISCRIPT_COMPILER_NAME "gcc(mingw)"
|
||||
#else
|
||||
#define CHAISCRIPT_COMPILER_NAME "msvc"
|
||||
#endif
|
||||
#else
|
||||
#if defined(__llvm__)
|
||||
#define CHAISCRIPT_COMPILER_NAME "clang"
|
||||
#elif defined(__GNUC__)
|
||||
#define CHAISCRIPT_COMPILER_NAME "gcc"
|
||||
#else
|
||||
#define CHAISCRIPT_COMPILER_NAME "unknown"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
||||
/// \todo Make this support other compilers when possible
|
||||
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
|
||||
#define CHAISCRIPT_GCC_4_6
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__)
|
||||
#define CHAISCRIPT_OVERRIDE override
|
||||
#else
|
||||
#define CHAISCRIPT_OVERRIDE
|
||||
#if defined(__llvm__)
|
||||
#define CHAISCRIPT_CLANG
|
||||
#endif
|
||||
|
||||
|
||||
@@ -52,20 +60,24 @@
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#define CHAISCRIPT_NOEXCEPT throw()
|
||||
#define CHAISCRIPT_CONSTEXPR
|
||||
#ifdef _DEBUG
|
||||
#define CHAISCRIPT_DEBUG true
|
||||
#else
|
||||
#define CHAISCRIPT_NOEXCEPT noexcept
|
||||
#define CHAISCRIPT_CONSTEXPR constexpr
|
||||
#define CHAISCRIPT_DEBUG false
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
namespace chaiscript {
|
||||
static const int version_major = 5;
|
||||
static const int version_minor = 7;
|
||||
static const int version_patch = 1;
|
||||
static const int version_major = 6;
|
||||
static const int version_minor = 0;
|
||||
static const int version_patch = 0;
|
||||
|
||||
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
|
||||
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
||||
static const bool debug_build = CHAISCRIPT_DEBUG;
|
||||
|
||||
template<typename B, typename D, typename ...Arg>
|
||||
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
||||
@@ -77,6 +89,126 @@ namespace chaiscript {
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Build_Info {
|
||||
static int version_major()
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
|
||||
static int version_minor()
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
|
||||
static int version_patch()
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
|
||||
static std::string version()
|
||||
{
|
||||
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
|
||||
}
|
||||
|
||||
static std::string compiler_id()
|
||||
{
|
||||
return compiler_name() + '-' + compiler_version();
|
||||
}
|
||||
|
||||
static std::string build_id()
|
||||
{
|
||||
return compiler_id() + (debug_build()?"-Debug":"-Release");
|
||||
}
|
||||
|
||||
static std::string compiler_version()
|
||||
{
|
||||
return chaiscript::compiler_version;
|
||||
}
|
||||
|
||||
static std::string compiler_name()
|
||||
{
|
||||
return chaiscript::compiler_name;
|
||||
}
|
||||
|
||||
static bool debug_build()
|
||||
{
|
||||
return chaiscript::debug_build;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Iter, typename Distance>
|
||||
Iter advance_copy(Iter iter, Distance distance) {
|
||||
std::advance(iter, static_cast<typename std::iterator_traits<Iter>::difference_type>(distance));
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||
{
|
||||
T t = 0;
|
||||
for (char c = *t_str; (c = *t_str); ++t_str) {
|
||||
if (c < '0' || c > '9') {
|
||||
return t;
|
||||
}
|
||||
t *= 10;
|
||||
t += c - '0';
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
||||
{
|
||||
T t = 0;
|
||||
T base = 0;
|
||||
T decimal_place = 0;
|
||||
bool exponent = false;
|
||||
bool neg_exponent = false;
|
||||
|
||||
const auto final_value = [](const T val, const T baseval, const bool hasexp, const bool negexp) -> T {
|
||||
if (!hasexp) {
|
||||
return val;
|
||||
} else {
|
||||
return baseval * std::pow(T(10), val*T(negexp?-1:1));
|
||||
}
|
||||
};
|
||||
|
||||
for(; *t_str != '\0'; ++t_str) {
|
||||
char c = *t_str;
|
||||
if (c == '.') {
|
||||
decimal_place = 10;
|
||||
} else if (c == 'e' || c == 'E') {
|
||||
exponent = true;
|
||||
decimal_place = 0;
|
||||
base = t;
|
||||
t = 0;
|
||||
} else if (c == '-' && exponent) {
|
||||
neg_exponent = true;
|
||||
} else if (c == '+' && exponent) {
|
||||
neg_exponent = false;
|
||||
} else if (c < '0' || c > '9') {
|
||||
return final_value(t, base, exponent, neg_exponent);
|
||||
} else if (decimal_place < T(10)) {
|
||||
t *= T(10);
|
||||
t += T(c - '0');
|
||||
} else {
|
||||
t += (T(c - '0') / (T(decimal_place)));
|
||||
decimal_place *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
return final_value(t, base, exponent, neg_exponent);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T parse_num(const std::string &t_str)
|
||||
{
|
||||
return parse_num<T>(t_str.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -14,11 +14,16 @@
|
||||
#include <vector>
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "language/chaiscript_common.hpp"
|
||||
|
||||
//#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/operators.hpp"
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
#include "dispatchkit/boxed_value.hpp"
|
||||
#include "language/chaiscript_prelude.chai"
|
||||
//#include "dispatchkit/boxed_value.hpp"
|
||||
#include "language/chaiscript_prelude.hpp"
|
||||
#include "dispatchkit/register_function.hpp"
|
||||
#include "utility/json_wrap.hpp"
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <future>
|
||||
@@ -37,20 +42,23 @@ namespace chaiscript
|
||||
|
||||
static ModulePtr library()
|
||||
{
|
||||
using namespace bootstrap;
|
||||
// using namespace bootstrap;
|
||||
|
||||
ModulePtr lib = Bootstrap::bootstrap();
|
||||
auto lib = std::make_shared<Module>();
|
||||
bootstrap::Bootstrap::bootstrap(*lib);
|
||||
|
||||
lib->add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
lib->add(standard_library::string_type<std::string>("string"));
|
||||
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
bootstrap::standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
|
||||
bootstrap::standard_library::string_type<std::string>("string", *lib);
|
||||
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
|
||||
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
lib->add(standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future"));
|
||||
bootstrap::standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);
|
||||
lib->add(chaiscript::fun([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
|
||||
#endif
|
||||
|
||||
json_wrap::library(*lib);
|
||||
|
||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
|
||||
|
||||
return lib;
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||
@@ -42,28 +42,16 @@ namespace chaiscript
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
|
||||
template<typename T>
|
||||
class unique_lock : public std::unique_lock<T>
|
||||
{
|
||||
public:
|
||||
unique_lock(T &t) : std::unique_lock<T>(t) {}
|
||||
};
|
||||
using unique_lock = std::unique_lock<T>;
|
||||
|
||||
template<typename T>
|
||||
class shared_lock : public std::unique_lock<T>
|
||||
{
|
||||
public:
|
||||
shared_lock(T &t) : std::unique_lock<T>(t) {}
|
||||
void unlock() {}
|
||||
};
|
||||
using shared_lock = std::unique_lock<T>;
|
||||
|
||||
template<typename T>
|
||||
class lock_guard : public std::lock_guard<T>
|
||||
{
|
||||
public:
|
||||
lock_guard(T &t) : std::lock_guard<T>(t) {}
|
||||
};
|
||||
using lock_guard = std::lock_guard<T>;
|
||||
|
||||
class shared_mutex : public std::mutex { };
|
||||
|
||||
using shared_mutex = std::mutex;
|
||||
|
||||
using std::mutex;
|
||||
|
||||
@@ -77,7 +65,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
|
||||
Thread_Storage(void *t_key)
|
||||
explicit Thread_Storage(void *t_key)
|
||||
: m_key(t_key)
|
||||
{
|
||||
}
|
||||
@@ -120,6 +108,9 @@ namespace chaiscript
|
||||
|
||||
#else
|
||||
|
||||
#pragma message ("Threading without thread_local support is not well supported.")
|
||||
|
||||
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
///
|
||||
@@ -129,7 +120,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
|
||||
Thread_Storage(void *)
|
||||
explicit Thread_Storage(void *)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -160,13 +151,14 @@ namespace chaiscript
|
||||
{
|
||||
unique_lock<mutex> lock(m_mutex);
|
||||
|
||||
auto itr = m_instances.find(std::this_thread::get_id());
|
||||
const auto id = std::this_thread::get_id();
|
||||
auto itr = m_instances.find(id);
|
||||
|
||||
if (itr != m_instances.end()) { return itr->second; }
|
||||
|
||||
std::shared_ptr<T> new_instance(std::make_shared<T>());
|
||||
|
||||
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
|
||||
m_instances.insert(std::make_pair(id, new_instance));
|
||||
|
||||
return new_instance;
|
||||
}
|
||||
@@ -182,7 +174,7 @@ namespace chaiscript
|
||||
class unique_lock
|
||||
{
|
||||
public:
|
||||
unique_lock(T &) {}
|
||||
explicit unique_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
@@ -191,7 +183,7 @@ namespace chaiscript
|
||||
class shared_lock
|
||||
{
|
||||
public:
|
||||
shared_lock(T &) {}
|
||||
explicit shared_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
@@ -200,7 +192,7 @@ namespace chaiscript
|
||||
class lock_guard
|
||||
{
|
||||
public:
|
||||
lock_guard(T &) {}
|
||||
explicit lock_guard(T &) {}
|
||||
};
|
||||
|
||||
class shared_mutex { };
|
||||
@@ -212,7 +204,7 @@ namespace chaiscript
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
Thread_Storage(void *)
|
||||
explicit Thread_Storage(void *)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -21,17 +21,17 @@ namespace chaiscript {
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_any_cast() CHAISCRIPT_NOEXCEPT
|
||||
bad_any_cast() noexcept
|
||||
: m_what("bad any cast")
|
||||
{
|
||||
}
|
||||
|
||||
bad_any_cast(const bad_any_cast &) = default;
|
||||
|
||||
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
~bad_any_cast() noexcept override = default;
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
const char * what() const noexcept override
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
@@ -46,16 +46,17 @@ namespace chaiscript {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
Data(const std::type_info &t_type)
|
||||
explicit Data(const std::type_info &t_type)
|
||||
: m_type(t_type)
|
||||
{
|
||||
}
|
||||
|
||||
Data &operator=(const Data &) = delete;
|
||||
|
||||
virtual ~Data() {}
|
||||
virtual ~Data() = default;
|
||||
|
||||
virtual void *data() = 0;
|
||||
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return m_type;
|
||||
@@ -74,14 +75,12 @@ namespace chaiscript {
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Data_Impl() {}
|
||||
|
||||
virtual void *data() CHAISCRIPT_OVERRIDE
|
||||
virtual void *data() override
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
|
||||
std::unique_ptr<Data> clone() const override
|
||||
{
|
||||
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
|
||||
}
|
||||
@@ -96,6 +95,8 @@ namespace chaiscript {
|
||||
public:
|
||||
// construct/copy/destruct
|
||||
Any() = default;
|
||||
Any(Any &&) = default;
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
|
||||
Any(const Any &t_any)
|
||||
{
|
||||
@@ -107,10 +108,6 @@ namespace chaiscript {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Any(Any &&) = default;
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
#endif
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
||||
@@ -139,10 +136,6 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
|
||||
~Any()
|
||||
{
|
||||
}
|
||||
|
||||
// modifiers
|
||||
Any & swap(Any &t_other)
|
||||
{
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
@@ -30,7 +30,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
std::string t_what) noexcept
|
||||
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
@@ -40,16 +40,16 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
explicit bad_boxed_cast(std::string t_what) noexcept
|
||||
: to(nullptr), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const bad_boxed_cast &) = default;
|
||||
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~bad_boxed_cast() noexcept = default;
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
virtual const char * what() const noexcept override
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||
@@ -27,45 +27,52 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
auto bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
auto bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
auto bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
});
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename F, typename O, typename Ret, typename Class, typename P1, typename ... Param>
|
||||
auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
|
||||
{
|
||||
return [fo, o, f](Param ...param) -> Ret {
|
||||
return (fo.*f)(o, std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename F, typename O>
|
||||
auto bind_first(const F &f, O&& o)
|
||||
{
|
||||
return bind_first(f, std::forward<O>(o), &F::operator());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,38 +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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "proxy_functions_detail.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "../utility/utility.hpp"
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -52,12 +28,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
|
||||
ModulePtr array(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void array(const std::string &type, Module& m)
|
||||
{
|
||||
typedef typename std::remove_extent<T>::type ReturnType;
|
||||
const auto extent = std::extent<T>::value;
|
||||
m->add(user_type<T>(), type);
|
||||
m->add(fun(
|
||||
m.add(user_type<T>(), type);
|
||||
m.add(fun(
|
||||
[extent](T& t, size_t index)->ReturnType &{
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
@@ -68,7 +44,7 @@ namespace chaiscript
|
||||
), "[]"
|
||||
);
|
||||
|
||||
m->add(fun(
|
||||
m.add(fun(
|
||||
[extent](const T &t, size_t index)->const ReturnType &{
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
@@ -79,33 +55,29 @@ namespace chaiscript
|
||||
), "[]"
|
||||
);
|
||||
|
||||
m->add(fun(
|
||||
m.add(fun(
|
||||
[extent](const T &) {
|
||||
return extent;
|
||||
}), "size");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Adds a copy constructor for the given type to the given Model
|
||||
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
||||
/// \param[in,out] m The Module to add the copy constructor to
|
||||
/// \tparam T The type to add a copy constructor for
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
/// \returns The passed in Module
|
||||
template<typename T>
|
||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void copy_constructor(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(constructor<T (const T &)>(), type);
|
||||
return m;
|
||||
m.add(constructor<T (const T &)>(), type);
|
||||
}
|
||||
|
||||
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
||||
/// \tparam T Type to create comparison operators for
|
||||
/// \param[in,out] m module to add comparison operators to
|
||||
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
|
||||
/// \returns the passed in Module.
|
||||
template<typename T>
|
||||
ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
|
||||
void opers_comparison(Module& m)
|
||||
{
|
||||
operators::equal<T>(m);
|
||||
operators::greater_than<T>(m);
|
||||
@@ -113,7 +85,6 @@ namespace chaiscript
|
||||
operators::less_than<T>(m);
|
||||
operators::less_than_equal<T>(m);
|
||||
operators::not_equal<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,15 +93,14 @@ namespace chaiscript
|
||||
/// \param[in] type The name of the type to add the constructors for.
|
||||
/// \param[in,out] m The Module to add the basic constructors to
|
||||
/// \tparam T Type to generate basic constructors for
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
/// \returns The passed in Module
|
||||
/// \sa copy_constructor
|
||||
/// \sa constructor
|
||||
template<typename T>
|
||||
ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void basic_constructors(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(constructor<T ()>(), type);
|
||||
m.add(constructor<T ()>(), type);
|
||||
copy_constructor<T>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Adds a constructor for a POD type
|
||||
@@ -138,22 +108,12 @@ namespace chaiscript
|
||||
/// \param[in] type The name of the type
|
||||
/// \param[in,out] m The Module to add the constructor to
|
||||
template<typename T>
|
||||
ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void construct_pod(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(fun(&detail::construct_pod<T>), type);
|
||||
return m;
|
||||
m.add(fun(&detail::construct_pod<T>), type);
|
||||
}
|
||||
|
||||
|
||||
/// to_string function for internal use. Uses ostream operator<<
|
||||
template<typename Input>
|
||||
std::string to_string(Input i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/// Internal function for converting from a string to a value
|
||||
/// uses ostream operator >> to perform the conversion
|
||||
template<typename Input>
|
||||
@@ -185,14 +145,13 @@ namespace chaiscript
|
||||
/// Add all common functions for a POD type. All operators, and
|
||||
/// common conversions
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared<Module>())
|
||||
void bootstrap_pod_type(const std::string &name, Module& m)
|
||||
{
|
||||
m->add(user_type<T>(), name);
|
||||
m->add(constructor<T()>(), name);
|
||||
m.add(user_type<T>(), name);
|
||||
m.add(constructor<T()>(), name);
|
||||
construct_pod<T>(name, m);
|
||||
|
||||
m->add(fun(&parse_string<T>), "to_" + name);
|
||||
return m;
|
||||
m.add(fun(&parse_string<T>), "to_" + name);
|
||||
}
|
||||
|
||||
|
||||
@@ -261,43 +220,41 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Add all arithmetic operators for PODs
|
||||
static void opers_arithmetic_pod(ModulePtr m = std::make_shared<Module>())
|
||||
static void opers_arithmetic_pod(Module& m)
|
||||
{
|
||||
m->add(fun(&Boxed_Number::equals), "==");
|
||||
m->add(fun(&Boxed_Number::less_than), "<");
|
||||
m->add(fun(&Boxed_Number::greater_than), ">");
|
||||
m->add(fun(&Boxed_Number::greater_than_equal), ">=");
|
||||
m->add(fun(&Boxed_Number::less_than_equal), "<=");
|
||||
m->add(fun(&Boxed_Number::not_equal), "!=");
|
||||
|
||||
m->add(fun(&Boxed_Number::pre_decrement), "--");
|
||||
m->add(fun(&Boxed_Number::pre_increment), "++");
|
||||
m->add(fun(&Boxed_Number::sum), "+");
|
||||
m->add(fun(&Boxed_Number::unary_plus), "+");
|
||||
m->add(fun(&Boxed_Number::unary_minus), "-");
|
||||
m->add(fun(&Boxed_Number::difference), "-");
|
||||
m->add(fun(&Boxed_Number::assign_bitwise_and), "&=");
|
||||
m->add(fun(&Boxed_Number::assign), "=");
|
||||
m->add(fun(&Boxed_Number::assign_bitwise_or), "|=");
|
||||
m->add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
|
||||
m->add(fun(&Boxed_Number::assign_remainder), "%=");
|
||||
m->add(fun(&Boxed_Number::assign_shift_left), "<<=");
|
||||
m->add(fun(&Boxed_Number::assign_shift_right), ">>=");
|
||||
m->add(fun(&Boxed_Number::bitwise_and), "&");
|
||||
m->add(fun(&Boxed_Number::bitwise_complement), "~");
|
||||
m->add(fun(&Boxed_Number::bitwise_xor), "^");
|
||||
m->add(fun(&Boxed_Number::bitwise_or), "|");
|
||||
m->add(fun(&Boxed_Number::assign_product), "*=");
|
||||
m->add(fun(&Boxed_Number::assign_quotient), "/=");
|
||||
m->add(fun(&Boxed_Number::assign_sum), "+=");
|
||||
m->add(fun(&Boxed_Number::assign_difference), "-=");
|
||||
m->add(fun(&Boxed_Number::quotient), "/");
|
||||
m->add(fun(&Boxed_Number::shift_left), "<<");
|
||||
m->add(fun(&Boxed_Number::product), "*");
|
||||
m->add(fun(&Boxed_Number::remainder), "%");
|
||||
m->add(fun(&Boxed_Number::shift_right), ">>");
|
||||
|
||||
m.add(fun(&Boxed_Number::equals), "==");
|
||||
m.add(fun(&Boxed_Number::less_than), "<");
|
||||
m.add(fun(&Boxed_Number::greater_than), ">");
|
||||
m.add(fun(&Boxed_Number::greater_than_equal), ">=");
|
||||
m.add(fun(&Boxed_Number::less_than_equal), "<=");
|
||||
m.add(fun(&Boxed_Number::not_equal), "!=");
|
||||
|
||||
m.add(fun(&Boxed_Number::pre_decrement), "--");
|
||||
m.add(fun(&Boxed_Number::pre_increment), "++");
|
||||
m.add(fun(&Boxed_Number::sum), "+");
|
||||
m.add(fun(&Boxed_Number::unary_plus), "+");
|
||||
m.add(fun(&Boxed_Number::unary_minus), "-");
|
||||
m.add(fun(&Boxed_Number::difference), "-");
|
||||
m.add(fun(&Boxed_Number::assign_bitwise_and), "&=");
|
||||
m.add(fun(&Boxed_Number::assign), "=");
|
||||
m.add(fun(&Boxed_Number::assign_bitwise_or), "|=");
|
||||
m.add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
|
||||
m.add(fun(&Boxed_Number::assign_remainder), "%=");
|
||||
m.add(fun(&Boxed_Number::assign_shift_left), "<<=");
|
||||
m.add(fun(&Boxed_Number::assign_shift_right), ">>=");
|
||||
m.add(fun(&Boxed_Number::bitwise_and), "&");
|
||||
m.add(fun(&Boxed_Number::bitwise_complement), "~");
|
||||
m.add(fun(&Boxed_Number::bitwise_xor), "^");
|
||||
m.add(fun(&Boxed_Number::bitwise_or), "|");
|
||||
m.add(fun(&Boxed_Number::assign_product), "*=");
|
||||
m.add(fun(&Boxed_Number::assign_quotient), "/=");
|
||||
m.add(fun(&Boxed_Number::assign_sum), "+=");
|
||||
m.add(fun(&Boxed_Number::assign_difference), "-=");
|
||||
m.add(fun(&Boxed_Number::quotient), "/");
|
||||
m.add(fun(&Boxed_Number::shift_left), "<<");
|
||||
m.add(fun(&Boxed_Number::product), "*");
|
||||
m.add(fun(&Boxed_Number::remainder), "%");
|
||||
m.add(fun(&Boxed_Number::shift_right), ">>");
|
||||
}
|
||||
|
||||
/// Create a bound function object. The first param is the function to bind
|
||||
@@ -337,26 +294,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static void throw_exception(const Boxed_Value &bv) {
|
||||
throw bv;
|
||||
}
|
||||
|
||||
static std::string what(const std::exception &e)
|
||||
{
|
||||
return e.what();
|
||||
}
|
||||
|
||||
/// Boolean specialization of internal to_string function
|
||||
static std::string bool_to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FunctionType>
|
||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
||||
const dispatch::Proxy_Function_Base *b)
|
||||
@@ -392,7 +329,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
static auto return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return [f](const dispatch::Proxy_Function_Base *b) {
|
||||
return do_return_boxed_value_vector(f, b);
|
||||
@@ -403,98 +340,139 @@ namespace chaiscript
|
||||
public:
|
||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||
/// \param[in,out] m Module to add bootstrapped functions to
|
||||
/// \returns passed in ModulePtr, or newly created one if default argument is used
|
||||
static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
|
||||
/// \returns passed in Module
|
||||
static void bootstrap(Module& m)
|
||||
{
|
||||
m->add(user_type<void>(), "void");
|
||||
m->add(user_type<bool>(), "bool");
|
||||
m->add(user_type<Boxed_Value>(), "Object");
|
||||
m->add(user_type<Boxed_Number>(), "Number");
|
||||
m->add(user_type<Proxy_Function>(), "Function");
|
||||
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
||||
m->add(user_type<std::exception>(), "exception");
|
||||
m.add(user_type<void>(), "void");
|
||||
m.add(user_type<bool>(), "bool");
|
||||
m.add(user_type<Boxed_Value>(), "Object");
|
||||
m.add(user_type<Boxed_Number>(), "Number");
|
||||
m.add(user_type<Proxy_Function>(), "Function");
|
||||
m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
||||
m.add(user_type<std::exception>(), "exception");
|
||||
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
||||
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
||||
|
||||
|
||||
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
|
||||
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
|
||||
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
|
||||
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
|
||||
|
||||
m.add(fun([](const std::exception &e){ return std::string(e.what()); }), "what");
|
||||
|
||||
m->add(user_type<std::out_of_range>(), "out_of_range");
|
||||
m->add(user_type<std::logic_error>(), "logic_error");
|
||||
m->add(chaiscript::base_class<std::exception, std::logic_error>());
|
||||
m->add(chaiscript::base_class<std::logic_error, std::out_of_range>());
|
||||
m->add(chaiscript::base_class<std::exception, std::out_of_range>());
|
||||
m.add(user_type<std::out_of_range>(), "out_of_range");
|
||||
m.add(user_type<std::logic_error>(), "logic_error");
|
||||
m.add(chaiscript::base_class<std::exception, std::logic_error>());
|
||||
m.add(chaiscript::base_class<std::logic_error, std::out_of_range>());
|
||||
m.add(chaiscript::base_class<std::exception, std::out_of_range>());
|
||||
|
||||
m->add(user_type<std::runtime_error>(), "runtime_error");
|
||||
m->add(chaiscript::base_class<std::exception, std::runtime_error>());
|
||||
m.add(user_type<std::runtime_error>(), "runtime_error");
|
||||
m.add(chaiscript::base_class<std::exception, std::runtime_error>());
|
||||
|
||||
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
m.add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
|
||||
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||
m.add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||
m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||
m.add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
|
||||
m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
||||
m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||
m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
|
||||
m.add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
|
||||
m.add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr");
|
||||
|
||||
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
|
||||
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
|
||||
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m.add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
|
||||
m->eval("def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
|
||||
m.eval(R"chaiscript(
|
||||
def Dynamic_Object::clone() {
|
||||
auto &new_o = Dynamic_Object(this.get_type_name());
|
||||
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
|
||||
new_o;
|
||||
}
|
||||
|
||||
m->add(fun(&has_guard), "has_guard");
|
||||
m->add(fun(&get_guard), "get_guard");
|
||||
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||
{
|
||||
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
|
||||
}
|
||||
|
||||
m->add(fun(&Boxed_Value::is_undef), "is_var_undef");
|
||||
m->add(fun(&Boxed_Value::is_null), "is_var_null");
|
||||
m->add(fun(&Boxed_Value::is_const), "is_var_const");
|
||||
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
||||
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
||||
m->add(fun(&Boxed_Value::is_type), "is_type");
|
||||
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
|
||||
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
|
||||
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||
{
|
||||
var rhs_attrs := rhs.get_attrs();
|
||||
var lhs_attrs := lhs.get_attrs();
|
||||
|
||||
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
||||
m->add(user_type<Type_Info>(), "Type_Info");
|
||||
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
|
||||
if (rhs_attrs.size() != lhs_attrs.size()) {
|
||||
true;
|
||||
} else {
|
||||
return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } );
|
||||
}
|
||||
}
|
||||
|
||||
def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||
{
|
||||
var rhs_attrs := rhs.get_attrs();
|
||||
var lhs_attrs := lhs.get_attrs();
|
||||
|
||||
if (rhs_attrs.size() != lhs_attrs.size()) {
|
||||
false;
|
||||
} else {
|
||||
return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } );
|
||||
}
|
||||
}
|
||||
)chaiscript");
|
||||
|
||||
m.add(fun(&has_guard), "has_guard");
|
||||
m.add(fun(&get_guard), "get_guard");
|
||||
|
||||
m.add(fun(&Boxed_Value::is_undef), "is_var_undef");
|
||||
m.add(fun(&Boxed_Value::is_null), "is_var_null");
|
||||
m.add(fun(&Boxed_Value::is_const), "is_var_const");
|
||||
m.add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
||||
m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
||||
m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
|
||||
m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
|
||||
m.add(fun(&Boxed_Value::is_type), "is_type");
|
||||
m.add(fun(&Boxed_Value::get_attr), "get_var_attr");
|
||||
m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
|
||||
m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
|
||||
|
||||
m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
||||
m.add(user_type<Type_Info>(), "Type_Info");
|
||||
m.add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
|
||||
|
||||
|
||||
operators::equal<Type_Info>(m);
|
||||
|
||||
m->add(fun(&Type_Info::is_const), "is_type_const");
|
||||
m->add(fun(&Type_Info::is_reference), "is_type_reference");
|
||||
m->add(fun(&Type_Info::is_void), "is_type_void");
|
||||
m->add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||
m->add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
||||
m->add(fun(&Type_Info::name), "cpp_name");
|
||||
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
m.add(fun(&Type_Info::is_const), "is_type_const");
|
||||
m.add(fun(&Type_Info::is_reference), "is_type_reference");
|
||||
m.add(fun(&Type_Info::is_void), "is_type_void");
|
||||
m.add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||
m.add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||
m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
||||
m.add(fun(&Type_Info::name), "cpp_name");
|
||||
m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||
m.add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
|
||||
|
||||
basic_constructors<bool>("bool", m);
|
||||
operators::assign<bool>(m);
|
||||
operators::equal<bool>(m);
|
||||
operators::not_equal<bool>(m);
|
||||
|
||||
m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "to_string");
|
||||
m->add(fun(&unknown_assign), "=");
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
m->add(fun(&what), "what");
|
||||
m.add(fun([](const std::string &s) { return s; }), "to_string");
|
||||
m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
|
||||
m.add(fun(&unknown_assign), "=");
|
||||
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
|
||||
|
||||
m->add(fun(&to_string<char>), "to_string");
|
||||
m->add(fun(&Boxed_Number::to_string), "to_string");
|
||||
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
||||
m.add(fun(&Boxed_Number::to_string), "to_string");
|
||||
|
||||
|
||||
bootstrap_pod_type<double>("double", m);
|
||||
bootstrap_pod_type<long double>("long_double", m);
|
||||
bootstrap_pod_type<float>("float", m);
|
||||
@@ -502,6 +480,8 @@ namespace chaiscript
|
||||
bootstrap_pod_type<long>("long", m);
|
||||
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
||||
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
||||
bootstrap_pod_type<long long>("long_long", m);
|
||||
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
|
||||
bootstrap_pod_type<size_t>("size_t", m);
|
||||
bootstrap_pod_type<char>("char", m);
|
||||
bootstrap_pod_type<wchar_t>("wchar_t", m);
|
||||
@@ -516,57 +496,71 @@ namespace chaiscript
|
||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||
|
||||
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
opers_arithmetic_pod(m);
|
||||
|
||||
|
||||
m.add(fun(&Build_Info::version_major), "version_major");
|
||||
m.add(fun(&Build_Info::version_minor), "version_minor");
|
||||
m.add(fun(&Build_Info::version_patch), "version_patch");
|
||||
m.add(fun(&Build_Info::version), "version");
|
||||
m.add(fun(&Build_Info::compiler_version), "compiler_version");
|
||||
m.add(fun(&Build_Info::compiler_name), "compiler_name");
|
||||
m.add(fun(&Build_Info::compiler_id), "compiler_id");
|
||||
m.add(fun(&Build_Info::debug_build), "debug_build");
|
||||
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m->add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||
m.add(fun(&print), "print_string");
|
||||
m.add(fun(&println), "println_string");
|
||||
|
||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
|
||||
m->add(fun(
|
||||
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||
|
||||
m.add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
m.add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m.add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m.add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
|
||||
m.add(fun(
|
||||
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
||||
t_lhs.assign(t_rhs);
|
||||
}
|
||||
), "="
|
||||
);
|
||||
|
||||
m->add(fun(&Boxed_Value::type_match), "type_match");
|
||||
m.add(fun(&Boxed_Value::type_match), "type_match");
|
||||
|
||||
|
||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
||||
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
||||
m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||
|
||||
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
||||
m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
||||
m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
|
||||
|
||||
|
||||
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
|
||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
|
||||
"eval_error",
|
||||
{ },
|
||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<std::shared_ptr<const chaiscript::AST_Node>>);
|
||||
return retval;
|
||||
})), "call_stack"} }
|
||||
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
||||
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
|
||||
return retval;
|
||||
}), "call_stack"} }
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(m,
|
||||
"File_Position",
|
||||
{ constructor<File_Position()>(),
|
||||
constructor<File_Position(int, int)>() },
|
||||
@@ -575,7 +569,7 @@ namespace chaiscript
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<AST_Node>(*m,
|
||||
chaiscript::utility::add_class<AST_Node>(m,
|
||||
"AST_Node",
|
||||
{ },
|
||||
{ {fun(&AST_Node::text), "text"},
|
||||
@@ -584,28 +578,17 @@ namespace chaiscript
|
||||
{fun(&AST_Node::start), "start"},
|
||||
{fun(&AST_Node::end), "end"},
|
||||
{fun(&AST_Node::to_string), "to_string"},
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
||||
{fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_node.children.begin(), t_node.children.end(),
|
||||
const auto children = t_node.get_children();
|
||||
std::transform(children.begin(), children.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
|
||||
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
|
||||
return retval;
|
||||
})), "children"},
|
||||
{fun(&AST_Node::replace_child), "replace_child"}
|
||||
}), "children"}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
|
||||
"ChaiScript_Parser",
|
||||
{ constructor<parser::ChaiScript_Parser ()>() },
|
||||
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
|
||||
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
|
||||
);
|
||||
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
/// \file
|
||||
@@ -177,22 +177,20 @@ namespace chaiscript
|
||||
|
||||
/// Add Bidir_Range support for the given ContainerType
|
||||
template<typename Bidir_Type>
|
||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void input_range_type_impl(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<Bidir_Type>(), type + "_Range");
|
||||
m.add(user_type<Bidir_Type>(), type + "_Range");
|
||||
|
||||
copy_constructor<Bidir_Type>(type + "_Range", m);
|
||||
|
||||
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
m.add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
|
||||
m->add(fun(&Bidir_Type::empty), "empty");
|
||||
m->add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||
m->add(fun(&Bidir_Type::front), "front");
|
||||
m->add(fun(&Bidir_Type::pop_back), "pop_back");
|
||||
m->add(fun(&Bidir_Type::back), "back");
|
||||
|
||||
return m;
|
||||
}
|
||||
m.add(fun(&Bidir_Type::empty), "empty");
|
||||
m.add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||
m.add(fun(&Bidir_Type::front), "front");
|
||||
m.add(fun(&Bidir_Type::pop_back), "pop_back");
|
||||
m.add(fun(&Bidir_Type::back), "back");
|
||||
}
|
||||
|
||||
|
||||
/// Algorithm for inserting at a specific position into a container
|
||||
@@ -230,10 +228,16 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void input_range_type(const std::string &type, Module& m)
|
||||
{
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
|
||||
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr input_range_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
input_range_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -241,33 +245,83 @@ namespace chaiscript
|
||||
/// Add random_access_container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
void random_access_container_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||
//to throw an exception in an out of bounds condition.
|
||||
m->add(
|
||||
m.add(
|
||||
fun(
|
||||
[](ContainerType &c, int index) -> typename ContainerType::reference {
|
||||
return c.at(index);
|
||||
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
|
||||
/// during dispatch. reevaluate
|
||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||
}), "[]");
|
||||
|
||||
m->add(
|
||||
m.add(
|
||||
fun(
|
||||
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||
return c.at(index);
|
||||
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
|
||||
/// during dispatch. reevaluate
|
||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||
}), "[]");
|
||||
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr random_access_container_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
random_access_container_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Add assignable concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void assignable_type(const std::string &type, Module& m)
|
||||
{
|
||||
copy_constructor<ContainerType>(type, m);
|
||||
operators::assign<ContainerType>(m);
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr assignable_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
assignable_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add container resize concept to the given ContainerType
|
||||
/// http://www.cplusplus.com/reference/stl/
|
||||
template<typename ContainerType>
|
||||
void resizable_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize");
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr resizable_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
resizable_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add container reserve concept to the given ContainerType
|
||||
/// http://www.cplusplus.com/reference/stl/
|
||||
template<typename ContainerType>
|
||||
void reservable_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
|
||||
m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr reservable_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
reservable_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -275,33 +329,44 @@ namespace chaiscript
|
||||
/// Add container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Container.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
void container_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m->add(fun([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m->add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
return m;
|
||||
m.add(fun([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
}
|
||||
template <typename ContainerType>
|
||||
ModulePtr container_type(const std::string& type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
container_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add default constructable concept to the given Type
|
||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
template<typename Type>
|
||||
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void default_constructible_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(constructor<Type ()>(), type);
|
||||
m.add(constructor<Type ()>(), type);
|
||||
}
|
||||
template <typename Type>
|
||||
ModulePtr default_constructible_type(const std::string& type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
default_constructible_type<Type>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Add sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
void sequence_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m->add(fun(&detail::insert_at<ContainerType>),
|
||||
m.add(fun(&detail::insert_at<ContainerType>),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref_at";
|
||||
@@ -310,31 +375,40 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||
|
||||
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||
}
|
||||
template <typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
sequence_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add back insertion sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void back_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
m.add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
|
||||
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m->eval(
|
||||
m.eval(
|
||||
"# Pushes the second value onto the container while making a clone of the value\n"
|
||||
"def push_back(" + type + " container, x)\n"
|
||||
"{ \n"
|
||||
" container.push_back_ref(clone(x)) \n"
|
||||
" if (x.is_var_return_value()) {\n"
|
||||
" x.reset_var_return_value() \n"
|
||||
" container.push_back_ref(x) \n"
|
||||
" } else { \n"
|
||||
" container.push_back_ref(clone(x)); \n"
|
||||
" }\n"
|
||||
"} \n"
|
||||
);
|
||||
|
||||
@@ -344,7 +418,13 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m->add(fun(&ContainerType::pop_back), "pop_back");
|
||||
m.add(fun(&ContainerType::pop_back), "pop_back");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr back_insertion_sequence_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
back_insertion_sequence_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -353,24 +433,29 @@ namespace chaiscript
|
||||
/// Front insertion sequence
|
||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void front_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
||||
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*pop_ptr)();
|
||||
|
||||
m->add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
m.add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
|
||||
m.add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
|
||||
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m->eval(
|
||||
m.eval(
|
||||
"# Pushes the second value onto the front of container while making a clone of the value\n"
|
||||
"def push_front(" + type + " container, x)\n"
|
||||
"{ \n"
|
||||
" container.push_front_ref(clone(x)) \n"
|
||||
" if (x.is_var_return_value()) {\n"
|
||||
" x.reset_var_return_value() \n"
|
||||
" container.push_front_ref(x) \n"
|
||||
" } else { \n"
|
||||
" container.push_front_ref(clone(x)); \n"
|
||||
" }\n"
|
||||
"} \n"
|
||||
);
|
||||
return "push_front_ref";
|
||||
@@ -379,7 +464,13 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m->add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
|
||||
m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
front_insertion_sequence_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -387,20 +478,25 @@ namespace chaiscript
|
||||
/// bootstrap a given PairType
|
||||
/// http://www.sgi.com/tech/stl/pair.html
|
||||
template<typename PairType>
|
||||
ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void pair_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<PairType>(), type);
|
||||
m.add(user_type<PairType>(), type);
|
||||
|
||||
|
||||
typename PairType::first_type PairType::* f = &PairType::first;
|
||||
typename PairType::second_type PairType::* s = &PairType::second;
|
||||
|
||||
m->add(fun(f), "first");
|
||||
m->add(fun(s), "second");
|
||||
m.add(fun(f), "first");
|
||||
m.add(fun(s), "second");
|
||||
|
||||
basic_constructors<PairType>(type, m);
|
||||
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||
|
||||
m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||
}
|
||||
template<typename PairType>
|
||||
ModulePtr pair_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
pair_type<PairType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -410,10 +506,15 @@ namespace chaiscript
|
||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||
|
||||
template<typename ContainerType>
|
||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void pair_associative_container_type(const std::string &type, Module& m)
|
||||
{
|
||||
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr pair_associative_container_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
pair_associative_container_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -421,17 +522,17 @@ namespace chaiscript
|
||||
/// Add unique associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
void unique_associative_container_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m->add(fun(detail::count<ContainerType>), "count");
|
||||
m.add(fun(detail::count<ContainerType>), "count");
|
||||
|
||||
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
|
||||
|
||||
m->add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
|
||||
m->add(fun(&detail::insert<ContainerType>), "insert");
|
||||
m.add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
m->add(fun(&detail::insert_ref<ContainerType>),
|
||||
m.add(fun(&detail::insert_ref<ContainerType>),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref";
|
||||
@@ -439,8 +540,12 @@ namespace chaiscript
|
||||
return "insert";
|
||||
}
|
||||
}());
|
||||
|
||||
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
unique_associative_container_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -448,17 +553,41 @@ namespace chaiscript
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename MapType>
|
||||
ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void map_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<MapType>(), type);
|
||||
m.add(user_type<MapType>(), type);
|
||||
|
||||
typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
|
||||
typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const;
|
||||
|
||||
m->add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||
m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||
|
||||
m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
|
||||
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||
m.add(fun(static_cast<elem_access>(&MapType::at)), "at");
|
||||
m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||
|
||||
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
|
||||
{
|
||||
m.eval(R"(
|
||||
def Map::`==`(Map rhs) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
} else {
|
||||
auto r1 = range(this);
|
||||
auto r2 = range(rhs);
|
||||
while (!r1.empty())
|
||||
{
|
||||
if (!eq(r1.front().first, r2.front().first) || !eq(r1.front().second, r2.front().second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
r1.pop_front();
|
||||
r2.pop_front();
|
||||
}
|
||||
true;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
}
|
||||
|
||||
container_type<MapType>(type, m);
|
||||
default_constructible_type<MapType>(type, m);
|
||||
@@ -466,7 +595,12 @@ namespace chaiscript
|
||||
unique_associative_container_type<MapType>(type, m);
|
||||
pair_associative_container_type<MapType>(type, m);
|
||||
input_range_type<MapType>(type, m);
|
||||
|
||||
}
|
||||
template<typename MapType>
|
||||
ModulePtr map_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
map_type<MapType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -474,18 +608,24 @@ namespace chaiscript
|
||||
/// hopefully working List type
|
||||
/// http://www.sgi.com/tech/stl/List.html
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void list_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<ListType>(), type);
|
||||
m.add(user_type<ListType>(), type);
|
||||
|
||||
front_insertion_sequence_type<ListType>(type, m);
|
||||
back_insertion_sequence_type<ListType>(type, m);
|
||||
sequence_type<ListType>(type, m);
|
||||
resizable_type<ListType>(type, m);
|
||||
container_type<ListType>(type, m);
|
||||
default_constructible_type<ListType>(type, m);
|
||||
assignable_type<ListType>(type, m);
|
||||
input_range_type<ListType>(type, m);
|
||||
|
||||
}
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
list_type<ListType>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -493,20 +633,22 @@ namespace chaiscript
|
||||
/// Create a vector type with associated concepts
|
||||
/// http://www.sgi.com/tech/stl/Vector.html
|
||||
template<typename VectorType>
|
||||
ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void vector_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<VectorType>(), type);
|
||||
m.add(user_type<VectorType>(), type);
|
||||
|
||||
typedef typename VectorType::reference (VectorType::*frontptr)();
|
||||
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
|
||||
|
||||
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||
m.add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||
m.add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||
|
||||
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
sequence_type<VectorType>(type, m);
|
||||
random_access_container_type<VectorType>(type, m);
|
||||
resizable_type<VectorType>(type, m);
|
||||
reservable_type<VectorType>(type, m);
|
||||
container_type<VectorType>(type, m);
|
||||
default_constructible_type<VectorType>(type, m);
|
||||
assignable_type<VectorType>(type, m);
|
||||
@@ -514,8 +656,8 @@ namespace chaiscript
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
m->eval(R"(
|
||||
def Vector::`==`(rhs) : type_match(rhs, this) {
|
||||
m.eval(R"(
|
||||
def Vector::`==`(Vector rhs) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -535,16 +677,21 @@ namespace chaiscript
|
||||
} )"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
template<typename VectorType>
|
||||
ModulePtr vector_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
vector_type<VectorType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// Add a String container
|
||||
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||
template<typename String>
|
||||
ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void string_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<String>(), type);
|
||||
m.add(user_type<String>(), type);
|
||||
operators::addition<String>(m);
|
||||
operators::assign_sum<String>(m);
|
||||
opers_comparison<String>(m);
|
||||
@@ -556,7 +703,7 @@ namespace chaiscript
|
||||
input_range_type<String>(type, m);
|
||||
|
||||
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||
m->add(fun(&String::push_back),
|
||||
m.add(fun(&String::push_back),
|
||||
[]()->std::string{
|
||||
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
||||
return "push_back_ref";
|
||||
@@ -566,21 +713,26 @@ namespace chaiscript
|
||||
}());
|
||||
|
||||
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
|
||||
|
||||
m->add(fun([](String *s) { s->clear(); } ), "clear");
|
||||
m->add(fun([](const String *s) { return s->empty(); } ), "empty");
|
||||
m->add(fun([](const String *s) { return s->size(); } ), "size");
|
||||
|
||||
m->add(fun([](const String *s) { return s->c_str(); } ), "c_str");
|
||||
m->add(fun([](const String *s) { return s->data(); } ), "data");
|
||||
m->add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
|
||||
m.add(fun([](String *s) { s->clear(); } ), "clear");
|
||||
m.add(fun([](const String *s) { return s->empty(); } ), "empty");
|
||||
m.add(fun([](const String *s) { return s->size(); } ), "size");
|
||||
|
||||
m.add(fun([](const String *s) { return s->c_str(); } ), "c_str");
|
||||
m.add(fun([](const String *s) { return s->data(); } ), "data");
|
||||
m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
|
||||
}
|
||||
template<typename String>
|
||||
ModulePtr string_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
string_type<String>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -589,14 +741,19 @@ namespace chaiscript
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename FutureType>
|
||||
ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
void future_type(const std::string &type, Module& m)
|
||||
{
|
||||
m->add(user_type<FutureType>(), type);
|
||||
|
||||
m->add(fun([](const FutureType &t) { return t.valid(); }), "valid");
|
||||
m->add(fun(&FutureType::get), "get");
|
||||
m->add(fun(&FutureType::wait), "wait");
|
||||
m.add(user_type<FutureType>(), type);
|
||||
|
||||
m.add(fun([](const FutureType &t) { return t.valid(); }), "valid");
|
||||
m.add(fun(&FutureType::get), "get");
|
||||
m.add(fun(&FutureType::wait), "wait");
|
||||
}
|
||||
template<typename FutureType>
|
||||
ModulePtr future_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
future_type<FutureType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
@@ -69,34 +69,32 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
|
||||
{
|
||||
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !t_conversions->convertable_type<Type>())) {
|
||||
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
return(detail::Cast_Helper<Type>::cast(bv, t_conversions));
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
||||
if (t_conversions && (*t_conversions)->convertable_type<Type>())
|
||||
{
|
||||
try {
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
|
||||
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
} catch (...) {
|
||||
try {
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
|
||||
// try going the other way - down the inheritance graph
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
|
||||
// try going the other way
|
||||
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it's not polymorphic, just throw the error, don't waste the time on the
|
||||
// If it's not convertable, just throw the error, don't waste the time on the
|
||||
// attempted dynamic_cast
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Type_Conversions;
|
||||
class Type_Conversions_State;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -29,21 +29,50 @@ namespace chaiscript
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
||||
if (ob.get_type_info() == ti) {
|
||||
return ptr;
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
|
||||
if (!ob.is_const() && ob.get_type_info() == ti) {
|
||||
return ptr;
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
||||
if (ob.get_type_info().bare_equal_type_info(ti)) {
|
||||
return throw_if_null(ptr);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *verify_type(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
|
||||
if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) {
|
||||
return throw_if_null(ptr);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic Cast_Helper_Inner, for casting to any type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
auto p = throw_if_null(ob.get_const_ptr());
|
||||
return std::cref(*static_cast<const Result *>(p));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,26 +81,14 @@ namespace chaiscript
|
||||
{
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -79,15 +96,30 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
|
||||
{
|
||||
return static_cast<Result *>(throw_if_null(ob.get_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -97,16 +129,9 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,9 +139,7 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
typedef std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
@@ -126,9 +149,7 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
typedef std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@@ -150,6 +171,18 @@ namespace chaiscript
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> &>
|
||||
{
|
||||
static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
|
||||
return ob.pointer_sentinel(res);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
@@ -166,9 +199,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
typedef const Boxed_Value & Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
@@ -178,11 +209,9 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value &>
|
||||
{
|
||||
typedef Boxed_Value& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return const_cast<Boxed_Value &>(ob);
|
||||
return std::ref(const_cast<Boxed_Value &>(ob));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -234,11 +263,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Cast_Helper
|
||||
{
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||
@@ -30,7 +30,7 @@ namespace chaiscript
|
||||
{
|
||||
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||
arithmetic_error(const arithmetic_error &) = default;
|
||||
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~arithmetic_error() noexcept = default;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -43,16 +43,19 @@ namespace chaiscript
|
||||
// this is OK, so we're disabling size/and sign type warnings
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244 4018 4389 4146 4365 4267)
|
||||
#pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#endif
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
@@ -88,7 +91,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
static CHAISCRIPT_CONSTEXPR Common_Types get_common_type(size_t t_size, bool t_signed)
|
||||
static constexpr Common_Types get_common_type(size_t t_size, bool t_signed)
|
||||
{
|
||||
return (t_size == 1 && t_signed)?(Common_Types::t_int8)
|
||||
:(t_size == 1)?(Common_Types::t_uint8)
|
||||
@@ -100,6 +103,7 @@ namespace chaiscript
|
||||
:(Common_Types::t_uint64);
|
||||
}
|
||||
|
||||
|
||||
static Common_Types get_common_type(const Boxed_Value &t_bv)
|
||||
{
|
||||
const Type_Info &inp_ = t_bv.get_type_info();
|
||||
@@ -120,8 +124,12 @@ namespace chaiscript
|
||||
return get_common_type(sizeof(unsigned int), false);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return get_common_type(sizeof(long), true);
|
||||
} else if (inp_ == typeid(long long)) {
|
||||
return get_common_type(sizeof(long long), true);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return get_common_type(sizeof(unsigned long), false);
|
||||
} else if (inp_ == typeid(unsigned long long)) {
|
||||
return get_common_type(sizeof(unsigned long long), false);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return Common_Types::t_int8;
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
@@ -154,17 +162,17 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::equals:
|
||||
case Operators::Opers::equals:
|
||||
return const_var(t == u);
|
||||
case Operators::less_than:
|
||||
case Operators::Opers::less_than:
|
||||
return const_var(t < u);
|
||||
case Operators::greater_than:
|
||||
case Operators::Opers::greater_than:
|
||||
return const_var(t > u);
|
||||
case Operators::less_than_equal:
|
||||
case Operators::Opers::less_than_equal:
|
||||
return const_var(t <= u);
|
||||
case Operators::greater_than_equal:
|
||||
case Operators::Opers::greater_than_equal:
|
||||
return const_var(t >= u);
|
||||
case Operators::not_equal:
|
||||
case Operators::Opers::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -176,10 +184,10 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::pre_increment:
|
||||
case Operators::Opers::pre_increment:
|
||||
++t;
|
||||
break;
|
||||
case Operators::pre_decrement:
|
||||
case Operators::Opers::pre_decrement:
|
||||
--t;
|
||||
break;
|
||||
default:
|
||||
@@ -194,20 +202,20 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::assign:
|
||||
case Operators::Opers::assign:
|
||||
t = u;
|
||||
break;
|
||||
case Operators::assign_product:
|
||||
case Operators::Opers::assign_product:
|
||||
t *= u;
|
||||
break;
|
||||
case Operators::assign_sum:
|
||||
case Operators::Opers::assign_sum:
|
||||
t += u;
|
||||
break;
|
||||
case Operators::assign_quotient:
|
||||
case Operators::Opers::assign_quotient:
|
||||
check_divide_by_zero(u);
|
||||
t /= u;
|
||||
break;
|
||||
case Operators::assign_difference:
|
||||
case Operators::Opers::assign_difference:
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
@@ -222,23 +230,23 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::assign_bitwise_and:
|
||||
case Operators::Opers::assign_bitwise_and:
|
||||
t &= u;
|
||||
break;
|
||||
case Operators::assign_bitwise_or:
|
||||
case Operators::Opers::assign_bitwise_or:
|
||||
t |= u;
|
||||
break;
|
||||
case Operators::assign_shift_left:
|
||||
case Operators::Opers::assign_shift_left:
|
||||
t <<= u;
|
||||
break;
|
||||
case Operators::assign_shift_right:
|
||||
case Operators::Opers::assign_shift_right:
|
||||
t >>= u;
|
||||
break;
|
||||
case Operators::assign_remainder:
|
||||
case Operators::Opers::assign_remainder:
|
||||
check_divide_by_zero(u);
|
||||
t %= u;
|
||||
break;
|
||||
case Operators::assign_bitwise_xor:
|
||||
case Operators::Opers::assign_bitwise_xor:
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
@@ -252,7 +260,7 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::bitwise_complement:
|
||||
case Operators::Opers::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -264,18 +272,18 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::shift_left:
|
||||
case Operators::Opers::shift_left:
|
||||
return const_var(t << u);
|
||||
case Operators::shift_right:
|
||||
case Operators::Opers::shift_right:
|
||||
return const_var(t >> u);
|
||||
case Operators::remainder:
|
||||
case Operators::Opers::remainder:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t % u);
|
||||
case Operators::bitwise_and:
|
||||
case Operators::Opers::bitwise_and:
|
||||
return const_var(t & u);
|
||||
case Operators::bitwise_or:
|
||||
case Operators::Opers::bitwise_or:
|
||||
return const_var(t | u);
|
||||
case Operators::bitwise_xor:
|
||||
case Operators::Opers::bitwise_xor:
|
||||
return const_var(t ^ u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -287,9 +295,9 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::unary_minus:
|
||||
case Operators::Opers::unary_minus:
|
||||
return const_var(-t);
|
||||
case Operators::unary_plus:
|
||||
case Operators::Opers::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -301,14 +309,14 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::sum:
|
||||
case Operators::Opers::sum:
|
||||
return const_var(t + u);
|
||||
case Operators::quotient:
|
||||
case Operators::Opers::quotient:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t / u);
|
||||
case Operators::product:
|
||||
case Operators::Opers::product:
|
||||
return const_var(t * u);
|
||||
case Operators::difference:
|
||||
case Operators::Opers::difference:
|
||||
return const_var(t - u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -320,16 +328,16 @@ namespace chaiscript
|
||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
|
||||
{
|
||||
typedef typename std::common_type<LHS, RHS>::type common_type;
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
|
||||
{
|
||||
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_int_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
|
||||
return const_binary_int_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -341,12 +349,12 @@ namespace chaiscript
|
||||
-> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
|
||||
{
|
||||
typedef typename std::common_type<LHS, RHS>::type common_type;
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
|
||||
{
|
||||
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -358,11 +366,11 @@ namespace chaiscript
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value, Boxed_Value>::type
|
||||
{
|
||||
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
|
||||
return const_unary_int_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -373,9 +381,9 @@ namespace chaiscript
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
-> typename std::enable_if<std::is_floating_point<LHS>::value, Boxed_Value>::type
|
||||
{
|
||||
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -494,18 +502,15 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Boxed_Number(Boxed_Value v)
|
||||
explicit Boxed_Number(Boxed_Value v)
|
||||
: bv(std::move(v))
|
||||
{
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
Boxed_Number(const Boxed_Number &) = default;
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Boxed_Number(Boxed_Number &&) = default;
|
||||
Boxed_Number& operator=(Boxed_Number &&) = default;
|
||||
#endif
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
: bv(Boxed_Value(t))
|
||||
@@ -513,6 +518,21 @@ namespace chaiscript
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
static bool is_floating_point(const Boxed_Value &t_bv)
|
||||
{
|
||||
const Type_Info &inp_ = t_bv.get_type_info();
|
||||
|
||||
if (inp_ == typeid(double)) {
|
||||
return true;
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return true;
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Number get_as(const Type_Info &inp_) const
|
||||
{
|
||||
if (inp_.bare_equal_type_info(typeid(int))) {
|
||||
@@ -537,8 +557,12 @@ namespace chaiscript
|
||||
return Boxed_Number(get_as<unsigned int>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long))) {
|
||||
return Boxed_Number(get_as<long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long long))) {
|
||||
return Boxed_Number(get_as<long long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
|
||||
return Boxed_Number(get_as<unsigned long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned long long))) {
|
||||
return Boxed_Number(get_as<unsigned long long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
|
||||
return Boxed_Number(get_as<int8_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {
|
||||
@@ -621,71 +645,6 @@ namespace chaiscript
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
bool operator==(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator<(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator>(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator>=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator<=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator!=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
Boxed_Number operator--()
|
||||
{
|
||||
return oper(Operators::pre_decrement, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator++()
|
||||
{
|
||||
return oper(Operators::pre_increment, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator+(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::sum, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator+() const
|
||||
{
|
||||
return oper(Operators::unary_plus, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator-() const
|
||||
{
|
||||
return oper(Operators::unary_minus, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator-(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::difference, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator&=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static void validate_boxed_number(const Boxed_Value &v)
|
||||
{
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
@@ -700,266 +659,165 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress operatorEq
|
||||
Boxed_Number operator=(const Boxed_Value &v)
|
||||
{
|
||||
validate_boxed_number(v);
|
||||
bv = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// cppcheck-suppress operatorEq
|
||||
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::assign, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator|=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator^=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator%=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator&(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator~() const
|
||||
{
|
||||
return oper(Operators::bitwise_complement, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator^(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator|(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator*=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_product, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator/=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator+=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator-=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator/(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::quotient, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::shift_left, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator*(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::product, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator%(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::remainder, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::shift_right, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
|
||||
{
|
||||
return oper(Operators::pre_decrement, t_lhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number pre_increment(Boxed_Number t_lhs)
|
||||
{
|
||||
return oper(Operators::pre_increment, t_lhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return oper(Operators::unary_plus, t_lhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return oper(Operators::unary_minus, t_lhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
|
||||
return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
|
||||
@@ -985,9 +843,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_Number>
|
||||
{
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
@@ -62,10 +62,8 @@ namespace chaiscript
|
||||
|
||||
Data(const Data &) = delete;
|
||||
|
||||
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
|
||||
Data(Data &&) = default;
|
||||
Data &operator=(Data &&rhs) = default;
|
||||
#endif
|
||||
|
||||
|
||||
Type_Info m_type_info;
|
||||
@@ -189,11 +187,8 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Boxed_Value(Boxed_Value&&) = default;
|
||||
Boxed_Value& operator=(Boxed_Value&&) = default;
|
||||
#endif
|
||||
|
||||
Boxed_Value(const Boxed_Value&) = default;
|
||||
Boxed_Value& operator=(const Boxed_Value&) = default;
|
||||
|
||||
@@ -210,63 +205,98 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
|
||||
const Type_Info &get_type_info() const noexcept
|
||||
{
|
||||
return m_data->m_type_info;
|
||||
}
|
||||
|
||||
/// return true if the object is uninitialized
|
||||
bool is_undef() const CHAISCRIPT_NOEXCEPT
|
||||
bool is_undef() const noexcept
|
||||
{
|
||||
return m_data->m_type_info.is_undef();
|
||||
}
|
||||
|
||||
bool is_const() const CHAISCRIPT_NOEXCEPT
|
||||
bool is_const() const noexcept
|
||||
{
|
||||
return m_data->m_type_info.is_const();
|
||||
}
|
||||
|
||||
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
bool is_type(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
|
||||
bool is_null() const CHAISCRIPT_NOEXCEPT
|
||||
|
||||
template<typename T>
|
||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const
|
||||
{
|
||||
struct Sentinel {
|
||||
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
|
||||
: m_ptr(t_ptr), m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
~Sentinel()
|
||||
{
|
||||
// save new pointer data
|
||||
m_data.get().m_data_ptr = m_ptr.get().get();
|
||||
m_data.get().m_const_data_ptr = m_ptr.get().get();
|
||||
}
|
||||
|
||||
Sentinel& operator=(Sentinel&&s) = default;
|
||||
Sentinel(Sentinel &&s) = default;
|
||||
|
||||
operator std::shared_ptr<T>&() const
|
||||
{
|
||||
return m_ptr.get();
|
||||
}
|
||||
|
||||
Sentinel &operator=(const Sentinel &) = delete;
|
||||
Sentinel(Sentinel&) = delete;
|
||||
|
||||
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
||||
std::reference_wrapper<Data> m_data;
|
||||
};
|
||||
|
||||
return Sentinel(ptr, *(m_data.get()));
|
||||
}
|
||||
|
||||
bool is_null() const noexcept
|
||||
{
|
||||
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
||||
}
|
||||
|
||||
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
|
||||
const chaiscript::detail::Any & get() const noexcept
|
||||
{
|
||||
return m_data->m_obj;
|
||||
}
|
||||
|
||||
bool is_ref() const CHAISCRIPT_NOEXCEPT
|
||||
bool is_ref() const noexcept
|
||||
{
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
|
||||
bool is_return_value() const CHAISCRIPT_NOEXCEPT
|
||||
bool is_return_value() const noexcept
|
||||
{
|
||||
return m_data->m_return_value;
|
||||
}
|
||||
|
||||
void reset_return_value() const CHAISCRIPT_NOEXCEPT
|
||||
void reset_return_value() const noexcept
|
||||
{
|
||||
m_data->m_return_value = false;
|
||||
}
|
||||
|
||||
bool is_pointer() const CHAISCRIPT_NOEXCEPT
|
||||
bool is_pointer() const noexcept
|
||||
{
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
void *get_ptr() const noexcept
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
}
|
||||
|
||||
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
const void *get_const_ptr() const noexcept
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
}
|
||||
@@ -297,9 +327,16 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Boxed_Value &clone_attrs(const Boxed_Value &t_obj)
|
||||
{
|
||||
copy_attrs(t_obj);
|
||||
reset_return_value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// \returns true if the two Boxed_Values share the same internal type
|
||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
|
||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
@@ -330,9 +367,9 @@ namespace chaiscript
|
||||
///
|
||||
/// @sa @ref adding_objects
|
||||
template<typename T>
|
||||
Boxed_Value var(T t)
|
||||
Boxed_Value var(T &&t)
|
||||
{
|
||||
return Boxed_Value(t);
|
||||
return Boxed_Value(std::forward<T>(t));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -409,10 +446,14 @@ namespace chaiscript
|
||||
return detail::const_var_impl(t);
|
||||
}
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
|
||||
inline Boxed_Value void_var() {
|
||||
static const auto v = Boxed_Value(Boxed_Value::Void_Type());
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Boxed_Value const_var(bool b) {
|
||||
static auto t = detail::const_var_impl(true);
|
||||
static auto f = detail::const_var_impl(false);
|
||||
static const auto t = detail::const_var_impl(true);
|
||||
static const auto f = detail::const_var_impl(false);
|
||||
|
||||
if (b) {
|
||||
return t;
|
||||
@@ -420,7 +461,6 @@ namespace chaiscript
|
||||
return f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
|
||||
@@ -61,6 +61,17 @@ namespace chaiscript {
|
||||
Ret (Class::*m_func)(Param...);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Arity
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
struct Arity<Ret (Params...)>
|
||||
{
|
||||
static const size_t arity = sizeof...(Params);
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Function_Signature
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
@@ -24,16 +24,36 @@ namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
struct option_explicit_set : std::runtime_error {
|
||||
option_explicit_set(const std::string &t_param_name)
|
||||
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
option_explicit_set(const option_explicit_set &) = default;
|
||||
|
||||
virtual ~option_explicit_set() noexcept = default;
|
||||
};
|
||||
|
||||
class Dynamic_Object
|
||||
{
|
||||
public:
|
||||
Dynamic_Object(std::string t_type_name)
|
||||
: m_type_name(std::move(t_type_name))
|
||||
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
|
||||
{
|
||||
}
|
||||
|
||||
Dynamic_Object() : m_type_name("")
|
||||
Dynamic_Object() = default;
|
||||
|
||||
bool is_explicit() const
|
||||
{
|
||||
return m_option_explicit;
|
||||
}
|
||||
|
||||
void set_explicit(const bool t_explicit)
|
||||
{
|
||||
m_option_explicit = t_explicit;
|
||||
}
|
||||
|
||||
std::string get_type_name() const
|
||||
@@ -41,6 +61,16 @@ namespace chaiscript
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
const Boxed_Value &operator[](const std::string &t_attr_name) const
|
||||
{
|
||||
return get_attr(t_attr_name);
|
||||
}
|
||||
|
||||
Boxed_Value &operator[](const std::string &t_attr_name)
|
||||
{
|
||||
return get_attr(t_attr_name);
|
||||
}
|
||||
|
||||
const Boxed_Value &get_attr(const std::string &t_attr_name) const
|
||||
{
|
||||
auto a = m_attrs.find(t_attr_name);
|
||||
@@ -52,6 +82,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
bool has_attr(const std::string &t_attr_name) const {
|
||||
return m_attrs.find(t_attr_name) != m_attrs.end();
|
||||
}
|
||||
|
||||
Boxed_Value &get_attr(const std::string &t_attr_name)
|
||||
{
|
||||
return m_attrs[t_attr_name];
|
||||
@@ -59,22 +93,30 @@ namespace chaiscript
|
||||
|
||||
Boxed_Value &method_missing(const std::string &t_method_name)
|
||||
{
|
||||
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
|
||||
throw option_explicit_set(t_method_name);
|
||||
}
|
||||
|
||||
return get_attr(t_method_name);
|
||||
}
|
||||
|
||||
const Boxed_Value &method_missing(const std::string &t_method_name) const
|
||||
{
|
||||
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
|
||||
throw option_explicit_set(t_method_name);
|
||||
}
|
||||
|
||||
return get_attr(t_method_name);
|
||||
}
|
||||
|
||||
|
||||
std::map<std::string, Boxed_Value> get_attrs() const
|
||||
{
|
||||
return m_attrs;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_type_name;
|
||||
const std::string m_type_name = "";
|
||||
bool m_option_explicit = false;
|
||||
|
||||
std::map<std::string, Boxed_Value> m_attrs;
|
||||
};
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
||||
@@ -39,7 +39,7 @@ namespace chaiscript
|
||||
/// A Proxy_Function implementation designed for calling a function
|
||||
/// that is automatically guarded based on the first param based on the
|
||||
/// param's type name
|
||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
||||
class Dynamic_Object_Function final : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
@@ -67,12 +67,11 @@ namespace chaiscript
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
bool operator==(const Proxy_Function_Base &f) const override
|
||||
{
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
{
|
||||
@@ -82,9 +81,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
|
||||
bool is_attribute_function() const override { return m_is_attribute; }
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@@ -94,19 +93,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
std::vector<Const_Proxy_Function> get_contained_functions() const override
|
||||
{
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@@ -116,7 +109,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
@@ -134,7 +127,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
@@ -156,7 +149,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 &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
@@ -170,9 +163,7 @@ namespace chaiscript
|
||||
Proxy_Function m_func;
|
||||
std::unique_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
bool m_is_attribute;
|
||||
|
||||
|
||||
const bool m_is_attribute;
|
||||
};
|
||||
|
||||
|
||||
@@ -182,7 +173,7 @@ namespace chaiscript
|
||||
* that is automatically guarded based on the first param based on the
|
||||
* param's type name
|
||||
*/
|
||||
class Dynamic_Object_Constructor : public Proxy_Function_Base
|
||||
class Dynamic_Object_Constructor final : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Constructor(
|
||||
@@ -208,31 +199,24 @@ namespace chaiscript
|
||||
return std::vector<Type_Info>(begin, end);
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Constructor() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
bool operator==(const Proxy_Function_Base &f) const override
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
|
||||
return m_func->call_match(new_vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
auto bv = var(Dynamic_Object(m_type_name));
|
||||
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
|
||||
@@ -242,8 +226,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
const std::string m_type_name;
|
||||
const Proxy_Function m_func;
|
||||
|
||||
};
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
@@ -23,80 +23,26 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this a variadic template
|
||||
struct Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||
|
||||
virtual ~Exception_Handler_Base() {}
|
||||
virtual ~Exception_Handler_Base() = default;
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||
{
|
||||
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1>
|
||||
struct Exception_Handler_Impl1 : Exception_Handler_Base
|
||||
template<typename ... T>
|
||||
struct Exception_Handler_Impl : Exception_Handler_Base
|
||||
{
|
||||
virtual ~Exception_Handler_Impl1() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
|
||||
{
|
||||
throw_type<T1>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Exception_Handler_Impl2 : Exception_Handler_Base
|
||||
{
|
||||
virtual ~Exception_Handler_Impl2() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
struct Exception_Handler_Impl3 : Exception_Handler_Base
|
||||
{
|
||||
virtual ~Exception_Handler_Impl3() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
throw_type<T3>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
struct Exception_Handler_Impl4 : Exception_Handler_Base
|
||||
{
|
||||
virtual ~Exception_Handler_Impl4() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
throw_type<T3>(bv, t_engine);
|
||||
throw_type<T4>(bv, t_engine);
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct Exception_Handler_Impl5 : Exception_Handler_Base
|
||||
{
|
||||
virtual ~Exception_Handler_Impl5() {}
|
||||
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw_type<T1>(bv, t_engine);
|
||||
throw_type<T2>(bv, t_engine);
|
||||
throw_type<T3>(bv, t_engine);
|
||||
throw_type<T4>(bv, t_engine);
|
||||
throw_type<T5>(bv, t_engine);
|
||||
(void)std::initializer_list<int>{(throw_type<T>(bv, t_engine), 0)...};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -155,42 +101,10 @@ namespace chaiscript
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1>
|
||||
template<typename ... T>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2, typename T3>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
|
||||
}
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
Exception_Handler exception_specification()
|
||||
{
|
||||
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
|
||||
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
@@ -14,10 +14,11 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "function_call_detail.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "callable_traits.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Type_Conversions;
|
||||
class Type_Conversions_State;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
@@ -34,9 +35,17 @@ namespace chaiscript
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] funcs the set of functions to dispatch on.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
||||
[](const Const_Proxy_Function &f) {
|
||||
return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
|
||||
});
|
||||
|
||||
if (!has_arity_match) {
|
||||
throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
|
||||
}
|
||||
|
||||
FunctionType *p=nullptr;
|
||||
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||
}
|
||||
@@ -53,8 +62,7 @@ namespace chaiscript
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] func A function to execute.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
||||
std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
|
||||
}
|
||||
@@ -62,8 +70,7 @@ namespace chaiscript
|
||||
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
/// and creating a typesafe C++ function caller from it.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
|
||||
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||
}
|
||||
@@ -74,9 +81,7 @@ namespace chaiscript
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -91,9 +96,7 @@ namespace chaiscript
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -108,9 +111,7 @@ namespace chaiscript
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
@@ -31,9 +31,15 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions);
|
||||
if (t_conversions) {
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,9 +50,15 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<Ret, true>
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as<Ret>();
|
||||
if (t_conversions) {
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,9 +70,15 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<void, false>
|
||||
{
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions());
|
||||
if (t_conversions) {
|
||||
dispatch::dispatch(t_funcs, params, *t_conversions);
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
dispatch::dispatch(t_funcs, params, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -79,11 +97,18 @@ namespace chaiscript
|
||||
template<typename ... P>
|
||||
Ret operator()(P&& ... param)
|
||||
{
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, m_conversions
|
||||
|
||||
);
|
||||
if (m_conversions) {
|
||||
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, &state
|
||||
);
|
||||
} else {
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -114,7 +139,7 @@ namespace chaiscript
|
||||
|
||||
/// \todo what happens if t_conversions is deleted out from under us?!
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
/*
|
||||
if (funcs.size() == 1)
|
||||
@@ -132,7 +157,7 @@ namespace chaiscript
|
||||
}
|
||||
*/
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
@@ -59,13 +59,8 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::function<Ret>>
|
||||
struct Handle_Return<std::function<Ret>> : Handle_Return<const std::function<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
@@ -79,23 +74,13 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
|
||||
struct Handle_Return<std::shared_ptr<std::function<Ret>>> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
@@ -115,6 +100,24 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret *&>
|
||||
{
|
||||
static Boxed_Value handle(Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *&>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret *>
|
||||
{
|
||||
@@ -143,21 +146,13 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> >
|
||||
struct Handle_Return<std::shared_ptr<Ret>> : Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<Ret> &>
|
||||
struct Handle_Return<const std::shared_ptr<Ret> &> : Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
@@ -169,10 +164,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret>
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret &>
|
||||
{
|
||||
@@ -180,16 +180,8 @@ namespace chaiscript
|
||||
{
|
||||
return Boxed_Value(std::ref(r));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value>
|
||||
{
|
||||
@@ -199,40 +191,19 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Value>
|
||||
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value &>
|
||||
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Value &>
|
||||
struct Handle_Return<const Boxed_Value &> : Handle_Return<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -247,16 +218,9 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Number>
|
||||
struct Handle_Return<const Boxed_Number> : Handle_Return<Boxed_Number>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Number &r)
|
||||
{
|
||||
return r.bv;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -268,7 +232,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle()
|
||||
{
|
||||
return Boxed_Value(Boxed_Value::Void_Type());
|
||||
return void_var();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
@@ -16,447 +16,202 @@ namespace chaiscript
|
||||
{
|
||||
namespace operators
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign(L l, R r) -> L&
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_xor(L l, R r) -> decltype((l^=r))
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_difference(L l, R r) -> decltype(( l -= r))
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_product(L l, R r) -> decltype(( l *= r ))
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign_sum(L l, R r) -> L&
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto prefix_decrement(L l) -> decltype(( --l ))
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto prefix_increment(L l) -> decltype(( ++l ))
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto equal(L l, R r) -> decltype(( l == r ))
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto greater_than(L l, R r) -> decltype(( l > r ))
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto less_than(L l, R r) -> decltype(( l < r ))
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto logical_compliment(L l) -> decltype(( !l ))
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto not_equal(L l, R r) -> decltype(( l != r ))
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto addition(L l, R r) -> decltype(( l + r ))
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto unary_plus(L l) -> decltype(( +l ))
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto subtraction(L l, R r) -> decltype(( l - r ))
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto unary_minus(L l) -> decltype(( -l ))
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
return (-l);
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
return (-l);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto bitwise_and(L l, R r) -> decltype(( l & r ))
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto bitwise_compliment(L l) -> decltype(( ~l ))
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto bitwise_or(L l, R r) -> decltype(( l | r ))
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto division(L l, R r) -> decltype(( l / r ))
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto left_shift(L l, R r) -> decltype(( l << r ))
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto multiplication(L l, R r) -> decltype(( l * r ))
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto remainder(L l, R r) -> decltype(( l % r ))
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto right_shift(L l, R r) -> decltype(( l >> r ))
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign(ModulePtr m = std::make_shared<Module>())
|
||||
void assign(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_bitwise_and(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_xor(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_xor(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_bitwise_or(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_difference(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_difference(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_left_shift(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_left_shift(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_product(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_product(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_quotient(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_quotient(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_remainder(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_remainder(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_right_shift(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_right_shift(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_sum(ModulePtr m = std::make_shared<Module>())
|
||||
void assign_sum(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_decrement(ModulePtr m = std::make_shared<Module>())
|
||||
void prefix_decrement(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_increment(ModulePtr m = std::make_shared<Module>())
|
||||
void prefix_increment(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr equal(ModulePtr m = std::make_shared<Module>())
|
||||
void equal(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than(ModulePtr m = std::make_shared<Module>())
|
||||
void greater_than(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than_equal(ModulePtr m = std::make_shared<Module>())
|
||||
void greater_than_equal(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than(ModulePtr m = std::make_shared<Module>())
|
||||
void less_than(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than_equal(ModulePtr m = std::make_shared<Module>())
|
||||
void less_than_equal(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr logical_compliment(ModulePtr m = std::make_shared<Module>())
|
||||
void logical_compliment(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr not_equal(ModulePtr m = std::make_shared<Module>())
|
||||
void not_equal(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr addition(ModulePtr m = std::make_shared<Module>())
|
||||
void addition(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_plus(ModulePtr m = std::make_shared<Module>())
|
||||
void unary_plus(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr subtraction(ModulePtr m = std::make_shared<Module>())
|
||||
void subtraction(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_minus(ModulePtr m = std::make_shared<Module>())
|
||||
void unary_minus(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_and(ModulePtr m = std::make_shared<Module>())
|
||||
void bitwise_and(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_compliment(ModulePtr m = std::make_shared<Module>())
|
||||
void bitwise_compliment(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_xor(ModulePtr m = std::make_shared<Module>())
|
||||
void bitwise_xor(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_or(ModulePtr m = std::make_shared<Module>())
|
||||
void bitwise_or(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr division(ModulePtr m = std::make_shared<Module>())
|
||||
void division(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr left_shift(ModulePtr m = std::make_shared<Module>())
|
||||
void left_shift(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr multiplication(ModulePtr m = std::make_shared<Module>())
|
||||
void multiplication(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr remainder(ModulePtr m = std::make_shared<Module>())
|
||||
void remainder(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr right_shift(ModulePtr m = std::make_shared<Module>())
|
||||
void right_shift(Module& m)
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
|
||||
return m;
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace chaiscript
|
||||
namespace dispatch
|
||||
{
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions *t_conversions);
|
||||
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions_State *t_conversions);
|
||||
|
||||
class Param_Types
|
||||
{
|
||||
@@ -72,7 +72,7 @@ namespace chaiscript
|
||||
return m_types == t_rhs.m_types;
|
||||
}
|
||||
|
||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (!m_has_types) return true;
|
||||
if (vals.size() != m_types.size()) return false;
|
||||
@@ -145,9 +145,9 @@ namespace chaiscript
|
||||
class Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
virtual ~Proxy_Function_Base() {}
|
||||
virtual ~Proxy_Function_Base() = default;
|
||||
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (m_arity < 0 || size_t(m_arity) == params.size()) {
|
||||
return do_call(params, t_conversions);
|
||||
@@ -163,7 +163,7 @@ namespace chaiscript
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||
|
||||
virtual bool is_attribute_function() const { return false; }
|
||||
|
||||
@@ -179,22 +179,17 @@ namespace chaiscript
|
||||
|
||||
//! Return true if the function is a possible match
|
||||
//! to the passed in values
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
|
||||
|
||||
if (m_arity < 0)
|
||||
{
|
||||
return true;
|
||||
} else if (static_cast<size_t>(m_arity) == vals.size()) {
|
||||
if (m_arity == 0)
|
||||
{
|
||||
return true;
|
||||
} else if (m_arity > 1) {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
|
||||
} else {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions);
|
||||
}
|
||||
} else if (m_arity > 1) {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,17 +199,15 @@ namespace chaiscript
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
|| (!bv.get_type_info().is_undef()
|
||||
&& (ti.bare_equal(user_type<Boxed_Number>())
|
||||
&& ( (ti.bare_equal(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|
||||
|| ti.bare_equal(bv.get_type_info())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| t_conversions.converts(ti, bv.get_type_info())
|
||||
|| t_conversions->converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -225,13 +218,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
return compare_type_to_param(m_types[1], bv, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const = 0;
|
||||
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
|
||||
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
|
||||
@@ -248,7 +241,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs,
|
||||
const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
if (tis.size() - 1 != bvs.size())
|
||||
{
|
||||
@@ -257,10 +251,7 @@ namespace chaiscript
|
||||
const size_t size = bvs.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (!(tis[i+1].bare_equal(bvs[i].get_type_info()) && tis[i+1].is_const() >= bvs[i].get_type_info().is_const() ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!compare_type_to_param(tis[i + 1], bvs[i], t_conversions)) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -285,14 +276,13 @@ namespace chaiscript
|
||||
class guard_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
guard_error() CHAISCRIPT_NOEXCEPT
|
||||
guard_error() noexcept
|
||||
: std::runtime_error("Guard evaluation failed")
|
||||
{ }
|
||||
|
||||
guard_error(const guard_error &) = default;
|
||||
|
||||
virtual ~guard_error() CHAISCRIPT_NOEXCEPT
|
||||
{ }
|
||||
virtual ~guard_error() noexcept = default;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -309,17 +299,15 @@ namespace chaiscript
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
||||
m_param_types(std::move(t_param_types)),
|
||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description))
|
||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Proxy_Function() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool operator==(const Proxy_Function_Base &rhs) const override
|
||||
{
|
||||
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||
|
||||
@@ -330,7 +318,7 @@ namespace chaiscript
|
||||
&& this->m_param_types == prhs->m_param_types);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
|
||||
&& test_guard(vals, t_conversions);
|
||||
@@ -347,14 +335,9 @@ namespace chaiscript
|
||||
return m_parsenode;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (m_guard)
|
||||
{
|
||||
@@ -391,13 +374,12 @@ namespace chaiscript
|
||||
Param_Types m_param_types;
|
||||
Proxy_Function m_guard;
|
||||
AST_NodePtr m_parsenode;
|
||||
std::string m_description;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
class Dynamic_Proxy_Function_Impl : public Dynamic_Proxy_Function
|
||||
class Dynamic_Proxy_Function_Impl final : public Dynamic_Proxy_Function
|
||||
{
|
||||
public:
|
||||
Dynamic_Proxy_Function_Impl(
|
||||
@@ -405,24 +387,20 @@ namespace chaiscript
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Dynamic_Proxy_Function(
|
||||
t_arity,
|
||||
std::move(t_parsenode),
|
||||
std::move(t_param_types),
|
||||
std::move(t_description),
|
||||
std::move(t_guard)
|
||||
),
|
||||
m_f(std::move(t_f))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Proxy_Function_Impl() {}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
|
||||
{
|
||||
@@ -433,7 +411,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Callable m_f;
|
||||
};
|
||||
|
||||
@@ -454,7 +431,7 @@ namespace chaiscript
|
||||
/// and substitutes bound parameters into the parameter list
|
||||
/// at runtime, when call() is executed.
|
||||
/// it is used for bind(function, param1, _, param2) style calls
|
||||
class Bound_Function : public Proxy_Function_Base
|
||||
class Bound_Function final : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Bound_Function(const Const_Proxy_Function &t_f,
|
||||
@@ -465,19 +442,18 @@ namespace chaiscript
|
||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||
}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_f) const CHAISCRIPT_OVERRIDE
|
||||
bool operator==(const Proxy_Function_Base &t_f) const override
|
||||
{
|
||||
return &t_f == this;
|
||||
}
|
||||
|
||||
virtual ~Bound_Function() {}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
std::vector<Const_Proxy_Function> get_contained_functions() const override
|
||||
{
|
||||
return std::vector<Const_Proxy_Function>{m_f};
|
||||
}
|
||||
@@ -514,10 +490,6 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "Bound: " + m_f->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
|
||||
@@ -527,18 +499,11 @@ namespace chaiscript
|
||||
|
||||
if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }
|
||||
|
||||
std::vector<Type_Info> types = t_f->get_param_types();
|
||||
const auto types = t_f->get_param_types();
|
||||
assert(types.size() == t_args.size() + 1);
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6011)
|
||||
#endif
|
||||
// this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14
|
||||
std::vector<Type_Info> retval{types[0]};
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < types.size() - 1; ++i)
|
||||
{
|
||||
@@ -551,7 +516,7 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
@@ -569,26 +534,20 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Impl_Base() {}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return "";
|
||||
return static_cast<int>(vals.size()) == get_arity()
|
||||
&& (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions));
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions));
|
||||
}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// For any callable object
|
||||
template<typename Func, typename Callable>
|
||||
class Proxy_Function_Callable_Impl : public Proxy_Function_Impl_Base
|
||||
class Proxy_Function_Callable_Impl final : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Callable_Impl(Callable f)
|
||||
@@ -597,24 +556,21 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Callable_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
{
|
||||
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
typedef typename detail::Function_Signature<Func>::Return_Type Return_Type;
|
||||
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
|
||||
return detail::call_func(detail::Function_Signature<Func>(), m_f, params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -630,16 +586,11 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Assignable_Proxy_Function() {}
|
||||
|
||||
|
||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
|
||||
|
||||
|
||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
|
||||
};
|
||||
|
||||
template<typename Func>
|
||||
class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function
|
||||
class Assignable_Proxy_Function_Impl final : public Assignable_Proxy_Function
|
||||
{
|
||||
public:
|
||||
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
|
||||
@@ -649,14 +600,12 @@ namespace chaiscript
|
||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||
}
|
||||
|
||||
virtual ~Assignable_Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
{
|
||||
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
|
||||
}
|
||||
@@ -666,14 +615,14 @@ namespace chaiscript
|
||||
return m_f.get();
|
||||
}
|
||||
|
||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) CHAISCRIPT_OVERRIDE {
|
||||
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
|
||||
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::template go<Func>(m_f.get(), params, t_conversions);
|
||||
return detail::call_func(detail::Function_Signature<Func>(), m_f.get(), params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
@@ -681,9 +630,11 @@ namespace chaiscript
|
||||
std::reference_wrapper<std::function<Func>> m_f;
|
||||
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
|
||||
};
|
||||
|
||||
|
||||
/// Attribute getter Proxy_Function implementation
|
||||
template<typename T, typename Class>
|
||||
class Attribute_Access : public Proxy_Function_Base
|
||||
class Attribute_Access final : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
@@ -692,11 +643,9 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
bool is_attribute_function() const override { return true; }
|
||||
|
||||
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
{
|
||||
const Attribute_Access<T, Class> * aa
|
||||
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
|
||||
@@ -708,7 +657,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const override
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@@ -718,26 +667,47 @@ namespace chaiscript
|
||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
const Boxed_Value &bv = params[0];
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
||||
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
return do_call_impl<T>(o);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
return do_call_impl<T>(o);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Type>
|
||||
auto do_call_impl(Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<Type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(const Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<const Type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(const Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static std::vector<Type_Info> param_types()
|
||||
{
|
||||
return {user_type<T>(), user_type<Class>()};
|
||||
@@ -763,8 +733,16 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
dispatch_error(std::vector<Boxed_Value> t_parameters,
|
||||
std::vector<Const_Proxy_Function> t_functions,
|
||||
const std::string &t_desc)
|
||||
: std::runtime_error(t_desc), parameters(std::move(t_parameters)), functions(std::move(t_functions))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
dispatch_error(const dispatch_error &) = default;
|
||||
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~dispatch_error() noexcept = default;
|
||||
|
||||
std::vector<Boxed_Value> parameters;
|
||||
std::vector<Const_Proxy_Function> functions;
|
||||
@@ -777,7 +755,7 @@ namespace chaiscript
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||
|
||||
@@ -796,7 +774,7 @@ namespace chaiscript
|
||||
|
||||
template<typename InItr, typename Funcs>
|
||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions, const Funcs &t_funcs)
|
||||
const Type_Conversions_State &t_conversions, const Funcs &t_funcs)
|
||||
{
|
||||
InItr matching_func(end);
|
||||
|
||||
@@ -873,7 +851,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
|
||||
ordered_funcs.reserve(funcs.size());
|
||||
@@ -904,7 +882,7 @@ namespace chaiscript
|
||||
for (const auto &func : ordered_funcs )
|
||||
{
|
||||
try {
|
||||
if (func.first == i && func.second->filter(plist, t_conversions))
|
||||
if (func.first == i && (i == 0 || func.second->filter(plist, t_conversions)))
|
||||
{
|
||||
return (*(func.second))(plist, t_conversions);
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
@@ -19,7 +20,7 @@
|
||||
#include "callable_traits.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Type_Conversions_State;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
@@ -43,7 +44,7 @@ namespace chaiscript
|
||||
|
||||
arity_error(const arity_error &) = default;
|
||||
|
||||
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~arity_error() noexcept {}
|
||||
|
||||
int got;
|
||||
int expected;
|
||||
@@ -66,34 +67,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_GCC_4_6
|
||||
/// \todo REMOVE THIS WHEN WE DROP G++4.6
|
||||
|
||||
|
||||
// Forward declaration
|
||||
template<typename ... Rest>
|
||||
struct Try_Cast;
|
||||
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Try_Cast<Param, Rest...>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, size_t generation, const Type_Conversions &t_conversions)
|
||||
{
|
||||
boxed_cast<Param>(params[generation], &t_conversions);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
|
||||
}
|
||||
};
|
||||
|
||||
// 0th case
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions &)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||
@@ -101,140 +74,49 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Ret, int count, typename ... Params>
|
||||
struct Call_Func
|
||||
{
|
||||
|
||||
template<typename Callable, typename ... InnerParams>
|
||||
static Ret do_call(const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
struct Call_Func<Ret, 0, Params...>
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this
|
||||
#endif
|
||||
template<typename Callable, typename ... InnerParams>
|
||||
static Ret do_call(const Callable &f,
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
* The function attempts to unbox each parameter to the expected type.
|
||||
* if any unboxing fails the execution of the function fails and
|
||||
* the bad_boxed_cast is passed up to the caller.
|
||||
*/
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
{
|
||||
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params, t_conversions);
|
||||
}
|
||||
|
||||
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
template<size_t ... I>
|
||||
struct Indexes
|
||||
{
|
||||
};
|
||||
|
||||
template<size_t S, size_t ... I>
|
||||
struct Make_Indexes
|
||||
{
|
||||
typedef typename Make_Indexes<S-1, I..., sizeof...(I)>::indexes indexes;
|
||||
};
|
||||
|
||||
template<size_t ... I>
|
||||
struct Make_Indexes<0, I...>
|
||||
{
|
||||
typedef Indexes<I...> indexes;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret, typename ... Params, size_t ... I>
|
||||
bool compare_types_cast(Indexes<I...>, Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
try {
|
||||
std::vector<Boxed_Value>::size_type i = 0;
|
||||
(void)i;
|
||||
(void)params; (void)t_conversions;
|
||||
(void)std::initializer_list<int>{(boxed_cast<Params>(params[I], &t_conversions), 0)...};
|
||||
// this is ok because the order of evaluation of initializer lists is well defined
|
||||
(void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*f)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
|
||||
return compare_types_cast(indexes(), f, params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
|
||||
std::index_sequence<I...>, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
(void)params; (void)t_conversions;
|
||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
* The function attempts to unbox each parameter to the expected type.
|
||||
* if any unboxing fails the execution of the function fails and
|
||||
* the bad_boxed_cast is passed up to the caller.
|
||||
*/
|
||||
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
/// The function attempts to unbox each parameter to the expected type.
|
||||
/// if any unboxing fails the execution of the function fails and
|
||||
/// the bad_boxed_cast is passed up to the caller.
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
|
||||
return call_func(sig, indexes(), f, params, t_conversions);
|
||||
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
||||
}
|
||||
|
||||
#endif
|
||||
template<typename Callable, typename ... Params>
|
||||
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -242,34 +124,4 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Ret>
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Signature, typename Callable>
|
||||
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Signature, typename Callable>
|
||||
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
@@ -29,48 +29,48 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
const std::string &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~bad_boxed_dynamic_cast() noexcept = default;
|
||||
};
|
||||
|
||||
class bad_boxed_type_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
const std::string &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
bad_boxed_type_cast(const std::string &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
|
||||
|
||||
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~bad_boxed_type_cast() noexcept = default;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace chaiscript
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~Type_Conversion_Base() {}
|
||||
virtual ~Type_Conversion_Base() = default;
|
||||
|
||||
protected:
|
||||
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
|
||||
@@ -107,8 +107,8 @@ namespace chaiscript
|
||||
|
||||
|
||||
private:
|
||||
Type_Info m_to;
|
||||
Type_Info m_from;
|
||||
const Type_Info m_to;
|
||||
const Type_Info m_from;
|
||||
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace chaiscript
|
||||
if (t_from.is_const())
|
||||
{
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<const To>{
|
||||
[&](){
|
||||
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
@@ -137,7 +137,7 @@ namespace chaiscript
|
||||
);
|
||||
} else {
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<To>{
|
||||
[&](){
|
||||
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
@@ -182,7 +182,7 @@ namespace chaiscript
|
||||
if (t_from.is_const())
|
||||
{
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<const To>{
|
||||
[&](){
|
||||
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
@@ -193,7 +193,7 @@ namespace chaiscript
|
||||
);
|
||||
} else {
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<To>{
|
||||
[&](){
|
||||
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
@@ -242,12 +242,12 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value convert_down(const Boxed_Value &t_base) const override
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value convert(const Boxed_Value &t_derived) const override
|
||||
{
|
||||
return Static_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
@@ -262,17 +262,18 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value convert_down(const Boxed_Value &t_base) const override
|
||||
{
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types");
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived),
|
||||
"Unable to cast down inheritance hierarchy with non-polymorphic types");
|
||||
}
|
||||
|
||||
virtual bool bidir() const CHAISCRIPT_OVERRIDE
|
||||
bool bidir() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value convert(const Boxed_Value &t_derived) const override
|
||||
{
|
||||
return Static_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
@@ -290,18 +291,18 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value convert_down(const Boxed_Value &) const override
|
||||
{
|
||||
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
|
||||
Boxed_Value convert(const Boxed_Value &t_from) const override
|
||||
{
|
||||
/// \todo better handling of errors from the conversion function
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
virtual bool bidir() const CHAISCRIPT_OVERRIDE
|
||||
virtual bool bidir() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -310,12 +311,17 @@ namespace chaiscript
|
||||
private:
|
||||
Callable m_func;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class Type_Conversions
|
||||
{
|
||||
public:
|
||||
struct Conversion_Saves
|
||||
{
|
||||
bool enabled = false;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||
@@ -341,7 +347,6 @@ namespace chaiscript
|
||||
m_num_types(m_conversions.size()),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
@@ -387,15 +392,14 @@ namespace chaiscript
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
|
||||
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
if (t_saves.enabled) t_saves.saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
|
||||
@@ -405,11 +409,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
|
||||
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
if (t_saves.enabled) t_saves.saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
|
||||
@@ -418,15 +422,15 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
void enable_conversion_saves(bool t_val)
|
||||
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val)
|
||||
{
|
||||
m_conversion_saves->enabled = t_val;
|
||||
t_saves.enabled = t_val;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> take_saves()
|
||||
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves)
|
||||
{
|
||||
std::vector<Boxed_Value> ret;
|
||||
std::swap(ret, m_conversion_saves->saves);
|
||||
std::swap(ret, t_saves.saves);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -440,7 +444,7 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr = find(to, from);
|
||||
const auto itr = find(to, from);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
@@ -450,6 +454,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
Conversion_Saves &conversion_saves() const {
|
||||
return *m_conversion_saves;
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
@@ -459,7 +467,6 @@ namespace chaiscript
|
||||
{
|
||||
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|
||||
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
|
||||
;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -483,15 +490,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
struct Conversion_Saves
|
||||
{
|
||||
Conversion_Saves()
|
||||
: enabled(false)
|
||||
{}
|
||||
|
||||
bool enabled;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||
@@ -501,6 +499,33 @@ namespace chaiscript
|
||||
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||
};
|
||||
|
||||
class Type_Conversions_State
|
||||
{
|
||||
public:
|
||||
Type_Conversions_State(const Type_Conversions &t_conversions,
|
||||
Type_Conversions::Conversion_Saves &t_saves)
|
||||
: m_conversions(t_conversions),
|
||||
m_saves(t_saves)
|
||||
{
|
||||
}
|
||||
|
||||
const Type_Conversions *operator->() const {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
|
||||
const Type_Conversions *get() const {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
|
||||
Type_Conversions::Conversion_Saves &saves() const {
|
||||
return m_saves;
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const Type_Conversions> m_conversions;
|
||||
std::reference_wrapper<Type_Conversions::Conversion_Saves> m_saves;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||
|
||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||
@@ -582,7 +607,7 @@ namespace chaiscript
|
||||
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
||||
|
||||
To vec;
|
||||
|
||||
vec.reserve(from_vec.size());
|
||||
for (const Boxed_Value &bv : from_vec) {
|
||||
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
||||
}
|
||||
@@ -593,6 +618,22 @@ namespace chaiscript
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Type_Conversion map_conversion()
|
||||
{
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
|
||||
|
||||
To map;
|
||||
for (const std::pair<std::string, Boxed_Value> &p : from_map) {
|
||||
map.insert(std::make_pair(p.first, detail::Cast_Helper<typename To::mapped_type>::cast(p.second, nullptr)));
|
||||
}
|
||||
|
||||
return Boxed_Value(std::move(map));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||
@@ -29,70 +29,56 @@ namespace chaiscript
|
||||
class Type_Info
|
||||
{
|
||||
public:
|
||||
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
|
||||
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
|
||||
m_is_undef(false)
|
||||
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
|
||||
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
||||
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
|
||||
+ (static_cast<unsigned int>(t_is_void) << is_void_flag)
|
||||
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
|
||||
{
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR Type_Info()
|
||||
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
||||
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||
m_is_void(false), m_is_arithmetic(false),
|
||||
m_is_undef(true)
|
||||
{
|
||||
}
|
||||
constexpr Type_Info() = default;
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Type_Info(Type_Info&&) = default;
|
||||
Type_Info& operator=(Type_Info&&) = default;
|
||||
#endif
|
||||
|
||||
Type_Info(const Type_Info&) = default;
|
||||
Type_Info& operator=(const Type_Info&) = default;
|
||||
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
constexpr bool operator<(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return m_type_info < ti.m_type_info;
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
constexpr bool operator==(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return ti.m_type_info == m_type_info
|
||||
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
|
||||
|| *ti.m_type_info == *m_type_info;
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
constexpr bool operator==(const std::type_info &ti) const noexcept
|
||||
{
|
||||
return m_type_info != nullptr && (*m_type_info) == ti;
|
||||
return !is_undef() && (*m_type_info) == ti;
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
constexpr bool bare_equal(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return ti.m_bare_type_info == m_bare_type_info
|
||||
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
||||
return ti.m_bare_type_info == m_bare_type_info
|
||||
|| *ti.m_bare_type_info == *m_bare_type_info;
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
|
||||
{
|
||||
return m_bare_type_info != nullptr
|
||||
&& (*m_bare_type_info) == ti;
|
||||
return !is_undef() && (*m_bare_type_info) == ti;
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
|
||||
constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
|
||||
constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
|
||||
constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
|
||||
constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
|
||||
constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
|
||||
constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
if (m_type_info)
|
||||
if (!is_undef())
|
||||
{
|
||||
return m_type_info->name();
|
||||
} else {
|
||||
@@ -102,7 +88,7 @@ namespace chaiscript
|
||||
|
||||
std::string bare_name() const
|
||||
{
|
||||
if (m_bare_type_info)
|
||||
if (!is_undef())
|
||||
{
|
||||
return m_bare_type_info->name();
|
||||
} else {
|
||||
@@ -110,20 +96,23 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
|
||||
constexpr const std::type_info *bare_type_info() const
|
||||
{
|
||||
return m_bare_type_info;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
bool m_is_const;
|
||||
bool m_is_reference;
|
||||
bool m_is_pointer;
|
||||
bool m_is_void;
|
||||
bool m_is_arithmetic;
|
||||
bool m_is_undef;
|
||||
struct Unknown_Type {};
|
||||
|
||||
const std::type_info *m_type_info = &typeid(Unknown_Type);
|
||||
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
|
||||
static const int is_const_flag = 0;
|
||||
static const int is_reference_flag = 1;
|
||||
static const int is_pointer_flag = 2;
|
||||
static const int is_void_flag = 3;
|
||||
static const int is_arithmetic_flag = 4;
|
||||
static const int is_undef_flag = 5;
|
||||
unsigned int m_flags = (1 << is_undef_flag);
|
||||
};
|
||||
|
||||
namespace detail
|
||||
@@ -132,9 +121,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
static constexpr Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
@@ -149,9 +136,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::shared_ptr<T> >
|
||||
{
|
||||
typedef T type;
|
||||
// typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
static constexpr Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -161,12 +148,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
static constexpr Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -179,9 +169,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
static constexpr Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -194,9 +182,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
static constexpr Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -218,7 +204,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
Type_Info user_type(const T &/*t*/)
|
||||
constexpr Type_Info user_type(const T &/*t*/)
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
@@ -233,7 +219,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
Type_Info user_type()
|
||||
constexpr Type_Info user_type()
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
@@ -13,7 +13,7 @@ namespace chaiscript
|
||||
{
|
||||
|
||||
struct Operators {
|
||||
enum Opers
|
||||
enum class Opers
|
||||
{
|
||||
boolean_flag,
|
||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
||||
@@ -31,7 +31,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
static const char *to_string(Opers t_oper) {
|
||||
const char *opers[] = {
|
||||
static const char *opers[] = {
|
||||
"",
|
||||
"==", "<", ">", "<=", ">=", "!=",
|
||||
"",
|
||||
@@ -46,80 +46,80 @@ namespace chaiscript
|
||||
"+", "/", "*", "-", "+", "-",
|
||||
""
|
||||
};
|
||||
return opers[t_oper];
|
||||
return opers[static_cast<int>(t_oper)];
|
||||
}
|
||||
|
||||
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
||||
{
|
||||
if (t_str == "==")
|
||||
{
|
||||
return equals;
|
||||
return Opers::equals;
|
||||
} else if (t_str == "<") {
|
||||
return less_than;
|
||||
return Opers::less_than;
|
||||
} else if (t_str == ">") {
|
||||
return greater_than;
|
||||
return Opers::greater_than;
|
||||
} else if (t_str == "<=") {
|
||||
return less_than_equal;
|
||||
return Opers::less_than_equal;
|
||||
} else if (t_str == ">=") {
|
||||
return greater_than_equal;
|
||||
return Opers::greater_than_equal;
|
||||
} else if (t_str == "!=") {
|
||||
return not_equal;
|
||||
return Opers::not_equal;
|
||||
} else if (t_str == "=") {
|
||||
return assign;
|
||||
return Opers::assign;
|
||||
} else if (t_str == "++") {
|
||||
return pre_increment;
|
||||
return Opers::pre_increment;
|
||||
} else if (t_str == "--") {
|
||||
return pre_decrement;
|
||||
return Opers::pre_decrement;
|
||||
} else if (t_str == "*=") {
|
||||
return assign_product;
|
||||
return Opers::assign_product;
|
||||
} else if (t_str == "+=") {
|
||||
return assign_sum;
|
||||
return Opers::assign_sum;
|
||||
} else if (t_str == "-=") {
|
||||
return assign_difference;
|
||||
return Opers::assign_difference;
|
||||
} else if (t_str == "&=") {
|
||||
return assign_bitwise_and;
|
||||
return Opers::assign_bitwise_and;
|
||||
} else if (t_str == "|=") {
|
||||
return assign_bitwise_or;
|
||||
return Opers::assign_bitwise_or;
|
||||
} else if (t_str == "<<=") {
|
||||
return assign_shift_left;
|
||||
return Opers::assign_shift_left;
|
||||
} else if (t_str == ">>=") {
|
||||
return assign_shift_right;
|
||||
return Opers::assign_shift_right;
|
||||
} else if (t_str == "%=") {
|
||||
return assign_remainder;
|
||||
return Opers::assign_remainder;
|
||||
} else if (t_str == "^=") {
|
||||
return assign_bitwise_xor;
|
||||
return Opers::assign_bitwise_xor;
|
||||
} else if (t_str == "<<") {
|
||||
return shift_left;
|
||||
return Opers::shift_left;
|
||||
} else if (t_str == ">>") {
|
||||
return shift_right;
|
||||
return Opers::shift_right;
|
||||
} else if (t_str == "%") {
|
||||
return remainder;
|
||||
return Opers::remainder;
|
||||
} else if (t_str == "&") {
|
||||
return bitwise_and;
|
||||
return Opers::bitwise_and;
|
||||
} else if (t_str == "|") {
|
||||
return bitwise_or;
|
||||
return Opers::bitwise_or;
|
||||
} else if (t_str == "^") {
|
||||
return bitwise_xor;
|
||||
return Opers::bitwise_xor;
|
||||
} else if (t_str == "~") {
|
||||
return bitwise_complement;
|
||||
return Opers::bitwise_complement;
|
||||
} else if (t_str == "+") {
|
||||
if (t_is_unary) {
|
||||
return unary_plus;
|
||||
return Opers::unary_plus;
|
||||
} else {
|
||||
return sum;
|
||||
return Opers::sum;
|
||||
}
|
||||
} else if (t_str == "-") {
|
||||
if (t_is_unary) {
|
||||
return unary_minus;
|
||||
return Opers::unary_minus;
|
||||
} else {
|
||||
return difference;
|
||||
return Opers::difference;
|
||||
}
|
||||
} else if (t_str == "/") {
|
||||
return quotient;
|
||||
return Opers::quotient;
|
||||
} else if (t_str == "*") {
|
||||
return product;
|
||||
return Opers::product;
|
||||
} else {
|
||||
return invalid;
|
||||
return Opers::invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
@@ -32,28 +32,26 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Types of AST nodes available to the parser and eval
|
||||
class AST_Node_Type {
|
||||
public:
|
||||
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
|
||||
};
|
||||
enum class AST_Node_Type { Id, Caching_Id, 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,
|
||||
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
|
||||
};
|
||||
|
||||
enum class Operator_Precidence { Ternary_Cond, Logical_Or, Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And, Equality, Comparison, Shift, Addition, Multiplication };
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/// Helper lookup to get the name of each node type
|
||||
const char *ast_node_type_to_string(int ast_node_type) {
|
||||
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
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",
|
||||
"Array_Call", "Dot_Access",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
|
||||
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
return ast_node_types[static_cast<int>(ast_node_type)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +99,36 @@ namespace chaiscript
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
namespace exception
|
||||
{
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &t_reason) noexcept
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
: std::runtime_error(format_error(t_name, t_errors))
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
virtual ~load_module_error() noexcept = default;
|
||||
|
||||
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Error loading module '" << t_name << "'\n"
|
||||
<< " The following locations were searched:\n";
|
||||
|
||||
for (const auto &err : t_errors) {
|
||||
ss << " " << err.what() << "\n";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Errors generated during parsing or evaluation
|
||||
struct eval_error : std::runtime_error {
|
||||
@@ -113,7 +141,7 @@ namespace chaiscript
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
@@ -121,18 +149,18 @@ namespace chaiscript
|
||||
eval_error(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
|
||||
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||
reason(t_why), start_position(t_where), filename(t_fname)
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
|
||||
eval_error(const std::string &t_why) noexcept
|
||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||
reason(t_why)
|
||||
{}
|
||||
@@ -161,12 +189,12 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~eval_error() noexcept = default;
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static int id(const T& t)
|
||||
static AST_Node_Type id(const T& t)
|
||||
{
|
||||
return t->identifier;
|
||||
}
|
||||
@@ -420,12 +448,12 @@ namespace chaiscript
|
||||
|
||||
/// Errors generated when loading a file
|
||||
struct file_not_found_error : std::runtime_error {
|
||||
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
|
||||
file_not_found_error(const std::string &t_filename) noexcept
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
{ }
|
||||
|
||||
file_not_found_error(const file_not_found_error &) = default;
|
||||
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~file_not_found_error() noexcept {}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -434,11 +462,9 @@ namespace chaiscript
|
||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
||||
public:
|
||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
||||
const AST_Node_Type identifier;
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
std::vector<AST_NodePtr> children;
|
||||
AST_NodePtr annotation;
|
||||
|
||||
const std::string &filename() const {
|
||||
return *location.filename;
|
||||
@@ -452,19 +478,22 @@ namespace chaiscript
|
||||
return location.end;
|
||||
}
|
||||
|
||||
virtual std::string pretty_print() const
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
for (auto & elem : this->children) {
|
||||
oss << elem->pretty_print();
|
||||
for (auto & elem : this->get_children()) {
|
||||
oss << elem->pretty_print() << ' ';
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
virtual std::vector<AST_NodePtr> get_children() const = 0;
|
||||
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
|
||||
|
||||
|
||||
/// Prints the contents of an AST node, including its children, recursively
|
||||
std::string to_string(const std::string &t_prepend = "") const {
|
||||
@@ -473,21 +502,12 @@ namespace chaiscript
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
||||
|
||||
for (auto & elem : this->children) {
|
||||
for (auto & elem : this->get_children()) {
|
||||
oss << elem->to_string(t_prepend + " ");
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const
|
||||
{
|
||||
try {
|
||||
return eval_internal(t_e);
|
||||
} catch (exception::eval_error &ee) {
|
||||
ee.call_stack.push_back(shared_from_this());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv) {
|
||||
try {
|
||||
@@ -499,33 +519,47 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
|
||||
{
|
||||
std::replace(children.begin(), children.end(), t_child, t_new_child);
|
||||
}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
||||
protected:
|
||||
AST_Node(std::string t_ast_node_text, int t_id, Parse_Location t_loc,
|
||||
std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
|
||||
identifier(t_id), text(std::move(t_ast_node_text)),
|
||||
location(std::move(t_loc)),
|
||||
children(std::move(t_children))
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const
|
||||
{
|
||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
||||
}
|
||||
|
||||
private:
|
||||
// Copy and assignment explicitly unimplemented
|
||||
virtual ~AST_Node() = default;
|
||||
AST_Node(AST_Node &&) = default;
|
||||
AST_Node &operator=(AST_Node &&) = default;
|
||||
AST_Node(const AST_Node &) = delete;
|
||||
AST_Node& operator=(const AST_Node &) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc)
|
||||
: identifier(t_id), text(std::move(t_ast_node_text)),
|
||||
location(std::move(t_loc))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
namespace parser {
|
||||
class ChaiScript_Parser_Base
|
||||
{
|
||||
public:
|
||||
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
|
||||
virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0;
|
||||
virtual void *get_tracer_ptr() = 0;
|
||||
virtual ~ChaiScript_Parser_Base() = default;
|
||||
ChaiScript_Parser_Base() = default;
|
||||
ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
|
||||
ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
|
||||
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
||||
|
||||
template<typename T>
|
||||
T &get_tracer()
|
||||
{
|
||||
// to do type check this somehow?
|
||||
return *static_cast<T*>(get_tracer_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
|
||||
};
|
||||
}
|
||||
|
||||
namespace eval
|
||||
{
|
||||
@@ -554,77 +588,83 @@ namespace chaiscript
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Scope_Push_Pop
|
||||
{
|
||||
Scope_Push_Pop(Scope_Push_Pop &&) = default;
|
||||
Scope_Push_Pop& operator=(Scope_Push_Pop &&) = default;
|
||||
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
|
||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
||||
|
||||
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds.get()->new_scope(m_ds.get().stack_holder());
|
||||
m_ds->new_scope(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
~Scope_Push_Pop()
|
||||
{
|
||||
m_ds.get()->pop_scope(m_ds.get().stack_holder());
|
||||
m_ds->pop_scope(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
};
|
||||
|
||||
/// Creates a new function call and pops it on destruction
|
||||
struct Function_Push_Pop
|
||||
{
|
||||
Function_Push_Pop(Function_Push_Pop &&) = default;
|
||||
Function_Push_Pop& operator=(Function_Push_Pop &&) = default;
|
||||
Function_Push_Pop(const Function_Push_Pop &) = delete;
|
||||
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
||||
|
||||
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds.get()->new_function_call(m_ds.get().stack_holder());
|
||||
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
}
|
||||
|
||||
~Function_Push_Pop()
|
||||
{
|
||||
m_ds.get()->pop_function_call(m_ds.get().stack_holder());
|
||||
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
}
|
||||
|
||||
void save_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
m_ds.get()->save_function_params(t_params);
|
||||
m_ds->save_function_params(t_params);
|
||||
}
|
||||
|
||||
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
m_ds.get()->save_function_params(std::move(t_params));
|
||||
m_ds->save_function_params(std::move(t_params));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
};
|
||||
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Stack_Push_Pop
|
||||
{
|
||||
Stack_Push_Pop(Stack_Push_Pop &&) = default;
|
||||
Stack_Push_Pop& operator=(Stack_Push_Pop &&) = default;
|
||||
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
|
||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
||||
|
||||
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds.get()->new_stack(m_ds.get().stack_holder());
|
||||
m_ds->new_stack(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
~Stack_Push_Pop()
|
||||
{
|
||||
m_ds.get()->pop_stack(m_ds.get().stack_holder());
|
||||
m_ds->pop_stack(m_ds.stack_holder());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||
@@ -33,12 +33,15 @@
|
||||
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#define VC_EXTRA_LEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#include "chaiscript_windows.hpp"
|
||||
#elif _POSIX_VERSION
|
||||
#include "chaiscript_posix.hpp"
|
||||
#else
|
||||
#include "chaiscript_unknown.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -47,205 +50,9 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &t_reason) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
|
||||
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
}
|
||||
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
static T cast_symbol(void *p)
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
T func_ptr;
|
||||
void *in_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = p;
|
||||
return c.func_ptr;
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
#else
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
||||
struct Loadable_Module
|
||||
{
|
||||
template<typename T>
|
||||
static std::wstring to_wstring(const T &t_str)
|
||||
{
|
||||
return std::wstring(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string to_string(const T &t_str)
|
||||
{
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
template<typename T>
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_wstring(t_str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_string(t_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
typedef LPTSTR StringType;
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
std::wstring retval = L"Unknown Error";
|
||||
#else
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = nullptr;
|
||||
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||
0, NULL ) != 0 && lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
return to_string(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
FreeLibrary(m_data);
|
||||
}
|
||||
|
||||
HMODULE m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
|
||||
#else
|
||||
struct Loadable_Module
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
}
|
||||
|
||||
@@ -263,19 +70,16 @@ namespace chaiscript
|
||||
std::vector<std::string> m_module_paths;
|
||||
std::vector<std::string> m_use_paths;
|
||||
|
||||
std::unique_ptr<parser::ChaiScript_Parser_Base> m_parser;
|
||||
|
||||
chaiscript::detail::Dispatch_Engine m_engine;
|
||||
|
||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||
{
|
||||
try {
|
||||
parser::ChaiScript_Parser parser;
|
||||
if (parser.parse(t_input, t_filename)) {
|
||||
//parser.show_match_stack();
|
||||
return parser.optimized_ast()->eval(m_engine);
|
||||
} else {
|
||||
return Boxed_Value();
|
||||
}
|
||||
const auto p = m_parser->parse(t_input, t_filename);
|
||||
return p->eval(m_engine);
|
||||
}
|
||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
@@ -284,15 +88,6 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
|
||||
{
|
||||
try {
|
||||
return t_ast->eval(m_engine);
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
throw Boxed_Value(t_ee);
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the given file and looks in the 'use' paths
|
||||
const Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||
for (const auto &path : m_use_paths)
|
||||
@@ -330,26 +125,6 @@ namespace chaiscript
|
||||
|
||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
void build_eval_system(const ModulePtr &t_lib) {
|
||||
m_engine.add_reserved_word("def");
|
||||
m_engine.add_reserved_word("fun");
|
||||
m_engine.add_reserved_word("while");
|
||||
m_engine.add_reserved_word("for");
|
||||
m_engine.add_reserved_word("if");
|
||||
m_engine.add_reserved_word("else");
|
||||
m_engine.add_reserved_word("&&");
|
||||
m_engine.add_reserved_word("||");
|
||||
m_engine.add_reserved_word(",");
|
||||
m_engine.add_reserved_word("auto");
|
||||
m_engine.add_reserved_word("return");
|
||||
m_engine.add_reserved_word("break");
|
||||
m_engine.add_reserved_word("true");
|
||||
m_engine.add_reserved_word("false");
|
||||
m_engine.add_reserved_word("class");
|
||||
m_engine.add_reserved_word("attr");
|
||||
m_engine.add_reserved_word("var");
|
||||
m_engine.add_reserved_word("GLOBAL");
|
||||
m_engine.add_reserved_word("_");
|
||||
|
||||
if (t_lib)
|
||||
{
|
||||
add(t_lib);
|
||||
@@ -372,11 +147,15 @@ namespace chaiscript
|
||||
|
||||
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
//
|
||||
//
|
||||
|
||||
m_engine.add(fun(
|
||||
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
|
||||
return t_fun(t_params, this->m_engine.conversions());
|
||||
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
|
||||
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
|
||||
return t_fun(t_params, s);
|
||||
}), "call");
|
||||
|
||||
|
||||
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
|
||||
@@ -396,16 +175,15 @@ namespace chaiscript
|
||||
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
|
||||
m_engine.add(fun([this](const std::string &t_file){ return 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 internal_eval_ast(t_ast); }), "eval");
|
||||
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
||||
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
|
||||
|
||||
m_engine.add(fun(&ChaiScript::version_major), "version_major");
|
||||
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
|
||||
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
|
||||
m_engine.add(fun(&ChaiScript::version), "version");
|
||||
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
||||
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
|
||||
}
|
||||
|
||||
|
||||
@@ -440,7 +218,10 @@ namespace chaiscript
|
||||
ChaiScript(const ModulePtr &t_lib,
|
||||
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
||||
: 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())
|
||||
{
|
||||
@@ -464,7 +245,9 @@ namespace chaiscript
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
||||
: 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())
|
||||
{
|
||||
@@ -500,10 +283,10 @@ namespace chaiscript
|
||||
|
||||
// Let's see if this is a link that we should expand
|
||||
std::vector<char> buf(2048);
|
||||
const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||
if (pathlen > 0 && pathlen < buf.size())
|
||||
const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||
if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size())
|
||||
{
|
||||
dllpath = std::string(&buf.front(), pathlen);
|
||||
dllpath = std::string(&buf.front(), static_cast<size_t>(pathlen));
|
||||
}
|
||||
|
||||
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
|
||||
@@ -511,33 +294,44 @@ namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib-" + version());
|
||||
try {
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib-" + Build_Info::version());
|
||||
} catch (const exception::load_module_error &t_err) {
|
||||
std::cout << "An error occured while trying to load the chaiscript standard library.\n"
|
||||
<< "\n"
|
||||
<< "You must either provide a standard library, or compile it in.\n"
|
||||
<< "For an example of compiling the standard library in,\n"
|
||||
<< "see: https://gist.github.com/lefticus/9456197\n"
|
||||
<< "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< t_err.what();
|
||||
throw;
|
||||
}
|
||||
|
||||
build_eval_system(ModulePtr());
|
||||
}
|
||||
|
||||
static int version_major()
|
||||
|
||||
const Boxed_Value eval(const AST_NodePtr &t_ast)
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
try {
|
||||
return t_ast->eval(m_engine);
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
throw Boxed_Value(t_ee);
|
||||
}
|
||||
}
|
||||
|
||||
static int version_minor()
|
||||
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
const auto ast = m_parser->parse(t_input, "PARSE");
|
||||
if (t_debug_print) {
|
||||
m_parser->debug_print(ast);
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
static int version_patch()
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
|
||||
static std::string version()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << version_major() << "." << version_minor() << "." << version_patch();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string get_type_name(const Type_Info &ti) const
|
||||
{
|
||||
@@ -608,6 +402,12 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
m_engine.set_global(t_bv, t_name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
||||
/// \warning State object does not contain the user defined type conversions of the engine. They
|
||||
/// are left out due to performance considerations involved in tracking the state
|
||||
@@ -747,7 +547,7 @@ namespace chaiscript
|
||||
{
|
||||
std::vector<exception::load_module_error> errors;
|
||||
std::string version_stripped_name = t_module_name;
|
||||
size_t version_pos = version_stripped_name.find("-"+version());
|
||||
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
|
||||
if (version_pos != std::string::npos)
|
||||
{
|
||||
version_stripped_name.erase(version_pos);
|
||||
@@ -777,21 +577,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::string errstring;
|
||||
|
||||
for (std::vector<exception::load_module_error>::const_iterator itr = errors.begin();
|
||||
itr != errors.end();
|
||||
++itr)
|
||||
{
|
||||
if (!errstring.empty())
|
||||
{
|
||||
errstring += "; ";
|
||||
}
|
||||
|
||||
errstring += itr->what();
|
||||
}
|
||||
|
||||
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
|
||||
throw chaiscript::exception::load_module_error(t_module_name, errors);
|
||||
}
|
||||
|
||||
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
||||
@@ -828,14 +614,7 @@ namespace chaiscript
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||
{
|
||||
try {
|
||||
return do_eval(t_script);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
return eval(t_script, t_handler);
|
||||
}
|
||||
|
||||
/// \brief Evaluates a string and returns a typesafe result.
|
||||
@@ -854,21 +633,14 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
try {
|
||||
return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
|
||||
}
|
||||
|
||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv) const
|
||||
{
|
||||
return m_engine.boxed_cast<Type>(bv);
|
||||
return(m_engine.boxed_cast<Type>(bv));
|
||||
}
|
||||
|
||||
|
||||
@@ -900,14 +672,7 @@ namespace chaiscript
|
||||
/// \return result of the script execution
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
try {
|
||||
return do_eval(load_file(t_filename), t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
return eval(load_file(t_filename), t_handler, t_filename);
|
||||
}
|
||||
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
|
||||
@@ -920,14 +685,7 @@ namespace chaiscript
|
||||
/// to the requested type.
|
||||
template<typename T>
|
||||
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
try {
|
||||
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
|
||||
}
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
284
include/chaiscript/language/chaiscript_optimizer.hpp
Normal file
284
include/chaiscript/language/chaiscript_optimizer.hpp
Normal file
@@ -0,0 +1,284 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
|
||||
#define CHAISCRIPT_OPTIMIZER_HPP_
|
||||
|
||||
#include "chaiscript_eval.hpp"
|
||||
|
||||
|
||||
namespace chaiscript {
|
||||
namespace optimizer {
|
||||
|
||||
template<typename ... T>
|
||||
struct Optimizer : T...
|
||||
{
|
||||
Optimizer() = default;
|
||||
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)... };
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
auto child_at(const eval::AST_Node_Impl_Ptr<T> &node, const size_t offset) {
|
||||
if (node->identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
|
||||
} else {
|
||||
return node->children[offset];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto child_count(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children.size();
|
||||
} else {
|
||||
return node->children.size();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Callable>
|
||||
auto make_compiled_node(const eval::AST_Node_Impl_Ptr<T> &original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
|
||||
{
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(original_node, std::move(children), std::move(callable));
|
||||
}
|
||||
|
||||
|
||||
struct Return {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
|
||||
{
|
||||
if (p->identifier == AST_Node_Type::Def
|
||||
&& !p->children.empty())
|
||||
{
|
||||
auto &last_child = p->children.back();
|
||||
if (last_child->identifier == AST_Node_Type::Block) {
|
||||
auto &block_last_child = last_child->children.back();
|
||||
if (block_last_child->identifier == AST_Node_Type::Return) {
|
||||
if (block_last_child->children.size() == 1) {
|
||||
last_child->children.back() = block_last_child->children[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool contains_var_decl_in_scope(const T &node)
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Var_Decl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto num = child_count(node);
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
const auto &child = child_at(node, i);
|
||||
if (child->identifier != AST_Node_Type::Block
|
||||
&& contains_var_decl_in_scope(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Block {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::Block
|
||||
&& node->children.size() == 1
|
||||
&& !contains_var_decl_in_scope(node))
|
||||
{
|
||||
return node->children[0];
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct If {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::If
|
||||
&& node->children.size() >= 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
const auto condition = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||
if (boxed_cast<bool>(condition)) {
|
||||
return node->children[1];
|
||||
} else if (node->children.size() == 3) {
|
||||
return node->children[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
struct Caching_Id {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::Id)
|
||||
{
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Caching_Id_AST_Node<T>>(node->text, node->location);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Constant_Fold {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
|
||||
if (node->identifier == AST_Node_Type::Binary
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant
|
||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
try {
|
||||
const auto &oper = node->text;
|
||||
const auto parsed = Operators::to_operator(oper);
|
||||
if (parsed != Operators::Opers::invalid) {
|
||||
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
||||
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
||||
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
||||
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
//failure to fold, that's OK
|
||||
}
|
||||
} else if (node->identifier == AST_Node_Type::Fun_Call
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Id
|
||||
&& node->children[1]->identifier == AST_Node_Type::Arg_List
|
||||
&& node->children[1]->children.size() == 1
|
||||
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||
|
||||
const auto arg = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1]->children[0])->m_value;
|
||||
if (arg.get_type_info().is_arithmetic()) {
|
||||
const auto &fun_name = node->children[0]->text;
|
||||
|
||||
const auto make_constant = [&node, &fun_name](auto val){
|
||||
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
||||
};
|
||||
|
||||
if (fun_name == "double") {
|
||||
return make_constant(Boxed_Number(arg).get_as<double>());
|
||||
} else if (fun_name == "int") {
|
||||
return make_constant(Boxed_Number(arg).get_as<int>());
|
||||
} else if (fun_name == "float") {
|
||||
return make_constant(Boxed_Number(arg).get_as<float>());
|
||||
} else if (fun_name == "long") {
|
||||
return make_constant(Boxed_Number(arg).get_as<long>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
struct For_Loop {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &for_node) {
|
||||
|
||||
if (for_node->identifier != AST_Node_Type::For) {
|
||||
return for_node;
|
||||
}
|
||||
|
||||
const auto eq_node = child_at(for_node, 0);
|
||||
const auto binary_node = child_at(for_node, 1);
|
||||
const auto prefix_node = child_at(for_node, 2);
|
||||
|
||||
if (eq_node->identifier == AST_Node_Type::Equation
|
||||
&& child_count(eq_node) == 2
|
||||
&& child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl
|
||||
&& child_at(eq_node, 1)->identifier == AST_Node_Type::Constant
|
||||
&& binary_node->identifier == AST_Node_Type::Binary
|
||||
&& binary_node->text == "<"
|
||||
&& child_count(binary_node) == 2
|
||||
&& child_at(binary_node, 0)->identifier == AST_Node_Type::Id
|
||||
&& child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text
|
||||
&& child_at(binary_node, 1)->identifier == AST_Node_Type::Constant
|
||||
&& prefix_node->identifier == AST_Node_Type::Prefix
|
||||
&& prefix_node->text == "++"
|
||||
&& child_count(prefix_node) == 1
|
||||
&& child_at(prefix_node, 0)->identifier == AST_Node_Type::Id
|
||||
&& child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text)
|
||||
{
|
||||
const Boxed_Value &begin = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(eq_node, 1))->m_value;
|
||||
const Boxed_Value &end = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(binary_node, 1))->m_value;
|
||||
const std::string &id = child_at(prefix_node, 0)->text;
|
||||
|
||||
if (begin.get_type_info().bare_equal(user_type<int>())
|
||||
&& end.get_type_info().bare_equal(user_type<int>())) {
|
||||
|
||||
const auto start_int = boxed_cast<int>(begin);
|
||||
const auto end_int = boxed_cast<int>(end);
|
||||
|
||||
const auto body = child_at(for_node, 3);
|
||||
|
||||
return make_compiled_node(for_node, {body},
|
||||
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
assert(children.size() == 1);
|
||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||
|
||||
int i = start_int;
|
||||
t_ss.add_object(id, var(&i));
|
||||
|
||||
try {
|
||||
for (; i < end_int; ++i) {
|
||||
try {
|
||||
// Body of Loop
|
||||
children[0]->eval(t_ss);
|
||||
} catch (eval::detail::Continue_Loop &) {
|
||||
// we got a continue exception, which means all of the remaining
|
||||
// loop implementation is skipped and we just need to continue to
|
||||
// the next iteration step
|
||||
}
|
||||
}
|
||||
} catch (eval::detail::Break_Loop &) {
|
||||
// loop broken
|
||||
}
|
||||
|
||||
return void_var();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return for_node;
|
||||
}
|
||||
} else {
|
||||
return for_node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
81
include/chaiscript/language/chaiscript_posix.hpp
Normal file
81
include/chaiscript/language/chaiscript_posix.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||
#define CHAISCRIPT_POSIX_HPP_
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(DLModule &&) = default;
|
||||
DLModule &operator=(DLModule &&) = default;
|
||||
DLModule(const DLModule &) = delete;
|
||||
DLModule &operator=(const DLModule &) = delete;
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
}
|
||||
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
static T cast_symbol(void *p)
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
T func_ptr;
|
||||
void *in_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = p;
|
||||
return c.func_ptr;
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// and 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
struct ChaiScript_Prelude {
|
||||
static std::string chaiscript_prelude() { return R""(
|
||||
static std::string chaiscript_prelude() { return R"chaiscript(
|
||||
|
||||
def lt(l, r) {
|
||||
if (call_exists(`<`, l, r)) {
|
||||
@@ -41,25 +41,25 @@ def new(x) {
|
||||
}
|
||||
|
||||
def clone(double x) {
|
||||
double(x).copy_var_attrs(x)
|
||||
double(x).clone_var_attrs(x)
|
||||
}
|
||||
|
||||
def clone(string x) {
|
||||
string(x).copy_var_attrs(x)
|
||||
string(x).clone_var_attrs(x)
|
||||
}
|
||||
|
||||
def clone(vector x) {
|
||||
vector(x).copy_var_attrs(x)
|
||||
vector(x).clone_var_attrs(x)
|
||||
}
|
||||
|
||||
|
||||
def clone(int x) {
|
||||
int(x).copy_var_attrs(x)
|
||||
int(x).clone_var_attrs(x)
|
||||
}
|
||||
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
|
||||
{
|
||||
eval(type_name(x))(x).copy_var_attrs(x);
|
||||
eval(type_name(x))(x).clone_var_attrs(x);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,11 +145,6 @@ def reverse(container) {
|
||||
retval;
|
||||
}
|
||||
|
||||
# Return a range from a range
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
|
||||
{
|
||||
clone(r);
|
||||
}
|
||||
|
||||
def range(r) : call_exists(range_internal, r)
|
||||
{
|
||||
@@ -158,6 +153,13 @@ def range(r) : call_exists(range_internal, r)
|
||||
ri;
|
||||
}
|
||||
|
||||
# Return a range from a range
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
|
||||
{
|
||||
clone(r);
|
||||
}
|
||||
|
||||
|
||||
# The retro attribute that contains the underlying range
|
||||
attr retro::m_range;
|
||||
|
||||
@@ -213,6 +215,29 @@ def for_each(container, func) : call_exists(range, container) {
|
||||
}
|
||||
}
|
||||
|
||||
def any_of(container, func) : call_exists(range, container) {
|
||||
var t_range := range(container);
|
||||
while (!t_range.empty()) {
|
||||
if (func(t_range.front())) {
|
||||
return true;
|
||||
}
|
||||
t_range.pop_front();
|
||||
}
|
||||
false;
|
||||
}
|
||||
|
||||
def all_of(container, func) : call_exists(range, container) {
|
||||
var t_range := range(container);
|
||||
while (!t_range.empty()) {
|
||||
if (!func(t_range.front())) {
|
||||
return false;
|
||||
}
|
||||
t_range.pop_front();
|
||||
}
|
||||
|
||||
true;
|
||||
}
|
||||
|
||||
def back_inserter(container) {
|
||||
bind(push_back, container, _);
|
||||
}
|
||||
@@ -528,7 +553,7 @@ def find(container, value) {
|
||||
}
|
||||
|
||||
|
||||
)"";
|
||||
)chaiscript";
|
||||
}
|
||||
|
||||
};
|
@@ -505,7 +505,7 @@ class Function
|
||||
/// \endcode
|
||||
Vector get_contained_functions() const;
|
||||
|
||||
/// \brief Returns a vector of the contained functions
|
||||
/// \brief Returns a function guard as function
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
|
43
include/chaiscript/language/chaiscript_tracer.hpp
Normal file
43
include/chaiscript/language/chaiscript_tracer.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||
#define CHAISCRIPT_TRACER_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
namespace eval {
|
||||
|
||||
struct Noop_Tracer
|
||||
{
|
||||
template<typename T>
|
||||
static void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... T>
|
||||
struct Tracer : T...
|
||||
{
|
||||
Tracer() = default;
|
||||
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)... };
|
||||
}
|
||||
|
||||
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
27
include/chaiscript/language/chaiscript_unknown.hpp
Normal file
27
include/chaiscript/language/chaiscript_unknown.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||
#define CHAISCRIPT_UNKNOWN_HPP_
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
133
include/chaiscript/language/chaiscript_windows.hpp
Normal file
133
include/chaiscript/language/chaiscript_windows.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_WINDOWS_HPP_
|
||||
#define CHAISCRIPT_WINDOWS_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#define VC_EXTRA_LEAN
|
||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
template<typename T>
|
||||
static std::wstring to_wstring(const T &t_str)
|
||||
{
|
||||
return std::wstring(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string to_string(const T &t_str)
|
||||
{
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
template<typename T>
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_wstring(t_str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_string(t_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
typedef LPTSTR StringType;
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
std::wstring retval = L"Unknown Error";
|
||||
#else
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = nullptr;
|
||||
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||
0, nullptr ) != 0 && lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
return to_string(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(DLModule &&) = default;
|
||||
DLModule &operator=(DLModule &&) = default;
|
||||
DLModule(const DLModule &) = delete;
|
||||
DLModule &operator=(const DLModule &) = delete;
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
FreeLibrary(m_data);
|
||||
}
|
||||
|
||||
HMODULE m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
589
include/chaiscript/utility/json.hpp
Normal file
589
include/chaiscript/utility/json.hpp
Normal file
@@ -0,0 +1,589 @@
|
||||
// From github.com/nbsdx/SimpleJSON.
|
||||
// Released under the DWTFYW PL
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SIMPLEJSON_HPP
|
||||
#define SIMPLEJSON_HPP
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <initializer_list>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
namespace json {
|
||||
|
||||
using std::enable_if;
|
||||
using std::initializer_list;
|
||||
using std::is_same;
|
||||
using std::is_convertible;
|
||||
using std::is_integral;
|
||||
using std::is_floating_point;
|
||||
|
||||
|
||||
|
||||
|
||||
class JSON
|
||||
{
|
||||
public:
|
||||
enum class Class {
|
||||
Null,
|
||||
Object,
|
||||
Array,
|
||||
String,
|
||||
Floating,
|
||||
Integral,
|
||||
Boolean
|
||||
};
|
||||
|
||||
private:
|
||||
struct Internal {
|
||||
template<typename T>
|
||||
auto clone(const std::unique_ptr<T> &ptr) {
|
||||
if (ptr != nullptr) {
|
||||
return std::make_unique<T>(*ptr);
|
||||
} else {
|
||||
return std::unique_ptr<T>(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Internal( double d ) : Float( d ), Type(Class::Floating) {}
|
||||
Internal( long l ) : Int( l ), Type(Class::Integral) {}
|
||||
Internal( bool b ) : Bool( b ), Type(Class::Boolean) {}
|
||||
Internal( std::string s ) : String(std::make_unique<std::string>(std::move(s))), Type(Class::String) {}
|
||||
Internal() : Type(Class::Null) {}
|
||||
|
||||
Internal(Class t_type) {
|
||||
set_type(t_type);
|
||||
}
|
||||
|
||||
Internal(const Internal &other)
|
||||
: List(clone(other.List)),
|
||||
Map(clone(other.Map)),
|
||||
String(clone(other.String)),
|
||||
Float(other.Float),
|
||||
Int(other.Int),
|
||||
Bool(other.Bool),
|
||||
Type(other.Type)
|
||||
{
|
||||
}
|
||||
|
||||
Internal &operator=(const Internal &other)
|
||||
{
|
||||
List = clone(other.List);
|
||||
Map = clone(other.Map);
|
||||
String = clone(other.String);
|
||||
Float = other.Float;
|
||||
Int = other.Int;
|
||||
Bool = other.Bool;
|
||||
Type = other.Type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set_type( Class type ) {
|
||||
if( type == Type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map.reset();
|
||||
List.reset();
|
||||
String.reset();
|
||||
|
||||
switch( type ) {
|
||||
case Class::Object: Map = std::make_unique<std::map<std::string,JSON>>(); 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;
|
||||
case Class::Integral: Int = 0; break;
|
||||
case Class::Boolean: Bool = false; break;
|
||||
case Class::Null: break;
|
||||
}
|
||||
|
||||
Type = type;
|
||||
}
|
||||
|
||||
Internal(Internal &&) = default;
|
||||
Internal &operator=(Internal &&) = default;
|
||||
|
||||
std::unique_ptr<std::vector<JSON>> List;
|
||||
std::unique_ptr<std::map<std::string,JSON>> Map;
|
||||
std::unique_ptr<std::string> String;
|
||||
double Float = 0;
|
||||
long Int = 0;
|
||||
bool Bool = false;
|
||||
|
||||
Class Type = Class::Null;
|
||||
};
|
||||
|
||||
Internal internal;
|
||||
|
||||
public:
|
||||
|
||||
template <typename Container>
|
||||
class JSONWrapper {
|
||||
Container *object = nullptr;
|
||||
|
||||
public:
|
||||
JSONWrapper( Container *val ) : object( val ) {}
|
||||
JSONWrapper( std::nullptr_t ) {}
|
||||
|
||||
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
|
||||
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
|
||||
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); }
|
||||
typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); }
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
class JSONConstWrapper {
|
||||
const Container *object = nullptr;
|
||||
|
||||
public:
|
||||
JSONConstWrapper( const Container *val ) : object( val ) {}
|
||||
JSONConstWrapper( std::nullptr_t ) {}
|
||||
|
||||
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); }
|
||||
typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); }
|
||||
};
|
||||
|
||||
JSON() = default;
|
||||
JSON( std::nullptr_t ) {}
|
||||
|
||||
explicit JSON(Class type)
|
||||
: internal(type)
|
||||
{
|
||||
}
|
||||
|
||||
JSON( initializer_list<JSON> list )
|
||||
: internal(Class::Object)
|
||||
{
|
||||
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) {
|
||||
operator[]( i->to_string() ) = *std::next( i );
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) : internal( static_cast<bool>(b) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) : internal( static_cast<long>(i) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) : internal( static_cast<double>(f) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T s, typename enable_if<is_convertible<T,std::string>::value>::type* = nullptr ) : internal( static_cast<std::string>(s) ) {}
|
||||
|
||||
|
||||
|
||||
static JSON Load( const std::string & );
|
||||
|
||||
JSON& operator[]( const std::string &key ) {
|
||||
internal.set_type( Class::Object );
|
||||
return internal.Map->operator[]( key );
|
||||
}
|
||||
|
||||
JSON& operator[]( const size_t index ) {
|
||||
internal.set_type( Class::Array );
|
||||
if( index >= internal.List->size() ) {
|
||||
internal.List->resize( index + 1 );
|
||||
}
|
||||
|
||||
return internal.List->operator[]( index );
|
||||
}
|
||||
|
||||
|
||||
JSON &at( const std::string &key ) {
|
||||
return operator[]( key );
|
||||
}
|
||||
|
||||
const JSON &at( const std::string &key ) const {
|
||||
return internal.Map->at( key );
|
||||
}
|
||||
|
||||
JSON &at( size_t index ) {
|
||||
return operator[]( index );
|
||||
}
|
||||
|
||||
const JSON &at( size_t index ) const {
|
||||
return internal.List->at( index );
|
||||
}
|
||||
|
||||
|
||||
long length() const {
|
||||
if( internal.Type == Class::Array ) {
|
||||
return static_cast<long>(internal.List->size());
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool has_key( const std::string &key ) const {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return internal.Map->find( key ) != internal.Map->end();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int size() const {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return static_cast<int>(internal.Map->size());
|
||||
} else if( internal.Type == Class::Array ) {
|
||||
return static_cast<int>(internal.List->size());
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Class JSONType() const { return internal.Type; }
|
||||
|
||||
/// Functions for getting primitives from the JSON object.
|
||||
bool is_null() const { return internal.Type == Class::Null; }
|
||||
|
||||
std::string to_string() const { bool b; return to_string( b ); }
|
||||
std::string to_string( bool &ok ) const {
|
||||
ok = (internal.Type == Class::String);
|
||||
return ok ? *internal.String : std::string("");
|
||||
}
|
||||
|
||||
double to_float() const { bool b; return to_float( b ); }
|
||||
double to_float( bool &ok ) const {
|
||||
ok = (internal.Type == Class::Floating);
|
||||
return ok ? internal.Float : 0.0;
|
||||
}
|
||||
|
||||
long to_int() const { bool b; return to_int( b ); }
|
||||
long to_int( bool &ok ) const {
|
||||
ok = (internal.Type == Class::Integral);
|
||||
return ok ? internal.Int : 0;
|
||||
}
|
||||
|
||||
bool to_bool() const { bool b; return to_bool( b ); }
|
||||
bool to_bool( bool &ok ) const {
|
||||
ok = (internal.Type == Class::Boolean);
|
||||
return ok ? internal.Bool : false;
|
||||
}
|
||||
|
||||
JSONWrapper<std::map<std::string,JSON>> object_range() {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return JSONWrapper<std::map<std::string,JSON>>( internal.Map.get() );
|
||||
} else {
|
||||
return JSONWrapper<std::map<std::string,JSON>>( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
JSONWrapper<std::vector<JSON>> array_range() {
|
||||
if( internal.Type == Class::Array ) {
|
||||
return JSONWrapper<std::vector<JSON>>( internal.List.get() );
|
||||
} else {
|
||||
return JSONWrapper<std::vector<JSON>>( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
JSONConstWrapper<std::map<std::string,JSON>> object_range() const {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return JSONConstWrapper<std::map<std::string,JSON>>( internal.Map.get() );
|
||||
} else {
|
||||
return JSONConstWrapper<std::map<std::string,JSON>>( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JSONConstWrapper<std::vector<JSON>> array_range() const {
|
||||
if( internal.Type == Class::Array ) {
|
||||
return JSONConstWrapper<std::vector<JSON>>( internal.List.get() );
|
||||
} else {
|
||||
return JSONConstWrapper<std::vector<JSON>>( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
std::string dump( long depth = 1, std::string tab = " ") const {
|
||||
switch( internal.Type ) {
|
||||
case Class::Null:
|
||||
return "null";
|
||||
case Class::Object: {
|
||||
std::string pad = "";
|
||||
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";
|
||||
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||
skip = false;
|
||||
}
|
||||
s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ;
|
||||
return s;
|
||||
}
|
||||
case Class::Array: {
|
||||
std::string s = "[";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.List ) {
|
||||
if( !skip ) s += ", ";
|
||||
s += p.dump( depth + 1, tab );
|
||||
skip = false;
|
||||
}
|
||||
s += "]";
|
||||
return s;
|
||||
}
|
||||
case Class::String:
|
||||
return "\"" + json_escape( *internal.String ) + "\"";
|
||||
case Class::Floating:
|
||||
return std::to_string( internal.Float );
|
||||
case Class::Integral:
|
||||
return std::to_string( internal.Int );
|
||||
case Class::Boolean:
|
||||
return internal.Bool ? "true" : "false";
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unhandled JSON type");
|
||||
}
|
||||
|
||||
|
||||
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] ) {
|
||||
case '\"': output += "\\\""; break;
|
||||
case '\\': output += "\\\\"; break;
|
||||
case '\b': output += "\\b"; break;
|
||||
case '\f': output += "\\f"; break;
|
||||
case '\n': output += "\\n"; break;
|
||||
case '\r': output += "\\r"; break;
|
||||
case '\t': output += "\\t"; break;
|
||||
default : output += str[i]; break;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
struct JSONParser {
|
||||
static bool isspace(const char c)
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// MSVC warns on these line in some circumstances
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6330)
|
||||
#endif
|
||||
return ::isspace(c) != 0;
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void consume_ws( const std::string &str, size_t &offset ) {
|
||||
while( isspace( str[offset] ) && offset <= str.size() ) ++offset;
|
||||
}
|
||||
|
||||
static JSON parse_object( const std::string &str, size_t &offset ) {
|
||||
JSON Object( JSON::Class::Object );
|
||||
|
||||
++offset;
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] == '}' ) {
|
||||
++offset; return Object;
|
||||
}
|
||||
|
||||
for (;offset<str.size();) {
|
||||
JSON Key = parse_next( str, offset );
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] != ':' ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str[offset] + "'\n");
|
||||
}
|
||||
consume_ws( str, ++offset );
|
||||
JSON Value = parse_next( str, offset );
|
||||
Object[Key.to_string()] = Value;
|
||||
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] == ',' ) {
|
||||
++offset; continue;
|
||||
}
|
||||
else if( str[offset] == '}' ) {
|
||||
++offset; break;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str[offset] + "'\n");
|
||||
}
|
||||
}
|
||||
|
||||
return Object;
|
||||
}
|
||||
|
||||
static JSON parse_array( const std::string &str, size_t &offset ) {
|
||||
JSON Array( JSON::Class::Array );
|
||||
size_t index = 0;
|
||||
|
||||
++offset;
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] == ']' ) {
|
||||
++offset; return Array;
|
||||
}
|
||||
|
||||
for (;offset < str.size();) {
|
||||
Array[index++] = parse_next( str, offset );
|
||||
consume_ws( str, offset );
|
||||
|
||||
if( str[offset] == ',' ) {
|
||||
++offset; continue;
|
||||
}
|
||||
else if( str[offset] == ']' ) {
|
||||
++offset; break;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str[offset] + "'\n");
|
||||
}
|
||||
}
|
||||
|
||||
return Array;
|
||||
}
|
||||
|
||||
static JSON parse_string( const std::string &str, size_t &offset ) {
|
||||
std::string val;
|
||||
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) {
|
||||
if( c == '\\' ) {
|
||||
switch( str[ ++offset ] ) {
|
||||
case '\"': val += '\"'; break;
|
||||
case '\\': val += '\\'; break;
|
||||
case '/' : val += '/' ; break;
|
||||
case 'b' : val += '\b'; break;
|
||||
case 'f' : val += '\f'; break;
|
||||
case 'n' : val += '\n'; break;
|
||||
case 'r' : val += '\r'; break;
|
||||
case 't' : val += '\t'; break;
|
||||
case 'u' : {
|
||||
val += "\\u" ;
|
||||
for( size_t i = 1; i <= 4; ++i ) {
|
||||
c = str[offset+i];
|
||||
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
|
||||
val += c;
|
||||
else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
||||
}
|
||||
}
|
||||
offset += 4;
|
||||
} break;
|
||||
default : val += '\\'; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
val += c;
|
||||
}
|
||||
++offset;
|
||||
return JSON(val);
|
||||
}
|
||||
|
||||
static JSON parse_number( const std::string &str, size_t &offset ) {
|
||||
std::string val, exp_str;
|
||||
char c = '\0';
|
||||
bool isDouble = false;
|
||||
long exp = 0;
|
||||
for (; offset < str.size() ;) {
|
||||
c = str[offset++];
|
||||
if( (c == '-') || (c >= '0' && c <= '9') )
|
||||
val += c;
|
||||
else if( c == '.' ) {
|
||||
val += c;
|
||||
isDouble = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if( offset < str.size() && (c == 'E' || c == 'e' )) {
|
||||
c = str[ offset++ ];
|
||||
if( c == '-' ) { exp_str += '-';}
|
||||
else if( c == '+' ) { }
|
||||
else --offset;
|
||||
|
||||
for (; offset < str.size() ;) {
|
||||
c = str[ offset++ ];
|
||||
if( c >= '0' && c <= '9' )
|
||||
exp_str += c;
|
||||
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
exp = chaiscript::parse_num<long>( exp_str );
|
||||
}
|
||||
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
||||
}
|
||||
--offset;
|
||||
|
||||
if( isDouble ) {
|
||||
return JSON(chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||
} else {
|
||||
if( !exp_str.empty() ) {
|
||||
return JSON(static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp ));
|
||||
} else {
|
||||
return JSON(chaiscript::parse_num<long>( val ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static JSON parse_bool( const std::string &str, size_t &offset ) {
|
||||
if( str.substr( offset, 4 ) == "true" ) {
|
||||
offset += 4;
|
||||
return JSON(true);
|
||||
} else if( str.substr( offset, 5 ) == "false" ) {
|
||||
offset += 5;
|
||||
return JSON(false);
|
||||
} else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
static JSON parse_null( const std::string &str, size_t &offset ) {
|
||||
if( str.substr( offset, 4 ) != "null" ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'");
|
||||
}
|
||||
offset += 4;
|
||||
return JSON();
|
||||
}
|
||||
|
||||
static JSON parse_next( const std::string &str, size_t &offset ) {
|
||||
char value;
|
||||
consume_ws( str, offset );
|
||||
value = str[offset];
|
||||
switch( value ) {
|
||||
case '[' : return parse_array( str, offset );
|
||||
case '{' : return parse_object( str, offset );
|
||||
case '\"': return parse_string( str, offset );
|
||||
case 't' :
|
||||
case 'f' : return parse_bool( str, offset );
|
||||
case 'n' : return parse_null( str, offset );
|
||||
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
|
||||
return parse_number( str, offset );
|
||||
}
|
||||
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline JSON JSON::Load( const std::string &str ) {
|
||||
size_t offset = 0;
|
||||
return JSONParser::parse_next( str, offset );
|
||||
}
|
||||
|
||||
} // End Namespace json
|
||||
|
||||
|
||||
#endif
|
150
include/chaiscript/utility/json_wrap.hpp
Normal file
150
include/chaiscript/utility/json_wrap.hpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#ifndef CHAISCRIPT_SIMPLEJSON_WRAP_HPP
|
||||
#define CHAISCRIPT_SIMPLEJSON_WRAP_HPP
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class json_wrap
|
||||
{
|
||||
public:
|
||||
|
||||
static Module& library(Module& m)
|
||||
{
|
||||
|
||||
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
||||
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
||||
|
||||
return m;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static Boxed_Value from_json(const json::JSON &t_json)
|
||||
{
|
||||
switch( t_json.JSONType() ) {
|
||||
case json::JSON::Class::Null:
|
||||
return Boxed_Value();
|
||||
case json::JSON::Class::Object:
|
||||
{
|
||||
std::map<std::string, Boxed_Value> m;
|
||||
|
||||
for (const auto &p : t_json.object_range())
|
||||
{
|
||||
m.insert(std::make_pair(p.first, from_json(p.second)));
|
||||
}
|
||||
|
||||
return Boxed_Value(m);
|
||||
}
|
||||
case json::JSON::Class::Array:
|
||||
{
|
||||
std::vector<Boxed_Value> vec;
|
||||
|
||||
for (const auto &p : t_json.array_range())
|
||||
{
|
||||
vec.emplace_back(from_json(p));
|
||||
}
|
||||
|
||||
return Boxed_Value(vec);
|
||||
}
|
||||
case json::JSON::Class::String:
|
||||
return Boxed_Value(t_json.to_string());
|
||||
case json::JSON::Class::Floating:
|
||||
return Boxed_Value(t_json.to_float());
|
||||
case json::JSON::Class::Integral:
|
||||
return Boxed_Value(t_json.to_int());
|
||||
case json::JSON::Class::Boolean:
|
||||
return Boxed_Value(t_json.to_bool());
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown JSON type");
|
||||
}
|
||||
|
||||
static Boxed_Value from_json(const std::string &t_json)
|
||||
{
|
||||
return from_json( json::JSON::Load(t_json) );
|
||||
}
|
||||
|
||||
static std::string to_json(const Boxed_Value &t_bv)
|
||||
{
|
||||
return to_json_object(t_bv).dump();
|
||||
}
|
||||
|
||||
static json::JSON to_json_object(const Boxed_Value &t_bv)
|
||||
{
|
||||
try {
|
||||
const std::map<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(t_bv);
|
||||
|
||||
json::JSON obj;
|
||||
for (const auto &o : m)
|
||||
{
|
||||
obj[o.first] = to_json_object(o.second);
|
||||
}
|
||||
return obj;
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
// not a map
|
||||
}
|
||||
|
||||
try {
|
||||
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
|
||||
|
||||
json::JSON obj;
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
obj[i] = to_json_object(v[i]);
|
||||
}
|
||||
return obj;
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
// not a vector
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Boxed_Number bn(t_bv);
|
||||
if (Boxed_Number::is_floating_point(t_bv))
|
||||
{
|
||||
return json::JSON(bn.get_as<double>());
|
||||
} else {
|
||||
return json::JSON(bn.get_as<long>());
|
||||
}
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
// not a number
|
||||
}
|
||||
|
||||
try {
|
||||
return json::JSON(boxed_cast<bool>(t_bv));
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
// not a bool
|
||||
}
|
||||
|
||||
try {
|
||||
return json::JSON(boxed_cast<std::string>(t_bv));
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
// not a string
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(t_bv);
|
||||
|
||||
json::JSON obj;
|
||||
for (const auto &attr : o.get_attrs())
|
||||
{
|
||||
obj[attr.first] = to_json_object(attr.second);
|
||||
}
|
||||
return obj;
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
// not a dynamic object
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown object type to convert to JSON");
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,19 +1,20 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "../dispatchkit/type_info.hpp"
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
#include "../dispatchkit/register_function.hpp"
|
||||
#include "../dispatchkit/operators.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
@@ -62,6 +63,32 @@ namespace chaiscript
|
||||
t_module.add(fun.first, fun.second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Enum, typename ModuleType>
|
||||
typename std::enable_if<std::is_enum<Enum>::value, void>::type
|
||||
add_class(ModuleType &t_module,
|
||||
const std::string &t_class_name,
|
||||
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants
|
||||
)
|
||||
{
|
||||
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
|
||||
|
||||
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
|
||||
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
|
||||
|
||||
using namespace chaiscript::bootstrap::operators;
|
||||
equal<Enum>(t_module);
|
||||
not_equal<Enum>(t_module);
|
||||
assign<Enum>(t_module);
|
||||
|
||||
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
|
||||
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
|
||||
|
||||
for (const auto &constant : t_constants)
|
||||
{
|
||||
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2015 Jason Turner
|
||||
Copyright 2009-2016 Jason Turner
|
||||
Copyright 2009-2012 Jonathan Turner.
|
||||
|
||||
All Rights Reserved.
|
||||
|
26
performance_tests/profile_cpp_calls.chai
Normal file
26
performance_tests/profile_cpp_calls.chai
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
var test_str = "bob was a string";
|
||||
|
||||
for( var i = 0; i < 200000; ++i)
|
||||
{
|
||||
test_str.size();
|
||||
// test_str.find("a", i);
|
||||
test_str.c_str();
|
||||
test_str.erase_at(1);
|
||||
test_str.erase_at(1);
|
||||
test_str.erase_at(1);
|
||||
test_str.erase_at(1);
|
||||
test_str.erase_at(1);
|
||||
test_str.erase_at(1);
|
||||
|
||||
size(test_str);
|
||||
// test_str.find("a", i);
|
||||
c_str(test_str);
|
||||
erase_at(test_str, 1);
|
||||
erase_at(test_str, 1);
|
||||
erase_at(test_str, 1);
|
||||
erase_at(test_str, 1);
|
||||
erase_at(test_str, 1);
|
||||
erase_at(test_str, 1);
|
||||
test_str = "bob was a string";
|
||||
}
|
20
performance_tests/profile_cpp_calls_2.cpp
Normal file
20
performance_tests/profile_cpp_calls_2.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
double f(const std::string &, double, bool) noexcept {
|
||||
return .0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
|
||||
chai.add(chaiscript::fun(&f), "f");
|
||||
|
||||
chai.eval(R"(
|
||||
for (var i = 0; i < 100000; ++i) {
|
||||
f("str", 1.2, false);
|
||||
}
|
||||
)");
|
||||
|
||||
}
|
20
performance_tests/profile_fun_wrappers.cpp
Normal file
20
performance_tests/profile_fun_wrappers.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
double f(const std::string &, double, bool) noexcept {
|
||||
return .0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
|
||||
chai.add(chaiscript::fun(&f), "f");
|
||||
|
||||
const auto f = chai.eval<std::function<void ()>>(R"(fun(){ f("str", 1.2, false); })");
|
||||
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
f();
|
||||
}
|
||||
|
||||
}
|
@@ -1,3 +1,8 @@
|
||||
<a href="https://www.patreon.com/bePatron?u=2977989&redirect_uri=https%3A%2F%2Fwww.patreon.com%2Flefticus">
|
||||
<img height="40" width="204" src="https://s3-us-west-1.amazonaws.com/widget-images/become-patron-widget-medium%402x.png">
|
||||
</a>
|
||||
|
||||
|
||||
Master Status: [](https://travis-ci.org/ChaiScript/ChaiScript) [](https://ci.appveyor.com/project/lefticus/chaiscript) [](http://codecov.io/github/ChaiScript/ChaiScript?branch=master)
|
||||
|
||||
Develop Status: [](https://travis-ci.org/ChaiScript/ChaiScript) [](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [](http://codecov.io/github/ChaiScript/ChaiScript?branch=develop)
|
||||
@@ -12,7 +17,7 @@ ChaiScript
|
||||
http://www.chaiscript.com
|
||||
|
||||
(c) 2009-2012 Jonathan Turner
|
||||
(c) 2009-2015 Jason Turner
|
||||
(c) 2009-2016 Jason Turner
|
||||
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
|
@@ -1,6 +1,38 @@
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.7.1
|
||||
Current Version: 5.8.2
|
||||
|
||||
### Changes since 5.8.1
|
||||
* Allow casting to non-const & std::shared_ptr<T>
|
||||
|
||||
|
||||
### Changes since 5.8.0
|
||||
* Fix parsing of floats to be locale independent #250
|
||||
* Various warning fixes on various platforms
|
||||
|
||||
|
||||
### Changes since 5.7.1
|
||||
* Make all parser iterator operations range checked
|
||||
* Parse in-string eval statements once, not once for each execution
|
||||
* Fix parsing of operators (ie 1<-1 now parses)
|
||||
* Fix variable scoping for functors
|
||||
* Exception reduction
|
||||
* Various object lifetime fixes
|
||||
* Add JSON support for load / save #207
|
||||
* Numeric overload resolution fixes #209
|
||||
* Fix long long #208
|
||||
* Add octal escapes in strings #211
|
||||
* Fixed sizing of binary literals #213
|
||||
* Added support for != with bool values #217
|
||||
* Various value assignment vector fixes
|
||||
* Fixed broken hex escape sequences from @ChristianKaeser
|
||||
* Multiply defined symbols fixes #232 @RaptorFactor
|
||||
* Add add_class<Enum> helper #233 @vrennert
|
||||
* Cheatsheet fixes #235 @mlamby
|
||||
* Fix parsing of strings inside of in-string eval statements
|
||||
* Allow lower-case global keyword
|
||||
* Enable thread-local on MSVC (should be significant performance boost)
|
||||
|
||||
|
||||
### Changes since 5.7.0
|
||||
* Build time reduction
|
||||
|
103
samples/factory.cpp
Normal file
103
samples/factory.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
int width;
|
||||
int height;
|
||||
int x;
|
||||
int y;
|
||||
std::string name;
|
||||
|
||||
std::function<void (Entity &)> updater;
|
||||
|
||||
Entity(const int t_width, const int t_height, const int t_x, const int t_y, std::string t_name)
|
||||
: width(t_width), height(t_height), x(t_x), y(t_y), name(std::move(t_name))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
// we may as well pass the parameters for the entity to the factory method, this does the initialization
|
||||
// in one step.
|
||||
Entity *make_entity(const int width, const int height, const int x, const int y, const std::string &name)
|
||||
{
|
||||
auto entity = entities.insert({name, Entity{width, height, x, y, name}});
|
||||
return &(entity.first->second);
|
||||
}
|
||||
|
||||
Entity *get_entity(const std::string &name)
|
||||
{
|
||||
return &entities.at(name);
|
||||
}
|
||||
|
||||
|
||||
// loop over all entities and all their updater function (if it exists)
|
||||
void update_entities()
|
||||
{
|
||||
for (auto &entity : entities)
|
||||
{
|
||||
if (entity.second.updater) {
|
||||
entity.second.updater(entity.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// we cannot store the entities in a std::vector if we want to return a pointer to them,
|
||||
// because a vector automatically resizing itself can invalidate the pointer that was returned.
|
||||
// using a map guarantees that the memory assigned to the entity will never change, plus
|
||||
// lets us easily look up an entity by name
|
||||
std::map<std::string, Entity> entities;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
|
||||
chai.add(chaiscript::fun(&Entity::width), "width");
|
||||
chai.add(chaiscript::fun(&Entity::height), "height");
|
||||
chai.add(chaiscript::fun(&Entity::x), "x");
|
||||
chai.add(chaiscript::fun(&Entity::y), "y");
|
||||
chai.add(chaiscript::fun(&Entity::name), "name");
|
||||
chai.add(chaiscript::fun(&Entity::updater), "updater");
|
||||
chai.add(chaiscript::user_type<Entity>(), "Entity"); // this isn't strictly necessary but makes error messages nicer
|
||||
|
||||
chai.add(chaiscript::fun(&Factory::make_entity), "make_entity");
|
||||
chai.add(chaiscript::fun(&Factory::get_entity), "get_entity");
|
||||
chai.add(chaiscript::fun(&Factory::update_entities), "update_entities");
|
||||
chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
|
||||
|
||||
|
||||
Factory f;
|
||||
chai.add(chaiscript::var(&f), "f");
|
||||
|
||||
std::string script = R""(
|
||||
f.make_entity(10,10,1,1,"entity1").updater = fun(e){ e.x += 1; e.y += 1 };
|
||||
f.make_entity(10,10,10,10,"entity2").updater = fun(e){ e.x += 2; e.y += 2 };
|
||||
f.make_entity(10,10,20,20,"entity3");
|
||||
|
||||
print(f.get_entity("entity1").x == 1)
|
||||
print(f.get_entity("entity2").x == 10)
|
||||
print(f.get_entity("entity3").x == 20)
|
||||
|
||||
f.update_entities(); // this runs the function objects we set in the previous lines
|
||||
// we should now see the updated values
|
||||
|
||||
print(f.get_entity("entity1").x == 2)
|
||||
print(f.get_entity("entity2").x == 12)
|
||||
print(f.get_entity("entity3").x == 20) // this one has no updater, so it stays the same
|
||||
)"";
|
||||
|
||||
|
||||
chai.eval(script);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
@@ -89,24 +89,24 @@ std::vector<std::string> default_search_paths()
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) > 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
////for (int i = 0; i < 1000; i++)
|
||||
////{
|
||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
||||
////}
|
||||
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
|
||||
|
||||
|
@@ -44,14 +44,14 @@ class ChaiScriptDerived : public BaseClass
|
||||
tie(t_funcs.at(1), m_validateValueImpl);
|
||||
}
|
||||
|
||||
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
|
||||
std::string doSomething(float f, double d) const override
|
||||
{
|
||||
assert(m_doSomethingImpl);
|
||||
return m_doSomethingImpl(*this, f, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
|
||||
bool validateValue(const std::string &t_val) override
|
||||
{
|
||||
assert(m_validateValueImpl);
|
||||
return m_validateValueImpl(*this, t_val);
|
||||
|
34
samples/test_num_exceptions.cpp
Normal file
34
samples/test_num_exceptions.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||
|
||||
int main( int /*argc*/ , char * /*argv*/[] )
|
||||
{
|
||||
chaiscript::ChaiScript ch( chaiscript::Std_Lib::library( ) );
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
static const char script[ ] =
|
||||
R""(
|
||||
|
||||
class Rectangle
|
||||
{
|
||||
def Rectangle() { }
|
||||
}
|
||||
|
||||
var rect = Rectangle( );
|
||||
|
||||
)"";
|
||||
|
||||
|
||||
ch.eval( script );
|
||||
}
|
||||
catch ( const std::exception &e )
|
||||
{
|
||||
printf( " >>> Exception thrown: %s \n" , e.what( ) );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
24
src/main.cpp
24
src/main.cpp
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
@@ -66,7 +66,7 @@ std::vector<std::string> default_search_paths()
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
@@ -88,24 +88,24 @@ std::vector<std::string> default_search_paths()
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,17 +344,16 @@ int main(int argc, char *argv[])
|
||||
mode = eFile;
|
||||
}
|
||||
|
||||
chaiscript::Boxed_Value val ;
|
||||
try {
|
||||
switch ( mode ) {
|
||||
case eInteractive:
|
||||
interactive(chai);
|
||||
break;
|
||||
case eCommand:
|
||||
val = chai.eval(arg);
|
||||
chai.eval(arg);
|
||||
break;
|
||||
case eFile:
|
||||
val = chai.eval_file(arg);
|
||||
chai.eval_file(arg);
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
@@ -372,6 +371,9 @@ int main(int argc, char *argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::load_module_error &e) {
|
||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
||||
}
|
||||
|
||||
// catch (std::exception &e) {
|
||||
// std::cout << e.what() << '\n';
|
||||
|
@@ -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-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||
{
|
||||
|
||||
auto module = chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||
module->add(chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector"));
|
||||
auto module = std::make_shared<chaiscript::Module>();
|
||||
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List", *module);
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector", *module);
|
||||
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
|
||||
return module;
|
||||
}
|
||||
|
@@ -8,18 +8,10 @@
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4351)
|
||||
#endif
|
||||
// MSVC 12 warns that we are using new (correct) behavior
|
||||
TestBaseType() : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
TestBaseType(const TestBaseType &) = default;
|
||||
virtual ~TestBaseType() {}
|
||||
virtual int func() { return 0; }
|
||||
@@ -30,6 +22,11 @@ class TestBaseType
|
||||
|
||||
int val;
|
||||
const int const_val;
|
||||
const int *const_val_ptr = &const_val;
|
||||
|
||||
const int *get_const_val_ptr() {
|
||||
return const_val_ptr;
|
||||
}
|
||||
|
||||
int mdarray[2][3][5];
|
||||
std::function<int (int)> func_member;
|
||||
@@ -84,7 +81,7 @@ class TestDerivedType : public TestBaseType
|
||||
virtual ~TestDerivedType() {}
|
||||
TestDerivedType(const TestDerivedType &) = default;
|
||||
TestDerivedType() = default;
|
||||
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
|
||||
virtual int func() override { return 1; }
|
||||
int derived_only_func() { return 19; }
|
||||
|
||||
private:
|
||||
@@ -114,6 +111,16 @@ std::shared_ptr<TestBaseType> null_factory()
|
||||
return std::shared_ptr<TestBaseType>();
|
||||
}
|
||||
|
||||
void update_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
|
||||
{
|
||||
ptr = std::make_shared<TestDerivedType>();
|
||||
}
|
||||
|
||||
void nullify_shared_ptr(std::shared_ptr<TestBaseType> &ptr)
|
||||
{
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
std::string hello_world()
|
||||
{
|
||||
return "Hello World";
|
||||
@@ -176,19 +183,15 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
||||
m->add(chaiscript::fun(&TestBaseType::val), "val");
|
||||
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
|
||||
m->add(chaiscript::fun(&TestBaseType::const_val_ptr), "const_val_ptr");
|
||||
m->add(chaiscript::fun(&TestBaseType::get_const_val_ptr), "get_const_val_ptr");
|
||||
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
|
||||
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
|
||||
|
||||
#ifndef CHAISCRIPT_MSVC_12
|
||||
// we cannot support these in MSVC_12 because of a bug in the implementation of
|
||||
// std::reference_wrapper
|
||||
// Array types
|
||||
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
|
||||
m->add(chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5"));
|
||||
m->add(chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5"));
|
||||
m->add(chaiscript::bootstrap::array<int[5]>("IntArray_5"));
|
||||
// end array types
|
||||
#endif
|
||||
chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5", *m);
|
||||
chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5", *m);
|
||||
chaiscript::bootstrap::array<int[5]>("IntArray_5", *m);
|
||||
|
||||
// member that is a function
|
||||
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
|
||||
@@ -209,6 +212,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::type_conversion<const char *, std::string>());
|
||||
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
|
||||
|
||||
m->add(chaiscript::fun(&update_shared_ptr), "update_shared_ptr");
|
||||
m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
1
supporters.md
Normal file
1
supporters.md
Normal file
@@ -0,0 +1 @@
|
||||
|
@@ -1,7 +1,6 @@
|
||||
assert_equal(`==`, `==`);
|
||||
assert_not_equal(`==`, `<`);
|
||||
assert_equal(`<`.get_arity(), 2);
|
||||
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
|
||||
assert_equal(get_arity.get_contained_functions().size(), 0);
|
||||
assert_equal(get_arity.get_arity(), 1);
|
||||
assert_equal(get_arity.get_param_types().size(), 2);
|
||||
|
@@ -10,7 +10,6 @@ def test_function(a)
|
||||
|
||||
// test_function tests
|
||||
assert_equal(test_function.get_arity(), 1);
|
||||
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
|
||||
assert_equal(test_function.get_contained_functions().size(), 0);
|
||||
assert_equal(test_function.get_param_types().size(), 2);
|
||||
|
||||
|
@@ -1,36 +0,0 @@
|
||||
var parser := ChaiScript_Parser()
|
||||
var parse_success = parser.parse("3 + 4", "INPUT")
|
||||
var a := parser.ast()
|
||||
|
||||
assert_equal(eval(a), 7)
|
||||
|
||||
var childs := a.children.front().children
|
||||
var node := childs[0]
|
||||
|
||||
var parser2 := ChaiScript_Parser()
|
||||
parser2.parse("9", "INPUT")
|
||||
|
||||
|
||||
a.children.front().replace_child(childs[0], parser2.ast())
|
||||
|
||||
assert_equal(eval(a), 13)
|
||||
assert_equal(node.filename, "INPUT")
|
||||
|
||||
|
||||
|
||||
def my_fun()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
assert_equal(true, my_fun.has_parse_tree());
|
||||
assert_equal(false, `+`.has_parse_tree());
|
||||
|
||||
assert_throws("Function does not have a parse tree", fun() { `+`.get_parse_tree(); } );
|
||||
|
||||
var parsetree := my_fun.get_parse_tree();
|
||||
|
||||
assert_equal(1, eval(parsetree));
|
||||
|
||||
print(parsetree.text());
|
3
unittests/array_access.chai
Normal file
3
unittests/array_access.chai
Normal file
@@ -0,0 +1,3 @@
|
||||
var v = [[[15]]]
|
||||
|
||||
assert_true(v[0][0][0] == 15)
|
12
unittests/bool_comparisons.chai
Normal file
12
unittests/bool_comparisons.chai
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
assert_true(true == true)
|
||||
assert_false(true == false)
|
||||
assert_true(true != false)
|
||||
assert_true(false != true)
|
||||
assert_true(false || true)
|
||||
assert_true(true || false)
|
||||
assert_false(true && false)
|
||||
assert_false(false && true)
|
||||
assert_true(!false)
|
||||
assert_false(!true)
|
||||
|
@@ -13,9 +13,9 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
try {
|
||||
To ret = chaiscript::boxed_cast<To>(bv);
|
||||
use(ret);
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &e) {
|
||||
if (expectedpass) {
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
||||
std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
@@ -54,12 +54,13 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr, bool ConstTPtr, bool TPtrConst,
|
||||
bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
|
||||
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
|
||||
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef,
|
||||
bool ConstWrappedRefRef, bool ConstWrappedConstRefRef, bool Number,
|
||||
bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, bool ConstTPtrConstRef)
|
||||
bool do_test(const Boxed_Value &bv,
|
||||
bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr,
|
||||
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
|
||||
bool SharedPtrTRef, bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
|
||||
bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef,
|
||||
bool ConstWrappedConstRefRef, bool Number, bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef,
|
||||
bool ConstTPtrConstRef)
|
||||
{
|
||||
bool passed = true;
|
||||
passed &= test_type_conversion<Type>(bv, T);
|
||||
@@ -72,8 +73,8 @@ bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTR
|
||||
passed &= test_type_conversion<const Type * const>(bv, ConstTPtrConst);
|
||||
passed &= test_type_conversion<std::shared_ptr<Type> >(bv, SharedPtrT);
|
||||
passed &= test_type_conversion<std::shared_ptr<const Type> >(bv, SharedConstPtrT);
|
||||
passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, false);
|
||||
passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
|
||||
passed &= test_type_conversion<std::shared_ptr<Type> &>(bv, SharedPtrTRef);
|
||||
//passed &= test_type_conversion<std::shared_ptr<const Type> &>(bv, false);
|
||||
passed &= test_type_conversion<const std::shared_ptr<Type> >(bv, ConstSharedPtrT);
|
||||
passed &= test_type_conversion<const std::shared_ptr<const Type> >(bv, ConstSharedConstPtrT);
|
||||
passed &= test_type_conversion<const std::shared_ptr<Type> &>(bv, ConstSharedPtrTRef);
|
||||
@@ -115,37 +116,37 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
T i = T(initial);
|
||||
passed &= do_test<T>(var(i), true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
|
||||
passed &= do_test<T>(const_var(i), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
passed &= do_test<T>(var(&i), true, true, true, true, true,
|
||||
true, true, true, false, false,
|
||||
false, false, false, false, true,
|
||||
false, false, false, false, false, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
|
||||
passed &= do_test<T>(const_var(&i), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
passed &= do_test<T>(var(std::ref(i)), true, true, true, true, true,
|
||||
true, true, true, false, false,
|
||||
false, false, false, false, true,
|
||||
false, false, false, false, false, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
|
||||
passed &= do_test<T>(var(std::cref(i)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
@@ -156,33 +157,33 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
|
||||
passed &= do_test<T>(var(i), true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
|
||||
// But a pointer or reference to it should be necessarily const
|
||||
passed &= do_test<T>(var(&ir), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
passed &= do_test<T>(var(std::ref(ir)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
// Make sure const of const works too
|
||||
passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
passed &= do_test<T>(const_var(std::ref(ir)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
@@ -192,46 +193,46 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
const T*cip = &i;
|
||||
passed &= do_test<T>(var(cip), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
// make sure const of const works
|
||||
passed &= do_test<T>(const_var(cip), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
/** shared_ptr tests **/
|
||||
|
||||
std::shared_ptr<T> ip(new T(initial));
|
||||
auto ip = std::make_shared<T>(initial);
|
||||
|
||||
passed &= do_test<T>(var(ip), true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
|
||||
passed &= do_test<T>(const_var(ip), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
/** const shared_ptr tests **/
|
||||
std::shared_ptr<const T> ipc(new T(initial));
|
||||
auto ipc = std::make_shared<const T>(T(initial));
|
||||
|
||||
passed &= do_test<T>(var(ipc), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
// const of this should be the same, making sure it compiles
|
||||
passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
false, false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
|
||||
|
3223
unittests/catch.hpp
3223
unittests/catch.hpp
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user