Compare commits
375 Commits
Workaround
...
develop
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0f9d9cae4a | ||
![]() |
468d65a661 | ||
![]() |
9847618cf3 | ||
![]() |
a281d9571e | ||
![]() |
204faa82c1 | ||
![]() |
be2fec02d9 | ||
![]() |
491b95099d | ||
![]() |
561c5bc981 | ||
![]() |
12829ee5d2 | ||
![]() |
f53a1ed951 | ||
![]() |
12100cce99 | ||
![]() |
d22c27b627 | ||
![]() |
60c43233c6 | ||
![]() |
c2f7ca3aa2 | ||
![]() |
72cb9bd940 | ||
![]() |
84f9c44ab6 | ||
![]() |
698dfb06db | ||
![]() |
244b5b224b | ||
![]() |
534897d835 | ||
![]() |
fac5a39066 | ||
![]() |
064a385a64 | ||
![]() |
e342243193 | ||
![]() |
283785faaf | ||
![]() |
c0c0bd3172 | ||
![]() |
40fb8d257e | ||
![]() |
f5f6ddf219 | ||
![]() |
87f1242ed4 | ||
![]() |
faba0f1317 | ||
![]() |
077c93ab27 | ||
![]() |
914bca6295 | ||
![]() |
2549b4e983 | ||
![]() |
1cb15d8b22 | ||
![]() |
2ce155237d | ||
![]() |
dca3ce4ea6 | ||
![]() |
ca7d4ab734 | ||
![]() |
f5ced799cf | ||
![]() |
1499061f86 | ||
![]() |
24352c62e8 | ||
![]() |
6b4c47c5ba | ||
![]() |
396d43a13f | ||
![]() |
18cf09b512 | ||
![]() |
2782cdd33b | ||
![]() |
d8d7bc79b7 | ||
![]() |
3e04210027 | ||
![]() |
c82c9ccb6e | ||
![]() |
efd37a7071 | ||
![]() |
83b7973cb8 | ||
![]() |
e7a6b2306c | ||
![]() |
0a18f0a809 | ||
![]() |
8efba903c3 | ||
![]() |
ca87c05cd4 | ||
![]() |
94fb7c2453 | ||
![]() |
c54d84fae6 | ||
![]() |
574f4a9664 | ||
![]() |
b7e8897a43 | ||
![]() |
7a588ed5cf | ||
![]() |
89f373d21c | ||
![]() |
037335a0ea | ||
![]() |
2431362e54 | ||
![]() |
9c59600b9f | ||
![]() |
51663df1ba | ||
![]() |
624c7c435b | ||
![]() |
cf89bdd804 | ||
![]() |
a8e70a4cfe | ||
![]() |
f79de06e0b | ||
![]() |
cee57f998a | ||
![]() |
ce62706fea | ||
![]() |
92c2ade1cd | ||
![]() |
6b7481e6a1 | ||
![]() |
d096f926d3 | ||
![]() |
fb7f8f194c | ||
![]() |
78f885ec61 | ||
![]() |
d6d50478de | ||
![]() |
defdb53a55 | ||
![]() |
0dea62dd54 | ||
![]() |
590905f4b3 | ||
![]() |
9218dda001 | ||
![]() |
9e17514b57 | ||
![]() |
5f402e71dd | ||
![]() |
95e119fffe | ||
![]() |
f17439a9d3 | ||
![]() |
940e0c2d86 | ||
![]() |
e8c03b33c6 | ||
![]() |
b68f917677 | ||
![]() |
7f4af72244 | ||
![]() |
6757b66f95 | ||
![]() |
c9034a0485 | ||
![]() |
50dcbc8c7e | ||
![]() |
1ea91faf52 | ||
![]() |
745e0c0f0b | ||
![]() |
c42477f2eb | ||
![]() |
335a02f165 | ||
![]() |
012f1ffff5 | ||
![]() |
9925b20fad | ||
![]() |
28122f7cb0 | ||
![]() |
b1f1803759 | ||
![]() |
359897a442 | ||
![]() |
ffcd7e3a76 | ||
![]() |
2c99e6cd32 | ||
![]() |
332a62769b | ||
![]() |
a38b254a98 | ||
![]() |
77231461ca | ||
![]() |
eefd50a6bc | ||
![]() |
0d4a99af82 | ||
![]() |
9f30d84f39 | ||
![]() |
8b18e301d2 | ||
![]() |
508729ec77 | ||
![]() |
0fe78f7ba5 | ||
![]() |
6202149b4f | ||
![]() |
4ad661475b | ||
![]() |
6d309b7516 | ||
![]() |
7d9e1b3af7 | ||
![]() |
b99ccafa07 | ||
![]() |
c97a69537d | ||
![]() |
fac8f3ec90 | ||
![]() |
ab07872857 | ||
![]() |
23c13e6570 | ||
![]() |
aa9267726f | ||
![]() |
396e78d295 | ||
![]() |
7339ff2c2f | ||
![]() |
1efcddd335 | ||
![]() |
21ccb1d1d0 | ||
![]() |
c37c901a0c | ||
![]() |
690b96d9ee | ||
![]() |
d638d87a0f | ||
![]() |
b091439567 | ||
![]() |
665125665a | ||
![]() |
d1c7645a4e | ||
![]() |
58faea1cf2 | ||
![]() |
8b7fe33bf1 | ||
![]() |
7cc100e3d7 | ||
![]() |
21495ebb40 | ||
![]() |
b2907fc608 | ||
![]() |
bec1b91b7b | ||
![]() |
4b81a24a0a | ||
![]() |
3b2c82ba2c | ||
![]() |
8cb3bd4af8 | ||
![]() |
26e6f51fa8 | ||
![]() |
87294fc89d | ||
![]() |
9cc0ce01b9 | ||
![]() |
c9ee707972 | ||
![]() |
cefb4d3c78 | ||
![]() |
4e6e63ab5d | ||
![]() |
7561aa8828 | ||
![]() |
e44724c780 | ||
![]() |
b0f07cbe5d | ||
![]() |
62639a4359 | ||
![]() |
176d608bb4 | ||
![]() |
a1d90c95f0 | ||
![]() |
a14f1983e8 | ||
![]() |
5642e062e6 | ||
![]() |
9e16cc2a79 | ||
![]() |
201fef49c6 | ||
![]() |
58ebb22c55 | ||
![]() |
830b7c93ca | ||
![]() |
368a3b78a2 | ||
![]() |
e3e90de02a | ||
![]() |
8478ddc470 | ||
![]() |
2adefaf46d | ||
![]() |
bd26355516 | ||
![]() |
19a730b78b | ||
![]() |
e3d1741c63 | ||
![]() |
09bdec4882 | ||
![]() |
c31ebb5665 | ||
![]() |
52a191df9e | ||
![]() |
228c942b6c | ||
![]() |
09ed0ca573 | ||
![]() |
ee68ff20ed | ||
![]() |
b72eed3921 | ||
![]() |
039d0edce3 | ||
![]() |
7b3f06b269 | ||
![]() |
5373bbd52e | ||
![]() |
17821be1e2 | ||
![]() |
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 | ||
![]() |
fd57bec676 | ||
![]() |
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 | ||
![]() |
da1511a092 | ||
![]() |
8bd7ccfa9f | ||
![]() |
0806df11d2 | ||
![]() |
7d3c23fc22 |
@ -1,11 +1,12 @@
|
|||||||
compilers:
|
compilers:
|
||||||
- name: "clang"
|
- name: "clang"
|
||||||
version: "3.5"
|
version: "3.6"
|
||||||
skip_packaging: true
|
skip_packaging: true
|
||||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
|
||||||
|
collect_performance_results: true
|
||||||
- name: "clang"
|
- name: "clang"
|
||||||
build_tag: "LibC++"
|
build_tag: "LibC++"
|
||||||
version: "3.5"
|
version: "3.6"
|
||||||
skip_packaging: true
|
skip_packaging: true
|
||||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||||
- name: "clang"
|
- name: "clang"
|
||||||
@ -18,13 +19,35 @@ compilers:
|
|||||||
version: "3.6"
|
version: "3.6"
|
||||||
skip_packaging: true
|
skip_packaging: true
|
||||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
|
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
|
||||||
- name: "gcc"
|
- name: "clang"
|
||||||
version: "4.8"
|
version: "3.7"
|
||||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
|
||||||
- name: "gcc"
|
|
||||||
version: "4.6"
|
|
||||||
skip_packaging: true
|
skip_packaging: true
|
||||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
cmake_extra_flags: -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
|
- 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
|
- name: clang
|
||||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||||
build_package_generator: TBZ2
|
build_package_generator: TBZ2
|
||||||
- name: clang
|
|
||||||
build_type: Debug
|
|
||||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
|
||||||
skip_packaging: true
|
|
||||||
|
|
||||||
|
@ -11,10 +11,11 @@ compilers:
|
|||||||
compiler_extra_flags: /analyze
|
compiler_extra_flags: /analyze
|
||||||
skip_packaging: true
|
skip_packaging: true
|
||||||
- name: Visual Studio
|
- name: Visual Studio
|
||||||
version: 12
|
version: 14
|
||||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
build_type: Debug
|
||||||
- name: Visual Studio
|
|
||||||
version: 12
|
|
||||||
architecture: Win64
|
architecture: Win64
|
||||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||||
|
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
|
||||||
|
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-
|
||||||
|
|
79
.travis.yml
79
.travis.yml
@ -1,33 +1,62 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
env:
|
|
||||||
matrix:
|
|
||||||
- GCC_VER="4.6"
|
|
||||||
- GCC_VER="4.8"
|
|
||||||
|
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.9
|
||||||
|
- g++-5
|
||||||
|
coverity_scan:
|
||||||
|
project:
|
||||||
|
name: "ChaiScript/ChaiScript"
|
||||||
|
description: "Build submitted via Travis CI"
|
||||||
|
notification_email: jason@emptycrate.com
|
||||||
|
build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . "
|
||||||
|
build_command: "cmake --build . -- -j2"
|
||||||
|
branch_pattern: coverity_scan
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
env: GCC_VER="4.9"
|
||||||
|
compiler: gcc
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
env: GCC_VER="4.9" CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1
|
||||||
|
compiler: gcc
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
env: GCC_VER="5" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
|
||||||
|
compiler: gcc
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
osx_image: xcode8
|
||||||
|
- os: osx
|
||||||
|
compiler: clang
|
||||||
|
osx_image: xcode8
|
||||||
|
env: CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1
|
||||||
|
|
||||||
|
env:
|
||||||
global:
|
global:
|
||||||
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
|
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
|
||||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||||
- secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM="
|
- secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM="
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
|
- if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi
|
||||||
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
|
- pip install --user cpp-coveralls
|
||||||
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
|
|
||||||
- sudo pip install cpp-coveralls
|
|
||||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install -qq g++-$GCC_VER
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi
|
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $CMAKE_OPTIONS .
|
||||||
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi
|
- cmake --build . -- -j2
|
||||||
- make test
|
- if [ "${BUILD_ONLY}" != "1" ]; then ctest; fi
|
||||||
- if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
|
- if [ "${COVERAGE}" = "1" ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
|
||||||
|
|
||||||
after_script:
|
#after_script:
|
||||||
- if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
|
# - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
|
||||||
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
@ -42,15 +71,3 @@ notifications:
|
|||||||
on_success: change # options: [always|never|change] default: always
|
on_success: change # options: [always|never|change] default: always
|
||||||
on_failure: always # options: [always|never|change] default: always
|
on_failure: always # options: [always|never|change] default: always
|
||||||
on_start: false # default: false
|
on_start: false # default: false
|
||||||
|
|
||||||
addons:
|
|
||||||
coverity_scan:
|
|
||||||
project:
|
|
||||||
name: "ChaiScript/ChaiScript"
|
|
||||||
description: "Build submitted via Travis CI"
|
|
||||||
notification_email: jason@emptycrate.com
|
|
||||||
build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . "
|
|
||||||
build_command: "cmake --build . -- -j2"
|
|
||||||
branch_pattern: coverity_scan
|
|
||||||
|
|
||||||
|
|
||||||
|
112
CMakeLists.txt
112
CMakeLists.txt
@ -14,12 +14,14 @@ ELSE()
|
|||||||
project(chaiscript)
|
project(chaiscript)
|
||||||
|
|
||||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||||
|
option(DYNLOAD_ENABLED "Dynamic Loading Support Enabled" TRUE)
|
||||||
|
|
||||||
|
|
||||||
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
||||||
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||||
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
|
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
|
||||||
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
||||||
|
option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE)
|
||||||
|
|
||||||
mark_as_advanced(USE_STD_MAKE_SHARED)
|
mark_as_advanced(USE_STD_MAKE_SHARED)
|
||||||
|
|
||||||
@ -100,9 +102,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_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
set(CPACK_PACKAGE_VERSION_MAJOR 6)
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR 7)
|
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH 2)
|
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||||
|
|
||||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||||
@ -122,16 +124,12 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
|||||||
include(CTest)
|
include(CTest)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
include(cmake/CheckCXX11Features.cmake)
|
|
||||||
|
|
||||||
if(NOT MINGW)
|
if(NOT MINGW)
|
||||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HAS_CXX11_VARIADIC_TEMPLATES)
|
if (UNIX AND NOT APPLE)
|
||||||
message(STATUS "Variadic Template support detected")
|
find_program(VALGRIND NAMES valgrind PATH /usr/bin /usr/local/bin)
|
||||||
else()
|
|
||||||
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
@ -151,21 +149,24 @@ endif()
|
|||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||||
|
|
||||||
if(GCC_VERSION VERSION_LESS 4.8)
|
if(GCC_VERSION VERSION_LESS 4.9)
|
||||||
set(CPP11_FLAG "-std=c++0x")
|
set(CPP11_FLAG "-std=c++1y")
|
||||||
else()
|
else()
|
||||||
set(CPP11_FLAG "-std=c++11")
|
set(CPP11_FLAG "-std=c++14")
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
set(CPP11_FLAG "-std=c++11")
|
set(CPP11_FLAG "-std=c++14")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_definitions(/W4)
|
add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
|
||||||
|
|
||||||
# VS2013 doesn't have magic statics
|
|
||||||
if (MSVC_VERSION STREQUAL "1800")
|
if (MSVC_VERSION STREQUAL "1800")
|
||||||
|
# VS2013 doesn't have magic statics
|
||||||
add_definitions(/w44640)
|
add_definitions(/w44640)
|
||||||
|
else()
|
||||||
|
# enum warnings are too noisy on MSVC2013
|
||||||
|
add_definitions(/w34062)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(/bigobj)
|
add_definitions(/bigobj)
|
||||||
@ -178,10 +179,10 @@ if(MSVC)
|
|||||||
# how to workaround or fix the error. So I'm disabling it globally.
|
# how to workaround or fix the error. So I'm disabling it globally.
|
||||||
add_definitions(/wd4503)
|
add_definitions(/wd4503)
|
||||||
else()
|
else()
|
||||||
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
|
add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors)
|
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
|
||||||
else()
|
else()
|
||||||
add_definitions(-Wnoexcept)
|
add_definitions(-Wnoexcept)
|
||||||
endif()
|
endif()
|
||||||
@ -213,7 +214,7 @@ endif()
|
|||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
|
||||||
|
|
||||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.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)
|
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||||
|
|
||||||
@ -221,10 +222,16 @@ if(NOT MULTITHREAD_SUPPORT_ENABLED)
|
|||||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT DYNLOAD_ENABLED)
|
||||||
|
add_definitions(-DCHAISCRIPT_NO_DYNLOAD)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CMAKE_HOST_UNIX)
|
if(CMAKE_HOST_UNIX)
|
||||||
|
if(DYNLOAD_ENABLED)
|
||||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
list(APPEND LIBS "dl")
|
list(APPEND LIBS "dl")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(MULTITHREAD_SUPPORT_ENABLED)
|
if(MULTITHREAD_SUPPORT_ENABLED)
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
@ -249,31 +256,37 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||||
|
|
||||||
|
add_library(stdlib STATIC static_libs/chaiscript_stdlib.cpp)
|
||||||
|
add_library(parser STATIC static_libs/chaiscript_parser.cpp)
|
||||||
|
|
||||||
add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib.cpp)
|
add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib_module.cpp)
|
||||||
target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
|
set(CHAISCRIPT_LIBS stdlib parser)
|
||||||
|
|
||||||
add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
||||||
target_link_libraries(chai ${LIBS})
|
target_link_libraries(chai ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION})
|
|
||||||
|
|
||||||
if(BUILD_SAMPLES)
|
if(BUILD_SAMPLES)
|
||||||
add_executable(example samples/example.cpp)
|
add_executable(example samples/example.cpp)
|
||||||
target_link_libraries(example ${LIBS})
|
target_link_libraries(example ${LIBS})
|
||||||
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
|
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
|
||||||
target_link_libraries(test_num_exceptions ${LIBS})
|
target_link_libraries(test_num_exceptions ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||||
target_link_libraries(memory_leak_test ${LIBS})
|
target_link_libraries(memory_leak_test ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_executable(inheritance samples/inheritance.cpp)
|
add_executable(inheritance samples/inheritance.cpp)
|
||||||
target_link_libraries(inheritance ${LIBS})
|
target_link_libraries(inheritance ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_executable(factory samples/factory.cpp)
|
add_executable(factory samples/factory.cpp)
|
||||||
target_link_libraries(factory ${LIBS})
|
target_link_libraries(factory ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
||||||
target_link_libraries(fun_call_performance ${LIBS})
|
target_link_libraries(fun_call_performance ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_MODULES)
|
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)
|
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||||
target_link_libraries(stl_extra ${LIBS})
|
target_link_libraries(stl_extra ${LIBS})
|
||||||
|
|
||||||
@ -283,13 +296,16 @@ endif()
|
|||||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||||
list(SORT UNIT_TESTS)
|
list(SORT UNIT_TESTS)
|
||||||
|
|
||||||
|
file(GLOB PERFORMANCE_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/ ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/*.chai)
|
||||||
|
list(SORT PERFORMANCE_TESTS)
|
||||||
|
|
||||||
|
|
||||||
if (RUN_FUZZY_TESTS)
|
if (RUN_FUZZY_TESTS)
|
||||||
|
|
||||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
|
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
|
||||||
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2
|
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -347,8 +363,8 @@ if(BUILD_TESTING)
|
|||||||
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
|
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
|
||||||
foreach(hit ${found_tests})
|
foreach(hit ${found_tests})
|
||||||
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
|
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
|
||||||
add_test(${test_name} "${executable}" ${test_name})
|
add_test(compiled.${test_name} "${executable}" ${test_name})
|
||||||
set_tests_properties(${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
|
set_tests_properties(compiled.${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -382,12 +398,32 @@ if(BUILD_TESTING)
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
set(TESTS "")
|
||||||
|
|
||||||
foreach(filename ${UNIT_TESTS})
|
foreach(filename ${UNIT_TESTS})
|
||||||
message(STATUS "Adding test ${filename}")
|
message(STATUS "Adding unit test ${filename}")
|
||||||
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
add_test(unit.${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
||||||
|
list(APPEND TESTS unit.${filename})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set_property(TEST ${UNIT_TESTS}
|
if (RUN_PERFORMANCE_TESTS)
|
||||||
|
foreach(filename ${PERFORMANCE_TESTS})
|
||||||
|
message(STATUS "Adding performance test ${filename}")
|
||||||
|
|
||||||
|
add_test(NAME performance.${filename} COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.${filename} $<TARGET_FILE:chai> ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/${filename})
|
||||||
|
list(APPEND TESTS performance.${filename})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_executable(profile_cpp_calls_2 performance_tests/profile_cpp_calls_2.cpp)
|
||||||
|
target_link_libraries(profile_cpp_calls_2 ${LIBS})
|
||||||
|
add_test(NAME performance.profile_cpp_calls_2 COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_cpp_calls_2 $<TARGET_FILE:profile_cpp_calls_2>)
|
||||||
|
|
||||||
|
add_executable(profile_fun_wrappers performance_tests/profile_fun_wrappers.cpp)
|
||||||
|
target_link_libraries(profile_fun_wrappers ${LIBS})
|
||||||
|
add_test(NAME performance.profile_fun_wrappers COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_fun_wrappers $<TARGET_FILE:profile_fun_wrappers>)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_property(TEST ${TESTS}
|
||||||
PROPERTY ENVIRONMENT
|
PROPERTY ENVIRONMENT
|
||||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||||
@ -395,9 +431,12 @@ if(BUILD_TESTING)
|
|||||||
|
|
||||||
if(NOT UNIT_TEST_LIGHT)
|
if(NOT UNIT_TEST_LIGHT)
|
||||||
add_executable(compiled_tests unittests/compiled_tests.cpp)
|
add_executable(compiled_tests unittests/compiled_tests.cpp)
|
||||||
target_link_libraries(compiled_tests ${LIBS})
|
target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
ADD_CATCH_TESTS(compiled_tests)
|
ADD_CATCH_TESTS(compiled_tests)
|
||||||
|
|
||||||
|
add_executable(static_chaiscript_test unittests/static_chaiscript.cpp)
|
||||||
|
target_link_libraries(static_chaiscript_test ${LIBS})
|
||||||
|
add_test(NAME Static_ChaiScript_Test COMMAND static_chaiscript_test)
|
||||||
|
|
||||||
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
|
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
|
||||||
target_link_libraries(boxed_cast_test ${LIBS})
|
target_link_libraries(boxed_cast_test ${LIBS})
|
||||||
@ -408,11 +447,11 @@ if(BUILD_TESTING)
|
|||||||
add_test(NAME Type_Info_Test COMMAND type_info_test)
|
add_test(NAME Type_Info_Test COMMAND type_info_test)
|
||||||
|
|
||||||
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
|
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
|
||||||
target_link_libraries(c_linkage_test ${LIBS})
|
target_link_libraries(c_linkage_test ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
|
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
|
||||||
|
|
||||||
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
|
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
|
||||||
target_link_libraries(integer_literal_test ${LIBS})
|
target_link_libraries(integer_literal_test ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
||||||
|
|
||||||
if(MULTITHREAD_SUPPORT_ENABLED)
|
if(MULTITHREAD_SUPPORT_ENABLED)
|
||||||
@ -436,9 +475,6 @@ if(BUILD_TESTING)
|
|||||||
target_link_libraries(multifile_test ${LIBS})
|
target_link_libraries(multifile_test ${LIBS})
|
||||||
add_test(NAME MultiFile_Test COMMAND multifile_test)
|
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)
|
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
28
DesignGoals.md
Normal file
28
DesignGoals.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Introduction
|
||||||
|
|
||||||
|
This document outlines the principles that drive the development of ChaiScript. ChaiScript does not intent to be the perfect tool for *every* situation, but it does intend to be a good general purpose tool for *most* situations.
|
||||||
|
|
||||||
|
# Goals
|
||||||
|
|
||||||
|
1. Trivially easy to integrate with C++ projects
|
||||||
|
2. 0 external depenencies
|
||||||
|
3. "Perfect" integration with C++
|
||||||
|
* Direct mapping between ChaiScript objects and C++ objects
|
||||||
|
* Direct mapping between ChaiScript functions and C++ functions
|
||||||
|
* Direct mapping between ChaiScript exceptions and C++ exceptions
|
||||||
|
3. Never surprise the C++ developer
|
||||||
|
* Object lifetimes managed by the stack
|
||||||
|
* Familiar syntax to C++ developers
|
||||||
|
4. Perform "well enough" to not get in the way
|
||||||
|
|
||||||
|
|
||||||
|
# Alternatives
|
||||||
|
|
||||||
|
## Sol2
|
||||||
|
|
||||||
|
If you are looking for the fastest performing scripting language and don't mind Lua, you might want to consider [sol2](https://github.com/ThePhD/sol2).
|
||||||
|
|
||||||
|
## SWIG
|
||||||
|
|
||||||
|
If you are looking for the most flexible solution to be able to support multiple target languages, consider [SWIG](http://swig.org)
|
||||||
|
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
|||||||
Copyright 2009-2015 Jason Turner
|
Copyright 2009-2016 Jason Turner
|
||||||
Copyright 2009-2012 Jonathan Turner.
|
Copyright 2009-2012 Jonathan Turner.
|
||||||
|
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
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
|
161
cheatsheet.md
161
cheatsheet.md
@ -27,6 +27,13 @@ chai.add(chaiscript::fun(&Class::method_name), "method_name");
|
|||||||
chai.add(chaiscript::fun(&Class::member_name), "member_name");
|
chai.add(chaiscript::fun(&Class::member_name), "member_name");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Bound Member Functions
|
||||||
|
|
||||||
|
```
|
||||||
|
chai.add(chaiscript::fun(&Class::method_name, Class_instance_ptr), "method_name");
|
||||||
|
chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name");
|
||||||
|
```
|
||||||
|
|
||||||
### With Overloads
|
### With Overloads
|
||||||
|
|
||||||
#### Preferred
|
#### Preferred
|
||||||
@ -84,12 +91,63 @@ chai.add(chaiscript::user_type<MyClass>(), "MyClass");
|
|||||||
|
|
||||||
User defined type conversions are possible, defined in either script or in C++.
|
User defined type conversions are possible, defined in either script or in C++.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ChaiScript Defined Conversions
|
||||||
|
|
||||||
|
Function objects (including lambdas) can be used to add type conversions
|
||||||
|
from inside of ChaiScript:
|
||||||
|
|
||||||
|
```
|
||||||
|
add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); });
|
||||||
|
```
|
||||||
|
|
||||||
|
### C++ Defined Conversions
|
||||||
|
|
||||||
|
Invoking a C++ type conversion possible with `static_cast`
|
||||||
|
|
||||||
|
```
|
||||||
|
chai.add(chaiscript::type_conversion<T, bool>());
|
||||||
|
```
|
||||||
|
|
||||||
|
Calling a user defined type conversion that takes a lambda
|
||||||
|
|
||||||
|
```
|
||||||
|
chai.add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { /* return converted thing */ }));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Class Hierarchies
|
||||||
|
|
||||||
|
If you want objects to be convertable between base and derived classes, you must tell ChaiScritp about the relationship.
|
||||||
|
|
||||||
|
```
|
||||||
|
chai.add(chaiscript::base_class<Base, Derived>());
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have multiple classes in your inheritance graph, you will probably want to tell ChaiScript about all relationships.
|
||||||
|
|
||||||
|
```
|
||||||
|
chai.add(chaiscript::base_class<Base, Derived>());
|
||||||
|
chai.add(chaiscript::base_class<Derived, MoreDerived>());
|
||||||
|
chai.add(chaiscript::base_class<Base, MoreDerived>());
|
||||||
|
```
|
||||||
|
|
||||||
|
### Helpers
|
||||||
|
|
||||||
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
|
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
|
||||||
|
|
||||||
```
|
```
|
||||||
chai.add(chaiscript::vector_conversion<std::vector<int>>());
|
chai.add(chaiscript::vector_conversion<std::vector<int>>());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A helper function also exists for strongly typed and ChaiScript `Map` function conversion definition:
|
||||||
|
|
||||||
|
```
|
||||||
|
chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
|
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
|
||||||
|
|
||||||
## Adding Objects
|
## Adding Objects
|
||||||
@ -100,9 +158,11 @@ chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared
|
|||||||
auto shareddouble = std::make_shared<double>(4.3);
|
auto shareddouble = std::make_shared<double>(4.3);
|
||||||
chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai
|
chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai
|
||||||
chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const
|
chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const
|
||||||
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const
|
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const, throws if object exists
|
||||||
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const
|
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists
|
||||||
|
chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object
|
||||||
```
|
```
|
||||||
|
|
||||||
# Using STL
|
# Using STL
|
||||||
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
|
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
|
||||||
|
|
||||||
@ -155,6 +215,28 @@ chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with an
|
|||||||
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
|
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Conversion Caveats
|
||||||
|
|
||||||
|
Conversion to `std::shared_ptr<T> &` is supported for function calls, but if you attempt to keep a reference to a `shared_ptr<>` you might invoke undefined behavior
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// ok this is supported, you can register it with chaiscript engine
|
||||||
|
void nullify_shared_ptr(std::shared_ptr<int> &t) {
|
||||||
|
t = nullptr
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// do some stuff and create a chaiscript instance
|
||||||
|
std::shared_ptr<int> &ptr = chai.eval<std::shared_ptr<int> &>(somevalue);
|
||||||
|
// DO NOT do this. Taking a non-const reference to a shared_ptr is not
|
||||||
|
// supported and causes undefined behavior in the chaiscript engine
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Sharing Values
|
## Sharing Values
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -221,11 +303,51 @@ var k = 5; // initialized to 5 (integer)
|
|||||||
var l := k; // reference to k
|
var l := k; // reference to k
|
||||||
auto &m = k; // reference to k
|
auto &m = k; // reference to k
|
||||||
|
|
||||||
GLOBAL g = 5; // creates a global variable. If global already exists, it is not re-added
|
global g = 5; // creates a global variable. If global already exists, it is not re-added
|
||||||
GLOBAL g = 2; // global 'g' now equals 2
|
global g = 2; // global 'g' now equals 2
|
||||||
|
|
||||||
GLOBAL g2;
|
global g2;
|
||||||
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once
|
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hit more than once
|
||||||
|
|
||||||
|
GLOBAL g3; // all upper case version also accepted
|
||||||
|
```
|
||||||
|
|
||||||
|
## Looping
|
||||||
|
|
||||||
|
```
|
||||||
|
// c-style for loops
|
||||||
|
for (var i = 0; i < 100; ++i) { print(i); }
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
// while
|
||||||
|
while (some_condition()) { /* do something */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
// ranged for
|
||||||
|
for (x : [1,2,3]) { print(i); }
|
||||||
|
```
|
||||||
|
|
||||||
|
Each of the loop styles can be broken using the `break` statement. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
while (some_condition()) {
|
||||||
|
/* do something */
|
||||||
|
if (another_condition()) { break; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conditionals
|
||||||
|
|
||||||
|
```
|
||||||
|
if (expression) { }
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
// C++17-style init-if blocks
|
||||||
|
// Value of 'statement' is scoped for entire `if` block
|
||||||
|
if (statement; expression) { }
|
||||||
```
|
```
|
||||||
|
|
||||||
## Built in Types
|
## Built in Types
|
||||||
@ -386,9 +508,33 @@ the contained function.
|
|||||||
|
|
||||||
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
|
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
* `__LINE__` Current file line number
|
||||||
|
* `__FILE__` Full path of current file
|
||||||
|
* `__CLASS__` Name of current class
|
||||||
|
* `__FUNC__` Mame of current function
|
||||||
|
|
||||||
|
|
||||||
# Built In Functions
|
# Built In Functions
|
||||||
|
|
||||||
|
## Disabling Built-Ins
|
||||||
|
|
||||||
|
When constructing a ChaiScript object, a vector of parameters can be passed in to disable or enable various built-in methods.
|
||||||
|
|
||||||
|
Current options:
|
||||||
|
|
||||||
|
```
|
||||||
|
enum class Options
|
||||||
|
{
|
||||||
|
Load_Modules,
|
||||||
|
No_Load_Modules,
|
||||||
|
External_Scripts,
|
||||||
|
No_External_Scripts
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Evaluation
|
## Evaluation
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -400,4 +546,7 @@ use("filename") // evals file exactly once and returns value of last statement
|
|||||||
|
|
||||||
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor
|
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor
|
||||||
|
|
||||||
|
## JSON
|
||||||
|
|
||||||
|
* `from_json` converts a JSON string into its strongly typed (map, vector, int, double, string) representations
|
||||||
|
* `to_json` converts a ChaiScript object (either a `Object` or one of map, vector, int, double, string) tree into its JSON string representation
|
||||||
|
@ -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" }
|
@ -4,7 +4,7 @@ pushd ..
|
|||||||
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
|
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
|
||||||
tar -xvf cppcheck-1.66.tar.bz2
|
tar -xvf cppcheck-1.66.tar.bz2
|
||||||
cd cppcheck-1.66
|
cd cppcheck-1.66
|
||||||
CXX=g++-4.8 make -j2
|
make -j2
|
||||||
popd
|
popd
|
||||||
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
|
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
|
||||||
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
|
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
# [PackageDev] target_format: plist, ext: tmLanguage
|
|
||||||
---
|
|
||||||
comment: 'ChaiScript Syntax: version 2.0'
|
|
||||||
fileTypes: [chai]
|
|
||||||
firstLineMatch: ^#!/usr/bin/env node
|
|
||||||
foldingStartMarker: ^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$
|
|
||||||
foldingStopMarker: ^\s*\}
|
|
||||||
keyEquivalent: ^~J
|
|
||||||
name: ChaiScript
|
|
||||||
patterns:
|
|
||||||
- {comment: chaiscript shebang, match: ^#, name: comment.line.chai}
|
|
||||||
- {match: '\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b', name: constant.numeric.chai}
|
|
||||||
- begin: ''''
|
|
||||||
beginCaptures:
|
|
||||||
'0': {name: punctuation.definition.string.begin.chai}
|
|
||||||
end: ''''
|
|
||||||
endCaptures:
|
|
||||||
'0': {name: punctuation.definition.string.end.chai}
|
|
||||||
name: string.quoted.single.chai
|
|
||||||
patterns:
|
|
||||||
- {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai}
|
|
||||||
- begin: '"'
|
|
||||||
beginCaptures:
|
|
||||||
'0': {name: punctuation.definition.string.begin.chai}
|
|
||||||
end: '"'
|
|
||||||
endCaptures:
|
|
||||||
'0': {name: punctuation.definition.string.end.chai}
|
|
||||||
name: string.quoted.double.chai
|
|
||||||
patterns:
|
|
||||||
- {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai}
|
|
||||||
- begin: /\*\*(?!/)
|
|
||||||
captures:
|
|
||||||
'0': {name: punctuation.definition.comment.chai}
|
|
||||||
end: \*/
|
|
||||||
name: comment.block.documentation.chai
|
|
||||||
- begin: /\*
|
|
||||||
captures:
|
|
||||||
'0': {name: punctuation.definition.comment.chai}
|
|
||||||
end: \*/
|
|
||||||
name: comment.block.chai
|
|
||||||
- captures:
|
|
||||||
'1': {name: punctuation.definition.comment.chai}
|
|
||||||
match: (//).*$\n?
|
|
||||||
name: comment.line.double-slash.chai
|
|
||||||
- captures:
|
|
||||||
'0': {name: punctuation.definition.comment.html.chai}
|
|
||||||
'2': {name: punctuation.definition.comment.html.chai}
|
|
||||||
match: (<!--|-->)
|
|
||||||
name: comment.block.html.chai
|
|
||||||
- {match: \b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b,
|
|
||||||
name: storage.type.chai}
|
|
||||||
- {match: \b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b,
|
|
||||||
name: keyword.control.chai}
|
|
||||||
- {match: \b(delete|in|instanceof|new|typeof|with)\b, name: keyword.operator.chai}
|
|
||||||
- {match: \btrue\b, name: constant.language.boolean.true.chai}
|
|
||||||
- {match: \bfalse\b, name: constant.language.boolean.false.chai}
|
|
||||||
- {match: \bnull\b, name: constant.language.null.chai}
|
|
||||||
- {match: \b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b,
|
|
||||||
name: support.class.chai}
|
|
||||||
- {match: '\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()',
|
|
||||||
name: support.function.chai}
|
|
||||||
- {match: '\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()',
|
|
||||||
name: support.function.dom.chai}
|
|
||||||
- {match: '(?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b',
|
|
||||||
name: support.constant.chai}
|
|
||||||
- {match: '(?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b',
|
|
||||||
name: support.constant.dom.chai}
|
|
||||||
- {match: \b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b,
|
|
||||||
name: support.constant.dom.chai}
|
|
||||||
- {match: '\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b',
|
|
||||||
name: support.function.event-handler.chai}
|
|
||||||
- {match: '!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|void)\b',
|
|
||||||
name: keyword.operator.chai}
|
|
||||||
- {match: \b(Infinity|NaN|undefined)\b, name: constant.language.chai}
|
|
||||||
- begin: (?<=[=(:]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?])
|
|
||||||
beginCaptures:
|
|
||||||
'1': {name: punctuation.definition.string.begin.chai}
|
|
||||||
end: (/)[igm]*
|
|
||||||
endCaptures:
|
|
||||||
'1': {name: punctuation.definition.string.end.chai}
|
|
||||||
name: string.regexp.chai
|
|
||||||
patterns:
|
|
||||||
- {match: \\., name: constant.character.escape.chai}
|
|
||||||
- {match: \;, name: punctuation.terminator.statement.chai}
|
|
||||||
- {match: ',[ |\t]*', name: meta.delimiter.object.comma.chai}
|
|
||||||
- {match: \., name: meta.delimiter.method.period.chai}
|
|
||||||
- {match: '\{|\}', name: meta.brace.curly.chai}
|
|
||||||
- {match: \(|\), name: meta.brace.round.chai}
|
|
||||||
- {match: '\[|\]', name: meta.brace.square.chai}
|
|
||||||
scopeName: source.chai
|
|
||||||
uuid: 93E017CC-6F27-11D9-90EB-000D93589AF6
|
|
||||||
|
|
||||||
...
|
|
@ -1,333 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>comment</key>
|
|
||||||
<string>ChaiScript Syntax: version 2.0</string>
|
|
||||||
<key>fileTypes</key>
|
|
||||||
<array>
|
|
||||||
<string>chai</string>
|
|
||||||
</array>
|
|
||||||
<key>firstLineMatch</key>
|
|
||||||
<string>^#!/usr/bin/env node</string>
|
|
||||||
<key>foldingStartMarker</key>
|
|
||||||
<string>^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$</string>
|
|
||||||
<key>foldingStopMarker</key>
|
|
||||||
<string>^\s*\}</string>
|
|
||||||
<key>keyEquivalent</key>
|
|
||||||
<string>^~J</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>ChaiScript</string>
|
|
||||||
<key>patterns</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>comment</key>
|
|
||||||
<string>chaiscript shebang</string>
|
|
||||||
<key>match</key>
|
|
||||||
<string>^#</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>comment.line.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.numeric.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>begin</key>
|
|
||||||
<string>'</string>
|
|
||||||
<key>beginCaptures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.string.begin.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>end</key>
|
|
||||||
<string>'</string>
|
|
||||||
<key>endCaptures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.string.end.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>string.quoted.single.chai</string>
|
|
||||||
<key>patterns</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.character.escape.chai</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>begin</key>
|
|
||||||
<string>"</string>
|
|
||||||
<key>beginCaptures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.string.begin.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>end</key>
|
|
||||||
<string>"</string>
|
|
||||||
<key>endCaptures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.string.end.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>string.quoted.double.chai</string>
|
|
||||||
<key>patterns</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.character.escape.chai</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>begin</key>
|
|
||||||
<string>/\*\*(?!/)</string>
|
|
||||||
<key>captures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.comment.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>end</key>
|
|
||||||
<string>\*/</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>comment.block.documentation.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>begin</key>
|
|
||||||
<string>/\*</string>
|
|
||||||
<key>captures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.comment.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>end</key>
|
|
||||||
<string>\*/</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>comment.block.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>captures</key>
|
|
||||||
<dict>
|
|
||||||
<key>1</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.comment.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>(//).*$\n?</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>comment.line.double-slash.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>captures</key>
|
|
||||||
<dict>
|
|
||||||
<key>0</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.comment.html.chai</string>
|
|
||||||
</dict>
|
|
||||||
<key>2</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.comment.html.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>(<!--|-->)</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>comment.block.html.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>storage.type.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>keyword.control.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(delete|in|instanceof|new|typeof|with)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>keyword.operator.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\btrue\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.language.boolean.true.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\bfalse\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.language.boolean.false.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\bnull\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.language.null.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.class.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.function.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.function.dom.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>(?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.constant.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>(?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.constant.dom.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.constant.dom.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>support.function.event-handler.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|void)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>keyword.operator.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\b(Infinity|NaN|undefined)\b</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.language.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>begin</key>
|
|
||||||
<string>(?<=[=(:]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?])</string>
|
|
||||||
<key>beginCaptures</key>
|
|
||||||
<dict>
|
|
||||||
<key>1</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.string.begin.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>end</key>
|
|
||||||
<string>(/)[igm]*</string>
|
|
||||||
<key>endCaptures</key>
|
|
||||||
<dict>
|
|
||||||
<key>1</key>
|
|
||||||
<dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.definition.string.end.chai</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>name</key>
|
|
||||||
<string>string.regexp.chai</string>
|
|
||||||
<key>patterns</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\\.</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>constant.character.escape.chai</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\;</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>punctuation.terminator.statement.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>,[ |\t]*</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>meta.delimiter.object.comma.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\.</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>meta.delimiter.method.period.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\{|\}</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>meta.brace.curly.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\(|\)</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>meta.brace.round.chai</string>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>match</key>
|
|
||||||
<string>\[|\]</string>
|
|
||||||
<key>name</key>
|
|
||||||
<string>meta.brace.square.chai</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
<key>scopeName</key>
|
|
||||||
<string>source.chai</string>
|
|
||||||
<key>uuid</key>
|
|
||||||
<string>93E017CC-6F27-11D9-90EB-000D93589AF6</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HPP_
|
#ifndef CHAISCRIPT_HPP_
|
||||||
#define CHAISCRIPT_HPP_
|
#define CHAISCRIPT_HPP_
|
||||||
|
|
||||||
@ -65,7 +69,7 @@
|
|||||||
/// int main()
|
/// int main()
|
||||||
/// {
|
/// {
|
||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai.add(&function, "function");
|
/// chai.add(chaiscript::fun(&function), "function");
|
||||||
///
|
///
|
||||||
/// double d = chai.eval<double>("function(3, 4.75);");
|
/// double d = chai.eval<double>("function(3, 4.75);");
|
||||||
/// }
|
/// }
|
||||||
@ -695,11 +699,10 @@
|
|||||||
/// Begins a function or method definition
|
/// Begins a function or method definition
|
||||||
///
|
///
|
||||||
/// ~~~~~~~~
|
/// ~~~~~~~~
|
||||||
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||||
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[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.
|
/// identifier: name of function. Required.
|
||||||
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
||||||
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
||||||
@ -817,16 +820,26 @@
|
|||||||
/// @namespace chaiscript::detail
|
/// @namespace chaiscript::detail
|
||||||
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
/// @brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
||||||
|
|
||||||
#include "chaiscript_defines.hpp"
|
#include "chaiscript_basic.hpp"
|
||||||
|
#include "language/chaiscript_parser.hpp"
|
||||||
#include "dispatchkit/dispatchkit.hpp"
|
#include "chaiscript_stdlib.hpp"
|
||||||
#include "dispatchkit/function_call.hpp"
|
|
||||||
#include "dispatchkit/dynamic_object.hpp"
|
|
||||||
#include "dispatchkit/boxed_number.hpp"
|
|
||||||
|
|
||||||
#include "language/chaiscript_eval.hpp"
|
|
||||||
#include "language/chaiscript_engine.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
class ChaiScript : public ChaiScript_Basic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
||||||
|
std::vector<std::string> t_usepaths = {},
|
||||||
|
const std::vector<Options> &t_opts = {})
|
||||||
|
: ChaiScript_Basic(
|
||||||
|
chaiscript::Std_Lib::library(),
|
||||||
|
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
||||||
|
t_modulepaths, t_usepaths, t_opts)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CHAISCRIPT_HPP_ */
|
#endif /* CHAISCRIPT_HPP_ */
|
||||||
|
39
include/chaiscript/chaiscript_basic.hpp
Normal file
39
include/chaiscript/chaiscript_basic.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_BASIC_HPP_
|
||||||
|
#define CHAISCRIPT_BASIC_HPP_
|
||||||
|
|
||||||
|
#include "chaiscript_defines.hpp"
|
||||||
|
|
||||||
|
#include "dispatchkit/dispatchkit.hpp"
|
||||||
|
#include "dispatchkit/function_call.hpp"
|
||||||
|
#include "dispatchkit/dynamic_object.hpp"
|
||||||
|
#include "dispatchkit/boxed_number.hpp"
|
||||||
|
|
||||||
|
#include "language/chaiscript_eval.hpp"
|
||||||
|
#include "language/chaiscript_engine.hpp"
|
||||||
|
|
||||||
|
// This file includes all of the basic requirements for ChaiScript,
|
||||||
|
// to use, you might do something like:
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
#include "chaiscript_stdlib.hpp"
|
||||||
|
#include "language/chaiscript_parser.hpp"
|
||||||
|
|
||||||
|
ChaiScript_Basic chai(
|
||||||
|
chaiscript::Std_Lib::library(),
|
||||||
|
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>());
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If you want a fully packaged ready to go ChaiScript, use chaiscript.hpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CHAISCRIPT_BASIC_HPP_ */
|
@ -1,22 +1,23 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||||
#define CHAISCRIPT_DEFINES_HPP_
|
#define CHAISCRIPT_DEFINES_HPP_
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
#define CHAISCRIPT_STRINGIZE(x) "" #x
|
||||||
|
#define CHAISCRIPT_STRINGIZE_EXPANDED(x) CHAISCRIPT_STRINGIZE(x)
|
||||||
|
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE_EXPANDED(_MSC_FULL_VER)
|
||||||
#define CHAISCRIPT_MSVC _MSC_VER
|
#define CHAISCRIPT_MSVC _MSC_VER
|
||||||
#define CHAISCRIPT_HAS_DECLSPEC
|
#define CHAISCRIPT_HAS_DECLSPEC
|
||||||
#if _MSC_VER <= 1800
|
|
||||||
#define CHAISCRIPT_MSVC_12
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_MSVC_12
|
static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later required");
|
||||||
#define CHAISCRIPT_HAS_MAGIC_STATICS
|
|
||||||
|
#else
|
||||||
|
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -29,26 +30,29 @@
|
|||||||
#define CHAISCRIPT_WINDOWS
|
#define CHAISCRIPT_WINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
#if defined(_WIN32)
|
||||||
/// Currently only g++>=4.8 supports this natively
|
#if defined(__llvm__)
|
||||||
/// \todo Make this support other compilers when possible
|
#define CHAISCRIPT_COMPILER_NAME "clang(windows)"
|
||||||
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
#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
|
#endif
|
||||||
|
|
||||||
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
|
|
||||||
#define CHAISCRIPT_GCC_4_6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__llvm__)
|
#if defined(__llvm__)
|
||||||
#define CHAISCRIPT_CLANG
|
#define CHAISCRIPT_CLANG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG)
|
|
||||||
#define CHAISCRIPT_OVERRIDE override
|
|
||||||
#else
|
|
||||||
#define CHAISCRIPT_OVERRIDE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
||||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||||
@ -56,20 +60,28 @@
|
|||||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC_12
|
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(CHAISCRIPT_CLANG)
|
||||||
#define CHAISCRIPT_NOEXCEPT throw()
|
#define CHAISCRIPT_UTF16_UTF32
|
||||||
#define CHAISCRIPT_CONSTEXPR
|
#endif
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define CHAISCRIPT_DEBUG true
|
||||||
#else
|
#else
|
||||||
#define CHAISCRIPT_NOEXCEPT noexcept
|
#define CHAISCRIPT_DEBUG false
|
||||||
#define CHAISCRIPT_CONSTEXPR constexpr
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
static const int version_major = 5;
|
static const int version_major = 6;
|
||||||
static const int version_minor = 7;
|
static const int version_minor = 0;
|
||||||
static const int version_patch = 2;
|
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>
|
template<typename B, typename D, typename ...Arg>
|
||||||
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
||||||
@ -81,6 +93,135 @@ namespace chaiscript {
|
|||||||
#endif
|
#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 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) != 0; ++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());
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Options
|
||||||
|
{
|
||||||
|
No_Load_Modules,
|
||||||
|
Load_Modules,
|
||||||
|
No_External_Scripts,
|
||||||
|
External_Scripts
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline std::vector<Options> default_options()
|
||||||
|
{
|
||||||
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
|
return {Options::No_Load_Modules, Options::External_Scripts};
|
||||||
|
#else
|
||||||
|
return {Options::Load_Modules, Options::External_Scripts};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -14,11 +14,17 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "chaiscript_defines.hpp"
|
#include "chaiscript_defines.hpp"
|
||||||
#include "dispatchkit/dispatchkit.hpp"
|
#include "language/chaiscript_common.hpp"
|
||||||
|
|
||||||
|
#include "dispatchkit/function_call.hpp"
|
||||||
|
|
||||||
|
//#include "dispatchkit/dispatchkit.hpp"
|
||||||
|
#include "dispatchkit/operators.hpp"
|
||||||
#include "dispatchkit/bootstrap.hpp"
|
#include "dispatchkit/bootstrap.hpp"
|
||||||
#include "dispatchkit/bootstrap_stl.hpp"
|
#include "dispatchkit/bootstrap_stl.hpp"
|
||||||
#include "dispatchkit/boxed_value.hpp"
|
//#include "dispatchkit/boxed_value.hpp"
|
||||||
#include "language/chaiscript_prelude.chai"
|
#include "language/chaiscript_prelude.hpp"
|
||||||
|
#include "dispatchkit/register_function.hpp"
|
||||||
#include "utility/json_wrap.hpp"
|
#include "utility/json_wrap.hpp"
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
@ -38,21 +44,20 @@ namespace chaiscript
|
|||||||
|
|
||||||
static ModulePtr library()
|
static ModulePtr library()
|
||||||
{
|
{
|
||||||
using namespace bootstrap;
|
auto lib = std::make_shared<Module>();
|
||||||
|
bootstrap::Bootstrap::bootstrap(*lib);
|
||||||
|
|
||||||
ModulePtr lib = Bootstrap::bootstrap();
|
bootstrap::standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
|
||||||
|
bootstrap::standard_library::string_type<std::string>("string", *lib);
|
||||||
lib->add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
|
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
|
||||||
lib->add(standard_library::string_type<std::string>("string"));
|
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
|
||||||
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"));
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#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");
|
lib->add(chaiscript::fun([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lib->add(json_wrap::library());
|
json_wrap::library(*lib);
|
||||||
|
|
||||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
|
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||||
#define CHAISCRIPT_THREADING_HPP_
|
#define CHAISCRIPT_THREADING_HPP_
|
||||||
|
|
||||||
@ -42,147 +46,92 @@ namespace chaiscript
|
|||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class unique_lock : public std::unique_lock<T>
|
using unique_lock = std::unique_lock<T>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
unique_lock(T &t) : std::unique_lock<T>(t) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class shared_lock : public std::unique_lock<T>
|
using shared_lock = std::unique_lock<T>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
shared_lock(T &t) : std::unique_lock<T>(t) {}
|
|
||||||
void unlock() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class lock_guard : public std::lock_guard<T>
|
using lock_guard = std::lock_guard<T>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
lock_guard(T &t) : std::lock_guard<T>(t) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class shared_mutex : public std::mutex { };
|
|
||||||
|
using shared_mutex = std::mutex;
|
||||||
|
|
||||||
using std::mutex;
|
using std::mutex;
|
||||||
|
|
||||||
using std::recursive_mutex;
|
using std::recursive_mutex;
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
|
|
||||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
/// 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.
|
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Thread_Storage
|
class Thread_Storage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Thread_Storage() = default;
|
||||||
Thread_Storage(void *t_key)
|
Thread_Storage(const Thread_Storage &) = delete;
|
||||||
: m_key(t_key)
|
Thread_Storage(Thread_Storage &&) = delete;
|
||||||
{
|
Thread_Storage &operator=(const Thread_Storage &) = delete;
|
||||||
}
|
Thread_Storage &operator=(Thread_Storage &&) = delete;
|
||||||
|
|
||||||
~Thread_Storage()
|
~Thread_Storage()
|
||||||
{
|
{
|
||||||
t().erase(m_key);
|
if (!destroyed) {
|
||||||
|
t().erase(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const T *operator->() const
|
inline const T *operator->() const
|
||||||
{
|
{
|
||||||
return &(t()[m_key]);
|
return &(t()[const_cast<Thread_Storage *>(this)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const T &operator*() const
|
inline const T &operator*() const
|
||||||
{
|
{
|
||||||
return t()[m_key];
|
return t()[const_cast<Thread_Storage *>(this)];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T *operator->()
|
inline T *operator->()
|
||||||
{
|
{
|
||||||
return &(t()[m_key]);
|
return &(t()[this]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T &operator*()
|
inline T &operator*()
|
||||||
{
|
{
|
||||||
return t()[m_key];
|
return t()[this];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *m_key;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::unordered_map<void*, T> &t()
|
struct Map_Holder {
|
||||||
{
|
std::unordered_map<Thread_Storage<T> *, T> map;
|
||||||
thread_local static std::unordered_map<void *, T> my_t;
|
|
||||||
return my_t;
|
Map_Holder() = default;
|
||||||
|
Map_Holder(const Map_Holder &) = delete;
|
||||||
|
Map_Holder(Map_Holder &&) = delete;
|
||||||
|
Map_Holder& operator=(Map_Holder &&) = delete;
|
||||||
|
Map_Holder& operator=(const Map_Holder &&) = delete;
|
||||||
|
~Map_Holder() {
|
||||||
|
// here is the theory:
|
||||||
|
// * If the Map_Holder is destroyed before the Thread_Storage, a flag will get set
|
||||||
|
// * If destroyed after the Thread_Storage, the * will have been removed from `map` and nothing will happen
|
||||||
|
for(auto &elem : map) { elem.first->destroyed = true; }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
static std::unordered_map<Thread_Storage<T> *, T> &t()
|
||||||
|
|
||||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
|
||||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
|
||||||
///
|
|
||||||
/// This version is used if the compiler does not support thread_local
|
|
||||||
template<typename T>
|
|
||||||
class Thread_Storage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Thread_Storage(void *)
|
|
||||||
{
|
{
|
||||||
|
thread_local Map_Holder my_map;
|
||||||
|
return my_map.map;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const T *operator->() const
|
bool destroyed{false};
|
||||||
{
|
|
||||||
return get_tls().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T &operator*() const
|
|
||||||
{
|
|
||||||
return *get_tls();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T *operator->()
|
|
||||||
{
|
|
||||||
return get_tls().get();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T &operator*()
|
|
||||||
{
|
|
||||||
return *get_tls();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// \todo this leaks thread instances. It needs to be culled from time to time
|
|
||||||
std::shared_ptr<T> get_tls() const
|
|
||||||
{
|
|
||||||
unique_lock<mutex> lock(m_mutex);
|
|
||||||
|
|
||||||
auto itr = m_instances.find(std::this_thread::get_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));
|
|
||||||
|
|
||||||
return new_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mutable mutex m_mutex;
|
|
||||||
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
|
|
||||||
};
|
};
|
||||||
#endif // threading enabled but no tls
|
|
||||||
|
|
||||||
#else // threading disabled
|
#else // threading disabled
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class unique_lock
|
class unique_lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
unique_lock(T &) {}
|
explicit unique_lock(T &) {}
|
||||||
void lock() {}
|
void lock() {}
|
||||||
void unlock() {}
|
void unlock() {}
|
||||||
};
|
};
|
||||||
@ -191,7 +140,7 @@ namespace chaiscript
|
|||||||
class shared_lock
|
class shared_lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
shared_lock(T &) {}
|
explicit shared_lock(T &) {}
|
||||||
void lock() {}
|
void lock() {}
|
||||||
void unlock() {}
|
void unlock() {}
|
||||||
};
|
};
|
||||||
@ -200,7 +149,7 @@ namespace chaiscript
|
|||||||
class lock_guard
|
class lock_guard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
lock_guard(T &) {}
|
explicit lock_guard(T &) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class shared_mutex { };
|
class shared_mutex { };
|
||||||
@ -212,7 +161,7 @@ namespace chaiscript
|
|||||||
class Thread_Storage
|
class Thread_Storage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Thread_Storage(void *)
|
explicit Thread_Storage(void *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,23 +21,20 @@ namespace chaiscript {
|
|||||||
class bad_any_cast : public std::bad_cast
|
class bad_any_cast : public std::bad_cast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bad_any_cast() CHAISCRIPT_NOEXCEPT
|
bad_any_cast() = default;
|
||||||
: m_what("bad any cast")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bad_any_cast(const bad_any_cast &) = default;
|
bad_any_cast(const bad_any_cast &) = default;
|
||||||
|
|
||||||
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
|
~bad_any_cast() noexcept override = default;
|
||||||
|
|
||||||
/// \brief Description of what error occurred
|
/// \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();
|
return m_what.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_what;
|
std::string m_what = "bad any cast";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,16 +43,17 @@ namespace chaiscript {
|
|||||||
private:
|
private:
|
||||||
struct Data
|
struct Data
|
||||||
{
|
{
|
||||||
Data(const std::type_info &t_type)
|
explicit Data(const std::type_info &t_type)
|
||||||
: m_type(t_type)
|
: m_type(t_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Data &operator=(const Data &) = delete;
|
Data &operator=(const Data &) = delete;
|
||||||
|
|
||||||
virtual ~Data() {}
|
virtual ~Data() = default;
|
||||||
|
|
||||||
virtual void *data() = 0;
|
virtual void *data() = 0;
|
||||||
|
|
||||||
const std::type_info &type() const
|
const std::type_info &type() const
|
||||||
{
|
{
|
||||||
return m_type;
|
return m_type;
|
||||||
@ -74,14 +72,12 @@ namespace chaiscript {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Data_Impl() {}
|
void *data() override
|
||||||
|
|
||||||
virtual void *data() CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
return &m_data;
|
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));
|
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
|
||||||
}
|
}
|
||||||
@ -96,6 +92,8 @@ namespace chaiscript {
|
|||||||
public:
|
public:
|
||||||
// construct/copy/destruct
|
// construct/copy/destruct
|
||||||
Any() = default;
|
Any() = default;
|
||||||
|
Any(Any &&) = default;
|
||||||
|
Any &operator=(Any &&t_any) = default;
|
||||||
|
|
||||||
Any(const Any &t_any)
|
Any(const Any &t_any)
|
||||||
{
|
{
|
||||||
@ -107,10 +105,6 @@ namespace chaiscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
|
||||||
Any(Any &&) = default;
|
|
||||||
Any &operator=(Any &&t_any) = default;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename ValueType,
|
template<typename ValueType,
|
||||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
||||||
@ -139,10 +133,6 @@ namespace chaiscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
~Any()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
Any & swap(Any &t_other)
|
Any & swap(Any &t_other)
|
||||||
{
|
{
|
||||||
@ -158,8 +148,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
const std::type_info & type() const
|
const std::type_info & type() const
|
||||||
{
|
{
|
||||||
if (m_data)
|
if (m_data) {
|
||||||
{
|
|
||||||
return m_data->type();
|
return m_data->type();
|
||||||
} else {
|
} else {
|
||||||
return typeid(void);
|
return typeid(void);
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||||
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||||
|
|
||||||
@ -30,32 +34,32 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
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))
|
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
||||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
|
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
: m_what(std::move(t_what))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_cast(const bad_boxed_cast &) = default;
|
bad_boxed_cast(const bad_boxed_cast &) = default;
|
||||||
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
|
~bad_boxed_cast() noexcept override = default;
|
||||||
|
|
||||||
/// \brief Description of what error occurred
|
/// \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();
|
return m_what.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Info from; ///< Type_Info contained in the Boxed_Value
|
Type_Info from; ///< Type_Info contained in the Boxed_Value
|
||||||
const std::type_info *to; ///< std::type_info of the desired (but failed) result type
|
const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_what;
|
std::string m_what;
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||||
#define CHAISCRIPT_BIND_FIRST_HPP_
|
#define CHAISCRIPT_BIND_FIRST_HPP_
|
||||||
|
|
||||||
@ -27,45 +31,52 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
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...)>(
|
return [f, o](Param...param) -> Ret {
|
||||||
[f, o](Param...param) -> Ret {
|
|
||||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename Class, typename ... 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...)>(
|
return [f, o](Param...param) -> Ret {
|
||||||
[f, o](Param...param) -> Ret {
|
|
||||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename Class, typename ... 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...)>(
|
return [f, o](Param...param) -> Ret {
|
||||||
[f, o](Param...param) -> Ret {
|
|
||||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename O, typename Ret, typename P1, typename ... 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...)>(
|
return [f, o](Param...param) -> Ret {
|
||||||
[f, o](Param...param) -> Ret {
|
|
||||||
return f(o, std::forward<Param>(param)...);
|
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,63 +1,31 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||||
#define 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 "../utility/utility.hpp"
|
||||||
#include "../language/chaiscript_common.hpp"
|
#include "register_function.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
||||||
namespace bootstrap
|
namespace bootstrap
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
/// \brief Constructs a new POD value object from a Boxed_Number
|
|
||||||
/// \param[in] v Boxed_Number to copy into the new object
|
|
||||||
/// \returns The newly created object.
|
|
||||||
template<typename P1>
|
|
||||||
std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
|
|
||||||
{
|
|
||||||
return std::make_shared<P1>(v.get_as<P1>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
|
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;
|
typedef typename std::remove_extent<T>::type ReturnType;
|
||||||
const auto extent = std::extent<T>::value;
|
const auto extent = std::extent<T>::value;
|
||||||
m->add(user_type<T>(), type);
|
m.add(user_type<T>(), type);
|
||||||
m->add(fun(
|
m.add(fun(
|
||||||
[extent](T& t, size_t index)->ReturnType &{
|
[extent](T& t, size_t index)->ReturnType &{
|
||||||
if (extent > 0 && index >= extent) {
|
if (extent > 0 && index >= extent) {
|
||||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||||
@ -68,7 +36,7 @@ namespace chaiscript
|
|||||||
), "[]"
|
), "[]"
|
||||||
);
|
);
|
||||||
|
|
||||||
m->add(fun(
|
m.add(fun(
|
||||||
[extent](const T &t, size_t index)->const ReturnType &{
|
[extent](const T &t, size_t index)->const ReturnType &{
|
||||||
if (extent > 0 && index >= extent) {
|
if (extent > 0 && index >= extent) {
|
||||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||||
@ -79,33 +47,29 @@ namespace chaiscript
|
|||||||
), "[]"
|
), "[]"
|
||||||
);
|
);
|
||||||
|
|
||||||
m->add(fun(
|
m.add(fun(
|
||||||
[extent](const T &) {
|
[extent](const T &) {
|
||||||
return extent;
|
return extent;
|
||||||
}), "size");
|
}), "size");
|
||||||
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Adds a copy constructor for the given type to the given Model
|
/// \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] 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
|
/// \param[in,out] m The Module to add the copy constructor to
|
||||||
/// \tparam T The type to add a copy constructor for
|
/// \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>
|
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);
|
m.add(constructor<T (const T &)>(), type);
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
||||||
/// \tparam T Type to create comparison operators for
|
/// \tparam T Type to create comparison operators for
|
||||||
/// \param[in,out] m module to add comparison operators to
|
/// \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>
|
template<typename T>
|
||||||
ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
|
void opers_comparison(Module& m)
|
||||||
{
|
{
|
||||||
operators::equal<T>(m);
|
operators::equal<T>(m);
|
||||||
operators::greater_than<T>(m);
|
operators::greater_than<T>(m);
|
||||||
@ -113,7 +77,6 @@ namespace chaiscript
|
|||||||
operators::less_than<T>(m);
|
operators::less_than<T>(m);
|
||||||
operators::less_than_equal<T>(m);
|
operators::less_than_equal<T>(m);
|
||||||
operators::not_equal<T>(m);
|
operators::not_equal<T>(m);
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -122,15 +85,14 @@ namespace chaiscript
|
|||||||
/// \param[in] type The name of the type to add the constructors for.
|
/// \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
|
/// \param[in,out] m The Module to add the basic constructors to
|
||||||
/// \tparam T Type to generate basic constructors for
|
/// \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 copy_constructor
|
||||||
/// \sa constructor
|
/// \sa constructor
|
||||||
template<typename T>
|
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);
|
copy_constructor<T>(type, m);
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Adds a constructor for a POD type
|
/// \brief Adds a constructor for a POD type
|
||||||
@ -138,22 +100,12 @@ namespace chaiscript
|
|||||||
/// \param[in] type The name of the type
|
/// \param[in] type The name of the type
|
||||||
/// \param[in,out] m The Module to add the constructor to
|
/// \param[in,out] m The Module to add the constructor to
|
||||||
template<typename T>
|
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);
|
m.add(fun([](const Boxed_Number &bn){ return bn.get_as<T>(); }), type);
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 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
|
/// Internal function for converting from a string to a value
|
||||||
/// uses ostream operator >> to perform the conversion
|
/// uses ostream operator >> to perform the conversion
|
||||||
template<typename Input>
|
template<typename Input>
|
||||||
@ -185,14 +137,13 @@ namespace chaiscript
|
|||||||
/// Add all common functions for a POD type. All operators, and
|
/// Add all common functions for a POD type. All operators, and
|
||||||
/// common conversions
|
/// common conversions
|
||||||
template<typename T>
|
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(user_type<T>(), name);
|
||||||
m->add(constructor<T()>(), name);
|
m.add(constructor<T()>(), name);
|
||||||
construct_pod<T>(name, m);
|
construct_pod<T>(name, m);
|
||||||
|
|
||||||
m->add(fun(&parse_string<T>), "to_" + name);
|
m.add(fun(&parse_string<T>), "to_" + name);
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,15 +153,14 @@ namespace chaiscript
|
|||||||
/// for handling of Proxy_Function object (that is,
|
/// for handling of Proxy_Function object (that is,
|
||||||
/// function variables.
|
/// function variables.
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
|
auto shared_ptr_clone(const std::shared_ptr<Type> &p)
|
||||||
{
|
{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::shared_ptr<typename std::remove_const<Type>::type>
|
std::shared_ptr<typename std::remove_const<Type>::type> shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
|
||||||
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
|
|
||||||
{
|
{
|
||||||
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
||||||
}
|
}
|
||||||
@ -261,43 +211,41 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
/// Add all arithmetic operators for PODs
|
/// 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::equals), "==");
|
||||||
m->add(fun(&Boxed_Number::less_than), "<");
|
m.add(fun(&Boxed_Number::less_than), "<");
|
||||||
m->add(fun(&Boxed_Number::greater_than), ">");
|
m.add(fun(&Boxed_Number::greater_than), ">");
|
||||||
m->add(fun(&Boxed_Number::greater_than_equal), ">=");
|
m.add(fun(&Boxed_Number::greater_than_equal), ">=");
|
||||||
m->add(fun(&Boxed_Number::less_than_equal), "<=");
|
m.add(fun(&Boxed_Number::less_than_equal), "<=");
|
||||||
m->add(fun(&Boxed_Number::not_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::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
|
/// Create a bound function object. The first param is the function to bind
|
||||||
@ -337,26 +285,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void throw_exception(const Boxed_Value &bv) {
|
|
||||||
throw bv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string what(const std::exception &e)
|
|
||||||
{
|
|
||||||
return e.what();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Boolean specialization of internal to_string function
|
|
||||||
static std::string bool_to_string(bool b)
|
|
||||||
{
|
|
||||||
if (b)
|
|
||||||
{
|
|
||||||
return "true";
|
|
||||||
} else {
|
|
||||||
return "false";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
||||||
const dispatch::Proxy_Function_Base *b)
|
const dispatch::Proxy_Function_Base *b)
|
||||||
@ -392,7 +320,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Function>
|
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 [f](const dispatch::Proxy_Function_Base *b) {
|
||||||
return do_return_boxed_value_vector(f, b);
|
return do_return_boxed_value_vector(f, b);
|
||||||
@ -403,94 +331,123 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||||
/// \param[in,out] m Module to add bootstrapped functions to
|
/// \param[in,out] m Module to add bootstrapped functions to
|
||||||
/// \returns passed in ModulePtr, or newly created one if default argument is used
|
/// \returns passed in Module
|
||||||
static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
|
static void bootstrap(Module& m)
|
||||||
{
|
{
|
||||||
m->add(user_type<void>(), "void");
|
m.add(user_type<void>(), "void");
|
||||||
m->add(user_type<bool>(), "bool");
|
m.add(user_type<bool>(), "bool");
|
||||||
m->add(user_type<Boxed_Value>(), "Object");
|
m.add(user_type<Boxed_Value>(), "Object");
|
||||||
m->add(user_type<Boxed_Number>(), "Number");
|
m.add(user_type<Boxed_Number>(), "Number");
|
||||||
m->add(user_type<Proxy_Function>(), "Function");
|
m.add(user_type<Proxy_Function>(), "Function");
|
||||||
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
||||||
m->add(user_type<std::exception>(), "exception");
|
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::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::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_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_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::out_of_range>(), "out_of_range");
|
||||||
m->add(user_type<std::logic_error>(), "logic_error");
|
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::exception, std::logic_error>());
|
||||||
m->add(chaiscript::base_class<std::logic_error, std::out_of_range>());
|
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(chaiscript::base_class<std::exception, std::out_of_range>());
|
||||||
|
|
||||||
m->add(user_type<std::runtime_error>(), "runtime_error");
|
m.add(user_type<std::runtime_error>(), "runtime_error");
|
||||||
m->add(chaiscript::base_class<std::exception, std::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(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
|
||||||
|
|
||||||
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
m.add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||||
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||||
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
|
m.add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
|
||||||
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
||||||
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||||
m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
|
m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
|
||||||
m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_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<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||||
|
|
||||||
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<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<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<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
m.add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||||
|
|
||||||
m->eval(R""(
|
m.eval(R"chaiscript(
|
||||||
def Dynamic_Object::clone() {
|
def Dynamic_Object::clone() {
|
||||||
auto &new_o = Dynamic_Object(this.get_type_name());
|
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; } );
|
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
|
||||||
new_o;
|
new_o;
|
||||||
}
|
}
|
||||||
)"");
|
|
||||||
|
|
||||||
m->add(fun(&has_guard), "has_guard");
|
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||||
m->add(fun(&get_guard), "get_guard");
|
{
|
||||||
|
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");
|
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
||||||
m->add(fun(&Boxed_Value::is_null), "is_var_null");
|
{
|
||||||
m->add(fun(&Boxed_Value::is_const), "is_var_const");
|
var rhs_attrs := rhs.get_attrs();
|
||||||
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
var lhs_attrs := lhs.get_attrs();
|
||||||
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");
|
if (rhs_attrs.size() != lhs_attrs.size()) {
|
||||||
m->add(user_type<Type_Info>(), "Type_Info");
|
true;
|
||||||
m->add(constructor<Type_Info (const Type_Info &)>(), "Type_Info");
|
} 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);
|
operators::equal<Type_Info>(m);
|
||||||
|
|
||||||
m->add(fun(&Type_Info::is_const), "is_type_const");
|
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_reference), "is_type_reference");
|
||||||
m->add(fun(&Type_Info::is_void), "is_type_void");
|
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_undef), "is_type_undef");
|
||||||
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
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::is_arithmetic), "is_type_arithmetic");
|
||||||
m->add(fun(&Type_Info::name), "cpp_name");
|
m.add(fun(&Type_Info::name), "cpp_name");
|
||||||
m->add(fun(&Type_Info::bare_name), "cpp_bare_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::bare_equal), "bare_equal");
|
||||||
|
|
||||||
|
|
||||||
basic_constructors<bool>("bool", m);
|
basic_constructors<bool>("bool", m);
|
||||||
@ -498,14 +455,14 @@ namespace chaiscript
|
|||||||
operators::equal<bool>(m);
|
operators::equal<bool>(m);
|
||||||
operators::not_equal<bool>(m);
|
operators::not_equal<bool>(m);
|
||||||
|
|
||||||
m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
|
m.add(fun([](const std::string &s) { return s; }), "to_string");
|
||||||
m->add(fun(&Bootstrap::bool_to_string), "to_string");
|
m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
|
||||||
m->add(fun(&unknown_assign), "=");
|
m.add(fun(&unknown_assign), "=");
|
||||||
m->add(fun(&throw_exception), "throw");
|
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
|
||||||
m->add(fun(&what), "what");
|
|
||||||
|
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
||||||
|
m.add(fun(&Boxed_Number::to_string), "to_string");
|
||||||
|
|
||||||
m->add(fun(&to_string<char>), "to_string");
|
|
||||||
m->add(fun(&Boxed_Number::to_string), "to_string");
|
|
||||||
|
|
||||||
bootstrap_pod_type<double>("double", m);
|
bootstrap_pod_type<double>("double", m);
|
||||||
bootstrap_pod_type<long double>("long_double", m);
|
bootstrap_pod_type<long double>("long_double", m);
|
||||||
@ -530,58 +487,71 @@ namespace chaiscript
|
|||||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||||
|
|
||||||
|
|
||||||
operators::logical_compliment<bool>(m);
|
operators::logical_compliment<bool>(m);
|
||||||
|
|
||||||
opers_arithmetic_pod(m);
|
opers_arithmetic_pod(m);
|
||||||
|
|
||||||
|
|
||||||
m->add(fun(&print), "print_string");
|
m.add(fun(&Build_Info::version_major), "version_major");
|
||||||
m->add(fun(&println), "println_string");
|
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(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
|
||||||
|
|
||||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
m.add(fun(&print), "print_string");
|
||||||
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
m.add(fun(&println), "println_string");
|
||||||
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(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||||
m->add(fun(
|
|
||||||
|
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) {
|
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
||||||
t_lhs.assign(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(&has_parse_tree), "has_parse_tree");
|
||||||
m->add(chaiscript::fun(&get_parse_tree), "get_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::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::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::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",
|
"eval_error",
|
||||||
{ },
|
{ },
|
||||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||||
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
||||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
|
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
|
||||||
std::vector<Boxed_Value> retval;
|
std::vector<Boxed_Value> retval;
|
||||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||||
std::back_inserter(retval),
|
std::back_inserter(retval),
|
||||||
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
|
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
|
||||||
return retval;
|
return retval;
|
||||||
})), "call_stack"} }
|
}), "call_stack"} }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
|
chaiscript::utility::add_class<chaiscript::File_Position>(m,
|
||||||
"File_Position",
|
"File_Position",
|
||||||
{ constructor<File_Position()>(),
|
{ constructor<File_Position()>(),
|
||||||
constructor<File_Position(int, int)>() },
|
constructor<File_Position(int, int)>() },
|
||||||
@ -590,7 +560,7 @@ namespace chaiscript
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
chaiscript::utility::add_class<AST_Node>(*m,
|
chaiscript::utility::add_class<AST_Node>(m,
|
||||||
"AST_Node",
|
"AST_Node",
|
||||||
{ },
|
{ },
|
||||||
{ {fun(&AST_Node::text), "text"},
|
{ {fun(&AST_Node::text), "text"},
|
||||||
@ -599,28 +569,17 @@ namespace chaiscript
|
|||||||
{fun(&AST_Node::start), "start"},
|
{fun(&AST_Node::start), "start"},
|
||||||
{fun(&AST_Node::end), "end"},
|
{fun(&AST_Node::end), "end"},
|
||||||
{fun(&AST_Node::to_string), "to_string"},
|
{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::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),
|
std::back_inserter(retval),
|
||||||
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
|
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
|
||||||
return retval;
|
return retval;
|
||||||
})), "children"},
|
}), "children"}
|
||||||
{fun(&AST_Node::replace_child), "replace_child"}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
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,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
/// \file
|
/// \file
|
||||||
/// This file contains utility functions for registration of STL container
|
/// This file contains utility functions for registration of STL container
|
||||||
/// classes. The methodology used is based on the SGI STL concepts.
|
/// classes. The methodology used is based on the SGI STL concepts.
|
||||||
@ -37,11 +41,10 @@ namespace chaiscript
|
|||||||
/// Bidir_Range, based on the D concept of ranges.
|
/// Bidir_Range, based on the D concept of ranges.
|
||||||
/// \todo Update the Range code to base its capabilities on
|
/// \todo Update the Range code to base its capabilities on
|
||||||
/// the user_typetraits of the iterator passed in
|
/// the user_typetraits of the iterator passed in
|
||||||
template<typename Container>
|
template<typename Container, typename IterType>
|
||||||
struct Bidir_Range
|
struct Bidir_Range
|
||||||
{
|
{
|
||||||
typedef Container container_type;
|
typedef Container container_type;
|
||||||
typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
|
|
||||||
|
|
||||||
Bidir_Range(Container &c)
|
Bidir_Range(Container &c)
|
||||||
: m_begin(c.begin()), m_end(c.end())
|
: m_begin(c.begin()), m_end(c.end())
|
||||||
@ -71,86 +74,28 @@ namespace chaiscript
|
|||||||
--m_end;
|
--m_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
reference_type front() const
|
decltype(auto) front() const
|
||||||
{
|
{
|
||||||
if (empty())
|
if (empty())
|
||||||
{
|
{
|
||||||
throw std::range_error("Range empty");
|
throw std::range_error("Range empty");
|
||||||
}
|
}
|
||||||
return *m_begin;
|
return (*m_begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
reference_type back() const
|
decltype(auto) back() const
|
||||||
{
|
{
|
||||||
if (empty())
|
if (empty())
|
||||||
{
|
{
|
||||||
throw std::range_error("Range empty");
|
throw std::range_error("Range empty");
|
||||||
}
|
}
|
||||||
typename Container::iterator pos = m_end;
|
auto pos = m_end;
|
||||||
--pos;
|
--pos;
|
||||||
return *(pos);
|
return (*(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
typename Container::iterator m_begin;
|
IterType m_begin;
|
||||||
typename Container::iterator m_end;
|
IterType m_end;
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Container>
|
|
||||||
struct Const_Bidir_Range
|
|
||||||
{
|
|
||||||
typedef const Container container_type;
|
|
||||||
typedef typename std::iterator_traits<typename Container::const_iterator>::reference const_reference_type;
|
|
||||||
|
|
||||||
Const_Bidir_Range(const Container &c)
|
|
||||||
: m_begin(c.begin()), m_end(c.end())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const
|
|
||||||
{
|
|
||||||
return m_begin == m_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_front()
|
|
||||||
{
|
|
||||||
if (empty())
|
|
||||||
{
|
|
||||||
throw std::range_error("Range empty");
|
|
||||||
}
|
|
||||||
++m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_back()
|
|
||||||
{
|
|
||||||
if (empty())
|
|
||||||
{
|
|
||||||
throw std::range_error("Range empty");
|
|
||||||
}
|
|
||||||
--m_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_reference_type front() const
|
|
||||||
{
|
|
||||||
if (empty())
|
|
||||||
{
|
|
||||||
throw std::range_error("Range empty");
|
|
||||||
}
|
|
||||||
return *m_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_reference_type back() const
|
|
||||||
{
|
|
||||||
if (empty())
|
|
||||||
{
|
|
||||||
throw std::range_error("Range empty");
|
|
||||||
}
|
|
||||||
typename Container::const_iterator pos = m_end;
|
|
||||||
--pos;
|
|
||||||
return *(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
typename Container::const_iterator m_begin;
|
|
||||||
typename Container::const_iterator m_end;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -177,21 +122,19 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Add Bidir_Range support for the given ContainerType
|
/// Add Bidir_Range support for the given ContainerType
|
||||||
template<typename Bidir_Type>
|
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);
|
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::empty), "empty");
|
||||||
m->add(fun(&Bidir_Type::pop_front), "pop_front");
|
m.add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||||
m->add(fun(&Bidir_Type::front), "front");
|
m.add(fun(&Bidir_Type::front), "front");
|
||||||
m->add(fun(&Bidir_Type::pop_back), "pop_back");
|
m.add(fun(&Bidir_Type::pop_back), "pop_back");
|
||||||
m->add(fun(&Bidir_Type::back), "back");
|
m.add(fun(&Bidir_Type::back), "back");
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -230,10 +173,16 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename ContainerType>
|
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<Bidir_Range<ContainerType, typename ContainerType::iterator> >(type,m);
|
||||||
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
|
detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator> >("Const_" + type,m);
|
||||||
|
}
|
||||||
|
template<typename ContainerType>
|
||||||
|
ModulePtr input_range_type(const std::string &type)
|
||||||
|
{
|
||||||
|
auto m = std::make_shared<Module>();
|
||||||
|
input_range_type<ContainerType>(type, *m);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,33 +190,83 @@ namespace chaiscript
|
|||||||
/// Add random_access_container concept to the given ContainerType
|
/// Add random_access_container concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||||
template<typename ContainerType>
|
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,
|
//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.
|
//to throw an exception in an out of bounds condition.
|
||||||
m->add(
|
m.add(
|
||||||
fun(
|
fun(
|
||||||
[](ContainerType &c, int index) -> typename ContainerType::reference {
|
[](ContainerType &c, int index) -> typename ContainerType::reference {
|
||||||
return c.at(index);
|
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
|
||||||
|
/// during dispatch. reevaluate
|
||||||
|
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||||
}), "[]");
|
}), "[]");
|
||||||
|
|
||||||
m->add(
|
m.add(
|
||||||
fun(
|
fun(
|
||||||
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||||
return c.at(index);
|
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
|
||||||
|
/// during dispatch. reevaluate
|
||||||
|
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||||
}), "[]");
|
}), "[]");
|
||||||
|
}
|
||||||
|
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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Add assignable concept to the given ContainerType
|
/// Add assignable concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||||
template<typename ContainerType>
|
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);
|
copy_constructor<ContainerType>(type, m);
|
||||||
operators::assign<ContainerType>(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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,11 +274,17 @@ namespace chaiscript
|
|||||||
/// Add container concept to the given ContainerType
|
/// Add container concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/Container.html
|
/// http://www.sgi.com/tech/stl/Container.html
|
||||||
template<typename ContainerType>
|
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->size(); } ), "size");
|
||||||
m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||||
m->add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,21 +292,26 @@ namespace chaiscript
|
|||||||
/// Add default constructable concept to the given Type
|
/// Add default constructable concept to the given Type
|
||||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||||
template<typename Type>
|
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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Add sequence concept to the given ContainerType
|
/// Add sequence concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||||
template<typename ContainerType>
|
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{
|
[]()->std::string{
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||||
return "insert_ref_at";
|
return "insert_ref_at";
|
||||||
@ -310,27 +320,31 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|
||||||
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||||
|
}
|
||||||
|
template <typename ContainerType>
|
||||||
|
ModulePtr sequence_type(const std::string &type)
|
||||||
|
{
|
||||||
|
auto m = std::make_shared<Module>();
|
||||||
|
sequence_type<ContainerType>(type, *m);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Add back insertion sequence concept to the given ContainerType
|
/// Add back insertion sequence concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||||
template<typename ContainerType>
|
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)();
|
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 &);
|
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{
|
[&]()->std::string{
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
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"
|
"# Pushes the second value onto the container while making a clone of the value\n"
|
||||||
"def push_back(" + type + " container, x)\n"
|
"def push_back(" + type + " container, x)\n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
@ -349,7 +363,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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,20 +378,20 @@ namespace chaiscript
|
|||||||
/// Front insertion sequence
|
/// Front insertion sequence
|
||||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||||
template<typename ContainerType>
|
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::reference (ContainerType::*front_ptr)();
|
||||||
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
||||||
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
||||||
typedef void (ContainerType::*pop_ptr)();
|
typedef void (ContainerType::*pop_ptr)();
|
||||||
|
|
||||||
m->add(fun(static_cast<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<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{
|
[&]()->std::string{
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
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"
|
"# Pushes the second value onto the front of container while making a clone of the value\n"
|
||||||
"def push_front(" + type + " container, x)\n"
|
"def push_front(" + type + " container, x)\n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
@ -389,7 +409,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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,20 +423,21 @@ namespace chaiscript
|
|||||||
/// bootstrap a given PairType
|
/// bootstrap a given PairType
|
||||||
/// http://www.sgi.com/tech/stl/pair.html
|
/// http://www.sgi.com/tech/stl/pair.html
|
||||||
template<typename PairType>
|
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);
|
||||||
|
|
||||||
|
m.add(fun(&PairType::first), "first");
|
||||||
typename PairType::first_type PairType::* f = &PairType::first;
|
m.add(fun(&PairType::second), "second");
|
||||||
typename PairType::second_type PairType::* s = &PairType::second;
|
|
||||||
|
|
||||||
m->add(fun(f), "first");
|
|
||||||
m->add(fun(s), "second");
|
|
||||||
|
|
||||||
basic_constructors<PairType>(type, m);
|
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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,10 +447,15 @@ namespace chaiscript
|
|||||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||||
|
|
||||||
template<typename ContainerType>
|
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);
|
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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,17 +463,17 @@ namespace chaiscript
|
|||||||
/// Add unique associative container concept to the given ContainerType
|
/// Add unique associative container concept to the given ContainerType
|
||||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||||
template<typename ContainerType>
|
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 &);
|
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{
|
[]()->std::string{
|
||||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
||||||
return "insert_ref";
|
return "insert_ref";
|
||||||
@ -449,8 +481,12 @@ namespace chaiscript
|
|||||||
return "insert";
|
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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,21 +494,21 @@ namespace chaiscript
|
|||||||
/// Add a MapType container
|
/// Add a MapType container
|
||||||
/// http://www.sgi.com/tech/stl/Map.html
|
/// http://www.sgi.com/tech/stl/Map.html
|
||||||
template<typename MapType>
|
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 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;
|
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<elem_access>(&MapType::at)), "at");
|
||||||
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||||
|
|
||||||
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
|
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
|
||||||
{
|
{
|
||||||
m->eval(R"(
|
m.eval(R"(
|
||||||
def Map::`==`(Map rhs) {
|
def Map::`==`(Map rhs) {
|
||||||
if ( rhs.size() != this.size() ) {
|
if ( rhs.size() != this.size() ) {
|
||||||
return false;
|
return false;
|
||||||
@ -500,26 +536,36 @@ namespace chaiscript
|
|||||||
unique_associative_container_type<MapType>(type, m);
|
unique_associative_container_type<MapType>(type, m);
|
||||||
pair_associative_container_type<MapType>(type, m);
|
pair_associative_container_type<MapType>(type, m);
|
||||||
input_range_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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// hopefully working List type
|
|
||||||
/// http://www.sgi.com/tech/stl/List.html
|
/// http://www.sgi.com/tech/stl/List.html
|
||||||
template<typename ListType>
|
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);
|
front_insertion_sequence_type<ListType>(type, m);
|
||||||
back_insertion_sequence_type<ListType>(type, m);
|
back_insertion_sequence_type<ListType>(type, m);
|
||||||
sequence_type<ListType>(type, m);
|
sequence_type<ListType>(type, m);
|
||||||
|
resizable_type<ListType>(type, m);
|
||||||
container_type<ListType>(type, m);
|
container_type<ListType>(type, m);
|
||||||
default_constructible_type<ListType>(type, m);
|
default_constructible_type<ListType>(type, m);
|
||||||
assignable_type<ListType>(type, m);
|
assignable_type<ListType>(type, m);
|
||||||
input_range_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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,20 +573,22 @@ namespace chaiscript
|
|||||||
/// Create a vector type with associated concepts
|
/// Create a vector type with associated concepts
|
||||||
/// http://www.sgi.com/tech/stl/Vector.html
|
/// http://www.sgi.com/tech/stl/Vector.html
|
||||||
template<typename VectorType>
|
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::reference (VectorType::*frontptr)();
|
||||||
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
|
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
|
||||||
|
|
||||||
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
m.add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||||
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
m.add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||||
|
|
||||||
|
|
||||||
back_insertion_sequence_type<VectorType>(type, m);
|
back_insertion_sequence_type<VectorType>(type, m);
|
||||||
sequence_type<VectorType>(type, m);
|
sequence_type<VectorType>(type, m);
|
||||||
random_access_container_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);
|
container_type<VectorType>(type, m);
|
||||||
default_constructible_type<VectorType>(type, m);
|
default_constructible_type<VectorType>(type, m);
|
||||||
assignable_type<VectorType>(type, m);
|
assignable_type<VectorType>(type, m);
|
||||||
@ -548,7 +596,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||||
{
|
{
|
||||||
m->eval(R"(
|
m.eval(R"(
|
||||||
def Vector::`==`(Vector rhs) {
|
def Vector::`==`(Vector rhs) {
|
||||||
if ( rhs.size() != this.size() ) {
|
if ( rhs.size() != this.size() ) {
|
||||||
return false;
|
return false;
|
||||||
@ -569,16 +617,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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a String container
|
/// Add a String container
|
||||||
/// http://www.sgi.com/tech/stl/basic_string.html
|
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||||
template<typename String>
|
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::addition<String>(m);
|
||||||
operators::assign_sum<String>(m);
|
operators::assign_sum<String>(m);
|
||||||
opers_comparison<String>(m);
|
opers_comparison<String>(m);
|
||||||
@ -590,7 +643,7 @@ namespace chaiscript
|
|||||||
input_range_type<String>(type, m);
|
input_range_type<String>(type, m);
|
||||||
|
|
||||||
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
//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{
|
[]()->std::string{
|
||||||
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
||||||
return "push_back_ref";
|
return "push_back_ref";
|
||||||
@ -600,21 +653,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->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->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_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_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_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_first_not_of(f, pos); } ), "find_first_not_of");
|
||||||
|
|
||||||
m->add(fun([](String *s) { s->clear(); } ), "clear");
|
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->empty(); } ), "empty");
|
||||||
m->add(fun([](const String *s) { return s->size(); } ), "size");
|
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([](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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,14 +681,19 @@ namespace chaiscript
|
|||||||
/// Add a MapType container
|
/// Add a MapType container
|
||||||
/// http://www.sgi.com/tech/stl/Map.html
|
/// http://www.sgi.com/tech/stl/Map.html
|
||||||
template<typename FutureType>
|
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(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(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;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||||
|
|
||||||
@ -69,34 +73,32 @@ namespace chaiscript
|
|||||||
/// assert(i == 5);
|
/// assert(i == 5);
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
|
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 {
|
try {
|
||||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
return(detail::Cast_Helper<Type>::cast(bv, t_conversions));
|
||||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
if (t_conversions && (*t_conversions)->convertable_type<Type>())
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
|
|
||||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||||
// either way, we are not responsible if it doesn't work
|
// either way, we are not responsible if it doesn't work
|
||||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
|
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
try {
|
try {
|
||||||
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
|
// try going the other way
|
||||||
// try going the other way - down the inheritance graph
|
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
|
|
||||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// attempted dynamic_cast
|
||||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||||
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||||
|
|
||||||
@ -16,7 +20,7 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
class Type_Conversions;
|
class Type_Conversions_State;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@ -25,25 +29,54 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T* throw_if_null(T *t)
|
T* throw_if_null(T *t)
|
||||||
{
|
{
|
||||||
if (t) return t;
|
if (t) { return t; }
|
||||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
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
|
/// Generic Cast_Helper_Inner, for casting to any type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner
|
struct Cast_Helper_Inner
|
||||||
{
|
{
|
||||||
typedef typename std::add_const<Result>::type Result_Type;
|
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||||
{
|
|
||||||
auto p = throw_if_null(ob.get_const_ptr());
|
|
||||||
return *static_cast<const Result *>(p);
|
|
||||||
} else {
|
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,15 +90,9 @@ namespace chaiscript
|
|||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const Result *>
|
struct Cast_Helper_Inner<const Result *>
|
||||||
{
|
{
|
||||||
typedef const Result * Result_Type;
|
static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
|
||||||
{
|
|
||||||
return static_cast<const Result *>(ob.get_const_ptr());
|
|
||||||
} else {
|
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -73,15 +100,9 @@ namespace chaiscript
|
|||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<Result *>
|
struct Cast_Helper_Inner<Result *>
|
||||||
{
|
{
|
||||||
typedef Result * Result_Type;
|
static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
|
return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
|
||||||
{
|
|
||||||
return static_cast<Result *>(ob.get_ptr());
|
|
||||||
} else {
|
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,17 +121,9 @@ namespace chaiscript
|
|||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const Result &>
|
struct Cast_Helper_Inner<const Result &>
|
||||||
{
|
{
|
||||||
typedef const Result& Result_Type;
|
static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||||
{
|
|
||||||
auto p = throw_if_null(ob.get_const_ptr());
|
|
||||||
return *static_cast<const Result *>(p);
|
|
||||||
} else {
|
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,26 +133,61 @@ namespace chaiscript
|
|||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<Result &>
|
struct Cast_Helper_Inner<Result &>
|
||||||
{
|
{
|
||||||
typedef Result& Result_Type;
|
static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
|
||||||
{
|
|
||||||
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
|
|
||||||
} else {
|
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Cast_Helper_Inner for casting to a && type
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<Result &&>
|
||||||
|
{
|
||||||
|
static Result&& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
{
|
||||||
|
return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
|
||||||
|
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
|
||||||
|
{
|
||||||
|
static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
{
|
||||||
|
return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
||||||
|
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<std::unique_ptr<Result> &>
|
||||||
|
{
|
||||||
|
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
{
|
||||||
|
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
||||||
|
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<const std::unique_ptr<Result> &>
|
||||||
|
{
|
||||||
|
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
{
|
||||||
|
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||||
{
|
{
|
||||||
typedef std::shared_ptr<Result> Result_Type;
|
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
return ob.get().cast<std::shared_ptr<Result> >();
|
return ob.get().cast<std::shared_ptr<Result> >();
|
||||||
}
|
}
|
||||||
@ -149,9 +197,7 @@ namespace chaiscript
|
|||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||||
{
|
{
|
||||||
typedef std::shared_ptr<const Result> Result_Type;
|
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
if (!ob.get_type_info().is_const())
|
if (!ob.get_type_info().is_const())
|
||||||
{
|
{
|
||||||
@ -173,6 +219,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
|
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||||
@ -189,9 +247,7 @@ namespace chaiscript
|
|||||||
template<>
|
template<>
|
||||||
struct Cast_Helper_Inner<Boxed_Value>
|
struct Cast_Helper_Inner<Boxed_Value>
|
||||||
{
|
{
|
||||||
typedef Boxed_Value Result_Type;
|
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
return ob;
|
return ob;
|
||||||
}
|
}
|
||||||
@ -201,9 +257,7 @@ namespace chaiscript
|
|||||||
template<>
|
template<>
|
||||||
struct Cast_Helper_Inner<Boxed_Value &>
|
struct Cast_Helper_Inner<Boxed_Value &>
|
||||||
{
|
{
|
||||||
typedef std::reference_wrapper<Boxed_Value> Result_Type;
|
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
return std::ref(const_cast<Boxed_Value &>(ob));
|
return std::ref(const_cast<Boxed_Value &>(ob));
|
||||||
}
|
}
|
||||||
@ -257,11 +311,9 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Cast_Helper
|
struct Cast_Helper
|
||||||
{
|
{
|
||||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||||
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
|
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||||
|
|
||||||
@ -28,9 +31,9 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
struct arithmetic_error : std::runtime_error
|
struct arithmetic_error : std::runtime_error
|
||||||
{
|
{
|
||||||
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||||
arithmetic_error(const arithmetic_error &) = default;
|
arithmetic_error(const arithmetic_error &) = default;
|
||||||
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
|
~arithmetic_error() noexcept override = default;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,16 +46,19 @@ namespace chaiscript
|
|||||||
// this is OK, so we're disabling size/and sign type warnings
|
// this is OK, so we're disabling size/and sign type warnings
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4244 4018 4389 4146 4365 4267)
|
#pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||||
|
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||||
#pragma GCC diagnostic ignored "-Wconversion"
|
#pragma GCC diagnostic ignored "-Wconversion"
|
||||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||||
|
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||||
@ -88,7 +94,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)
|
return (t_size == 1 && t_signed)?(Common_Types::t_int8)
|
||||||
:(t_size == 1)?(Common_Types::t_uint8)
|
:(t_size == 1)?(Common_Types::t_uint8)
|
||||||
@ -159,17 +165,17 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::equals:
|
case Operators::Opers::equals:
|
||||||
return const_var(t == u);
|
return const_var(t == u);
|
||||||
case Operators::less_than:
|
case Operators::Opers::less_than:
|
||||||
return const_var(t < u);
|
return const_var(t < u);
|
||||||
case Operators::greater_than:
|
case Operators::Opers::greater_than:
|
||||||
return const_var(t > u);
|
return const_var(t > u);
|
||||||
case Operators::less_than_equal:
|
case Operators::Opers::less_than_equal:
|
||||||
return const_var(t <= u);
|
return const_var(t <= u);
|
||||||
case Operators::greater_than_equal:
|
case Operators::Opers::greater_than_equal:
|
||||||
return const_var(t >= u);
|
return const_var(t >= u);
|
||||||
case Operators::not_equal:
|
case Operators::Opers::not_equal:
|
||||||
return const_var(t != u);
|
return const_var(t != u);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -181,10 +187,10 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::pre_increment:
|
case Operators::Opers::pre_increment:
|
||||||
++t;
|
++t;
|
||||||
break;
|
break;
|
||||||
case Operators::pre_decrement:
|
case Operators::Opers::pre_decrement:
|
||||||
--t;
|
--t;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -199,20 +205,20 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::assign:
|
case Operators::Opers::assign:
|
||||||
t = u;
|
t = u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_product:
|
case Operators::Opers::assign_product:
|
||||||
t *= u;
|
t *= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_sum:
|
case Operators::Opers::assign_sum:
|
||||||
t += u;
|
t += u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_quotient:
|
case Operators::Opers::assign_quotient:
|
||||||
check_divide_by_zero(u);
|
check_divide_by_zero(u);
|
||||||
t /= u;
|
t /= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_difference:
|
case Operators::Opers::assign_difference:
|
||||||
t -= u;
|
t -= u;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -227,23 +233,23 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::assign_bitwise_and:
|
case Operators::Opers::assign_bitwise_and:
|
||||||
t &= u;
|
t &= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_bitwise_or:
|
case Operators::Opers::assign_bitwise_or:
|
||||||
t |= u;
|
t |= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_shift_left:
|
case Operators::Opers::assign_shift_left:
|
||||||
t <<= u;
|
t <<= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_shift_right:
|
case Operators::Opers::assign_shift_right:
|
||||||
t >>= u;
|
t >>= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_remainder:
|
case Operators::Opers::assign_remainder:
|
||||||
check_divide_by_zero(u);
|
check_divide_by_zero(u);
|
||||||
t %= u;
|
t %= u;
|
||||||
break;
|
break;
|
||||||
case Operators::assign_bitwise_xor:
|
case Operators::Opers::assign_bitwise_xor:
|
||||||
t ^= u;
|
t ^= u;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -257,7 +263,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::bitwise_complement:
|
case Operators::Opers::bitwise_complement:
|
||||||
return const_var(~t);
|
return const_var(~t);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -269,18 +275,18 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::shift_left:
|
case Operators::Opers::shift_left:
|
||||||
return const_var(t << u);
|
return const_var(t << u);
|
||||||
case Operators::shift_right:
|
case Operators::Opers::shift_right:
|
||||||
return const_var(t >> u);
|
return const_var(t >> u);
|
||||||
case Operators::remainder:
|
case Operators::Opers::remainder:
|
||||||
check_divide_by_zero(u);
|
check_divide_by_zero(u);
|
||||||
return const_var(t % u);
|
return const_var(t % u);
|
||||||
case Operators::bitwise_and:
|
case Operators::Opers::bitwise_and:
|
||||||
return const_var(t & u);
|
return const_var(t & u);
|
||||||
case Operators::bitwise_or:
|
case Operators::Opers::bitwise_or:
|
||||||
return const_var(t | u);
|
return const_var(t | u);
|
||||||
case Operators::bitwise_xor:
|
case Operators::Opers::bitwise_xor:
|
||||||
return const_var(t ^ u);
|
return const_var(t ^ u);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -292,9 +298,9 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::unary_minus:
|
case Operators::Opers::unary_minus:
|
||||||
return const_var(-t);
|
return const_var(-t);
|
||||||
case Operators::unary_plus:
|
case Operators::Opers::unary_plus:
|
||||||
return const_var(+t);
|
return const_var(+t);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -306,14 +312,14 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
switch (t_oper)
|
switch (t_oper)
|
||||||
{
|
{
|
||||||
case Operators::sum:
|
case Operators::Opers::sum:
|
||||||
return const_var(t + u);
|
return const_var(t + u);
|
||||||
case Operators::quotient:
|
case Operators::Opers::quotient:
|
||||||
check_divide_by_zero(u);
|
check_divide_by_zero(u);
|
||||||
return const_var(t / u);
|
return const_var(t / u);
|
||||||
case Operators::product:
|
case Operators::Opers::product:
|
||||||
return const_var(t * u);
|
return const_var(t * u);
|
||||||
case Operators::difference:
|
case Operators::Opers::difference:
|
||||||
return const_var(t - u);
|
return const_var(t - u);
|
||||||
default:
|
default:
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -325,16 +331,16 @@ namespace chaiscript
|
|||||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
|
-> 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;
|
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));
|
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);
|
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);
|
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));
|
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));
|
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -346,12 +352,12 @@ namespace chaiscript
|
|||||||
-> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
|
-> 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;
|
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));
|
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);
|
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));
|
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -363,11 +369,11 @@ namespace chaiscript
|
|||||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
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
|
-> 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);
|
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()));
|
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()));
|
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -378,9 +384,9 @@ namespace chaiscript
|
|||||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
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
|
-> 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);
|
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()));
|
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
@ -499,18 +505,15 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Number(Boxed_Value v)
|
explicit Boxed_Number(Boxed_Value v)
|
||||||
: bv(std::move(v))
|
: bv(std::move(v))
|
||||||
{
|
{
|
||||||
validate_boxed_number(bv);
|
validate_boxed_number(bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Number(const Boxed_Number &) = default;
|
Boxed_Number(const Boxed_Number &) = default;
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
|
||||||
Boxed_Number(Boxed_Number &&) = default;
|
Boxed_Number(Boxed_Number &&) = default;
|
||||||
Boxed_Number& operator=(Boxed_Number &&) = default;
|
Boxed_Number& operator=(Boxed_Number &&) = default;
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename T> explicit Boxed_Number(T t)
|
template<typename T> explicit Boxed_Number(T t)
|
||||||
: bv(Boxed_Value(t))
|
: bv(Boxed_Value(t))
|
||||||
@ -585,6 +588,67 @@ namespace chaiscript
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Source, typename Target>
|
||||||
|
static void check_type()
|
||||||
|
{
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
// MSVC complains about this being redundant / tautologica l
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4127 6287)
|
||||||
|
#endif
|
||||||
|
if (sizeof(Source) != sizeof(Target)
|
||||||
|
|| std::is_signed<Source>() != std::is_signed<Target>()
|
||||||
|
|| std::is_floating_point<Source>() != std::is_floating_point<Target>())
|
||||||
|
{
|
||||||
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
|
}
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Target> Target get_as_checked() const
|
||||||
|
{
|
||||||
|
switch (get_common_type(bv)) {
|
||||||
|
case Common_Types::t_int32:
|
||||||
|
check_type<int32_t, Target>();
|
||||||
|
return get_as_aux<Target, int32_t>(bv);
|
||||||
|
case Common_Types::t_uint8:
|
||||||
|
check_type<uint8_t, Target>();
|
||||||
|
return get_as_aux<Target, uint8_t>(bv);
|
||||||
|
case Common_Types::t_int8:
|
||||||
|
check_type<int8_t, Target>();
|
||||||
|
return get_as_aux<Target, int8_t>(bv);
|
||||||
|
case Common_Types::t_uint16:
|
||||||
|
check_type<uint16_t, Target>();
|
||||||
|
return get_as_aux<Target, uint16_t>(bv);
|
||||||
|
case Common_Types::t_int16:
|
||||||
|
check_type<int16_t, Target>();
|
||||||
|
return get_as_aux<Target, int16_t>(bv);
|
||||||
|
case Common_Types::t_uint32:
|
||||||
|
check_type<uint32_t, Target>();
|
||||||
|
return get_as_aux<Target, uint32_t>(bv);
|
||||||
|
case Common_Types::t_uint64:
|
||||||
|
check_type<uint64_t, Target>();
|
||||||
|
return get_as_aux<Target, uint64_t>(bv);
|
||||||
|
case Common_Types::t_int64:
|
||||||
|
check_type<int64_t, Target>();
|
||||||
|
return get_as_aux<Target, int64_t>(bv);
|
||||||
|
case Common_Types::t_double:
|
||||||
|
check_type<double, Target>();
|
||||||
|
return get_as_aux<Target, double>(bv);
|
||||||
|
case Common_Types::t_float:
|
||||||
|
check_type<float, Target>();
|
||||||
|
return get_as_aux<Target, float>(bv);
|
||||||
|
case Common_Types::t_long_double:
|
||||||
|
check_type<long double, Target>();
|
||||||
|
return get_as_aux<Target, long double>(bv);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Target> Target get_as() const
|
template<typename Target> Target get_as() const
|
||||||
{
|
{
|
||||||
switch (get_common_type(bv)) {
|
switch (get_common_type(bv)) {
|
||||||
@ -645,71 +709,6 @@ namespace chaiscript
|
|||||||
throw chaiscript::detail::exception::bad_any_cast();
|
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)
|
static void validate_boxed_number(const Boxed_Value &v)
|
||||||
{
|
{
|
||||||
const Type_Info &inp_ = v.get_type_info();
|
const Type_Info &inp_ = v.get_type_info();
|
||||||
@ -724,266 +723,165 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cppcheck-suppress operatorEq
|
|
||||||
Boxed_Number operator=(const Boxed_Value &v)
|
|
||||||
{
|
|
||||||
validate_boxed_number(v);
|
|
||||||
bv = v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cppcheck-suppress operatorEq
|
|
||||||
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::assign, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator|=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator^=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator%=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator&(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator~() const
|
|
||||||
{
|
|
||||||
return oper(Operators::bitwise_complement, this->bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator^(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator|(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator*=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_product, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
Boxed_Number operator/=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
Boxed_Number operator+=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
Boxed_Number operator-=(const Boxed_Number &t_rhs)
|
|
||||||
{
|
|
||||||
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator/(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::quotient, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::shift_left, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator*(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::product, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator%(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::remainder, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
|
|
||||||
{
|
|
||||||
return oper(Operators::shift_right, this->bv, t_rhs.bv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||||
{
|
{
|
||||||
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
|
return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1009,9 +907,7 @@ namespace chaiscript
|
|||||||
template<>
|
template<>
|
||||||
struct Cast_Helper<Boxed_Number>
|
struct Cast_Helper<Boxed_Number>
|
||||||
{
|
{
|
||||||
typedef Boxed_Number Result_Type;
|
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
|
||||||
{
|
{
|
||||||
return Boxed_Number(ob);
|
return Boxed_Number(ob);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||||
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
||||||
|
|
||||||
@ -35,11 +39,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
Data(const Type_Info &ti,
|
Data(const Type_Info &ti,
|
||||||
chaiscript::detail::Any to,
|
chaiscript::detail::Any to,
|
||||||
bool tr,
|
bool is_ref,
|
||||||
const void *t_void_ptr,
|
const void *t_void_ptr,
|
||||||
bool t_return_value)
|
bool t_return_value)
|
||||||
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||||
m_is_ref(tr), m_return_value(t_return_value)
|
m_is_ref(is_ref), m_return_value(t_return_value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +58,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (rhs.m_attrs)
|
if (rhs.m_attrs)
|
||||||
{
|
{
|
||||||
m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*rhs.m_attrs));
|
m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*rhs.m_attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -62,10 +66,8 @@ namespace chaiscript
|
|||||||
|
|
||||||
Data(const Data &) = delete;
|
Data(const Data &) = delete;
|
||||||
|
|
||||||
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
|
|
||||||
Data(Data &&) = default;
|
Data(Data &&) = default;
|
||||||
Data &operator=(Data &&rhs) = default;
|
Data &operator=(Data &&rhs) = default;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
Type_Info m_type_info;
|
Type_Info m_type_info;
|
||||||
@ -79,7 +81,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Object_Data
|
struct Object_Data
|
||||||
{
|
{
|
||||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
|
static auto get(Boxed_Value::Void_Type, bool t_return_value)
|
||||||
{
|
{
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
detail::Get_Type_Info<void>::get(),
|
detail::Get_Type_Info<void>::get(),
|
||||||
@ -91,13 +93,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
|
static auto get(const std::shared_ptr<T> *obj, bool t_return_value)
|
||||||
{
|
{
|
||||||
return get(*obj, t_return_value);
|
return get(*obj, t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
|
static auto get(const std::shared_ptr<T> &obj, bool t_return_value)
|
||||||
{
|
{
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
@ -109,7 +111,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
|
static auto get(std::shared_ptr<T> &&obj, bool t_return_value)
|
||||||
{
|
{
|
||||||
auto ptr = obj.get();
|
auto ptr = obj.get();
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
@ -121,21 +123,23 @@ namespace chaiscript
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(T *t, bool t_return_value)
|
static auto get(T *t, bool t_return_value)
|
||||||
{
|
{
|
||||||
return get(std::ref(*t), t_return_value);
|
return get(std::ref(*t), t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
|
static auto get(const T *t, bool t_return_value)
|
||||||
{
|
{
|
||||||
return get(std::cref(*t), t_return_value);
|
return get(std::cref(*t), t_return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
|
static auto get(std::reference_wrapper<T> obj, bool t_return_value)
|
||||||
{
|
{
|
||||||
auto p = &obj.get();
|
auto p = &obj.get();
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
@ -148,7 +152,20 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(T t, bool t_return_value)
|
static auto get(std::unique_ptr<T> &&obj, bool t_return_value)
|
||||||
|
{
|
||||||
|
auto ptr = obj.get();
|
||||||
|
return std::make_shared<Data>(
|
||||||
|
detail::Get_Type_Info<T>::get(),
|
||||||
|
chaiscript::detail::Any(std::make_shared<std::unique_ptr<T>>(std::move(obj))),
|
||||||
|
true,
|
||||||
|
ptr,
|
||||||
|
t_return_value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static auto get(T t, bool t_return_value)
|
||||||
{
|
{
|
||||||
auto p = std::make_shared<T>(std::move(t));
|
auto p = std::make_shared<T>(std::move(t));
|
||||||
auto ptr = p.get();
|
auto ptr = p.get();
|
||||||
@ -184,16 +201,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Unknown-type constructor
|
/// Unknown-type constructor
|
||||||
Boxed_Value()
|
Boxed_Value() = default;
|
||||||
: m_data(Object_Data::get())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
|
||||||
Boxed_Value(Boxed_Value&&) = default;
|
Boxed_Value(Boxed_Value&&) = default;
|
||||||
Boxed_Value& operator=(Boxed_Value&&) = default;
|
Boxed_Value& operator=(Boxed_Value&&) = default;
|
||||||
#endif
|
|
||||||
|
|
||||||
Boxed_Value(const Boxed_Value&) = default;
|
Boxed_Value(const Boxed_Value&) = default;
|
||||||
Boxed_Value& operator=(const Boxed_Value&) = default;
|
Boxed_Value& operator=(const Boxed_Value&) = default;
|
||||||
|
|
||||||
@ -210,63 +221,99 @@ namespace chaiscript
|
|||||||
return *this;
|
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 m_data->m_type_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return true if the object is uninitialized
|
/// 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();
|
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();
|
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);
|
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
|
||||||
|
const auto ptr_ = m_ptr.get().get();
|
||||||
|
m_data.get().m_data_ptr = ptr_;
|
||||||
|
m_data.get().m_const_data_ptr = ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sentinel& operator=(Sentinel&&s) = default;
|
||||||
|
Sentinel(Sentinel &&s) = default;
|
||||||
|
|
||||||
|
operator std::shared_ptr<T>&() const
|
||||||
|
{
|
||||||
|
return m_ptr.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sentinel &operator=(const Sentinel &) = delete;
|
||||||
|
Sentinel(Sentinel&) = delete;
|
||||||
|
|
||||||
|
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
||||||
|
std::reference_wrapper<Data> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Sentinel(ptr, *(m_data.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_null() const noexcept
|
||||||
{
|
{
|
||||||
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
|
const chaiscript::detail::Any & get() const noexcept
|
||||||
{
|
{
|
||||||
return m_data->m_obj;
|
return m_data->m_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_ref() const CHAISCRIPT_NOEXCEPT
|
bool is_ref() const noexcept
|
||||||
{
|
{
|
||||||
return m_data->m_is_ref;
|
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;
|
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;
|
m_data->m_return_value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_pointer() const CHAISCRIPT_NOEXCEPT
|
bool is_pointer() const noexcept
|
||||||
{
|
{
|
||||||
return !is_ref();
|
return !is_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
void *get_ptr() const noexcept
|
||||||
{
|
{
|
||||||
return m_data->m_data_ptr;
|
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;
|
return m_data->m_const_data_ptr;
|
||||||
}
|
}
|
||||||
@ -275,7 +322,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
if (!m_data->m_attrs)
|
if (!m_data->m_attrs)
|
||||||
{
|
{
|
||||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>());
|
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &attr = (*m_data->m_attrs)[t_name];
|
auto &attr = (*m_data->m_attrs)[t_name];
|
||||||
@ -292,7 +339,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
if (t_obj.m_data->m_attrs)
|
if (t_obj.m_data->m_attrs)
|
||||||
{
|
{
|
||||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*t_obj.m_data->m_attrs));
|
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*t_obj.m_data->m_attrs);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -306,7 +353,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
/// \returns true if the two Boxed_Values share the same internal type
|
/// \returns true if the two Boxed_Values share the same internal type
|
||||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
|
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept
|
||||||
{
|
{
|
||||||
return l.get_type_info() == r.get_type_info();
|
return l.get_type_info() == r.get_type_info();
|
||||||
}
|
}
|
||||||
@ -315,11 +362,11 @@ namespace chaiscript
|
|||||||
// necessary to avoid hitting the templated && constructor of Boxed_Value
|
// necessary to avoid hitting the templated && constructor of Boxed_Value
|
||||||
struct Internal_Construction{};
|
struct Internal_Construction{};
|
||||||
|
|
||||||
Boxed_Value(const std::shared_ptr<Data> &t_data, Internal_Construction)
|
Boxed_Value(std::shared_ptr<Data> t_data, Internal_Construction)
|
||||||
: m_data(t_data) {
|
: m_data(std::move(t_data)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Data> m_data;
|
std::shared_ptr<Data> m_data = Object_Data::get();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
|
/// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
|
||||||
@ -416,10 +463,14 @@ namespace chaiscript
|
|||||||
return detail::const_var_impl(t);
|
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) {
|
inline Boxed_Value const_var(bool b) {
|
||||||
static auto t = detail::const_var_impl(true);
|
static const auto t = detail::const_var_impl(true);
|
||||||
static auto f = detail::const_var_impl(false);
|
static const auto f = detail::const_var_impl(false);
|
||||||
|
|
||||||
if (b) {
|
if (b) {
|
||||||
return t;
|
return t;
|
||||||
@ -427,7 +478,6 @@ namespace chaiscript
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
|
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
|
||||||
@ -25,7 +25,7 @@ namespace chaiscript {
|
|||||||
template<typename Ret, typename Class, typename ... Param>
|
template<typename Ret, typename Class, typename ... Param>
|
||||||
struct Const_Caller
|
struct Const_Caller
|
||||||
{
|
{
|
||||||
Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
||||||
|
|
||||||
template<typename ... Inner>
|
template<typename ... Inner>
|
||||||
Ret operator()(const Class &o, Inner&& ... inner) const {
|
Ret operator()(const Class &o, Inner&& ... inner) const {
|
||||||
@ -38,7 +38,7 @@ namespace chaiscript {
|
|||||||
template<typename Ret, typename ... Param>
|
template<typename Ret, typename ... Param>
|
||||||
struct Fun_Caller
|
struct Fun_Caller
|
||||||
{
|
{
|
||||||
Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
||||||
|
|
||||||
template<typename ... Inner>
|
template<typename ... Inner>
|
||||||
Ret operator()(Inner&& ... inner) const {
|
Ret operator()(Inner&& ... inner) const {
|
||||||
@ -51,7 +51,7 @@ namespace chaiscript {
|
|||||||
template<typename Ret, typename Class, typename ... Param>
|
template<typename Ret, typename Class, typename ... Param>
|
||||||
struct Caller
|
struct Caller
|
||||||
{
|
{
|
||||||
Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
||||||
|
|
||||||
template<typename ... Inner>
|
template<typename ... Inner>
|
||||||
Ret operator()(Class &o, Inner&& ... inner) const {
|
Ret operator()(Class &o, Inner&& ... inner) const {
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
|
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
|
||||||
#define CHAISCRIPT_DISPATCHKIT_HPP_
|
#define CHAISCRIPT_DISPATCHKIT_HPP_
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <deque>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -31,12 +34,16 @@
|
|||||||
#include "proxy_constructors.hpp"
|
#include "proxy_constructors.hpp"
|
||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
|
#include "short_alloc.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Boxed_Number;
|
class Boxed_Number;
|
||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
|
namespace parser {
|
||||||
|
class ChaiScript_Parser_Base;
|
||||||
|
}
|
||||||
namespace dispatch {
|
namespace dispatch {
|
||||||
class Dynamic_Proxy_Function;
|
class Dynamic_Proxy_Function;
|
||||||
class Proxy_Function_Base;
|
class Proxy_Function_Base;
|
||||||
@ -45,6 +52,7 @@ struct Placeholder_Object;
|
|||||||
} // namespace chaiscript
|
} // namespace chaiscript
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// \namespace chaiscript::dispatch
|
/// \namespace chaiscript::dispatch
|
||||||
/// \brief Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use to the end user.
|
/// \brief Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use to the end user.
|
||||||
|
|
||||||
@ -56,14 +64,14 @@ namespace chaiscript
|
|||||||
class reserved_word_error : public std::runtime_error
|
class reserved_word_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
reserved_word_error(const std::string &t_word) CHAISCRIPT_NOEXCEPT
|
explicit reserved_word_error(const std::string &t_word) noexcept
|
||||||
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
reserved_word_error(const reserved_word_error &) = default;
|
reserved_word_error(const reserved_word_error &) = default;
|
||||||
|
|
||||||
virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {}
|
~reserved_word_error() noexcept override = default;
|
||||||
|
|
||||||
std::string word() const
|
std::string word() const
|
||||||
{
|
{
|
||||||
@ -78,14 +86,14 @@ namespace chaiscript
|
|||||||
class illegal_name_error : public std::runtime_error
|
class illegal_name_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
illegal_name_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
|
explicit illegal_name_error(const std::string &t_name) noexcept
|
||||||
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
|
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
illegal_name_error(const illegal_name_error &) = default;
|
illegal_name_error(const illegal_name_error &) = default;
|
||||||
|
|
||||||
virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {}
|
~illegal_name_error() noexcept override = default;
|
||||||
|
|
||||||
std::string name() const
|
std::string name() const
|
||||||
{
|
{
|
||||||
@ -101,14 +109,14 @@ namespace chaiscript
|
|||||||
class name_conflict_error : public std::runtime_error
|
class name_conflict_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
name_conflict_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
|
explicit name_conflict_error(const std::string &t_name) noexcept
|
||||||
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
|
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
name_conflict_error(const name_conflict_error &) = default;
|
name_conflict_error(const name_conflict_error &) = default;
|
||||||
|
|
||||||
virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {}
|
~name_conflict_error() noexcept override = default;
|
||||||
|
|
||||||
std::string name() const
|
std::string name() const
|
||||||
{
|
{
|
||||||
@ -125,13 +133,13 @@ namespace chaiscript
|
|||||||
class global_non_const : public std::runtime_error
|
class global_non_const : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
global_non_const() CHAISCRIPT_NOEXCEPT
|
global_non_const() noexcept
|
||||||
: std::runtime_error("a global object must be const")
|
: std::runtime_error("a global object must be const")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
global_non_const(const global_non_const &) = default;
|
global_non_const(const global_non_const &) = default;
|
||||||
virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {}
|
~global_non_const() noexcept override = default;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +151,7 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
Module &add(Type_Info ti, std::string name)
|
Module &add(Type_Info ti, std::string name)
|
||||||
{
|
{
|
||||||
m_typeinfos.emplace_back(std::move(ti), std::move(name));
|
m_typeinfos.emplace_back(ti, std::move(name));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,12 +186,6 @@ namespace chaiscript
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Module &add(const std::shared_ptr<Module> &m)
|
|
||||||
{
|
|
||||||
m->apply(*this, *this);
|
|
||||||
return *m;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Eval, typename Engine>
|
template<typename Eval, typename Engine>
|
||||||
void apply(Eval &t_eval, Engine &t_engine) const
|
void apply(Eval &t_eval, Engine &t_engine) const
|
||||||
{
|
{
|
||||||
@ -194,15 +196,13 @@ namespace chaiscript
|
|||||||
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
|
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Module()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_function(const Proxy_Function &new_f, const std::string &name)
|
bool has_function(const Proxy_Function &new_f, const std::string &name)
|
||||||
{
|
{
|
||||||
return std::any_of(m_funcs.begin(), m_funcs.end(), [&](const std::pair<Proxy_Function, std::string> &existing_f) {
|
return std::any_of(m_funcs.begin(), m_funcs.end(),
|
||||||
|
[&](const std::pair<Proxy_Function, std::string> &existing_f) {
|
||||||
return existing_f.second == name && *(existing_f.first) == *(new_f);
|
return existing_f.second == name && *(existing_f.first) == *(new_f);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -216,8 +216,8 @@ namespace chaiscript
|
|||||||
template<typename T, typename InItr>
|
template<typename T, typename InItr>
|
||||||
static void apply(InItr begin, const InItr end, T &t)
|
static void apply(InItr begin, const InItr end, T &t)
|
||||||
{
|
{
|
||||||
for_each(begin, end, [&t](typename std::iterator_traits<InItr>::reference obj)
|
for_each(begin, end,
|
||||||
{
|
[&t](const auto &obj) {
|
||||||
try {
|
try {
|
||||||
t.add(obj.first, obj.second);
|
t.add(obj.first, obj.second);
|
||||||
} catch (const chaiscript::exception::name_conflict_error &) {
|
} catch (const chaiscript::exception::name_conflict_error &) {
|
||||||
@ -267,16 +267,16 @@ namespace chaiscript
|
|||||||
/// A Proxy_Function implementation that is able to take
|
/// A Proxy_Function implementation that is able to take
|
||||||
/// a vector of Proxy_Functions and perform a dispatch on them. It is
|
/// a vector of Proxy_Functions and perform a dispatch on them. It is
|
||||||
/// used specifically in the case of dealing with Function object variables
|
/// used specifically in the case of dealing with Function object variables
|
||||||
class Dispatch_Function : public dispatch::Proxy_Function_Base
|
class Dispatch_Function final : public dispatch::Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
explicit Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
||||||
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
|
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
|
||||||
m_funcs(std::move(t_funcs))
|
m_funcs(std::move(t_funcs))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
bool operator==(const dispatch::Proxy_Function_Base &rhs) const override
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
|
const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||||
@ -286,9 +286,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dispatch_Function() {}
|
std::vector<Const_Proxy_Function> get_contained_functions() const override
|
||||||
|
|
||||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
|
return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
|
||||||
}
|
}
|
||||||
@ -314,19 +312,14 @@ namespace chaiscript
|
|||||||
return arity;
|
return arity;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 std::any_of(m_funcs.cbegin(), m_funcs.cend(),
|
return std::any_of(std::begin(m_funcs), std::end(m_funcs),
|
||||||
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
|
||||||
return "Multiple method dispatch function wrapper.";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
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 dispatch::dispatch(m_funcs, params, t_conversions);
|
return dispatch::dispatch(m_funcs, params, t_conversions);
|
||||||
}
|
}
|
||||||
@ -367,7 +360,7 @@ namespace chaiscript
|
|||||||
++begin;
|
++begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(type_infos.size() > 0 && " type_info vector size is < 0, this is only possible if something else is broken");
|
assert(!type_infos.empty() && " type_info vector size is < 0, this is only possible if something else is broken");
|
||||||
|
|
||||||
if (size_mismatch)
|
if (size_mismatch)
|
||||||
{
|
{
|
||||||
@ -387,22 +380,56 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
struct Stack_Holder
|
struct Stack_Holder
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
|
//template <class T, std::size_t BufSize = sizeof(T)*20000>
|
||||||
typedef std::vector<Scope> StackData;
|
// using SmallVector = std::vector<T, short_alloc<T, BufSize>>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using SmallVector = std::vector<T>;
|
||||||
|
|
||||||
|
|
||||||
|
typedef SmallVector<std::pair<std::string, Boxed_Value>> Scope;
|
||||||
|
typedef SmallVector<Scope> StackData;
|
||||||
|
typedef SmallVector<StackData> Stacks;
|
||||||
|
typedef SmallVector<Boxed_Value> Call_Param_List;
|
||||||
|
typedef SmallVector<Call_Param_List> Call_Params;
|
||||||
|
|
||||||
Stack_Holder()
|
Stack_Holder()
|
||||||
: call_depth(0)
|
|
||||||
{
|
{
|
||||||
stacks.reserve(2);
|
push_stack();
|
||||||
stacks.emplace_back(1);
|
push_call_params();
|
||||||
call_params.emplace_back();
|
|
||||||
call_params.back().reserve(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<StackData> stacks;
|
void push_stack_data()
|
||||||
|
{
|
||||||
|
stacks.back().emplace_back();
|
||||||
|
// stacks.back().emplace_back(Scope(scope_allocator));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::vector<Boxed_Value>> call_params;
|
void push_stack()
|
||||||
int call_depth;
|
{
|
||||||
|
stacks.emplace_back(1);
|
||||||
|
// stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator));
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_call_params()
|
||||||
|
{
|
||||||
|
call_params.emplace_back();
|
||||||
|
// call_params.emplace_back(Call_Param_List(call_param_list_allocator));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scope::allocator_type::arena_type scope_allocator;
|
||||||
|
//StackData::allocator_type::arena_type stack_data_allocator;
|
||||||
|
//Stacks::allocator_type::arena_type stacks_allocator;
|
||||||
|
//Call_Param_List::allocator_type::arena_type call_param_list_allocator;
|
||||||
|
//Call_Params::allocator_type::arena_type call_params_allocator;
|
||||||
|
|
||||||
|
// Stacks stacks = Stacks(stacks_allocator);
|
||||||
|
// Call_Params call_params = Call_Params(call_params_allocator);
|
||||||
|
|
||||||
|
Stacks stacks;
|
||||||
|
Call_Params call_params;
|
||||||
|
|
||||||
|
int call_depth = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Main class for the dispatchkit. Handles management
|
/// Main class for the dispatchkit. Handles management
|
||||||
@ -413,7 +440,7 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||||
typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
|
typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
|
||||||
typedef std::vector<Scope> StackData;
|
typedef Stack_Holder::StackData StackData;
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
@ -422,27 +449,20 @@ namespace chaiscript
|
|||||||
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
||||||
std::map<std::string, Boxed_Value> m_global_objects;
|
std::map<std::string, Boxed_Value> m_global_objects;
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
std::set<std::string> m_reserved_words;
|
|
||||||
|
|
||||||
State &operator=(const State &) = default;
|
|
||||||
State() = default;
|
|
||||||
State(const State &) = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Dispatch_Engine()
|
explicit Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
|
||||||
: m_stack_holder(this)
|
: m_stack_holder(),
|
||||||
{
|
m_parser(parser)
|
||||||
}
|
|
||||||
|
|
||||||
~Dispatch_Engine()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||||
template<typename Type>
|
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 chaiscript::boxed_cast<Type>(bv, &m_conversions);
|
Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
|
||||||
|
return(chaiscript::boxed_cast<Type>(bv, &state));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new conversion for upcasting to a base class
|
/// Add a new conversion for upcasting to a base class
|
||||||
@ -454,7 +474,6 @@ namespace chaiscript
|
|||||||
/// Add a new named Proxy_Function to the system
|
/// Add a new named Proxy_Function to the system
|
||||||
void add(const Proxy_Function &f, const std::string &name)
|
void add(const Proxy_Function &f, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
add_function(f, name);
|
add_function(f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +481,6 @@ namespace chaiscript
|
|||||||
/// is not available in the current scope it is created
|
/// is not available in the current scope it is created
|
||||||
void add(Boxed_Value obj, const std::string &name)
|
void add(Boxed_Value obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
auto &stack = get_stack_data();
|
auto &stack = get_stack_data();
|
||||||
|
|
||||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||||
@ -482,6 +500,26 @@ namespace chaiscript
|
|||||||
add_object(name, std::move(obj));
|
add_object(name, std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a named object to the current scope
|
||||||
|
/// \warning This version does not check the validity of the name
|
||||||
|
/// it is meant for internal use only
|
||||||
|
Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
|
||||||
|
{
|
||||||
|
auto &stack_elem = get_stack_data(t_holder).back();
|
||||||
|
|
||||||
|
if (std::any_of(stack_elem.begin(), stack_elem.end(),
|
||||||
|
[&](const std::pair<std::string, Boxed_Value> &o) {
|
||||||
|
return o.first == t_name;
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
throw chaiscript::exception::name_conflict_error(t_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_elem.emplace_back(t_name, std::move(obj));
|
||||||
|
return stack_elem.back().second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Adds a named object to the current scope
|
/// Adds a named object to the current scope
|
||||||
/// \warning This version does not check the validity of the name
|
/// \warning This version does not check the validity of the name
|
||||||
/// it is meant for internal use only
|
/// it is meant for internal use only
|
||||||
@ -497,7 +535,7 @@ namespace chaiscript
|
|||||||
throw chaiscript::exception::name_conflict_error(t_name);
|
throw chaiscript::exception::name_conflict_error(t_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_stack_data(t_holder).back().emplace_back(t_name, std::move(obj));
|
stack_elem.emplace_back(t_name, std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -512,7 +550,6 @@ namespace chaiscript
|
|||||||
/// Adds a new global shared object, between all the threads
|
/// Adds a new global shared object, between all the threads
|
||||||
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
if (!obj.is_const())
|
if (!obj.is_const())
|
||||||
{
|
{
|
||||||
throw chaiscript::exception::global_non_const();
|
throw chaiscript::exception::global_non_const();
|
||||||
@ -531,8 +568,6 @@ namespace chaiscript
|
|||||||
/// Adds a new global (non-const) shared object, between all the threads
|
/// Adds a new global (non-const) shared object, between all the threads
|
||||||
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
|
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
const auto itr = m_state.m_global_objects.find(name);
|
const auto itr = m_state.m_global_objects.find(name);
|
||||||
@ -549,8 +584,6 @@ namespace chaiscript
|
|||||||
/// Adds a new global (non-const) shared object, between all the threads
|
/// Adds a new global (non-const) shared object, between all the threads
|
||||||
void add_global(const Boxed_Value &obj, const std::string &name)
|
void add_global(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||||
@ -561,6 +594,19 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates an existing global shared object or adds a new global shared object if not found
|
||||||
|
void set_global(const Boxed_Value &obj, const std::string &name)
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
|
const auto itr = m_state.m_global_objects.find(name);
|
||||||
|
if (itr != m_state.m_global_objects.end())
|
||||||
|
{
|
||||||
|
itr->second.assign(obj);
|
||||||
|
} else {
|
||||||
|
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a new scope to the stack
|
/// Adds a new scope to the stack
|
||||||
void new_scope()
|
void new_scope()
|
||||||
@ -575,34 +621,32 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a new scope to the stack
|
/// Adds a new scope to the stack
|
||||||
void new_scope(Stack_Holder &t_holder)
|
static void new_scope(Stack_Holder &t_holder)
|
||||||
{
|
{
|
||||||
get_stack_data(t_holder).emplace_back();
|
t_holder.push_stack_data();
|
||||||
t_holder.call_params.emplace_back();
|
t_holder.push_call_params();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pops the current scope from the stack
|
/// Pops the current scope from the stack
|
||||||
void pop_scope(Stack_Holder &t_holder)
|
static void pop_scope(Stack_Holder &t_holder)
|
||||||
{
|
{
|
||||||
t_holder.call_params.pop_back();
|
t_holder.call_params.pop_back();
|
||||||
StackData &stack = get_stack_data(t_holder);
|
StackData &stack = get_stack_data(t_holder);
|
||||||
if (stack.size() > 1)
|
|
||||||
{
|
assert(!stack.empty());
|
||||||
|
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
} else {
|
|
||||||
throw std::range_error("Unable to pop global stack");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Pushes a new stack on to the list of stacks
|
/// Pushes a new stack on to the list of stacks
|
||||||
void new_stack(Stack_Holder &t_holder)
|
static void new_stack(Stack_Holder &t_holder)
|
||||||
{
|
{
|
||||||
// add a new Stack with 1 element
|
// add a new Stack with 1 element
|
||||||
t_holder.stacks.emplace_back(1);
|
t_holder.push_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_stack(Stack_Holder &t_holder)
|
static void pop_stack(Stack_Holder &t_holder)
|
||||||
{
|
{
|
||||||
t_holder.stacks.pop_back();
|
t_holder.stacks.pop_back();
|
||||||
}
|
}
|
||||||
@ -610,7 +654,7 @@ namespace chaiscript
|
|||||||
/// Searches the current stack for an object of the given name
|
/// Searches the current stack for an object of the given name
|
||||||
/// includes a special overload for the _ place holder object to
|
/// includes a special overload for the _ place holder object to
|
||||||
/// ensure that it is always in scope.
|
/// ensure that it is always in scope.
|
||||||
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc) const
|
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
|
||||||
{
|
{
|
||||||
enum class Loc : uint_fast32_t {
|
enum class Loc : uint_fast32_t {
|
||||||
located = 0x80000000,
|
located = 0x80000000,
|
||||||
@ -619,11 +663,11 @@ namespace chaiscript
|
|||||||
loc_mask = 0x0000FFFF
|
loc_mask = 0x0000FFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
|
uint_fast32_t loc = t_loc;
|
||||||
|
|
||||||
if (loc == 0)
|
if (loc == 0)
|
||||||
{
|
{
|
||||||
auto &stack = get_stack_data();
|
auto &stack = get_stack_data(t_holder);
|
||||||
|
|
||||||
// Is it in the stack?
|
// Is it in the stack?
|
||||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||||
@ -631,19 +675,18 @@ namespace chaiscript
|
|||||||
for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s )
|
for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s )
|
||||||
{
|
{
|
||||||
if (s->first == name) {
|
if (s->first == name) {
|
||||||
t_loc.store( static_cast<uint_fast32_t>(std::distance(stack.rbegin(), stack_elem) << 16)
|
t_loc = static_cast<uint_fast32_t>(std::distance(stack.rbegin(), stack_elem) << 16)
|
||||||
| static_cast<uint_fast32_t>(std::distance(stack_elem->begin(), s))
|
| static_cast<uint_fast32_t>(std::distance(stack_elem->begin(), s))
|
||||||
| static_cast<uint_fast32_t>(Loc::located)
|
| static_cast<uint_fast32_t>(Loc::located)
|
||||||
| static_cast<uint_fast32_t>(Loc::is_local),
|
| static_cast<uint_fast32_t>(Loc::is_local);
|
||||||
std::memory_order_relaxed);
|
|
||||||
return s->second;
|
return s->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t_loc.store( static_cast<uint_fast32_t>(Loc::located), std::memory_order_relaxed);
|
t_loc = static_cast<uint_fast32_t>(Loc::located);
|
||||||
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
|
} else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) {
|
||||||
auto &stack = get_stack_data();
|
auto &stack = get_stack_data(t_holder);
|
||||||
|
|
||||||
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
|
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
|
||||||
}
|
}
|
||||||
@ -659,9 +702,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
// no? is it a function object?
|
// no? is it a function object?
|
||||||
auto obj = get_function_object_int(name, loc);
|
auto obj = get_function_object_int(name, loc);
|
||||||
if (obj.first != loc) t_loc.store(uint_fast32_t(obj.first), std::memory_order_relaxed);
|
if (obj.first != loc) { t_loc = uint_fast32_t(obj.first); }
|
||||||
return obj.second;
|
|
||||||
|
|
||||||
|
return obj.second;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -722,9 +765,12 @@ namespace chaiscript
|
|||||||
|
|
||||||
std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
|
std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
|
||||||
{
|
{
|
||||||
uint_fast32_t method_missing_loc = m_method_missing_loc.load(std::memory_order_relaxed);
|
uint_fast32_t method_missing_loc = m_method_missing_loc;
|
||||||
auto method_missing_funs = get_function("method_missing", method_missing_loc);
|
auto method_missing_funs = get_function("method_missing", method_missing_loc);
|
||||||
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc.store(uint_fast32_t(method_missing_funs.first), std::memory_order_relaxed);
|
if (method_missing_funs.first != method_missing_loc) {
|
||||||
|
m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
|
||||||
|
}
|
||||||
|
|
||||||
return std::move(method_missing_funs.second);
|
return std::move(method_missing_funs.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,7 +858,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
auto &stack = get_stack_data();
|
auto &stack = get_stack_data();
|
||||||
auto &scope = stack.front();
|
auto &scope = stack.front();
|
||||||
scope = std::vector<std::pair<std::string, Boxed_Value>>(t_locals.begin(), t_locals.end());
|
scope.assign(t_locals.begin(), t_locals.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -883,34 +929,25 @@ namespace chaiscript
|
|||||||
return rets;
|
return rets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_reserved_word(const std::string &name)
|
|
||||||
{
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
m_state.m_reserved_words.insert(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Type_Conversions &conversions() const
|
const Type_Conversions &conversions() const
|
||||||
{
|
{
|
||||||
return m_conversions;
|
return m_conversions;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
|
static bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
|
||||||
bool t_has_params) const
|
bool t_has_params, const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
if (!t_has_params || t_params.empty()) {
|
if (!t_has_params || t_params.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &fun : t_funs) {
|
return std::any_of(std::begin(t_funs), std::end(t_funs),
|
||||||
if (fun->is_attribute_function()) {
|
[&](const auto &fun) {
|
||||||
if (fun->compare_first_type(t_params[0], m_conversions)) {
|
return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
@ -919,14 +956,15 @@ namespace chaiscript
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4715)
|
#pragma warning(disable : 4715)
|
||||||
#endif
|
#endif
|
||||||
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms, bool t_has_params)
|
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms, bool t_has_params,
|
||||||
|
const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
|
uint_fast32_t loc = t_loc;
|
||||||
const auto funs = get_function(t_name, loc);
|
const auto funs = get_function(t_name, loc);
|
||||||
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
|
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first); }
|
||||||
|
|
||||||
const auto do_attribute_call =
|
const auto do_attribute_call =
|
||||||
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value
|
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
|
std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
|
||||||
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
|
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
|
||||||
@ -946,27 +984,34 @@ namespace chaiscript
|
|||||||
|
|
||||||
This_Foist fi(*this, l_params.front());
|
This_Foist fi(*this, l_params.front());
|
||||||
|
|
||||||
auto func = boxed_cast<std::shared_ptr<const dispatch::Proxy_Function_Base>>(bv);
|
try {
|
||||||
|
auto func = boxed_cast<const dispatch::Proxy_Function_Base *>(bv);
|
||||||
try {
|
try {
|
||||||
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
|
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
} catch (const chaiscript::exception::arity_error &) {
|
} catch (const chaiscript::exception::arity_error &) {
|
||||||
} catch (const chaiscript::exception::guard_error &) {
|
} catch (const chaiscript::exception::guard_error &) {
|
||||||
}
|
}
|
||||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector<Const_Proxy_Function>{func});
|
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
||||||
|
std::vector<Const_Proxy_Function>{boxed_cast<Const_Proxy_Function>(bv)});
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
// unable to convert bv into a Proxy_Function_Base
|
||||||
|
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
||||||
|
std::vector<Const_Proxy_Function>(l_funs.begin(), l_funs.end()));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (is_attribute_call(*funs.second, params, t_has_params)) {
|
if (is_attribute_call(*funs.second, params, t_has_params, t_conversions)) {
|
||||||
return do_attribute_call(1, params, *funs.second, m_conversions);
|
return do_attribute_call(1, params, *funs.second, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
|
|
||||||
if (!funs.second->empty()) {
|
if (!funs.second->empty()) {
|
||||||
try {
|
try {
|
||||||
return dispatch::dispatch(*funs.second, params, m_conversions);
|
return dispatch::dispatch(*funs.second, params, t_conversions);
|
||||||
} catch(chaiscript::exception::dispatch_error&) {
|
} catch(chaiscript::exception::dispatch_error&) {
|
||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
@ -982,7 +1027,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
for (const auto &f : *method_missing_funs)
|
for (const auto &f : *method_missing_funs)
|
||||||
{
|
{
|
||||||
if(f->compare_first_type(params[0], m_conversions)) {
|
if(f->compare_first_type(params[0], t_conversions)) {
|
||||||
fs.push_back(f);
|
fs.push_back(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1006,9 +1051,9 @@ namespace chaiscript
|
|||||||
if (is_no_param) {
|
if (is_no_param) {
|
||||||
std::vector<Boxed_Value> tmp_params(params);
|
std::vector<Boxed_Value> tmp_params(params);
|
||||||
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
||||||
return do_attribute_call(2, tmp_params, functions, m_conversions);
|
return do_attribute_call(2, tmp_params, functions, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
|
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, t_conversions);
|
||||||
}
|
}
|
||||||
} catch (const dispatch::option_explicit_set &e) {
|
} catch (const dispatch::option_explicit_set &e) {
|
||||||
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
|
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
|
||||||
@ -1031,12 +1076,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms) const
|
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms,
|
||||||
|
const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
|
uint_fast32_t loc = t_loc;
|
||||||
const auto funs = get_function(t_name, loc);
|
const auto funs = get_function(t_name, loc);
|
||||||
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
|
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first);
|
||||||
return dispatch::dispatch(*funs.second, params, m_conversions);
|
}
|
||||||
|
return dispatch::dispatch(*funs.second, params, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1056,11 +1103,7 @@ namespace chaiscript
|
|||||||
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
|
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
|
||||||
{
|
{
|
||||||
std::vector<Type_Info> params = f.second->get_param_types();
|
std::vector<Type_Info> params = f.second->get_param_types();
|
||||||
std::string annotation = f.second->annotation();
|
|
||||||
|
|
||||||
if (annotation.size() > 0) {
|
|
||||||
std::cout << annotation;
|
|
||||||
}
|
|
||||||
dump_type(params.front());
|
dump_type(params.front());
|
||||||
std::cout << " " << f.first << "(";
|
std::cout << " " << f.first << "(";
|
||||||
|
|
||||||
@ -1082,7 +1125,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Returns true if a call can be made that consists of the first parameter
|
/// Returns true if a call can be made that consists of the first parameter
|
||||||
/// (the function) with the remaining parameters as its arguments.
|
/// (the function) with the remaining parameters as its arguments.
|
||||||
Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms)
|
Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms) const
|
||||||
{
|
{
|
||||||
if (params.empty())
|
if (params.empty())
|
||||||
{
|
{
|
||||||
@ -1090,8 +1133,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||||
|
const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves());
|
||||||
|
|
||||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
|
return const_var(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dump all system info to stdout
|
/// Dump all system info to stdout
|
||||||
@ -1160,12 +1204,12 @@ namespace chaiscript
|
|||||||
m_state = t_state;
|
m_state = t_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
|
static void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
|
||||||
{
|
{
|
||||||
t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(t_params));
|
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
|
static void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
|
||||||
{
|
{
|
||||||
for (auto &¶m : t_params)
|
for (auto &¶m : t_params)
|
||||||
{
|
{
|
||||||
@ -1173,14 +1217,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_function_params(Stack_Holder &t_s, const std::vector<Boxed_Value> &t_params)
|
static void save_function_params(Stack_Holder &t_s, const std::vector<Boxed_Value> &t_params)
|
||||||
{
|
{
|
||||||
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end());
|
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_function_params(std::initializer_list<Boxed_Value> t_params)
|
void save_function_params(std::initializer_list<Boxed_Value> t_params)
|
||||||
{
|
{
|
||||||
save_function_params(*m_stack_holder, std::move(t_params));
|
save_function_params(*m_stack_holder, t_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_function_params(std::vector<Boxed_Value> &&t_params)
|
void save_function_params(std::vector<Boxed_Value> &&t_params)
|
||||||
@ -1193,19 +1237,19 @@ namespace chaiscript
|
|||||||
save_function_params(*m_stack_holder, t_params);
|
save_function_params(*m_stack_holder, t_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void new_function_call(Stack_Holder &t_s)
|
void new_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
|
||||||
{
|
{
|
||||||
if (t_s.call_depth == 0)
|
if (t_s.call_depth == 0)
|
||||||
{
|
{
|
||||||
m_conversions.enable_conversion_saves(true);
|
m_conversions.enable_conversion_saves(t_saves, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
++t_s.call_depth;
|
++t_s.call_depth;
|
||||||
|
|
||||||
save_function_params(m_conversions.take_saves());
|
save_function_params(m_conversions.take_saves(t_saves));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_function_call(Stack_Holder &t_s)
|
void pop_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
|
||||||
{
|
{
|
||||||
--t_s.call_depth;
|
--t_s.call_depth;
|
||||||
|
|
||||||
@ -1214,18 +1258,18 @@ namespace chaiscript
|
|||||||
if (t_s.call_depth == 0)
|
if (t_s.call_depth == 0)
|
||||||
{
|
{
|
||||||
t_s.call_params.back().clear();
|
t_s.call_params.back().clear();
|
||||||
m_conversions.enable_conversion_saves(false);
|
m_conversions.enable_conversion_saves(t_saves, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void new_function_call()
|
void new_function_call()
|
||||||
{
|
{
|
||||||
new_function_call(*m_stack_holder);
|
new_function_call(*m_stack_holder, m_conversions.conversion_saves());
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_function_call()
|
void pop_function_call()
|
||||||
{
|
{
|
||||||
pop_function_call(*m_stack_holder);
|
pop_function_call(*m_stack_holder, m_conversions.conversion_saves());
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack_Holder &get_stack_holder()
|
Stack_Holder &get_stack_holder()
|
||||||
@ -1240,7 +1284,7 @@ namespace chaiscript
|
|||||||
return m_stack_holder->stacks.back();
|
return m_stack_holder->stacks.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
StackData &get_stack_data(Stack_Holder &t_holder)
|
static StackData &get_stack_data(Stack_Holder &t_holder)
|
||||||
{
|
{
|
||||||
return t_holder.stacks.back();
|
return t_holder.stacks.back();
|
||||||
}
|
}
|
||||||
@ -1250,6 +1294,11 @@ namespace chaiscript
|
|||||||
return m_stack_holder->stacks.back();
|
return m_stack_holder->stacks.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser::ChaiScript_Parser_Base &get_parser()
|
||||||
|
{
|
||||||
|
return m_parser.get();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
|
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
|
||||||
@ -1314,13 +1363,8 @@ namespace chaiscript
|
|||||||
const auto lhssize = lhsparamtypes.size();
|
const auto lhssize = lhsparamtypes.size();
|
||||||
const auto rhssize = rhsparamtypes.size();
|
const auto rhssize = rhsparamtypes.size();
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
|
static const auto boxed_type = user_type<Boxed_Value>();
|
||||||
static auto boxed_type = user_type<Boxed_Value>();
|
static const auto boxed_pod_type = user_type<Boxed_Number>();
|
||||||
static auto boxed_pod_type = user_type<Boxed_Number>();
|
|
||||||
#else
|
|
||||||
auto boxed_type = user_type<Boxed_Value>();
|
|
||||||
auto boxed_pod_type = user_type<Boxed_Number>();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
|
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
|
||||||
{
|
{
|
||||||
@ -1351,10 +1395,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (rt.bare_equal(boxed_type))
|
if (rt.bare_equal(boxed_type))
|
||||||
{
|
{
|
||||||
if (lt.bare_equal(boxed_pod_type))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1376,20 +1416,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Throw a reserved_word exception if the name is not allowed
|
|
||||||
void validate_object_name(const std::string &name) const
|
|
||||||
{
|
|
||||||
if (name.find("::") != std::string::npos) {
|
|
||||||
throw chaiscript::exception::illegal_name_error(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
|
||||||
{
|
|
||||||
throw chaiscript::exception::reserved_word_error(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Key, typename Value>
|
template<typename Container, typename Key, typename Value>
|
||||||
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
|
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
|
||||||
@ -1427,7 +1453,7 @@ namespace chaiscript
|
|||||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
|
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
|
||||||
{
|
{
|
||||||
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
|
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
|
||||||
return t_c.begin() + t_hint;
|
return std::next(t_c.begin(), static_cast<typename std::iterator_traits<typename Container::const_iterator>::difference_type>(t_hint));
|
||||||
} else {
|
} else {
|
||||||
return find_keyed_value(t_c, t_key);
|
return find_keyed_value(t_c, t_key);
|
||||||
}
|
}
|
||||||
@ -1484,8 +1510,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
Type_Conversions m_conversions;
|
Type_Conversions m_conversions;
|
||||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||||
|
std::reference_wrapper<parser::ChaiScript_Parser_Base> m_parser;
|
||||||
|
|
||||||
mutable std::atomic_uint_fast32_t m_method_missing_loc;
|
mutable std::atomic_uint_fast32_t m_method_missing_loc = {0};
|
||||||
|
|
||||||
State m_state;
|
State m_state;
|
||||||
};
|
};
|
||||||
@ -1493,9 +1520,10 @@ namespace chaiscript
|
|||||||
class Dispatch_State
|
class Dispatch_State
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dispatch_State(Dispatch_Engine &t_engine)
|
explicit Dispatch_State(Dispatch_Engine &t_engine)
|
||||||
: m_engine(t_engine),
|
: m_engine(t_engine),
|
||||||
m_stack_holder(t_engine.get_stack_holder())
|
m_stack_holder(t_engine.get_stack_holder()),
|
||||||
|
m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1511,16 +1539,34 @@ namespace chaiscript
|
|||||||
return m_stack_holder.get();
|
return m_stack_holder.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Type_Conversions_State &conversions() const {
|
||||||
|
return m_conversions;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type_Conversions::Conversion_Saves &conversion_saves() const {
|
||||||
|
return m_conversions.saves();
|
||||||
|
}
|
||||||
|
|
||||||
|
Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj) const {
|
||||||
|
return m_engine.get().add_get_object(t_name, std::move(obj), m_stack_holder.get());
|
||||||
|
}
|
||||||
|
|
||||||
void add_object(const std::string &t_name, Boxed_Value obj) const {
|
void add_object(const std::string &t_name, Boxed_Value obj) const {
|
||||||
m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
|
return m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const {
|
||||||
|
return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper<Dispatch_Engine> m_engine;
|
std::reference_wrapper<Dispatch_Engine> m_engine;
|
||||||
std::reference_wrapper<Stack_Holder> m_stack_holder;
|
std::reference_wrapper<Stack_Holder> m_stack_holder;
|
||||||
|
Type_Conversions_State m_conversions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
|
|
||||||
@ -25,7 +29,7 @@ namespace chaiscript
|
|||||||
namespace dispatch
|
namespace dispatch
|
||||||
{
|
{
|
||||||
struct option_explicit_set : std::runtime_error {
|
struct option_explicit_set : std::runtime_error {
|
||||||
option_explicit_set(const std::string &t_param_name)
|
explicit option_explicit_set(const std::string &t_param_name)
|
||||||
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
|
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -33,20 +37,18 @@ namespace chaiscript
|
|||||||
|
|
||||||
option_explicit_set(const option_explicit_set &) = default;
|
option_explicit_set(const option_explicit_set &) = default;
|
||||||
|
|
||||||
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
|
~option_explicit_set() noexcept override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamic_Object
|
class Dynamic_Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Object(std::string t_type_name)
|
explicit Dynamic_Object(std::string t_type_name)
|
||||||
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
|
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynamic_Object() : m_type_name(""), m_option_explicit(false)
|
Dynamic_Object() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_explicit() const
|
bool is_explicit() const
|
||||||
{
|
{
|
||||||
@ -84,6 +86,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)
|
Boxed_Value &get_attr(const std::string &t_attr_name)
|
||||||
{
|
{
|
||||||
return m_attrs[t_attr_name];
|
return m_attrs[t_attr_name];
|
||||||
@ -107,15 +113,14 @@ namespace chaiscript
|
|||||||
return get_attr(t_method_name);
|
return get_attr(t_method_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::map<std::string, Boxed_Value> get_attrs() const
|
std::map<std::string, Boxed_Value> get_attrs() const
|
||||||
{
|
{
|
||||||
return m_attrs;
|
return m_attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_type_name;
|
const std::string m_type_name = "";
|
||||||
bool m_option_explicit;
|
bool m_option_explicit = false;
|
||||||
|
|
||||||
std::map<std::string, Boxed_Value> m_attrs;
|
std::map<std::string, Boxed_Value> m_attrs;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
||||||
@ -39,7 +39,7 @@ namespace chaiscript
|
|||||||
/// A Proxy_Function implementation designed for calling a function
|
/// A Proxy_Function implementation designed for calling a function
|
||||||
/// that is automatically guarded based on the first param based on the
|
/// that is automatically guarded based on the first param based on the
|
||||||
/// param's type name
|
/// param's type name
|
||||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
class Dynamic_Object_Function final : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Object_Function(
|
Dynamic_Object_Function(
|
||||||
@ -67,12 +67,11 @@ namespace chaiscript
|
|||||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
&& "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 &operator=(const Dynamic_Object_Function) = delete;
|
||||||
Dynamic_Object_Function(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))
|
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))
|
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};
|
return {m_func};
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
|
||||||
return m_func->annotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
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 (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||||
{
|
{
|
||||||
@ -116,7 +109,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
|
||||||
{
|
{
|
||||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
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,
|
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
if (bv.get_type_info().bare_equal(m_doti))
|
if (bv.get_type_info().bare_equal(m_doti))
|
||||||
{
|
{
|
||||||
@ -156,9 +149,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
if (bvs.size() > 0)
|
if (!bvs.empty())
|
||||||
{
|
{
|
||||||
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
@ -170,9 +163,7 @@ namespace chaiscript
|
|||||||
Proxy_Function m_func;
|
Proxy_Function m_func;
|
||||||
std::unique_ptr<Type_Info> m_ti;
|
std::unique_ptr<Type_Info> m_ti;
|
||||||
const Type_Info m_doti;
|
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
|
* that is automatically guarded based on the first param based on the
|
||||||
* param's type name
|
* param's type name
|
||||||
*/
|
*/
|
||||||
class Dynamic_Object_Constructor : public Proxy_Function_Base
|
class Dynamic_Object_Constructor final : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Object_Constructor(
|
Dynamic_Object_Constructor(
|
||||||
@ -208,15 +199,13 @@ namespace chaiscript
|
|||||||
return std::vector<Type_Info>(begin, end);
|
return std::vector<Type_Info>(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dynamic_Object_Constructor() {}
|
bool operator==(const Proxy_Function_Base &f) const override
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||||
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
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))};
|
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||||
@ -224,13 +213,8 @@ namespace chaiscript
|
|||||||
return m_func->call_match(new_vals, t_conversions);
|
return m_func->call_match(new_vals, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
|
||||||
return m_func->annotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
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 = Boxed_Value(Dynamic_Object(m_type_name), true);
|
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
|
||||||
std::vector<Boxed_Value> new_params{bv};
|
std::vector<Boxed_Value> new_params{bv};
|
||||||
@ -242,8 +226,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_type_name;
|
const std::string m_type_name;
|
||||||
Proxy_Function m_func;
|
const Proxy_Function m_func;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||||
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||||
|
|
||||||
@ -23,80 +27,26 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
/// \todo make this a variadic template
|
|
||||||
struct Exception_Handler_Base
|
struct Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||||
|
|
||||||
virtual ~Exception_Handler_Base() {}
|
virtual ~Exception_Handler_Base() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T1>
|
template<typename ... T>
|
||||||
struct Exception_Handler_Impl1 : Exception_Handler_Base
|
struct Exception_Handler_Impl : Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual ~Exception_Handler_Impl1() {}
|
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
|
||||||
|
|
||||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
throw_type<T1>(bv, t_engine);
|
(void)std::initializer_list<int>{(throw_type<T>(bv, t_engine), 0)...};
|
||||||
}
|
|
||||||
};
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -155,42 +105,10 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
||||||
/// \sa \ref exceptions
|
/// \sa \ref exceptions
|
||||||
template<typename T1>
|
template<typename ... T>
|
||||||
Exception_Handler exception_specification()
|
Exception_Handler exception_specification()
|
||||||
{
|
{
|
||||||
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
|
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
|
||||||
}
|
|
||||||
|
|
||||||
/// \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>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
|
|
||||||
@ -18,7 +22,7 @@
|
|||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Boxed_Value;
|
class Boxed_Value;
|
||||||
class Type_Conversions;
|
class Type_Conversions_State;
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename T> struct Cast_Helper;
|
template <typename T> struct Cast_Helper;
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -35,8 +39,7 @@ namespace chaiscript
|
|||||||
/// \returns A std::function object for dispatching
|
/// \returns A std::function object for dispatching
|
||||||
/// \param[in] funcs the set of functions to dispatch on.
|
/// \param[in] funcs the set of functions to dispatch on.
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
std::function<FunctionType>
|
std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
||||||
[](const Const_Proxy_Function &f) {
|
[](const Const_Proxy_Function &f) {
|
||||||
@ -63,8 +66,7 @@ namespace chaiscript
|
|||||||
/// \returns A std::function object for dispatching
|
/// \returns A std::function object for dispatching
|
||||||
/// \param[in] func A function to execute.
|
/// \param[in] func A function to execute.
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
std::function<FunctionType>
|
std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
|
||||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
|
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
|
||||||
}
|
}
|
||||||
@ -72,8 +74,7 @@ namespace chaiscript
|
|||||||
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||||
/// and creating a typesafe C++ function caller from it.
|
/// and creating a typesafe C++ function caller from it.
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
std::function<FunctionType>
|
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
|
||||||
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||||
}
|
}
|
||||||
@ -84,9 +85,7 @@ namespace chaiscript
|
|||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct Cast_Helper<const std::function<Signature> &>
|
struct Cast_Helper<const std::function<Signature> &>
|
||||||
{
|
{
|
||||||
typedef std::function<Signature> Result_Type;
|
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
@ -101,9 +100,7 @@ namespace chaiscript
|
|||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct Cast_Helper<std::function<Signature> >
|
struct Cast_Helper<std::function<Signature> >
|
||||||
{
|
{
|
||||||
typedef std::function<Signature> Result_Type;
|
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
@ -118,9 +115,7 @@ namespace chaiscript
|
|||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct Cast_Helper<const std::function<Signature> >
|
struct Cast_Helper<const std::function<Signature> >
|
||||||
{
|
{
|
||||||
typedef std::function<Signature> Result_Type;
|
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||||
|
|
||||||
@ -31,9 +35,15 @@ namespace chaiscript
|
|||||||
struct Function_Caller_Ret
|
struct Function_Caller_Ret
|
||||||
{
|
{
|
||||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶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 != nullptr) {
|
||||||
|
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 +54,15 @@ namespace chaiscript
|
|||||||
struct Function_Caller_Ret<Ret, true>
|
struct Function_Caller_Ret<Ret, true>
|
||||||
{
|
{
|
||||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶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 != nullptr) {
|
||||||
|
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 +74,15 @@ namespace chaiscript
|
|||||||
struct Function_Caller_Ret<void, false>
|
struct Function_Caller_Ret<void, false>
|
||||||
{
|
{
|
||||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶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 != nullptr) {
|
||||||
|
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 +101,18 @@ namespace chaiscript
|
|||||||
template<typename ... P>
|
template<typename ... P>
|
||||||
Ret operator()(P&& ... param)
|
Ret operator()(P&& ... param)
|
||||||
{
|
{
|
||||||
|
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, {
|
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))...
|
box<P>(std::forward<P>(param))...
|
||||||
}, m_conversions
|
}, &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 +143,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// \todo what happens if t_conversions is deleted out from under us?!
|
/// \todo what happens if t_conversions is deleted out from under us?!
|
||||||
template<typename Ret, typename ... Params>
|
template<typename Ret, typename ... Params>
|
||||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
if (funcs.size() == 1)
|
if (funcs.size() == 1)
|
||||||
@ -132,7 +161,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,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||||
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||||
|
|
||||||
@ -27,9 +31,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
/**
|
/// Used internally for handling a return value from a Proxy_Function call
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return
|
struct Handle_Return
|
||||||
{
|
{
|
||||||
@ -59,13 +61,8 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Ret>
|
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>
|
template<typename Ret>
|
||||||
@ -79,23 +76,13 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Ret>
|
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>
|
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>
|
template<typename Ret>
|
||||||
@ -115,6 +102,24 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<Ret *&>
|
||||||
|
{
|
||||||
|
static Boxed_Value handle(Ret *p)
|
||||||
|
{
|
||||||
|
return Boxed_Value(p, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<const Ret *&>
|
||||||
|
{
|
||||||
|
static Boxed_Value handle(const Ret *p)
|
||||||
|
{
|
||||||
|
return Boxed_Value(p, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<Ret *>
|
struct Handle_Return<Ret *>
|
||||||
{
|
{
|
||||||
@ -143,23 +148,27 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Ret>
|
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>
|
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)
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<std::unique_ptr<Ret>> : Handle_Return<std::unique_ptr<Ret> &>
|
||||||
{
|
{
|
||||||
return Boxed_Value(r, true);
|
static Boxed_Value handle(std::unique_ptr<Ret> &&r)
|
||||||
|
{
|
||||||
|
return Boxed_Value(std::move(r), true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<const Ret &>
|
struct Handle_Return<const Ret &>
|
||||||
{
|
{
|
||||||
@ -169,10 +178,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>
|
template<typename Ret>
|
||||||
struct Handle_Return<Ret &>
|
struct Handle_Return<Ret &>
|
||||||
{
|
{
|
||||||
@ -180,16 +194,8 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return Boxed_Value(std::ref(r));
|
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<>
|
template<>
|
||||||
struct Handle_Return<Boxed_Value>
|
struct Handle_Return<Boxed_Value>
|
||||||
{
|
{
|
||||||
@ -199,40 +205,19 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<>
|
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<>
|
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<>
|
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 +232,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<>
|
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 +246,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
static Boxed_Value handle()
|
static Boxed_Value handle()
|
||||||
{
|
{
|
||||||
return Boxed_Value(Boxed_Value::Void_Type());
|
return void_var();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||||
#define CHAISCRIPT_OPERATORS_HPP_
|
#define CHAISCRIPT_OPERATORS_HPP_
|
||||||
|
|
||||||
@ -16,447 +20,202 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
namespace operators
|
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>
|
template<typename T>
|
||||||
ModulePtr assign(ModulePtr m = std::make_shared<Module>())
|
void assign(Module& m)
|
||||||
{
|
{
|
||||||
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "&=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "^=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "|=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "-=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "<<=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "*=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "/=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "%=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), ">>=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "+=");
|
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "--");
|
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "++");
|
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "==");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), ">");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), ">=");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "<");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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&>), "<=");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "!");
|
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "!=");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "+");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "+");
|
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "-");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "-");
|
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "&");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "~");
|
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "^");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "|");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "/");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "<<");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "*");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), "%");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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 &>), ">>");
|
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||||
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
||||||
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
||||||
@ -43,7 +46,7 @@ namespace chaiscript
|
|||||||
namespace dispatch
|
namespace dispatch
|
||||||
{
|
{
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions *t_conversions);
|
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions_State *t_conversions);
|
||||||
|
|
||||||
class Param_Types
|
class Param_Types
|
||||||
{
|
{
|
||||||
@ -53,7 +56,7 @@ namespace chaiscript
|
|||||||
m_doti(user_type<Dynamic_Object>())
|
m_doti(user_type<Dynamic_Object>())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
|
explicit Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
|
||||||
: m_types(std::move(t_types)),
|
: m_types(std::move(t_types)),
|
||||||
m_has_types(false),
|
m_has_types(false),
|
||||||
m_doti(user_type<Dynamic_Object>())
|
m_doti(user_type<Dynamic_Object>())
|
||||||
@ -63,7 +66,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
void push_front(std::string t_name, Type_Info t_ti)
|
void push_front(std::string t_name, Type_Info t_ti)
|
||||||
{
|
{
|
||||||
m_types.emplace(m_types.begin(), std::move(t_name), std::move(t_ti));
|
m_types.emplace(m_types.begin(), std::move(t_name), t_ti);
|
||||||
update_has_types();
|
update_has_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +75,51 @@ namespace chaiscript
|
|||||||
return m_types == t_rhs.m_types;
|
return m_types == t_rhs.m_types;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
std::vector<Boxed_Value> convert(std::vector<Boxed_Value> vals, const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
if (!m_has_types) return true;
|
for (size_t i = 0; i < vals.size(); ++i)
|
||||||
if (vals.size() != m_types.size()) return false;
|
{
|
||||||
|
const auto &name = m_types[i].first;
|
||||||
|
if (!name.empty()) {
|
||||||
|
const auto &bv = vals[i];
|
||||||
|
|
||||||
|
if (!bv.get_type_info().bare_equal(m_doti))
|
||||||
|
{
|
||||||
|
const auto &ti = m_types[i].second;
|
||||||
|
if (!ti.is_undef())
|
||||||
|
{
|
||||||
|
if (!bv.get_type_info().bare_equal(ti)) {
|
||||||
|
if (t_conversions->converts(ti, bv.get_type_info())) {
|
||||||
|
try {
|
||||||
|
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||||
|
// either way, we are not responsible if it doesn't work
|
||||||
|
vals[i] = t_conversions->boxed_type_conversion(m_types[i].second, t_conversions.saves(), vals[i]);
|
||||||
|
} catch (...) {
|
||||||
|
try {
|
||||||
|
// try going the other way
|
||||||
|
vals[i] = t_conversions->boxed_type_down_conversion(m_types[i].second, t_conversions.saves(), vals[i]);
|
||||||
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
|
throw exception::bad_boxed_cast(bv.get_type_info(), *m_types[i].second.bare_type_info());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first result: is a match
|
||||||
|
// second result: needs conversions
|
||||||
|
std::pair<bool, bool> match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||||
|
{
|
||||||
|
bool needs_conversion = false;
|
||||||
|
|
||||||
|
if (!m_has_types) { return std::make_pair(true, needs_conversion); }
|
||||||
|
if (vals.size() != m_types.size()) { return std::make_pair(false, needs_conversion); }
|
||||||
|
|
||||||
for (size_t i = 0; i < vals.size(); ++i)
|
for (size_t i = 0; i < vals.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -87,25 +131,31 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
if (!(name == "Dynamic_Object" || d.get_type_name() == name)) {
|
||||||
|
return std::make_pair(false, false);
|
||||||
|
}
|
||||||
} catch (const std::bad_cast &) {
|
} catch (const std::bad_cast &) {
|
||||||
return false;
|
return std::make_pair(false, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const auto &ti = m_types[i].second;
|
const auto &ti = m_types[i].second;
|
||||||
if (!ti.is_undef())
|
if (!ti.is_undef())
|
||||||
{
|
{
|
||||||
if (!bv.get_type_info().bare_equal(ti)) {
|
if (!bv.get_type_info().bare_equal(ti)) {
|
||||||
return false;
|
if (!t_conversions->converts(ti, bv.get_type_info())) {
|
||||||
|
return std::make_pair(false, false);
|
||||||
|
} else {
|
||||||
|
needs_conversion = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return std::make_pair(false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return std::make_pair(true, needs_conversion);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<std::string, Type_Info>> &types() const
|
const std::vector<std::pair<std::string, Type_Info>> &types() const
|
||||||
@ -145,9 +195,9 @@ namespace chaiscript
|
|||||||
class Proxy_Function_Base
|
class Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
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()) {
|
if (m_arity < 0 || size_t(m_arity) == params.size()) {
|
||||||
return do_call(params, t_conversions);
|
return do_call(params, t_conversions);
|
||||||
@ -163,7 +213,7 @@ namespace chaiscript
|
|||||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||||
|
|
||||||
virtual bool is_attribute_function() const { return false; }
|
virtual bool is_attribute_function() const { return false; }
|
||||||
|
|
||||||
@ -179,13 +229,11 @@ namespace chaiscript
|
|||||||
|
|
||||||
//! Return true if the function is a possible match
|
//! Return true if the function is a possible match
|
||||||
//! to the passed in values
|
//! to the passed in values
|
||||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
|
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
|
||||||
|
|
||||||
if (m_arity < 0)
|
if (m_arity < 0)
|
||||||
{
|
|
||||||
return true;
|
|
||||||
} else if (static_cast<size_t>(m_arity) == vals.size()) {
|
|
||||||
if (m_arity == 0)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
} else if (m_arity > 1) {
|
} else if (m_arity > 1) {
|
||||||
@ -193,9 +241,6 @@ namespace chaiscript
|
|||||||
} else {
|
} else {
|
||||||
return compare_type_to_param(m_types[1], vals[0], t_conversions);
|
return compare_type_to_param(m_types[1], vals[0], t_conversions);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns the number of arguments the function takes or -1 if it is variadic
|
/// \returns the number of arguments the function takes or -1 if it is variadic
|
||||||
@ -204,9 +249,7 @@ namespace chaiscript
|
|||||||
return m_arity;
|
return m_arity;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const = 0;
|
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
|
||||||
|
|
||||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
|
||||||
{
|
{
|
||||||
if (ti.is_undef()
|
if (ti.is_undef()
|
||||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||||
@ -214,7 +257,7 @@ namespace chaiscript
|
|||||||
&& ( (ti.bare_equal(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|
&& ( (ti.bare_equal(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|
||||||
|| ti.bare_equal(bv.get_type_info())
|
|| ti.bare_equal(bv.get_type_info())
|
||||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||||
|| t_conversions.converts(ti, bv.get_type_info())
|
|| t_conversions->converts(ti, bv.get_type_info())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -225,13 +268,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const
|
||||||
{
|
{
|
||||||
return compare_type_to_param(m_types[1], bv, t_conversions);
|
return compare_type_to_param(m_types[1], bv, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶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)
|
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
|
||||||
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
|
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
|
||||||
@ -248,7 +291,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs, const Type_Conversions &t_conversions)
|
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs,
|
||||||
|
const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
if (tis.size() - 1 != bvs.size())
|
if (tis.size() - 1 != bvs.size())
|
||||||
{
|
{
|
||||||
@ -282,14 +326,13 @@ namespace chaiscript
|
|||||||
class guard_error : public std::runtime_error
|
class guard_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
guard_error() CHAISCRIPT_NOEXCEPT
|
guard_error() noexcept
|
||||||
: std::runtime_error("Guard evaluation failed")
|
: std::runtime_error("Guard evaluation failed")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
guard_error(const guard_error &) = default;
|
guard_error(const guard_error &) = default;
|
||||||
|
|
||||||
virtual ~guard_error() CHAISCRIPT_NOEXCEPT
|
~guard_error() noexcept override = default;
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,31 +349,28 @@ namespace chaiscript
|
|||||||
int t_arity=-1,
|
int t_arity=-1,
|
||||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||||
Param_Types t_param_types = Param_Types(),
|
Param_Types t_param_types = Param_Types(),
|
||||||
std::string t_description = "",
|
|
||||||
Proxy_Function t_guard = Proxy_Function())
|
Proxy_Function t_guard = Proxy_Function())
|
||||||
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
||||||
m_param_types(std::move(t_param_types)),
|
m_param_types(std::move(t_param_types)),
|
||||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description))
|
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dynamic_Proxy_Function() {}
|
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
bool operator==(const Proxy_Function_Base &rhs) const override
|
||||||
{
|
{
|
||||||
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||||
|
|
||||||
return this == &rhs
|
return this == &rhs
|
||||||
|| (prhs
|
|| ((prhs != nullptr)
|
||||||
&& this->m_arity == prhs->m_arity
|
&& this->m_arity == prhs->m_arity
|
||||||
&& !this->m_guard && !prhs->m_guard
|
&& !this->m_guard && !prhs->m_guard
|
||||||
&& this->m_param_types == prhs->m_param_types);
|
&& this->m_param_types == prhs->m_param_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
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)))
|
return call_match_internal(vals, t_conversions).first;
|
||||||
&& test_guard(vals, t_conversions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -344,14 +384,9 @@ namespace chaiscript
|
|||||||
return m_parsenode;
|
return m_parsenode;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
|
||||||
return m_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
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)
|
if (m_guard)
|
||||||
{
|
{
|
||||||
@ -367,6 +402,26 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// first result: is a match
|
||||||
|
// second result: needs conversions
|
||||||
|
std::pair<bool, bool> call_match_internal(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||||
|
{
|
||||||
|
const auto comparison_result = [&](){
|
||||||
|
if (m_arity < 0) {
|
||||||
|
return std::make_pair(true, false);
|
||||||
|
} else if (vals.size() == size_t(m_arity)) {
|
||||||
|
return m_param_types.match(vals, t_conversions);
|
||||||
|
} else {
|
||||||
|
return std::make_pair(false, false);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
return std::make_pair(
|
||||||
|
comparison_result.first && test_guard(vals, t_conversions),
|
||||||
|
comparison_result.second
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
|
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
|
||||||
{
|
{
|
||||||
@ -385,16 +440,18 @@ namespace chaiscript
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
Param_Types m_param_types;
|
Param_Types m_param_types;
|
||||||
|
|
||||||
|
private:
|
||||||
Proxy_Function m_guard;
|
Proxy_Function m_guard;
|
||||||
AST_NodePtr m_parsenode;
|
AST_NodePtr m_parsenode;
|
||||||
std::string m_description;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Callable>
|
template<typename Callable>
|
||||||
class Dynamic_Proxy_Function_Impl : public Dynamic_Proxy_Function
|
class Dynamic_Proxy_Function_Impl final : public Dynamic_Proxy_Function
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Proxy_Function_Impl(
|
Dynamic_Proxy_Function_Impl(
|
||||||
@ -402,35 +459,35 @@ namespace chaiscript
|
|||||||
int t_arity=-1,
|
int t_arity=-1,
|
||||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||||
Param_Types t_param_types = Param_Types(),
|
Param_Types t_param_types = Param_Types(),
|
||||||
std::string t_description = "",
|
|
||||||
Proxy_Function t_guard = Proxy_Function())
|
Proxy_Function t_guard = Proxy_Function())
|
||||||
: Dynamic_Proxy_Function(
|
: Dynamic_Proxy_Function(
|
||||||
t_arity,
|
t_arity,
|
||||||
std::move(t_parsenode),
|
std::move(t_parsenode),
|
||||||
std::move(t_param_types),
|
std::move(t_param_types),
|
||||||
std::move(t_description),
|
|
||||||
std::move(t_guard)
|
std::move(t_guard)
|
||||||
),
|
),
|
||||||
m_f(std::move(t_f))
|
m_f(std::move(t_f))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dynamic_Proxy_Function_Impl() {}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
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))
|
const auto match_results = call_match_internal(params, t_conversions);
|
||||||
|
if (match_results.first)
|
||||||
{
|
{
|
||||||
|
if (match_results.second) {
|
||||||
|
return m_f(m_param_types.convert(params, t_conversions));
|
||||||
|
} else {
|
||||||
return m_f(params);
|
return m_f(params);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw exception::guard_error();
|
throw exception::guard_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Callable m_f;
|
Callable m_f;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -451,7 +508,7 @@ namespace chaiscript
|
|||||||
/// and substitutes bound parameters into the parameter list
|
/// and substitutes bound parameters into the parameter list
|
||||||
/// at runtime, when call() is executed.
|
/// at runtime, when call() is executed.
|
||||||
/// it is used for bind(function, param1, _, param2) style calls
|
/// 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:
|
public:
|
||||||
Bound_Function(const Const_Proxy_Function &t_f,
|
Bound_Function(const Const_Proxy_Function &t_f,
|
||||||
@ -462,19 +519,18 @@ namespace chaiscript
|
|||||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
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;
|
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);
|
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};
|
return std::vector<Const_Proxy_Function>{m_f};
|
||||||
}
|
}
|
||||||
@ -511,10 +567,6 @@ namespace chaiscript
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
|
||||||
return "Bound: " + m_f->annotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
|
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
|
||||||
@ -524,18 +576,11 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }
|
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);
|
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
|
// this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14
|
||||||
std::vector<Type_Info> retval{types[0]};
|
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)
|
for (size_t i = 0; i < types.size() - 1; ++i)
|
||||||
{
|
{
|
||||||
@ -548,7 +593,7 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (*m_f)(build_param_list(params), t_conversions);
|
return (*m_f)(build_param_list(params), t_conversions);
|
||||||
}
|
}
|
||||||
@ -561,57 +606,48 @@ namespace chaiscript
|
|||||||
class Proxy_Function_Impl_Base : public Proxy_Function_Base
|
class Proxy_Function_Impl_Base : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
explicit Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||||
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Proxy_Function_Impl_Base() {}
|
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_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
|
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||||
{
|
|
||||||
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// For any callable object
|
/// For any callable object
|
||||||
template<typename Func, typename Callable>
|
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:
|
public:
|
||||||
Proxy_Function_Callable_Impl(Callable f)
|
explicit Proxy_Function_Callable_Impl(Callable f)
|
||||||
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
||||||
m_f(std::move(f))
|
m_f(std::move(f))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Proxy_Function_Callable_Impl() {}
|
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||||
|
|
||||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
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::call_func(detail::Function_Signature<Func>(), m_f, params, t_conversions);
|
||||||
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -622,21 +658,16 @@ namespace chaiscript
|
|||||||
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
|
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
|
explicit Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
|
||||||
: Proxy_Function_Impl_Base(t_types)
|
: Proxy_Function_Impl_Base(t_types)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Assignable_Proxy_Function() {}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
|
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Func>
|
template<typename Func>
|
||||||
class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function
|
class Assignable_Proxy_Function_Impl final : public Assignable_Proxy_Function
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
|
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
|
||||||
@ -646,14 +677,12 @@ namespace chaiscript
|
|||||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Assignable_Proxy_Function_Impl() {}
|
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||||
|
|
||||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
|
||||||
}
|
}
|
||||||
@ -663,14 +692,14 @@ namespace chaiscript
|
|||||||
return m_f.get();
|
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);
|
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -678,22 +707,22 @@ namespace chaiscript
|
|||||||
std::reference_wrapper<std::function<Func>> m_f;
|
std::reference_wrapper<std::function<Func>> m_f;
|
||||||
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
|
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Attribute getter Proxy_Function implementation
|
/// Attribute getter Proxy_Function implementation
|
||||||
template<typename T, typename Class>
|
template<typename T, typename Class>
|
||||||
class Attribute_Access : public Proxy_Function_Base
|
class Attribute_Access final : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Attribute_Access(T Class::* t_attr)
|
explicit Attribute_Access(T Class::* t_attr)
|
||||||
: Proxy_Function_Base(param_types(), 1),
|
: Proxy_Function_Base(param_types(), 1),
|
||||||
m_attr(t_attr)
|
m_attr(t_attr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Attribute_Access() {}
|
bool is_attribute_function() const override { return true; }
|
||||||
|
|
||||||
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; }
|
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
{
|
||||||
const Attribute_Access<T, Class> * aa
|
const Attribute_Access<T, Class> * aa
|
||||||
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
|
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
|
||||||
@ -705,7 +734,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)
|
if (vals.size() != 1)
|
||||||
{
|
{
|
||||||
@ -715,26 +744,47 @@ namespace chaiscript
|
|||||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
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];
|
const Boxed_Value &bv = params[0];
|
||||||
if (bv.is_const())
|
if (bv.is_const())
|
||||||
{
|
{
|
||||||
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
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 {
|
} else {
|
||||||
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
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:
|
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()
|
static std::vector<Type_Info> param_types()
|
||||||
{
|
{
|
||||||
return {user_type<T>(), user_type<Class>()};
|
return {user_type<T>(), user_type<Class>()};
|
||||||
@ -769,7 +819,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
dispatch_error(const dispatch_error &) = default;
|
dispatch_error(const dispatch_error &) = default;
|
||||||
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
|
~dispatch_error() noexcept override = default;
|
||||||
|
|
||||||
std::vector<Boxed_Value> parameters;
|
std::vector<Boxed_Value> parameters;
|
||||||
std::vector<Const_Proxy_Function> functions;
|
std::vector<Const_Proxy_Function> functions;
|
||||||
@ -782,11 +832,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
template<typename FuncType>
|
template<typename FuncType>
|
||||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||||
const Type_Conversions &t_conversions)
|
const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||||
|
|
||||||
if (t_func->get_arity() == -1) return false;
|
if (t_func->get_arity() == -1) { return false; }
|
||||||
|
|
||||||
assert(plist.size() == types.size() - 1);
|
assert(plist.size() == types.size() - 1);
|
||||||
|
|
||||||
@ -801,7 +851,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
template<typename InItr, typename Funcs>
|
template<typename InItr, typename Funcs>
|
||||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||||
const Type_Conversions &t_conversions, const Funcs &t_funcs)
|
const Type_Conversions_State &t_conversions, const Funcs &t_funcs)
|
||||||
{
|
{
|
||||||
InItr matching_func(end);
|
InItr matching_func(end);
|
||||||
|
|
||||||
@ -846,7 +896,8 @@ namespace chaiscript
|
|||||||
plist.begin(),
|
plist.begin(),
|
||||||
std::back_inserter(newplist),
|
std::back_inserter(newplist),
|
||||||
[](const Type_Info &ti, const Boxed_Value ¶m) -> Boxed_Value {
|
[](const Type_Info &ti, const Boxed_Value ¶m) -> Boxed_Value {
|
||||||
if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()) {
|
if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()
|
||||||
|
&& param.get_type_info() != ti) {
|
||||||
return Boxed_Number(param).get_as(ti).bv;
|
return Boxed_Number(param).get_as(ti).bv;
|
||||||
} else {
|
} else {
|
||||||
return param;
|
return param;
|
||||||
@ -854,8 +905,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return (*(matching_func->second))(newplist, t_conversions);
|
return (*(matching_func->second))(newplist, t_conversions);
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
@ -871,14 +920,12 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Take a vector of functions and a vector of parameters. Attempt to execute
|
||||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
/// each function against the set of parameters, in order, until a matching
|
||||||
* each function against the set of parameters, in order, until a matching
|
/// function is found or throw dispatch_error if no matching function is found
|
||||||
* function is found or throw dispatch_error if no matching function is found
|
|
||||||
*/
|
|
||||||
template<typename Funcs>
|
template<typename Funcs>
|
||||||
Boxed_Value dispatch(const Funcs &funcs,
|
Boxed_Value dispatch(const Funcs &funcs,
|
||||||
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
|
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
|
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
|
||||||
ordered_funcs.reserve(funcs.size());
|
ordered_funcs.reserve(funcs.size());
|
||||||
@ -909,7 +956,7 @@ namespace chaiscript
|
|||||||
for (const auto &func : ordered_funcs )
|
for (const auto &func : ordered_funcs )
|
||||||
{
|
{
|
||||||
try {
|
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);
|
return (*(func.second))(plist, t_conversions);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
#include "boxed_cast.hpp"
|
#include "boxed_cast.hpp"
|
||||||
@ -19,7 +24,7 @@
|
|||||||
#include "callable_traits.hpp"
|
#include "callable_traits.hpp"
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
class Type_Conversions;
|
class Type_Conversions_State;
|
||||||
namespace exception {
|
namespace exception {
|
||||||
class bad_boxed_cast;
|
class bad_boxed_cast;
|
||||||
} // namespace exception
|
} // namespace exception
|
||||||
@ -43,7 +48,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
arity_error(const arity_error &) = default;
|
arity_error(const arity_error &) = default;
|
||||||
|
|
||||||
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
|
~arity_error() noexcept override = default;
|
||||||
|
|
||||||
int got;
|
int got;
|
||||||
int expected;
|
int expected;
|
||||||
@ -66,34 +71,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
|
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||||
@ -101,175 +78,62 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename Ret, typename ... Params>
|
template<typename Ret, typename ... Params>
|
||||||
bool compare_types_cast(Ret (*)(Params...),
|
bool compare_types_cast(Ret (*)(Params...),
|
||||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||||
{
|
|
||||||
try {
|
|
||||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ret, int count, typename ... Params>
|
|
||||||
struct Call_Func
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename Callable, typename ... InnerParams>
|
|
||||||
static Ret do_call(const Callable &f,
|
|
||||||
const std::vector<Boxed_Value> ¶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)
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
std::vector<Boxed_Value>::size_type i = 0;
|
||||||
|
(void)i;
|
||||||
(void)params; (void)t_conversions;
|
(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;
|
return true;
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
return false;
|
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>
|
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
||||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
|
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
|
||||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
std::index_sequence<I...>, const Callable &f,
|
||||||
|
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
(void)params; (void)t_conversions;
|
(void)params; (void)t_conversions;
|
||||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
/// The function attempts to unbox each parameter to the expected type.
|
||||||
* The function attempts to unbox each parameter to the expected type.
|
/// if any unboxing fails the execution of the function fails and
|
||||||
* if any unboxing fails the execution of the function fails and
|
/// the bad_boxed_cast is passed up to the caller.
|
||||||
* the bad_boxed_cast is passed up to the caller.
|
|
||||||
*/
|
|
||||||
template<typename Callable, typename Ret, typename ... Params>
|
template<typename Callable, typename Ret, typename ... Params>
|
||||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
|
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 &t_conversions)
|
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||||
{
|
{
|
||||||
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
|
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
||||||
return call_func(sig, indexes(), f, params, t_conversions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Callable, typename ... Params>
|
||||||
|
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
|
||||||
|
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||||
|
{
|
||||||
|
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4702)
|
||||||
#endif
|
#endif
|
||||||
|
// MSVC is reporting that this is unreachable code - and it's wrong.
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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();
|
return Handle_Return<void>::handle();
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||||
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||||
|
|
||||||
@ -107,31 +111,6 @@ namespace chaiscript
|
|||||||
return fun(detail::bind_first(std::forward<T>(t), q));
|
return fun(detail::bind_first(std::forward<T>(t), q));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
|
|
||||||
/// \param[in] t Function / member to expose
|
|
||||||
/// \param[in] q Value to bind to first parameter
|
|
||||||
/// \param[in] r Value to bind to second parameter
|
|
||||||
///
|
|
||||||
/// \b Example:
|
|
||||||
/// \code
|
|
||||||
/// struct MyClass
|
|
||||||
/// {
|
|
||||||
/// void memberfunction(int);
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// MyClass obj;
|
|
||||||
/// chaiscript::ChaiScript chai;
|
|
||||||
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
|
|
||||||
/// // memberfunction() will be equivalent to obj.memberfunction(1)
|
|
||||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// \sa \ref adding_functions
|
|
||||||
template<typename T, typename Q, typename R>
|
|
||||||
Proxy_Function fun(T &&t, Q &&q, R &&r)
|
|
||||||
{
|
|
||||||
return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
159
include/chaiscript/dispatchkit/short_alloc.hpp
Normal file
159
include/chaiscript/dispatchkit/short_alloc.hpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#ifndef SHORT_ALLOC_H
|
||||||
|
#define SHORT_ALLOC_H
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015 Howard Hinnant
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
||||||
|
class arena
|
||||||
|
{
|
||||||
|
alignas(alignment) char buf_[N];
|
||||||
|
char* ptr_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~arena() {ptr_ = nullptr;}
|
||||||
|
arena() noexcept : ptr_(buf_) {}
|
||||||
|
arena(const arena&) = delete;
|
||||||
|
arena& operator=(const arena&) = delete;
|
||||||
|
|
||||||
|
template <std::size_t ReqAlign> char* allocate(std::size_t n);
|
||||||
|
void deallocate(char* p, std::size_t n) noexcept;
|
||||||
|
|
||||||
|
static constexpr std::size_t size() noexcept {return N;}
|
||||||
|
std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
|
||||||
|
void reset() noexcept {ptr_ = buf_;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static
|
||||||
|
std::size_t
|
||||||
|
align_up(std::size_t n) noexcept
|
||||||
|
{return (n + (alignment-1)) & ~(alignment-1);}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pointer_in_buffer(char* p) noexcept
|
||||||
|
{return buf_ <= p && p <= buf_ + N;}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t N, std::size_t alignment>
|
||||||
|
template <std::size_t ReqAlign>
|
||||||
|
char*
|
||||||
|
arena<N, alignment>::allocate(std::size_t n)
|
||||||
|
{
|
||||||
|
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
|
||||||
|
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||||
|
auto const aligned_n = align_up(n);
|
||||||
|
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
|
||||||
|
{
|
||||||
|
char* r = ptr_;
|
||||||
|
ptr_ += aligned_n;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
|
||||||
|
"alignment that is larger than alignof(std::max_align_t), and "
|
||||||
|
"cannot be guaranteed by normal operator new");
|
||||||
|
return static_cast<char*>(::operator new(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t N, std::size_t alignment>
|
||||||
|
void
|
||||||
|
arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
|
||||||
|
{
|
||||||
|
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||||
|
if (pointer_in_buffer(p))
|
||||||
|
{
|
||||||
|
n = align_up(n);
|
||||||
|
if (p + n == ptr_) {
|
||||||
|
ptr_ = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
::operator delete(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||||
|
class short_alloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
static auto constexpr alignment = Align;
|
||||||
|
static auto constexpr size = N;
|
||||||
|
using arena_type = arena<size, alignment>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
arena_type& a_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
short_alloc(const short_alloc&) = default;
|
||||||
|
short_alloc& operator=(const short_alloc&) = delete;
|
||||||
|
|
||||||
|
explicit short_alloc(arena_type& a) noexcept : a_(a)
|
||||||
|
{
|
||||||
|
static_assert(size % alignment == 0,
|
||||||
|
"size N needs to be a multiple of alignment Align");
|
||||||
|
}
|
||||||
|
template <class U>
|
||||||
|
explicit short_alloc(const short_alloc<U, N, alignment>& a) noexcept
|
||||||
|
: a_(a.a_) {}
|
||||||
|
|
||||||
|
template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
|
||||||
|
|
||||||
|
T* allocate(std::size_t n)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
|
||||||
|
}
|
||||||
|
void deallocate(T* p, std::size_t n) noexcept
|
||||||
|
{
|
||||||
|
a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T1, std::size_t N1, std::size_t A1,
|
||||||
|
class U, std::size_t M, std::size_t A2>
|
||||||
|
friend
|
||||||
|
bool
|
||||||
|
operator==(const short_alloc<T1, N1, A1>& x, const short_alloc<U, M, A2>& y) noexcept;
|
||||||
|
|
||||||
|
template <class U, std::size_t M, std::size_t A> friend class short_alloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator==(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||||
|
{
|
||||||
|
return N == M && A1 == A2 && &x.a_ == &y.a_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||||
|
{
|
||||||
|
return !(x == y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SHORT_ALLOC_HPP
|
||||||
|
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||||
|
|
||||||
@ -29,48 +33,48 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
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_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_cast(t_from, t_to)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
explicit bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||||
: bad_boxed_cast(w)
|
: bad_boxed_cast(w)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
|
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
|
||||||
|
|
||||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
~bad_boxed_dynamic_cast() noexcept override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class bad_boxed_type_cast : public bad_boxed_cast
|
class bad_boxed_type_cast : public bad_boxed_cast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
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_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_cast(t_from, t_to)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
explicit bad_boxed_type_cast(const std::string &w) noexcept
|
||||||
: bad_boxed_cast(w)
|
: bad_boxed_cast(w)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
|
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
|
||||||
|
|
||||||
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
|
~bad_boxed_type_cast() noexcept override = default;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,18 +101,18 @@ namespace chaiscript
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Type_Conversion_Base() {}
|
virtual ~Type_Conversion_Base() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
|
Type_Conversion_Base(Type_Info t_to, Type_Info t_from)
|
||||||
: m_to(t_to), m_from(t_from)
|
: m_to(std::move(t_to)), m_from(std::move(t_from))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type_Info m_to;
|
const Type_Info m_to;
|
||||||
Type_Info m_from;
|
const Type_Info m_from;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,7 +130,7 @@ namespace chaiscript
|
|||||||
if (t_from.is_const())
|
if (t_from.is_const())
|
||||||
{
|
{
|
||||||
return Boxed_Value(
|
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)))
|
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
@ -137,7 +141,7 @@ namespace chaiscript
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Boxed_Value(
|
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)))
|
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
@ -182,7 +186,7 @@ namespace chaiscript
|
|||||||
if (t_from.is_const())
|
if (t_from.is_const())
|
||||||
{
|
{
|
||||||
return Boxed_Value(
|
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)))
|
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
@ -193,7 +197,7 @@ namespace chaiscript
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Boxed_Value(
|
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)))
|
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
@ -242,12 +246,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);
|
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);
|
return Static_Caster<Derived, Base>::cast(t_derived);
|
||||||
}
|
}
|
||||||
@ -262,17 +266,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;
|
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);
|
return Static_Caster<Derived, Base>::cast(t_derived);
|
||||||
}
|
}
|
||||||
@ -285,23 +290,23 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
||||||
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
|
: Type_Conversion_Base(t_to, t_from),
|
||||||
m_func(std::move(t_func))
|
m_func(std::move(t_func))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
|
Boxed_Value convert_down(const Boxed_Value &) const override
|
||||||
{
|
{
|
||||||
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
|
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
|
/// \todo better handling of errors from the conversion function
|
||||||
return m_func(t_from);
|
return m_func(t_from);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool bidir() const CHAISCRIPT_OVERRIDE
|
bool bidir() const override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -310,12 +315,17 @@ namespace chaiscript
|
|||||||
private:
|
private:
|
||||||
Callable m_func;
|
Callable m_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Type_Conversions
|
class Type_Conversions
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Conversion_Saves
|
||||||
|
{
|
||||||
|
bool enabled = false;
|
||||||
|
std::vector<Boxed_Value> saves;
|
||||||
|
};
|
||||||
|
|
||||||
struct Less_Than
|
struct Less_Than
|
||||||
{
|
{
|
||||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||||
@ -328,22 +338,15 @@ namespace chaiscript
|
|||||||
: m_mutex(),
|
: m_mutex(),
|
||||||
m_conversions(),
|
m_conversions(),
|
||||||
m_convertableTypes(),
|
m_convertableTypes(),
|
||||||
m_num_types(0),
|
m_num_types(0)
|
||||||
m_thread_cache(this),
|
|
||||||
m_conversion_saves(this)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Conversions(const Type_Conversions &t_other)
|
Type_Conversions(const Type_Conversions &t_other) = delete;
|
||||||
: m_mutex(),
|
Type_Conversions(Type_Conversions &&) = default;
|
||||||
m_conversions(t_other.get_conversions()),
|
|
||||||
m_convertableTypes(t_other.m_convertableTypes),
|
|
||||||
m_num_types(m_conversions.size()),
|
|
||||||
m_thread_cache(this),
|
|
||||||
m_conversion_saves(this)
|
|
||||||
|
|
||||||
{
|
Type_Conversions &operator=(const Type_Conversions &) = delete;
|
||||||
}
|
Type_Conversions &operator=(Type_Conversions &&) = default;
|
||||||
|
|
||||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
||||||
{
|
{
|
||||||
@ -387,46 +390,56 @@ namespace chaiscript
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename To>
|
template<typename To>
|
||||||
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
|
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||||
{
|
{
|
||||||
try {
|
return boxed_type_conversion(user_type<To>(), t_saves, from);
|
||||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
|
||||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
|
||||||
return ret;
|
|
||||||
} catch (const std::out_of_range &) {
|
|
||||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
|
|
||||||
} catch (const std::bad_cast &) {
|
|
||||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename From>
|
template<typename From>
|
||||||
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
|
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||||
|
{
|
||||||
|
return boxed_type_down_conversion(user_type<From>(), t_saves, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from);
|
||||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
|
||||||
return ret;
|
return ret;
|
||||||
} catch (const std::out_of_range &) {
|
} catch (const std::out_of_range &) {
|
||||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
|
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion");
|
||||||
} catch (const std::bad_cast &) {
|
} catch (const std::bad_cast &) {
|
||||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
|
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "Unable to perform dynamic_cast operation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_conversion_saves(bool t_val)
|
Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||||
{
|
{
|
||||||
m_conversion_saves->enabled = t_val;
|
try {
|
||||||
|
Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to);
|
||||||
|
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
|
||||||
|
return ret;
|
||||||
|
} catch (const std::out_of_range &) {
|
||||||
|
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "No known conversion");
|
||||||
|
} catch (const std::bad_cast &) {
|
||||||
|
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "Unable to perform dynamic_cast operation");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Boxed_Value> take_saves()
|
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val)
|
||||||
|
{
|
||||||
|
t_saves.enabled = t_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves)
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> ret;
|
std::vector<Boxed_Value> ret;
|
||||||
std::swap(ret, m_conversion_saves->saves);
|
std::swap(ret, t_saves.saves);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +453,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
auto itr = find(to, from);
|
const auto itr = find(to, from);
|
||||||
|
|
||||||
if (itr != m_conversions.end())
|
if (itr != m_conversions.end())
|
||||||
{
|
{
|
||||||
@ -450,6 +463,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Conversion_Saves &conversion_saves() const {
|
||||||
|
return *m_conversion_saves;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
|
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
|
||||||
const Type_Info &to, const Type_Info &from) const
|
const Type_Info &to, const Type_Info &from) const
|
||||||
@ -459,7 +476,6 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|
||||||
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
|
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
|
||||||
;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -483,15 +499,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Conversion_Saves
|
|
||||||
{
|
|
||||||
Conversion_Saves()
|
|
||||||
: enabled(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool enabled;
|
|
||||||
std::vector<Boxed_Value> saves;
|
|
||||||
};
|
|
||||||
|
|
||||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||||
@ -501,6 +508,33 @@ namespace chaiscript
|
|||||||
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Type_Conversions_State
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Type_Conversions_State(const Type_Conversions &t_conversions,
|
||||||
|
Type_Conversions::Conversion_Saves &t_saves)
|
||||||
|
: m_conversions(t_conversions),
|
||||||
|
m_saves(t_saves)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type_Conversions *operator->() const {
|
||||||
|
return &m_conversions.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type_Conversions *get() const {
|
||||||
|
return &m_conversions.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Type_Conversions::Conversion_Saves &saves() const {
|
||||||
|
return m_saves;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::reference_wrapper<const Type_Conversions> m_conversions;
|
||||||
|
std::reference_wrapper<Type_Conversions::Conversion_Saves> m_saves;
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||||
|
|
||||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||||
@ -582,7 +616,7 @@ namespace chaiscript
|
|||||||
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
||||||
|
|
||||||
To vec;
|
To vec;
|
||||||
|
vec.reserve(from_vec.size());
|
||||||
for (const Boxed_Value &bv : from_vec) {
|
for (const Boxed_Value &bv : from_vec) {
|
||||||
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
||||||
}
|
}
|
||||||
@ -593,6 +627,22 @@ namespace chaiscript
|
|||||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename To>
|
||||||
|
Type_Conversion map_conversion()
|
||||||
|
{
|
||||||
|
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||||
|
const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
|
||||||
|
|
||||||
|
To map;
|
||||||
|
for (const std::pair<std::string, Boxed_Value> &p : from_map) {
|
||||||
|
map.insert(std::make_pair(p.first, detail::Cast_Helper<typename To::mapped_type>::cast(p.second, nullptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Boxed_Value(std::move(map));
|
||||||
|
};
|
||||||
|
|
||||||
|
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||||
#define CHAISCRIPT_TYPE_INFO_HPP_
|
#define CHAISCRIPT_TYPE_INFO_HPP_
|
||||||
|
|
||||||
@ -29,70 +33,66 @@ namespace chaiscript
|
|||||||
class Type_Info
|
class Type_Info
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
|
||||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
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_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||||
m_flags((t_is_const << is_const_flag)
|
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
|
||||||
+ (t_is_reference << is_reference_flag)
|
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
||||||
+ (t_is_pointer << is_pointer_flag)
|
+ (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
|
||||||
+ (t_is_void << is_void_flag)
|
+ (static_cast<unsigned int>(t_is_void) << is_void_flag)
|
||||||
+ (t_is_arithmetic << is_arithmetic_flag))
|
+ (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAISCRIPT_CONSTEXPR Type_Info()
|
constexpr Type_Info() = default;
|
||||||
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
|
||||||
m_flags(1 << is_undef_flag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
constexpr bool operator<(const Type_Info &ti) const noexcept
|
||||||
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
|
|
||||||
{
|
{
|
||||||
return m_type_info < ti.m_type_info;
|
return m_type_info < ti.m_type_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
constexpr bool operator!=(const Type_Info &ti) const noexcept
|
||||||
|
{
|
||||||
|
return !(operator==(ti));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const std::type_info &ti) const noexcept
|
||||||
|
{
|
||||||
|
return !(operator==(ti));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const Type_Info &ti) const noexcept
|
||||||
{
|
{
|
||||||
return ti.m_type_info == m_type_info
|
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
|
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);
|
|| *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
|
return !is_undef() && (*m_bare_type_info) == ti;
|
||||||
&& (*m_bare_type_info) == ti;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_const_flag); }
|
constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_reference_flag); }
|
constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_void_flag); }
|
constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_arithmetic_flag); }
|
constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_undef_flag); }
|
constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_pointer_flag); }
|
constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
|
||||||
|
|
||||||
std::string name() const
|
std::string name() const
|
||||||
{
|
{
|
||||||
if (m_type_info)
|
if (!is_undef())
|
||||||
{
|
{
|
||||||
return m_type_info->name();
|
return m_type_info->name();
|
||||||
} else {
|
} else {
|
||||||
@ -102,7 +102,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
std::string bare_name() const
|
std::string bare_name() const
|
||||||
{
|
{
|
||||||
if (m_bare_type_info)
|
if (!is_undef())
|
||||||
{
|
{
|
||||||
return m_bare_type_info->name();
|
return m_bare_type_info->name();
|
||||||
} else {
|
} else {
|
||||||
@ -110,21 +110,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;
|
return m_bare_type_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::type_info *m_type_info;
|
struct Unknown_Type {};
|
||||||
const std::type_info *m_bare_type_info;
|
|
||||||
unsigned int m_flags;
|
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_const_flag = 0;
|
||||||
static const int is_reference_flag = 1;
|
static const int is_reference_flag = 1;
|
||||||
static const int is_pointer_flag = 2;
|
static const int is_pointer_flag = 2;
|
||||||
static const int is_void_flag = 3;
|
static const int is_void_flag = 3;
|
||||||
static const int is_arithmetic_flag = 4;
|
static const int is_arithmetic_flag = 4;
|
||||||
static const int is_undef_flag = 5;
|
static const int is_undef_flag = 5;
|
||||||
|
unsigned int m_flags = (1 << is_undef_flag);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -133,9 +135,7 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info
|
struct Get_Type_Info
|
||||||
{
|
{
|
||||||
typedef T type;
|
static constexpr Type_Info get()
|
||||||
|
|
||||||
static Type_Info get()
|
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
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,
|
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
@ -150,9 +150,9 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<std::shared_ptr<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,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
@ -162,12 +162,15 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||||
{
|
{
|
||||||
typedef T type;
|
static constexpr Type_Info get()
|
||||||
|
|
||||||
static Type_Info get()
|
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
@ -180,9 +183,7 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||||
{
|
{
|
||||||
typedef T type;
|
static constexpr Type_Info get()
|
||||||
|
|
||||||
static Type_Info get()
|
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
@ -195,9 +196,7 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||||
{
|
{
|
||||||
typedef T type;
|
static constexpr Type_Info get()
|
||||||
|
|
||||||
static Type_Info get()
|
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
@ -219,7 +218,7 @@ namespace chaiscript
|
|||||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename T>
|
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();
|
return detail::Get_Type_Info<T>::get();
|
||||||
}
|
}
|
||||||
@ -234,7 +233,7 @@ namespace chaiscript
|
|||||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Type_Info user_type()
|
constexpr Type_Info user_type()
|
||||||
{
|
{
|
||||||
return detail::Get_Type_Info<T>::get();
|
return detail::Get_Type_Info<T>::get();
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||||
|
|
||||||
|
#include "../utility/fnv1a.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
|
||||||
struct Operators {
|
struct Operators {
|
||||||
enum Opers
|
enum class Opers
|
||||||
{
|
{
|
||||||
boolean_flag,
|
boolean_flag,
|
||||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
||||||
@ -31,7 +37,7 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char *to_string(Opers t_oper) {
|
static const char *to_string(Opers t_oper) {
|
||||||
const char *opers[] = {
|
static const char *opers[] = {
|
||||||
"",
|
"",
|
||||||
"==", "<", ">", "<=", ">=", "!=",
|
"==", "<", ">", "<=", ">=", "!=",
|
||||||
"",
|
"",
|
||||||
@ -46,81 +52,53 @@ namespace chaiscript
|
|||||||
"+", "/", "*", "-", "+", "-",
|
"+", "/", "*", "-", "+", "-",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
return opers[t_oper];
|
return opers[static_cast<int>(t_oper)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
||||||
{
|
{
|
||||||
if (t_str == "==")
|
#ifdef CHAISCRIPT_MSVC
|
||||||
{
|
#pragma warning(push)
|
||||||
return equals;
|
#pragma warning(disable : 4307)
|
||||||
} else if (t_str == "<") {
|
#endif
|
||||||
return less_than;
|
|
||||||
} else if (t_str == ">") {
|
const auto op_hash = utility::fnv1a_32(t_str.c_str());
|
||||||
return greater_than;
|
switch (op_hash) {
|
||||||
} else if (t_str == "<=") {
|
case utility::fnv1a_32("=="): { return Opers::equals; }
|
||||||
return less_than_equal;
|
case utility::fnv1a_32("<"): { return Opers::less_than; }
|
||||||
} else if (t_str == ">=") {
|
case utility::fnv1a_32(">"): { return Opers::greater_than; }
|
||||||
return greater_than_equal;
|
case utility::fnv1a_32("<="): { return Opers::less_than_equal; }
|
||||||
} else if (t_str == "!=") {
|
case utility::fnv1a_32(">="): { return Opers::greater_than_equal; }
|
||||||
return not_equal;
|
case utility::fnv1a_32("!="): { return Opers::not_equal; }
|
||||||
} else if (t_str == "=") {
|
case utility::fnv1a_32("="): { return Opers::assign; }
|
||||||
return assign;
|
case utility::fnv1a_32("++"): { return Opers::pre_increment; }
|
||||||
} else if (t_str == "++") {
|
case utility::fnv1a_32("--"): { return Opers::pre_decrement; }
|
||||||
return pre_increment;
|
case utility::fnv1a_32("*="): { return Opers::assign_product; }
|
||||||
} else if (t_str == "--") {
|
case utility::fnv1a_32("+="): { return Opers::assign_sum; }
|
||||||
return pre_decrement;
|
case utility::fnv1a_32("-="): { return Opers::assign_difference; }
|
||||||
} else if (t_str == "*=") {
|
case utility::fnv1a_32("&="): { return Opers::assign_bitwise_and; }
|
||||||
return assign_product;
|
case utility::fnv1a_32("|="): { return Opers::assign_bitwise_or; }
|
||||||
} else if (t_str == "+=") {
|
case utility::fnv1a_32("<<="): { return Opers::assign_shift_left; }
|
||||||
return assign_sum;
|
case utility::fnv1a_32(">>="): { return Opers::assign_shift_right; }
|
||||||
} else if (t_str == "-=") {
|
case utility::fnv1a_32("%="): { return Opers::assign_remainder; }
|
||||||
return assign_difference;
|
case utility::fnv1a_32("^="): { return Opers::assign_bitwise_xor; }
|
||||||
} else if (t_str == "&=") {
|
case utility::fnv1a_32("<<"): { return Opers::shift_left; }
|
||||||
return assign_bitwise_and;
|
case utility::fnv1a_32(">>"): { return Opers::shift_right; }
|
||||||
} else if (t_str == "|=") {
|
case utility::fnv1a_32("%"): { return Opers::remainder; }
|
||||||
return assign_bitwise_or;
|
case utility::fnv1a_32("&"): { return Opers::bitwise_and; }
|
||||||
} else if (t_str == "<<=") {
|
case utility::fnv1a_32("|"): { return Opers::bitwise_or; }
|
||||||
return assign_shift_left;
|
case utility::fnv1a_32("^"): { return Opers::bitwise_xor; }
|
||||||
} else if (t_str == ">>=") {
|
case utility::fnv1a_32("~"): { return Opers::bitwise_complement; }
|
||||||
return assign_shift_right;
|
case utility::fnv1a_32("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
|
||||||
} else if (t_str == "%=") {
|
case utility::fnv1a_32("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
|
||||||
return assign_remainder;
|
case utility::fnv1a_32("/"): { return Opers::quotient; }
|
||||||
} else if (t_str == "^=") {
|
case utility::fnv1a_32("*"): { return Opers::product; }
|
||||||
return assign_bitwise_xor;
|
default: { return Opers::invalid; }
|
||||||
} else if (t_str == "<<") {
|
|
||||||
return shift_left;
|
|
||||||
} else if (t_str == ">>") {
|
|
||||||
return shift_right;
|
|
||||||
} else if (t_str == "%") {
|
|
||||||
return remainder;
|
|
||||||
} else if (t_str == "&") {
|
|
||||||
return bitwise_and;
|
|
||||||
} else if (t_str == "|") {
|
|
||||||
return bitwise_or;
|
|
||||||
} else if (t_str == "^") {
|
|
||||||
return bitwise_xor;
|
|
||||||
} else if (t_str == "~") {
|
|
||||||
return bitwise_complement;
|
|
||||||
} else if (t_str == "+") {
|
|
||||||
if (t_is_unary) {
|
|
||||||
return unary_plus;
|
|
||||||
} else {
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
} else if (t_str == "-") {
|
|
||||||
if (t_is_unary) {
|
|
||||||
return unary_minus;
|
|
||||||
} else {
|
|
||||||
return difference;
|
|
||||||
}
|
|
||||||
} else if (t_str == "/") {
|
|
||||||
return quotient;
|
|
||||||
} else if (t_str == "*") {
|
|
||||||
return product;
|
|
||||||
} else {
|
|
||||||
return invalid;
|
|
||||||
}
|
}
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||||
#define CHAISCRIPT_COMMON_HPP_
|
#define CHAISCRIPT_COMMON_HPP_
|
||||||
|
|
||||||
@ -26,34 +30,60 @@ struct AST_Node;
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
struct Name_Validator {
|
||||||
|
static bool is_reserved_word(const std::string &name)
|
||||||
|
{
|
||||||
|
static const std::set<std::string> m_reserved_words
|
||||||
|
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
|
||||||
|
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_",
|
||||||
|
"__LINE__", "__FILE__", "__FUNC__", "__CLASS__"};
|
||||||
|
return m_reserved_words.count(name) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool valid_object_name(const std::string &name)
|
||||||
|
{
|
||||||
|
return name.find("::") == std::string::npos && !is_reserved_word(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void validate_object_name(const std::string &name)
|
||||||
|
{
|
||||||
|
if (is_reserved_word(name)) {
|
||||||
|
throw exception::reserved_word_error(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.find("::") != std::string::npos) {
|
||||||
|
throw exception::illegal_name_error(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Signature of module entry point that all binary loadable modules must implement.
|
/// Signature of module entry point that all binary loadable modules must implement.
|
||||||
typedef ModulePtr (*Create_Module_Func)();
|
typedef ModulePtr (*Create_Module_Func)();
|
||||||
|
|
||||||
|
|
||||||
/// Types of AST nodes available to the parser and eval
|
/// Types of AST nodes available to the parser and eval
|
||||||
class AST_Node_Type {
|
enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl,
|
||||||
public:
|
Array_Call, Dot_Access,
|
||||||
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
|
||||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
|
||||||
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 Operator_Precidence { Ternary_Cond, Logical_Or,
|
||||||
|
Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And,
|
||||||
|
Equality, Comparison, Shift, Addition, Multiplication, Prefix };
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Helper lookup to get the name of each node type
|
/// Helper lookup to get the name of each node type
|
||||||
const char *ast_node_type_to_string(int ast_node_type) {
|
inline const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
|
||||||
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl",
|
||||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
"Array_Call", "Dot_Access",
|
||||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
"Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
|
||||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
|
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||||
|
|
||||||
return ast_node_types[ast_node_type];
|
return ast_node_types[static_cast<int>(ast_node_type)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +131,36 @@ namespace chaiscript
|
|||||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||||
namespace exception
|
namespace exception
|
||||||
{
|
{
|
||||||
|
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||||
|
struct load_module_error : std::runtime_error
|
||||||
|
{
|
||||||
|
explicit load_module_error(const std::string &t_reason) noexcept
|
||||||
|
: std::runtime_error(t_reason)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
load_module_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||||
|
: std::runtime_error(format_error(t_name, t_errors))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
load_module_error(const load_module_error &) = default;
|
||||||
|
~load_module_error() noexcept override = default;
|
||||||
|
|
||||||
|
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Error loading module '" << t_name << "'\n"
|
||||||
|
<< " The following locations were searched:\n";
|
||||||
|
|
||||||
|
for (const auto &err : t_errors) {
|
||||||
|
ss << " " << err.what() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Errors generated during parsing or evaluation
|
/// Errors generated during parsing or evaluation
|
||||||
struct eval_error : std::runtime_error {
|
struct eval_error : std::runtime_error {
|
||||||
@ -113,7 +173,7 @@ namespace chaiscript
|
|||||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
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,
|
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
bool t_dot_notation,
|
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)),
|
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))
|
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||||
{}
|
{}
|
||||||
@ -121,18 +181,18 @@ namespace chaiscript
|
|||||||
eval_error(const std::string &t_why,
|
eval_error(const std::string &t_why,
|
||||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
bool t_dot_notation,
|
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)),
|
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))
|
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)),
|
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||||
reason(t_why), start_position(t_where), filename(t_fname)
|
reason(t_why), start_position(t_where), filename(t_fname)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
|
explicit eval_error(const std::string &t_why) noexcept
|
||||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||||
reason(t_why)
|
reason(t_why)
|
||||||
{}
|
{}
|
||||||
@ -144,7 +204,7 @@ namespace chaiscript
|
|||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
|
|
||||||
ss << what();
|
ss << what();
|
||||||
if (call_stack.size() > 0) {
|
if (!call_stack.empty()) {
|
||||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
||||||
ss << '\n' << detail << '\n';
|
ss << '\n' << detail << '\n';
|
||||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||||
@ -161,12 +221,12 @@ namespace chaiscript
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
|
~eval_error() noexcept override = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static int id(const T& t)
|
static AST_Node_Type id(const T& t)
|
||||||
{
|
{
|
||||||
return t->identifier;
|
return t->identifier;
|
||||||
}
|
}
|
||||||
@ -420,12 +480,12 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Errors generated when loading a file
|
/// Errors generated when loading a file
|
||||||
struct file_not_found_error : std::runtime_error {
|
struct file_not_found_error : std::runtime_error {
|
||||||
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
|
explicit file_not_found_error(const std::string &t_filename) noexcept
|
||||||
: std::runtime_error("File Not Found: " + t_filename)
|
: std::runtime_error("File Not Found: " + t_filename)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
file_not_found_error(const file_not_found_error &) = default;
|
file_not_found_error(const file_not_found_error &) = default;
|
||||||
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
|
~file_not_found_error() noexcept override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -434,11 +494,9 @@ namespace chaiscript
|
|||||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
||||||
public:
|
public:
|
||||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
const AST_Node_Type identifier;
|
||||||
const std::string text;
|
const std::string text;
|
||||||
Parse_Location location;
|
Parse_Location location;
|
||||||
std::vector<AST_NodePtr> children;
|
|
||||||
AST_NodePtr annotation;
|
|
||||||
|
|
||||||
const std::string &filename() const {
|
const std::string &filename() const {
|
||||||
return *location.filename;
|
return *location.filename;
|
||||||
@ -452,19 +510,22 @@ namespace chaiscript
|
|||||||
return location.end;
|
return location.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string pretty_print() const
|
std::string pretty_print() const
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
|
||||||
oss << text;
|
oss << text;
|
||||||
|
|
||||||
for (auto & elem : this->children) {
|
for (auto & elem : this->get_children()) {
|
||||||
oss << elem->pretty_print();
|
oss << elem->pretty_print() << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return oss.str();
|
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
|
/// Prints the contents of an AST node, including its children, recursively
|
||||||
std::string to_string(const std::string &t_prepend = "") const {
|
std::string to_string(const std::string &t_prepend = "") const {
|
||||||
@ -473,25 +534,16 @@ namespace chaiscript
|
|||||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
<< 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 + " ");
|
oss << elem->to_string(t_prepend + " ");
|
||||||
}
|
}
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return eval_internal(t_e);
|
|
||||||
} catch (exception::eval_error &ee) {
|
|
||||||
ee.call_stack.push_back(shared_from_this());
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool get_bool_condition(const Boxed_Value &t_bv) {
|
static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||||
try {
|
try {
|
||||||
return boxed_cast<bool>(t_bv);
|
return t_ss->boxed_cast<bool>(t_bv);
|
||||||
}
|
}
|
||||||
catch (const exception::bad_boxed_cast &) {
|
catch (const exception::bad_boxed_cast &) {
|
||||||
throw exception::eval_error("Condition not boolean");
|
throw exception::eval_error("Condition not boolean");
|
||||||
@ -499,33 +551,47 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
|
virtual ~AST_Node() = default;
|
||||||
{
|
AST_Node(AST_Node &&) = default;
|
||||||
std::replace(children.begin(), children.end(), t_child, t_new_child);
|
AST_Node &operator=(AST_Node &&) = default;
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
AST_Node(const AST_Node &) = delete;
|
AST_Node(const AST_Node &) = delete;
|
||||||
AST_Node& operator=(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
|
namespace eval
|
||||||
{
|
{
|
||||||
@ -535,96 +601,102 @@ namespace chaiscript
|
|||||||
struct Return_Value {
|
struct Return_Value {
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
|
explicit Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Special type indicating a call to 'break'
|
/// Special type indicating a call to 'break'
|
||||||
struct Break_Loop {
|
struct Break_Loop {
|
||||||
Break_Loop() { }
|
Break_Loop() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Special type indicating a call to 'continue'
|
/// Special type indicating a call to 'continue'
|
||||||
struct Continue_Loop {
|
struct Continue_Loop {
|
||||||
Continue_Loop() { }
|
Continue_Loop() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Creates a new scope then pops it on destruction
|
/// Creates a new scope then pops it on destruction
|
||||||
struct Scope_Push_Pop
|
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(const Scope_Push_Pop &) = delete;
|
||||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
||||||
|
|
||||||
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
explicit Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||||
: m_ds(t_ds)
|
: m_ds(t_ds)
|
||||||
{
|
{
|
||||||
m_ds.get()->new_scope(m_ds.get().stack_holder());
|
m_ds->new_scope(m_ds.stack_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Scope_Push_Pop()
|
~Scope_Push_Pop()
|
||||||
{
|
{
|
||||||
m_ds.get()->pop_scope(m_ds.get().stack_holder());
|
m_ds->pop_scope(m_ds.stack_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
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
|
/// Creates a new function call and pops it on destruction
|
||||||
struct Function_Push_Pop
|
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(const Function_Push_Pop &) = delete;
|
||||||
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
||||||
|
|
||||||
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
explicit Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||||
: m_ds(t_ds)
|
: m_ds(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()
|
~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)
|
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)
|
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||||
{
|
{
|
||||||
m_ds.get()->save_function_params(std::move(t_params));
|
m_ds->save_function_params(t_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
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
|
/// Creates a new scope then pops it on destruction
|
||||||
struct Stack_Push_Pop
|
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(const Stack_Push_Pop &) = delete;
|
||||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
||||||
|
|
||||||
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
explicit Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||||
: m_ds(t_ds)
|
: m_ds(t_ds)
|
||||||
{
|
{
|
||||||
m_ds.get()->new_stack(m_ds.get().stack_holder());
|
m_ds->new_stack(m_ds.stack_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Stack_Push_Pop()
|
~Stack_Push_Pop()
|
||||||
{
|
{
|
||||||
m_ds.get()->pop_stack(m_ds.get().stack_holder());
|
m_ds->pop_stack(m_ds.stack_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
const chaiscript::detail::Dispatch_State &m_ds;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||||
#define CHAISCRIPT_ENGINE_HPP_
|
#define CHAISCRIPT_ENGINE_HPP_
|
||||||
|
|
||||||
@ -17,6 +21,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
#include "../chaiscript_threading.hpp"
|
#include "../chaiscript_threading.hpp"
|
||||||
@ -31,229 +36,34 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CHAISCRIPT_NO_DYNLOAD)
|
||||||
|
#include "chaiscript_unknown.hpp"
|
||||||
|
#elif defined(CHAISCRIPT_WINDOWS)
|
||||||
|
#include "chaiscript_windows.hpp"
|
||||||
|
#elif _POSIX_VERSION
|
||||||
|
#include "chaiscript_posix.hpp"
|
||||||
#else
|
#else
|
||||||
#ifdef CHAISCRIPT_WINDOWS
|
#include "chaiscript_unknown.hpp"
|
||||||
#define VC_EXTRA_LEAN
|
|
||||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "../dispatchkit/exception_specification.hpp"
|
#include "../dispatchkit/exception_specification.hpp"
|
||||||
#include "chaiscript_parser.hpp"
|
|
||||||
|
|
||||||
namespace chaiscript
|
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
|
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;
|
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief The main object that the ChaiScript user will use.
|
/// \brief The main object that the ChaiScript user will use.
|
||||||
class ChaiScript {
|
class ChaiScript_Basic {
|
||||||
|
|
||||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
|
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
|
||||||
@ -265,19 +75,16 @@ namespace chaiscript
|
|||||||
std::vector<std::string> m_module_paths;
|
std::vector<std::string> m_module_paths;
|
||||||
std::vector<std::string> m_use_paths;
|
std::vector<std::string> m_use_paths;
|
||||||
|
|
||||||
|
std::unique_ptr<parser::ChaiScript_Parser_Base> m_parser;
|
||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine m_engine;
|
chaiscript::detail::Dispatch_Engine m_engine;
|
||||||
|
|
||||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
/// 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)
|
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
parser::ChaiScript_Parser parser;
|
const auto p = m_parser->parse(t_input, t_filename);
|
||||||
if (parser.parse(t_input, t_filename)) {
|
return p->eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||||
//parser.show_match_stack();
|
|
||||||
return parser.optimized_ast()->eval(m_engine);
|
|
||||||
} else {
|
|
||||||
return Boxed_Value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||||
return rv.retval;
|
return rv.retval;
|
||||||
@ -286,8 +93,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Evaluates the given file and looks in the 'use' paths
|
/// Evaluates the given file and looks in the 'use' paths
|
||||||
const Boxed_Value internal_eval_file(const std::string &t_filename) {
|
const Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||||
for (const auto &path : m_use_paths)
|
for (const auto &path : m_use_paths)
|
||||||
@ -324,27 +129,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||||
void build_eval_system(const ModulePtr &t_lib) {
|
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
|
||||||
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)
|
if (t_lib)
|
||||||
{
|
{
|
||||||
add(t_lib);
|
add(t_lib);
|
||||||
@ -365,13 +150,14 @@ namespace chaiscript
|
|||||||
})
|
})
|
||||||
, "call_exists");
|
, "call_exists");
|
||||||
|
|
||||||
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
|
||||||
//
|
|
||||||
m_engine.add(fun(
|
m_engine.add(fun(
|
||||||
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
|
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
|
||||||
return t_fun(t_params, this->m_engine.conversions());
|
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
|
||||||
|
return t_fun(t_params, s);
|
||||||
}), "call");
|
}), "call");
|
||||||
|
|
||||||
|
|
||||||
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
|
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
|
||||||
|
|
||||||
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
|
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
|
||||||
@ -385,23 +171,30 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end()
|
||||||
|
&& std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end())
|
||||||
|
{
|
||||||
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
|
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
|
||||||
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
|
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::find(t_opts.begin(), t_opts.end(), Options::No_External_Scripts) == t_opts.end()
|
||||||
|
&& std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end())
|
||||||
|
{
|
||||||
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
|
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
|
||||||
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
|
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
|
||||||
|
}
|
||||||
|
|
||||||
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
||||||
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
||||||
m_engine.add(fun(&parse), "parse");
|
|
||||||
|
|
||||||
m_engine.add(fun(&ChaiScript::version_major), "version_major");
|
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
||||||
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
|
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
|
||||||
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_const(t_bv, t_name); }), "add_global_const");
|
||||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
||||||
|
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -428,65 +221,43 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths)
|
||||||
|
{
|
||||||
|
if (paths.empty()) { return {""}; }
|
||||||
|
else { return paths; }
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// \brief Constructor for ChaiScript
|
/// \brief Constructor for ChaiScript
|
||||||
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
|
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
|
||||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||||
ChaiScript(const ModulePtr &t_lib,
|
ChaiScript_Basic(const ModulePtr &t_lib,
|
||||||
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
std::vector<std::string> t_module_paths = {},
|
||||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
std::vector<std::string> t_use_paths = {},
|
||||||
|
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||||
|
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))),
|
||||||
|
m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths))),
|
||||||
|
m_parser(std::move(parser)),
|
||||||
|
m_engine(*m_parser)
|
||||||
{
|
{
|
||||||
if (m_module_paths.empty())
|
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||||
{
|
|
||||||
m_module_paths.push_back("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_use_paths.empty())
|
|
||||||
{
|
|
||||||
m_use_paths.push_back("");
|
|
||||||
}
|
|
||||||
|
|
||||||
build_eval_system(t_lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Constructor for ChaiScript.
|
|
||||||
///
|
|
||||||
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
|
||||||
/// at runtime generates an error if it cannot be found.
|
|
||||||
///
|
|
||||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
|
||||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
|
||||||
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
|
||||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
|
||||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
|
||||||
{
|
|
||||||
if (m_module_paths.empty())
|
|
||||||
{
|
|
||||||
m_module_paths.push_back("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_use_paths.empty())
|
|
||||||
{
|
|
||||||
m_use_paths.push_back("");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
|
||||||
// If on Unix, add the path of the current executable to the module search path
|
// If on Unix, add the path of the current executable to the module search path
|
||||||
// as windows would do
|
// as windows would do
|
||||||
|
|
||||||
union cast_union
|
union cast_union
|
||||||
{
|
{
|
||||||
Boxed_Value (ChaiScript::*in_ptr)(const std::string&);
|
Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&);
|
||||||
void *out_ptr;
|
void *out_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
Dl_info rInfo;
|
Dl_info rInfo;
|
||||||
memset( &rInfo, 0, sizeof(rInfo) );
|
memset( &rInfo, 0, sizeof(rInfo) );
|
||||||
cast_union u;
|
cast_union u;
|
||||||
u.in_ptr = &ChaiScript::use;
|
u.in_ptr = &ChaiScript_Basic::use;
|
||||||
if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
|
if ( (dladdr(static_cast<void*>(u.out_ptr), &rInfo) != 0) && (rInfo.dli_fname != nullptr) ) {
|
||||||
std::string dllpath(rInfo.dli_fname);
|
std::string dllpath(rInfo.dli_fname);
|
||||||
const size_t lastslash = dllpath.rfind('/');
|
const size_t lastslash = dllpath.rfind('/');
|
||||||
if (lastslash != std::string::npos)
|
if (lastslash != std::string::npos)
|
||||||
@ -496,67 +267,79 @@ namespace chaiscript
|
|||||||
|
|
||||||
// Let's see if this is a link that we should expand
|
// Let's see if this is a link that we should expand
|
||||||
std::vector<char> buf(2048);
|
std::vector<char> buf(2048);
|
||||||
const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||||
if (pathlen > 0 && pathlen < buf.size())
|
if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size())
|
||||||
{
|
{
|
||||||
dllpath = std::string(&buf.front(), pathlen);
|
dllpath = std::string(&buf.front(), static_cast<size_t>(pathlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
|
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
build_eval_system(t_lib, t_opts);
|
||||||
|
|
||||||
// attempt to load the stdlib
|
|
||||||
load_module("chaiscript_stdlib-" + version());
|
|
||||||
|
|
||||||
build_eval_system(ModulePtr());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
|
/// \brief Constructor for ChaiScript.
|
||||||
|
///
|
||||||
|
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
||||||
|
/// at runtime generates an error if it cannot be found.
|
||||||
|
///
|
||||||
|
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||||
|
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||||
|
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||||
|
std::vector<std::string> t_module_paths = {},
|
||||||
|
std::vector<std::string> t_use_paths = {},
|
||||||
|
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||||
|
: ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// attempt to load the stdlib
|
||||||
|
load_module("chaiscript_stdlib-" + Build_Info::version());
|
||||||
|
} catch (const exception::load_module_error &t_err) {
|
||||||
|
std::cout << "An error occured while trying to load the chaiscript standard library.\n"
|
||||||
|
<< "\n"
|
||||||
|
<< "You must either provide a standard library, or compile it in.\n"
|
||||||
|
<< "For an example of compiling the standard library in,\n"
|
||||||
|
<< "see: https://gist.github.com/lefticus/9456197\n"
|
||||||
|
<< "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
||||||
|
<< "\n"
|
||||||
|
<< "\n"
|
||||||
|
<< t_err.what();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else // CHAISCRIPT_NO_DYNLOAD
|
||||||
|
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||||
|
std::vector<std::string> t_module_paths = {},
|
||||||
|
std::vector<std::string> t_use_paths = {},
|
||||||
|
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options()) = delete;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
parser::ChaiScript_Parser_Base &get_parser()
|
||||||
|
{
|
||||||
|
return *m_parser;
|
||||||
|
}
|
||||||
|
|
||||||
const Boxed_Value eval(const AST_NodePtr &t_ast)
|
const Boxed_Value eval(const AST_NodePtr &t_ast)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return t_ast->eval(m_engine);
|
return t_ast->eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||||
} catch (const exception::eval_error &t_ee) {
|
} catch (const exception::eval_error &t_ee) {
|
||||||
throw Boxed_Value(t_ee);
|
throw Boxed_Value(t_ee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static AST_NodePtr parse(const std::string &t_input)
|
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
||||||
{
|
{
|
||||||
parser::ChaiScript_Parser parser;
|
const auto ast = m_parser->parse(t_input, "PARSE");
|
||||||
if (parser.parse(t_input, "PARSE")) {
|
if (t_debug_print) {
|
||||||
//parser.show_match_stack();
|
m_parser->debug_print(ast);
|
||||||
return parser.optimized_ast();
|
|
||||||
} else {
|
|
||||||
throw chaiscript::exception::eval_error("Unknown error while parsing");
|
|
||||||
}
|
}
|
||||||
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int version_major()
|
|
||||||
{
|
|
||||||
return chaiscript::version_major;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int version_minor()
|
|
||||||
{
|
|
||||||
return chaiscript::version_minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int version_patch()
|
|
||||||
{
|
|
||||||
return chaiscript::version_patch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string version()
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << version_major() << "." << version_minor() << "." << version_patch();
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_type_name(const Type_Info &ti) const
|
std::string get_type_name(const Type_Info &ti) const
|
||||||
{
|
{
|
||||||
return m_engine.get_type_name(ti);
|
return m_engine.get_type_name(ti);
|
||||||
@ -609,8 +392,9 @@ namespace chaiscript
|
|||||||
/// \param[in] t_name Name of the value to add
|
/// \param[in] t_name Name of the value to add
|
||||||
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
|
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
|
||||||
/// \sa Boxed_Value::is_const
|
/// \sa Boxed_Value::is_const
|
||||||
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
ChaiScript_Basic &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.add_global_const(t_bv, t_name);
|
m_engine.add_global_const(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -620,12 +404,20 @@ namespace chaiscript
|
|||||||
/// \param[in] t_name Name of the value to add
|
/// \param[in] t_name Name of the value to add
|
||||||
/// \warning The user is responsible for making sure the object is thread-safe if necessary
|
/// \warning The user is responsible for making sure the object is thread-safe if necessary
|
||||||
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
||||||
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
ChaiScript_Basic &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.add_global(t_bv, t_name);
|
m_engine.add_global(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChaiScript_Basic &set_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
|
{
|
||||||
|
Name_Validator::validate_object_name(t_name);
|
||||||
|
m_engine.set_global(t_bv, t_name);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
||||||
/// \warning State object does not contain the user defined type conversions of the engine. They
|
/// \warning State object does not contain the user defined type conversions of the engine. They
|
||||||
/// are left out due to performance considerations involved in tracking the state
|
/// are left out due to performance considerations involved in tracking the state
|
||||||
@ -719,8 +511,9 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// \sa \ref adding_items
|
/// \sa \ref adding_items
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ChaiScript &add(const T &t_t, const std::string &t_name)
|
ChaiScript_Basic &add(const T &t_t, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
Name_Validator::validate_object_name(t_name);
|
||||||
m_engine.add(t_t, t_name);
|
m_engine.add(t_t, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -734,7 +527,7 @@ namespace chaiscript
|
|||||||
/// chaiscript::ChaiScript chai;
|
/// chaiscript::ChaiScript chai;
|
||||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||||
/// \endcode
|
/// \endcode
|
||||||
ChaiScript &add(const Type_Conversion &d)
|
ChaiScript_Basic &add(const Type_Conversion &d)
|
||||||
{
|
{
|
||||||
m_engine.add(d);
|
m_engine.add(d);
|
||||||
return *this;
|
return *this;
|
||||||
@ -743,7 +536,7 @@ namespace chaiscript
|
|||||||
/// \brief Adds all elements of a module to ChaiScript runtime
|
/// \brief Adds all elements of a module to ChaiScript runtime
|
||||||
/// \param[in] t_p The module to add.
|
/// \param[in] t_p The module to add.
|
||||||
/// \sa chaiscript::Module
|
/// \sa chaiscript::Module
|
||||||
ChaiScript &add(const ModulePtr &t_p)
|
ChaiScript_Basic &add(const ModulePtr &t_p)
|
||||||
{
|
{
|
||||||
t_p->apply(*this, this->get_eval_engine());
|
t_p->apply(*this, this->get_eval_engine());
|
||||||
return *this;
|
return *this;
|
||||||
@ -763,9 +556,13 @@ namespace chaiscript
|
|||||||
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
|
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
|
||||||
std::string load_module(const std::string &t_module_name)
|
std::string load_module(const std::string &t_module_name)
|
||||||
{
|
{
|
||||||
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
|
(void)t_module_name; // -Wunused-parameter
|
||||||
|
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||||
|
#else
|
||||||
std::vector<exception::load_module_error> errors;
|
std::vector<exception::load_module_error> errors;
|
||||||
std::string version_stripped_name = t_module_name;
|
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)
|
if (version_pos != std::string::npos)
|
||||||
{
|
{
|
||||||
version_stripped_name.erase(version_pos);
|
version_stripped_name.erase(version_pos);
|
||||||
@ -795,21 +592,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string errstring;
|
throw chaiscript::exception::load_module_error(t_module_name, errors);
|
||||||
|
#endif
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
||||||
@ -846,14 +630,7 @@ namespace chaiscript
|
|||||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
/// \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())
|
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||||
{
|
{
|
||||||
try {
|
return eval(t_script, t_handler);
|
||||||
return do_eval(t_script);
|
|
||||||
} catch (Boxed_Value &bv) {
|
|
||||||
if (t_handler) {
|
|
||||||
t_handler->handle(bv, m_engine);
|
|
||||||
}
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Evaluates a string and returns a typesafe result.
|
/// \brief Evaluates a string and returns a typesafe result.
|
||||||
@ -872,21 +649,14 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
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>(eval(t_input, t_handler, t_filename));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||||
template<typename Type>
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -918,14 +688,7 @@ namespace chaiscript
|
|||||||
/// \return result of the script execution
|
/// \return result of the script execution
|
||||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
/// \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()) {
|
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||||
try {
|
return eval(load_file(t_filename), t_handler, t_filename);
|
||||||
return do_eval(load_file(t_filename), t_filename);
|
|
||||||
} catch (Boxed_Value &bv) {
|
|
||||||
if (t_handler) {
|
|
||||||
t_handler->handle(bv, m_engine);
|
|
||||||
}
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
|
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
|
||||||
@ -938,14 +701,7 @@ namespace chaiscript
|
|||||||
/// to the requested type.
|
/// to the requested type.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||||
try {
|
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
427
include/chaiscript/language/chaiscript_optimizer.hpp
Normal file
427
include/chaiscript/language/chaiscript_optimizer.hpp
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
|
||||||
|
#define CHAISCRIPT_OPTIMIZER_HPP_
|
||||||
|
|
||||||
|
#include "chaiscript_eval.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
|
namespace optimizer {
|
||||||
|
|
||||||
|
template<typename ... T>
|
||||||
|
struct Optimizer : T...
|
||||||
|
{
|
||||||
|
Optimizer() = default;
|
||||||
|
explicit Optimizer(T ... t)
|
||||||
|
: T(std::move(t))...
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Tracer>
|
||||||
|
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
||||||
|
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(p), 0)... };
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto child_at(const eval::AST_Node_Impl_Ptr<T> &node, const size_t offset) {
|
||||||
|
if (node->children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||||
|
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node->children[offset]).m_original_node;
|
||||||
|
} else {
|
||||||
|
return node->children[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (node->identifier == AST_Node_Type::Compiled) {
|
||||||
|
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
|
||||||
|
} else {
|
||||||
|
return node->children[offset];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto child_count(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
if (node->identifier == AST_Node_Type::Compiled) {
|
||||||
|
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children.size();
|
||||||
|
} else {
|
||||||
|
return node->children.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename Callable>
|
||||||
|
auto make_compiled_node(const eval::AST_Node_Impl_Ptr<T> &original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
|
||||||
|
{
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(original_node, std::move(children), std::move(callable));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Return {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
|
||||||
|
{
|
||||||
|
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
|
||||||
|
&& !p->children.empty())
|
||||||
|
{
|
||||||
|
auto &last_child = p->children.back();
|
||||||
|
if (last_child->identifier == AST_Node_Type::Block) {
|
||||||
|
auto &block_last_child = last_child->children.back();
|
||||||
|
if (block_last_child->identifier == AST_Node_Type::Return) {
|
||||||
|
if (block_last_child->children.size() == 1) {
|
||||||
|
last_child->children.back() = block_last_child->children[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool contains_var_decl_in_scope(const T &node)
|
||||||
|
{
|
||||||
|
if (node->identifier == AST_Node_Type::Var_Decl) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto num = child_count(node);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num; ++i) {
|
||||||
|
const auto &child = child_at(node, i);
|
||||||
|
if (child->identifier != AST_Node_Type::Block
|
||||||
|
&& child->identifier != AST_Node_Type::For
|
||||||
|
&& contains_var_decl_in_scope(child)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Block {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
if (node->identifier == AST_Node_Type::Block)
|
||||||
|
{
|
||||||
|
if (!contains_var_decl_in_scope(node))
|
||||||
|
{
|
||||||
|
if (node->children.size() == 1) {
|
||||||
|
return node->children[0];
|
||||||
|
} else {
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location, node->children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dead_Code {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
if (node->identifier == AST_Node_Type::Block)
|
||||||
|
{
|
||||||
|
std::vector<size_t> keepers;
|
||||||
|
const auto num_children = node->children.size();
|
||||||
|
keepers.reserve(num_children);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_children; ++i) {
|
||||||
|
auto child = node->children[i];
|
||||||
|
if ( (child->identifier != AST_Node_Type::Id
|
||||||
|
&& child->identifier != AST_Node_Type::Constant
|
||||||
|
&& child->identifier != AST_Node_Type::Noop)
|
||||||
|
|| i == num_children - 1) {
|
||||||
|
keepers.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keepers.size() == num_children) {
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
std::vector<eval::AST_Node_Impl_Ptr<T>> new_children;
|
||||||
|
for (const auto x : keepers)
|
||||||
|
{
|
||||||
|
new_children.push_back(node->children[x]);
|
||||||
|
}
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Unused_Return {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
if ((node->identifier == AST_Node_Type::Block
|
||||||
|
|| node->identifier == AST_Node_Type::Scopeless_Block)
|
||||||
|
&& !node->children.empty())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < node->children.size()-1; ++i) {
|
||||||
|
auto child = node->children[i];
|
||||||
|
if (child->identifier == AST_Node_Type::Fun_Call) {
|
||||||
|
node->children[i] = chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text, child->location, std::move(child->children));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((node->identifier == AST_Node_Type::For
|
||||||
|
|| node->identifier == AST_Node_Type::While)
|
||||||
|
&& child_count(node) > 0) {
|
||||||
|
auto child = child_at(node, child_count(node) - 1);
|
||||||
|
if (child->identifier == AST_Node_Type::Block
|
||||||
|
|| child->identifier == AST_Node_Type::Scopeless_Block)
|
||||||
|
{
|
||||||
|
auto num_sub_children = child_count(child);
|
||||||
|
for (size_t i = 0; i < num_sub_children; ++i) {
|
||||||
|
auto sub_child = child_at(child, i);
|
||||||
|
if (sub_child->identifier == AST_Node_Type::Fun_Call) {
|
||||||
|
child->children[i] = chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child->text, sub_child->location, std::move(sub_child->children));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct If {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
if ((node->identifier == AST_Node_Type::If)
|
||||||
|
&& node->children.size() >= 2
|
||||||
|
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||||
|
{
|
||||||
|
const auto condition = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||||
|
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||||
|
if (boxed_cast<bool>(condition)) {
|
||||||
|
return node->children[1];
|
||||||
|
} else if (node->children.size() == 3) {
|
||||||
|
return node->children[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Partial_Fold {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
|
||||||
|
// Fold right side
|
||||||
|
if (node->identifier == AST_Node_Type::Binary
|
||||||
|
&& node->children.size() == 2
|
||||||
|
&& node->children[0]->identifier != AST_Node_Type::Constant
|
||||||
|
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const auto &oper = node->text;
|
||||||
|
const auto parsed = Operators::to_operator(oper);
|
||||||
|
if (parsed != Operators::Opers::invalid) {
|
||||||
|
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
||||||
|
if (rhs.get_type_info().is_arithmetic()) {
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location, node->children, rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
//failure to fold, that's OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Constant_Fold {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||||
|
|
||||||
|
if (node->identifier == AST_Node_Type::Prefix
|
||||||
|
&& node->children.size() == 1
|
||||||
|
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const auto &oper = node->text;
|
||||||
|
const auto parsed = Operators::to_operator(oper, true);
|
||||||
|
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||||
|
const auto match = oper + node->children[0]->text;
|
||||||
|
|
||||||
|
if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
|
||||||
|
const auto val = Boxed_Number::do_oper(parsed, lhs);
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||||
|
} else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") {
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(!boxed_cast<bool>(lhs)));
|
||||||
|
}
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
//failure to fold, that's OK
|
||||||
|
}
|
||||||
|
} else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or)
|
||||||
|
&& node->children.size() == 2
|
||||||
|
&& node->children[0]->identifier == AST_Node_Type::Constant
|
||||||
|
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||||
|
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
||||||
|
if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||||
|
const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text;
|
||||||
|
const auto val = [lhs_val = boxed_cast<bool>(lhs), rhs_val = boxed_cast<bool>(rhs), id = node->identifier] {
|
||||||
|
if (id == AST_Node_Type::Logical_And) { return Boxed_Value(lhs_val && rhs_val); }
|
||||||
|
else { return Boxed_Value(lhs_val || rhs_val); }
|
||||||
|
}();
|
||||||
|
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||||
|
}
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
//failure to fold, that's OK
|
||||||
|
}
|
||||||
|
} else if (node->identifier == AST_Node_Type::Binary
|
||||||
|
&& node->children.size() == 2
|
||||||
|
&& node->children[0]->identifier == AST_Node_Type::Constant
|
||||||
|
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const auto &oper = node->text;
|
||||||
|
const auto parsed = Operators::to_operator(oper);
|
||||||
|
if (parsed != Operators::Opers::invalid) {
|
||||||
|
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||||
|
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
||||||
|
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
||||||
|
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
||||||
|
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
//failure to fold, that's OK
|
||||||
|
}
|
||||||
|
} else if (node->identifier == AST_Node_Type::Fun_Call
|
||||||
|
&& node->children.size() == 2
|
||||||
|
&& node->children[0]->identifier == AST_Node_Type::Id
|
||||||
|
&& node->children[1]->identifier == AST_Node_Type::Arg_List
|
||||||
|
&& node->children[1]->children.size() == 1
|
||||||
|
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||||
|
|
||||||
|
const auto arg = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1]->children[0])->m_value;
|
||||||
|
if (arg.get_type_info().is_arithmetic()) {
|
||||||
|
const auto &fun_name = node->children[0]->text;
|
||||||
|
|
||||||
|
const auto make_constant = [&node, &fun_name](auto val){
|
||||||
|
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||||
|
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fun_name == "double") {
|
||||||
|
return make_constant(Boxed_Number(arg).get_as<double>());
|
||||||
|
} else if (fun_name == "int") {
|
||||||
|
return make_constant(Boxed_Number(arg).get_as<int>());
|
||||||
|
} else if (fun_name == "float") {
|
||||||
|
return make_constant(Boxed_Number(arg).get_as<float>());
|
||||||
|
} else if (fun_name == "long") {
|
||||||
|
return make_constant(Boxed_Number(arg).get_as<long>());
|
||||||
|
} else if (fun_name == "size_t") {
|
||||||
|
return make_constant(Boxed_Number(arg).get_as<size_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct For_Loop {
|
||||||
|
template<typename T>
|
||||||
|
auto optimize(const eval::AST_Node_Impl_Ptr<T> &for_node) {
|
||||||
|
|
||||||
|
if (for_node->identifier != AST_Node_Type::For) {
|
||||||
|
return for_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto eq_node = child_at(for_node, 0);
|
||||||
|
const auto binary_node = child_at(for_node, 1);
|
||||||
|
const auto prefix_node = child_at(for_node, 2);
|
||||||
|
|
||||||
|
if (eq_node->identifier == AST_Node_Type::Equation
|
||||||
|
&& child_count(eq_node) == 2
|
||||||
|
&& child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl
|
||||||
|
&& child_at(eq_node, 1)->identifier == AST_Node_Type::Constant
|
||||||
|
&& binary_node->identifier == AST_Node_Type::Binary
|
||||||
|
&& binary_node->text == "<"
|
||||||
|
&& child_count(binary_node) == 2
|
||||||
|
&& child_at(binary_node, 0)->identifier == AST_Node_Type::Id
|
||||||
|
&& child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text
|
||||||
|
&& child_at(binary_node, 1)->identifier == AST_Node_Type::Constant
|
||||||
|
&& prefix_node->identifier == AST_Node_Type::Prefix
|
||||||
|
&& prefix_node->text == "++"
|
||||||
|
&& child_count(prefix_node) == 1
|
||||||
|
&& child_at(prefix_node, 0)->identifier == AST_Node_Type::Id
|
||||||
|
&& child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text)
|
||||||
|
{
|
||||||
|
const Boxed_Value &begin = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(eq_node, 1))->m_value;
|
||||||
|
const Boxed_Value &end = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(binary_node, 1))->m_value;
|
||||||
|
const std::string &id = child_at(prefix_node, 0)->text;
|
||||||
|
|
||||||
|
if (begin.get_type_info().bare_equal(user_type<int>())
|
||||||
|
&& end.get_type_info().bare_equal(user_type<int>())) {
|
||||||
|
|
||||||
|
const auto start_int = boxed_cast<int>(begin);
|
||||||
|
const auto end_int = boxed_cast<int>(end);
|
||||||
|
|
||||||
|
const auto body = child_at(for_node, 3);
|
||||||
|
|
||||||
|
return make_compiled_node(for_node, {body},
|
||||||
|
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||||
|
assert(children.size() == 1);
|
||||||
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
|
||||||
|
int i = start_int;
|
||||||
|
t_ss.add_object(id, var(&i));
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (; i < end_int; ++i) {
|
||||||
|
try {
|
||||||
|
// Body of Loop
|
||||||
|
children[0]->eval(t_ss);
|
||||||
|
} catch (eval::detail::Continue_Loop &) {
|
||||||
|
// we got a continue exception, which means all of the remaining
|
||||||
|
// loop implementation is skipped and we just need to continue to
|
||||||
|
// the next iteration step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (eval::detail::Break_Loop &) {
|
||||||
|
// loop broken
|
||||||
|
}
|
||||||
|
|
||||||
|
return void_var();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return for_node;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return for_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Optimizer<optimizer::Partial_Fold, optimizer::Unused_Return, optimizer::Constant_Fold,
|
||||||
|
optimizer::If, optimizer::Return, optimizer::Dead_Code, optimizer::Block, optimizer::For_Loop> Optimizer_Default;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
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-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||||
|
#define CHAISCRIPT_POSIX_HPP_
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct Loadable_Module
|
||||||
|
{
|
||||||
|
struct DLModule
|
||||||
|
{
|
||||||
|
explicit DLModule(const std::string &t_filename)
|
||||||
|
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||||
|
{
|
||||||
|
if (m_data == nullptr)
|
||||||
|
{
|
||||||
|
throw chaiscript::exception::load_module_error(dlerror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DLModule(DLModule &&) = default;
|
||||||
|
DLModule &operator=(DLModule &&) = default;
|
||||||
|
DLModule(const DLModule &) = delete;
|
||||||
|
DLModule &operator=(const DLModule &) = delete;
|
||||||
|
|
||||||
|
~DLModule()
|
||||||
|
{
|
||||||
|
dlclose(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct DLSym
|
||||||
|
{
|
||||||
|
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||||
|
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||||
|
{
|
||||||
|
if (!m_symbol)
|
||||||
|
{
|
||||||
|
throw chaiscript::exception::load_module_error(dlerror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static T cast_symbol(void *p)
|
||||||
|
{
|
||||||
|
union cast_union
|
||||||
|
{
|
||||||
|
T func_ptr;
|
||||||
|
void *in_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
cast_union c;
|
||||||
|
c.in_ptr = p;
|
||||||
|
return c.func_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T m_symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||||
|
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||||
|
m_moduleptr(m_func.m_symbol())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DLModule m_dlmodule;
|
||||||
|
DLSym<Create_Module_Func> m_func;
|
||||||
|
ModulePtr m_moduleptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||||
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
struct ChaiScript_Prelude {
|
struct ChaiScript_Prelude {
|
||||||
static std::string chaiscript_prelude() { return R""(
|
static std::string chaiscript_prelude() { return R"chaiscript(
|
||||||
|
|
||||||
def lt(l, r) {
|
def lt(l, r) {
|
||||||
if (call_exists(`<`, l, r)) {
|
if (call_exists(`<`, l, r)) {
|
||||||
@ -215,6 +215,29 @@ def for_each(container, func) : call_exists(range, container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def any_of(container, func) : call_exists(range, container) {
|
||||||
|
var t_range := range(container);
|
||||||
|
while (!t_range.empty()) {
|
||||||
|
if (func(t_range.front())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
t_range.pop_front();
|
||||||
|
}
|
||||||
|
false;
|
||||||
|
}
|
||||||
|
|
||||||
|
def all_of(container, func) : call_exists(range, container) {
|
||||||
|
var t_range := range(container);
|
||||||
|
while (!t_range.empty()) {
|
||||||
|
if (!func(t_range.front())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
t_range.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
true;
|
||||||
|
}
|
||||||
|
|
||||||
def back_inserter(container) {
|
def back_inserter(container) {
|
||||||
bind(push_back, container, _);
|
bind(push_back, container, _);
|
||||||
}
|
}
|
||||||
@ -530,7 +553,7 @@ def find(container, value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
)"";
|
)chaiscript";
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
@ -505,7 +505,7 @@ class Function
|
|||||||
/// \endcode
|
/// \endcode
|
||||||
Vector get_contained_functions() const;
|
Vector get_contained_functions() const;
|
||||||
|
|
||||||
/// \brief Returns a vector of the contained functions
|
/// \brief Returns a function guard as function
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// \code
|
/// \code
|
||||||
|
46
include/chaiscript/language/chaiscript_tracer.hpp
Normal file
46
include/chaiscript/language/chaiscript_tracer.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||||
|
#define CHAISCRIPT_TRACER_HPP_
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
|
namespace eval {
|
||||||
|
|
||||||
|
|
||||||
|
struct Noop_Tracer_Detail
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ... T>
|
||||||
|
struct Tracer : T...
|
||||||
|
{
|
||||||
|
Tracer() = default;
|
||||||
|
explicit Tracer(T ... t)
|
||||||
|
: T(std::move(t))...
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||||
|
(void)std::initializer_list<int>{ (static_cast<T&>(*this).trace(ds, node), 0)... };
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||||
|
ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Tracer<Noop_Tracer_Detail> Noop_Tracer;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
31
include/chaiscript/language/chaiscript_unknown.hpp
Normal file
31
include/chaiscript/language/chaiscript_unknown.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||||
|
#define CHAISCRIPT_UNKNOWN_HPP_
|
||||||
|
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct Loadable_Module
|
||||||
|
{
|
||||||
|
Loadable_Module(const std::string &, const std::string &)
|
||||||
|
{
|
||||||
|
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||||
|
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||||
|
#else
|
||||||
|
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModulePtr m_moduleptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
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-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_WINDOWS_HPP_
|
||||||
|
#define CHAISCRIPT_WINDOWS_HPP_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef CHAISCRIPT_WINDOWS
|
||||||
|
#define VC_EXTRA_LEAN
|
||||||
|
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct Loadable_Module
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
static std::wstring to_wstring(const T &t_str)
|
||||||
|
{
|
||||||
|
return std::wstring(t_str.begin(), t_str.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string to_string(const T &t_str)
|
||||||
|
{
|
||||||
|
return std::string(t_str.begin(), t_str.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_UNICODE) || defined(UNICODE)
|
||||||
|
template<typename T>
|
||||||
|
static std::wstring to_proper_string(const T &t_str)
|
||||||
|
{
|
||||||
|
return to_wstring(t_str);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<typename T>
|
||||||
|
static std::string to_proper_string(const T &t_str)
|
||||||
|
{
|
||||||
|
return to_string(t_str);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static std::string get_error_message(DWORD t_err)
|
||||||
|
{
|
||||||
|
typedef LPTSTR StringType;
|
||||||
|
|
||||||
|
#if defined(_UNICODE) || defined(UNICODE)
|
||||||
|
std::wstring retval = L"Unknown Error";
|
||||||
|
#else
|
||||||
|
std::string retval = "Unknown Error";
|
||||||
|
#endif
|
||||||
|
StringType lpMsgBuf = nullptr;
|
||||||
|
|
||||||
|
if (FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
nullptr,
|
||||||
|
t_err,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||||
|
0, nullptr ) != 0 && lpMsgBuf)
|
||||||
|
{
|
||||||
|
retval = lpMsgBuf;
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return to_string(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DLModule
|
||||||
|
{
|
||||||
|
explicit DLModule(const std::string &t_filename)
|
||||||
|
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||||
|
{
|
||||||
|
if (!m_data)
|
||||||
|
{
|
||||||
|
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DLModule(DLModule &&) = default;
|
||||||
|
DLModule &operator=(DLModule &&) = default;
|
||||||
|
DLModule(const DLModule &) = delete;
|
||||||
|
DLModule &operator=(const DLModule &) = delete;
|
||||||
|
|
||||||
|
~DLModule()
|
||||||
|
{
|
||||||
|
FreeLibrary(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct DLSym
|
||||||
|
{
|
||||||
|
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||||
|
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||||
|
{
|
||||||
|
if (!m_symbol)
|
||||||
|
{
|
||||||
|
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T m_symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||||
|
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||||
|
m_moduleptr(m_func.m_symbol())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DLModule m_dlmodule;
|
||||||
|
DLSym<Create_Module_Func> m_func;
|
||||||
|
ModulePtr m_moduleptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
50
include/chaiscript/utility/fnv1a.hpp
Normal file
50
include/chaiscript/utility/fnv1a.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||||
|
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include "../chaiscript_defines.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
namespace utility
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4307)
|
||||||
|
#endif
|
||||||
|
return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193));
|
||||||
|
#ifdef CHAISCRIPT_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -13,18 +13,16 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "../chaiscript_defines.hpp"
|
||||||
|
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
using std::map;
|
|
||||||
using std::deque;
|
|
||||||
using std::string;
|
|
||||||
using std::enable_if;
|
using std::enable_if;
|
||||||
using std::initializer_list;
|
using std::initializer_list;
|
||||||
using std::is_same;
|
using std::is_same;
|
||||||
@ -32,41 +30,11 @@ using std::is_convertible;
|
|||||||
using std::is_integral;
|
using std::is_integral;
|
||||||
using std::is_floating_point;
|
using std::is_floating_point;
|
||||||
|
|
||||||
namespace {
|
|
||||||
string json_escape( const string &str ) {
|
|
||||||
string output;
|
|
||||||
for( unsigned i = 0; i < str.length(); ++i )
|
|
||||||
switch( str[i] ) {
|
|
||||||
case '\"': output += "\\\""; break;
|
|
||||||
case '\\': output += "\\\\"; break;
|
|
||||||
case '\b': output += "\\b"; break;
|
|
||||||
case '\f': output += "\\f"; break;
|
|
||||||
case '\n': output += "\\n"; break;
|
|
||||||
case '\r': output += "\\r"; break;
|
|
||||||
case '\t': output += "\\t"; break;
|
|
||||||
default : output += str[i]; break;
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JSON
|
class JSON
|
||||||
{
|
{
|
||||||
union BackingData {
|
|
||||||
BackingData( double d ) : Float( d ){}
|
|
||||||
BackingData( long l ) : Int( l ){}
|
|
||||||
BackingData( bool b ) : Bool( b ){}
|
|
||||||
BackingData( string s ) : String( new string( s ) ){}
|
|
||||||
BackingData() : Int( 0 ){}
|
|
||||||
|
|
||||||
deque<JSON> *List;
|
|
||||||
map<string,JSON> *Map;
|
|
||||||
string *String;
|
|
||||||
double Float;
|
|
||||||
long Int;
|
|
||||||
bool Bool;
|
|
||||||
} Internal;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Class {
|
enum class Class {
|
||||||
Null,
|
Null,
|
||||||
@ -78,13 +46,169 @@ class JSON
|
|||||||
Boolean
|
Boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct QuickFlatMap
|
||||||
|
{
|
||||||
|
auto find(const std::string &s) {
|
||||||
|
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
||||||
|
}
|
||||||
|
|
||||||
|
auto find(const std::string &s) const {
|
||||||
|
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size() const {
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto begin() const {
|
||||||
|
return data.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end() const {
|
||||||
|
return data.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto begin() {
|
||||||
|
return data.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end() {
|
||||||
|
return data.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSON &operator[](const std::string &s) {
|
||||||
|
const auto itr = find(s);
|
||||||
|
if (itr != data.end()) {
|
||||||
|
return itr->second;
|
||||||
|
} else {
|
||||||
|
data.emplace_back(s, JSON());
|
||||||
|
return data.back().second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &at(const std::string &s) {
|
||||||
|
const auto itr = find(s);
|
||||||
|
if (itr != data.end()) {
|
||||||
|
return itr->second;
|
||||||
|
} else {
|
||||||
|
throw std::out_of_range("Unknown key: " + s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const JSON &at(const std::string &s) const {
|
||||||
|
const auto itr = find(s);
|
||||||
|
if (itr != data.end()) {
|
||||||
|
return itr->second;
|
||||||
|
} else {
|
||||||
|
throw std::out_of_range("Unknown key: " + s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count(const std::string &s) const {
|
||||||
|
return (find(s) != data.end())?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, JSON>> data;
|
||||||
|
|
||||||
|
using iterator = decltype(data)::iterator;
|
||||||
|
using const_iterator = decltype(data)::const_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Internal {
|
||||||
|
template<typename T>
|
||||||
|
auto clone(const std::unique_ptr<T> &ptr) {
|
||||||
|
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<QuickFlatMap>(); break;
|
||||||
|
case Class::Array: List = std::make_unique<std::vector<JSON>>(); break;
|
||||||
|
case Class::String: String = std::make_unique<std::string>(); break;
|
||||||
|
case Class::Floating: Float = 0.0; break;
|
||||||
|
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<QuickFlatMap> 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>
|
template <typename Container>
|
||||||
class JSONWrapper {
|
class JSONWrapper {
|
||||||
Container *object;
|
Container *object = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONWrapper( Container *val ) : object( val ) {}
|
JSONWrapper( Container *val ) : object( val ) {}
|
||||||
JSONWrapper( std::nullptr_t ) : object( nullptr ) {}
|
JSONWrapper( std::nullptr_t ) {}
|
||||||
|
|
||||||
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
|
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
|
||||||
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
|
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
|
||||||
@ -94,271 +218,180 @@ class JSON
|
|||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
class JSONConstWrapper {
|
class JSONConstWrapper {
|
||||||
const Container *object;
|
const Container *object = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONConstWrapper( const Container *val ) : object( val ) {}
|
JSONConstWrapper( const Container *val ) : object( val ) {}
|
||||||
JSONConstWrapper( std::nullptr_t ) : object( nullptr ) {}
|
JSONConstWrapper( std::nullptr_t ) {}
|
||||||
|
|
||||||
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); }
|
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(); }
|
typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
JSON() : Internal(), Type( Class::Null ){}
|
JSON() = default;
|
||||||
|
JSON( std::nullptr_t ) {}
|
||||||
|
|
||||||
explicit JSON(Class type)
|
explicit JSON(Class type)
|
||||||
: Internal(), Type(Class::Null)
|
: internal(type)
|
||||||
{
|
{
|
||||||
SetType( type );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON( initializer_list<JSON> list )
|
JSON( initializer_list<JSON> list )
|
||||||
: Internal(), Type(Class::Null)
|
: internal(Class::Object)
|
||||||
{
|
{
|
||||||
SetType( Class::Object );
|
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) {
|
||||||
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i )
|
operator[]( i->to_string() ) = *std::next( i );
|
||||||
operator[]( i->ToString() ) = *std::next( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON( JSON&& other )
|
|
||||||
: Internal( other.Internal )
|
|
||||||
, Type( other.Type )
|
|
||||||
{ other.Type = Class::Null; other.Internal.Map = nullptr; }
|
|
||||||
|
|
||||||
JSON& operator=( JSON&& other ) {
|
|
||||||
Internal = other.Internal;
|
|
||||||
Type = other.Type;
|
|
||||||
other.Internal.Map = nullptr;
|
|
||||||
other.Type = Class::Null;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON( const JSON &other ) {
|
|
||||||
switch( other.Type ) {
|
|
||||||
case Class::Object:
|
|
||||||
Internal.Map =
|
|
||||||
new map<string,JSON>( other.Internal.Map->begin(),
|
|
||||||
other.Internal.Map->end() );
|
|
||||||
break;
|
|
||||||
case Class::Array:
|
|
||||||
Internal.List =
|
|
||||||
new deque<JSON>( other.Internal.List->begin(),
|
|
||||||
other.Internal.List->end() );
|
|
||||||
break;
|
|
||||||
case Class::String:
|
|
||||||
Internal.String =
|
|
||||||
new string( *other.Internal.String );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Internal = other.Internal;
|
|
||||||
}
|
|
||||||
Type = other.Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON& operator=( const JSON &other ) {
|
|
||||||
if (&other == this) return *this;
|
|
||||||
|
|
||||||
switch( other.Type ) {
|
|
||||||
case Class::Object:
|
|
||||||
Internal.Map =
|
|
||||||
new map<string,JSON>( other.Internal.Map->begin(),
|
|
||||||
other.Internal.Map->end() );
|
|
||||||
break;
|
|
||||||
case Class::Array:
|
|
||||||
Internal.List =
|
|
||||||
new deque<JSON>( other.Internal.List->begin(),
|
|
||||||
other.Internal.List->end() );
|
|
||||||
break;
|
|
||||||
case Class::String:
|
|
||||||
Internal.String =
|
|
||||||
new string( *other.Internal.String );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Internal = other.Internal;
|
|
||||||
}
|
|
||||||
Type = other.Type;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~JSON() {
|
|
||||||
switch( Type ) {
|
|
||||||
case Class::Array:
|
|
||||||
delete Internal.List;
|
|
||||||
break;
|
|
||||||
case Class::Object:
|
|
||||||
delete Internal.Map;
|
|
||||||
break;
|
|
||||||
case Class::String:
|
|
||||||
delete Internal.String;
|
|
||||||
break;
|
|
||||||
default:;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = 0 ) : Internal( b ), Type( Class::Boolean ){}
|
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) : internal( static_cast<bool>(b) ) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = 0 ) : Internal( long(i) ), Type( Class::Integral ){}
|
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>
|
template <typename T>
|
||||||
JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = 0 ) : Internal( double(f) ), Type( Class::Floating ){}
|
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) : internal( static_cast<double>(f) ) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
JSON( T s, typename enable_if<is_convertible<T,string>::value>::type* = 0 ) : Internal( string( s ) ), Type( Class::String ){}
|
explicit JSON( T s, typename enable_if<is_convertible<T,std::string>::value>::type* = nullptr ) : internal( static_cast<std::string>(s) ) {}
|
||||||
|
|
||||||
JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){}
|
|
||||||
|
|
||||||
static JSON Make( Class type ) {
|
|
||||||
return JSON(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSON Load( const string & );
|
static JSON Load( const std::string & );
|
||||||
|
|
||||||
template <typename T>
|
JSON& operator[]( const std::string &key ) {
|
||||||
void append( T arg ) {
|
internal.set_type( Class::Object );
|
||||||
SetType( Class::Array ); Internal.List->emplace_back( arg );
|
return internal.Map->operator[]( key );
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... U>
|
|
||||||
void append( T arg, U... args ) {
|
|
||||||
append( arg ); append( args... );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename enable_if<is_same<T,bool>::value, JSON&>::type operator=( T b ) {
|
|
||||||
SetType( Class::Boolean ); Internal.Bool = b; return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename enable_if<is_integral<T>::value && !is_same<T,bool>::value, JSON&>::type operator=( T i ) {
|
|
||||||
SetType( Class::Integral ); Internal.Int = i; return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename enable_if<is_floating_point<T>::value, JSON&>::type operator=( T f ) {
|
|
||||||
SetType( Class::Floating ); Internal.Float = f; return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename enable_if<is_convertible<T,string>::value, JSON&>::type operator=( T s ) {
|
|
||||||
SetType( Class::String ); *Internal.String = string( s ); return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON& operator[]( const string &key ) {
|
|
||||||
SetType( Class::Object ); return Internal.Map->operator[]( key );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON& operator[]( const size_t index ) {
|
JSON& operator[]( const size_t index ) {
|
||||||
SetType( Class::Array );
|
internal.set_type( Class::Array );
|
||||||
if( index >= Internal.List->size() ) Internal.List->resize( index + 1 );
|
if( index >= internal.List->size() ) {
|
||||||
return Internal.List->operator[]( index );
|
internal.List->resize( index + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON &at( const string &key ) {
|
return internal.List->operator[]( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSON &at( const std::string &key ) {
|
||||||
return operator[]( key );
|
return operator[]( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSON &at( const string &key ) const {
|
const JSON &at( const std::string &key ) const {
|
||||||
return Internal.Map->at( key );
|
return internal.Map->at( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON &at( unsigned index ) {
|
JSON &at( size_t index ) {
|
||||||
return operator[]( index );
|
return operator[]( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSON &at( unsigned index ) const {
|
const JSON &at( size_t index ) const {
|
||||||
return Internal.List->at( index );
|
return internal.List->at( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
int length() const {
|
|
||||||
if( Type == Class::Array )
|
long length() const {
|
||||||
return static_cast<int>(Internal.List->size());
|
if( internal.Type == Class::Array ) {
|
||||||
else
|
return static_cast<long>(internal.List->size());
|
||||||
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_key( const std::string &key ) const {
|
||||||
|
if( internal.Type == Class::Object ) {
|
||||||
|
return internal.Map->count(key) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasKey( const string &key ) const {
|
|
||||||
if( Type == Class::Object )
|
|
||||||
return Internal.Map->find( key ) != Internal.Map->end();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size() const {
|
int size() const {
|
||||||
if( Type == Class::Object )
|
if( internal.Type == Class::Object ) {
|
||||||
return static_cast<int>(Internal.Map->size());
|
return static_cast<int>(internal.Map->size());
|
||||||
else if( Type == Class::Array )
|
} else if( internal.Type == Class::Array ) {
|
||||||
return static_cast<int>(Internal.List->size());
|
return static_cast<int>(internal.List->size());
|
||||||
else
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Class JSONType() const { return Type; }
|
Class JSONType() const { return internal.Type; }
|
||||||
|
|
||||||
/// Functions for getting primitives from the JSON object.
|
/// Functions for getting primitives from the JSON object.
|
||||||
bool IsNull() const { return Type == Class::Null; }
|
bool is_null() const { return internal.Type == Class::Null; }
|
||||||
|
|
||||||
string ToString() const { bool b; return ToString( b ); }
|
std::string to_string() const { bool b; return to_string( b ); }
|
||||||
string ToString( bool &ok ) const {
|
std::string to_string( bool &ok ) const {
|
||||||
ok = (Type == Class::String);
|
ok = (internal.Type == Class::String);
|
||||||
return ok ? *Internal.String : string("");
|
return ok ? *internal.String : std::string("");
|
||||||
}
|
}
|
||||||
|
|
||||||
double ToFloat() const { bool b; return ToFloat( b ); }
|
double to_float() const { bool b; return to_float( b ); }
|
||||||
double ToFloat( bool &ok ) const {
|
double to_float( bool &ok ) const {
|
||||||
ok = (Type == Class::Floating);
|
ok = (internal.Type == Class::Floating);
|
||||||
return ok ? Internal.Float : 0.0;
|
return ok ? internal.Float : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long ToInt() const { bool b; return ToInt( b ); }
|
long to_int() const { bool b; return to_int( b ); }
|
||||||
long ToInt( bool &ok ) const {
|
long to_int( bool &ok ) const {
|
||||||
ok = (Type == Class::Integral);
|
ok = (internal.Type == Class::Integral);
|
||||||
return ok ? Internal.Int : 0;
|
return ok ? internal.Int : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToBool() const { bool b; return ToBool( b ); }
|
bool to_bool() const { bool b; return to_bool( b ); }
|
||||||
bool ToBool( bool &ok ) const {
|
bool to_bool( bool &ok ) const {
|
||||||
ok = (Type == Class::Boolean);
|
ok = (internal.Type == Class::Boolean);
|
||||||
return ok ? Internal.Bool : false;
|
return ok ? internal.Bool : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONWrapper<map<string,JSON>> ObjectRange() {
|
JSONWrapper<QuickFlatMap> object_range() {
|
||||||
if( Type == Class::Object )
|
if( internal.Type == Class::Object ) {
|
||||||
return JSONWrapper<map<string,JSON>>( Internal.Map );
|
return JSONWrapper<QuickFlatMap>( internal.Map.get() );
|
||||||
return JSONWrapper<map<string,JSON>>( nullptr );
|
} else {
|
||||||
|
return JSONWrapper<QuickFlatMap>( nullptr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONWrapper<deque<JSON>> ArrayRange() {
|
JSONWrapper<std::vector<JSON>> array_range() {
|
||||||
if( Type == Class::Array )
|
if( internal.Type == Class::Array ) {
|
||||||
return JSONWrapper<deque<JSON>>( Internal.List );
|
return JSONWrapper<std::vector<JSON>>( internal.List.get() );
|
||||||
return JSONWrapper<deque<JSON>>( nullptr );
|
} else {
|
||||||
|
return JSONWrapper<std::vector<JSON>>( nullptr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONConstWrapper<map<string,JSON>> ObjectRange() const {
|
JSONConstWrapper<QuickFlatMap> object_range() const {
|
||||||
if( Type == Class::Object )
|
if( internal.Type == Class::Object ) {
|
||||||
return JSONConstWrapper<map<string,JSON>>( Internal.Map );
|
return JSONConstWrapper<QuickFlatMap>( internal.Map.get() );
|
||||||
return JSONConstWrapper<map<string,JSON>>( nullptr );
|
} else {
|
||||||
|
return JSONConstWrapper<QuickFlatMap>( nullptr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JSONConstWrapper<deque<JSON>> ArrayRange() const {
|
JSONConstWrapper<std::vector<JSON>> array_range() const {
|
||||||
if( Type == Class::Array )
|
if( internal.Type == Class::Array ) {
|
||||||
return JSONConstWrapper<deque<JSON>>( Internal.List );
|
return JSONConstWrapper<std::vector<JSON>>( internal.List.get() );
|
||||||
return JSONConstWrapper<deque<JSON>>( nullptr );
|
} else {
|
||||||
|
return JSONConstWrapper<std::vector<JSON>>( nullptr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string dump( int depth = 1, string tab = " ") const {
|
std::string dump( long depth = 1, std::string tab = " ") const {
|
||||||
switch( Type ) {
|
switch( internal.Type ) {
|
||||||
case Class::Null:
|
case Class::Null:
|
||||||
return "null";
|
return "null";
|
||||||
case Class::Object: {
|
case Class::Object: {
|
||||||
string pad = "";
|
std::string pad = "";
|
||||||
for( int i = 0; i < depth; ++i, pad += tab );
|
for( long i = 0; i < depth; ++i, pad += tab ) { }
|
||||||
|
|
||||||
string s = "{\n";
|
std::string s = "{\n";
|
||||||
bool skip = true;
|
bool skip = true;
|
||||||
for( auto &p : *Internal.Map ) {
|
for( auto &p : *internal.Map ) {
|
||||||
if( !skip ) s += ",\n";
|
if( !skip ) { s += ",\n"; }
|
||||||
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
|
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||||
skip = false;
|
skip = false;
|
||||||
}
|
}
|
||||||
@ -366,10 +399,10 @@ class JSON
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
case Class::Array: {
|
case Class::Array: {
|
||||||
string s = "[";
|
std::string s = "[";
|
||||||
bool skip = true;
|
bool skip = true;
|
||||||
for( auto &p : *Internal.List ) {
|
for( auto &p : *internal.List ) {
|
||||||
if( !skip ) s += ", ";
|
if( !skip ) { s += ", "; }
|
||||||
s += p.dump( depth + 1, tab );
|
s += p.dump( depth + 1, tab );
|
||||||
skip = false;
|
skip = false;
|
||||||
}
|
}
|
||||||
@ -377,79 +410,64 @@ class JSON
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
case Class::String:
|
case Class::String:
|
||||||
return "\"" + json_escape( *Internal.String ) + "\"";
|
return "\"" + json_escape( *internal.String ) + "\"";
|
||||||
case Class::Floating:
|
case Class::Floating:
|
||||||
return std::to_string( Internal.Float );
|
return std::to_string( internal.Float );
|
||||||
case Class::Integral:
|
case Class::Integral:
|
||||||
return std::to_string( Internal.Int );
|
return std::to_string( internal.Int );
|
||||||
case Class::Boolean:
|
case Class::Boolean:
|
||||||
return Internal.Bool ? "true" : "false";
|
return internal.Bool ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("Unhandled JSON type");
|
throw std::runtime_error("Unhandled JSON type");
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::ostream& operator<<( std::ostream&, const JSON & );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetType( Class type ) {
|
static std::string json_escape( const std::string &str ) {
|
||||||
if( type == Type )
|
std::string output;
|
||||||
return;
|
for(char i : str) {
|
||||||
|
switch( i ) {
|
||||||
switch( Type ) {
|
case '\"': output += "\\\""; break;
|
||||||
case Class::Object: delete Internal.Map; break;
|
case '\\': output += "\\\\"; break;
|
||||||
case Class::Array: delete Internal.List; break;
|
case '\b': output += "\\b"; break;
|
||||||
case Class::String: delete Internal.String; break;
|
case '\f': output += "\\f"; break;
|
||||||
default:;
|
case '\n': output += "\\n"; break;
|
||||||
|
case '\r': output += "\\r"; break;
|
||||||
|
case '\t': output += "\\t"; break;
|
||||||
|
default : output += i; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( type ) {
|
|
||||||
case Class::Null: Internal.Map = nullptr; break;
|
|
||||||
case Class::Object: Internal.Map = new map<string,JSON>(); break;
|
|
||||||
case Class::Array: Internal.List = new deque<JSON>(); break;
|
|
||||||
case Class::String: Internal.String = new string(); break;
|
|
||||||
case Class::Floating: Internal.Float = 0.0; break;
|
|
||||||
case Class::Integral: Internal.Int = 0; break;
|
|
||||||
case Class::Boolean: Internal.Bool = false; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Class Type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline JSON Array() {
|
|
||||||
return JSON::Make( JSON::Class::Array );
|
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
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
static void consume_ws( const std::string &str, size_t &offset ) {
|
||||||
inline JSON Array( T... args ) {
|
while( isspace( str[offset] ) && offset <= str.size() ) { ++offset; }
|
||||||
JSON arr = JSON::Make( JSON::Class::Array );
|
|
||||||
arr.append( args... );
|
|
||||||
return arr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSON Object() {
|
static JSON parse_object( const std::string &str, size_t &offset ) {
|
||||||
return JSON::Make( JSON::Class::Object );
|
JSON Object( JSON::Class::Object );
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream& operator<<( std::ostream &os, const JSON &json ) {
|
|
||||||
os << json.dump();
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
JSON parse_next( const string &, size_t & );
|
|
||||||
|
|
||||||
void consume_ws( const string &str, size_t &offset ) {
|
|
||||||
while( isspace( str[offset] ) ) ++offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON parse_object( const string &str, size_t &offset ) {
|
|
||||||
JSON Object = JSON::Make( JSON::Class::Object );
|
|
||||||
|
|
||||||
++offset;
|
++offset;
|
||||||
consume_ws( str, offset );
|
consume_ws( str, offset );
|
||||||
@ -465,7 +483,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
consume_ws( str, ++offset );
|
consume_ws( str, ++offset );
|
||||||
JSON Value = parse_next( str, offset );
|
JSON Value = parse_next( str, offset );
|
||||||
Object[Key.ToString()] = Value;
|
Object[Key.to_string()] = Value;
|
||||||
|
|
||||||
consume_ws( str, offset );
|
consume_ws( str, offset );
|
||||||
if( str[offset] == ',' ) {
|
if( str[offset] == ',' ) {
|
||||||
@ -482,9 +500,9 @@ namespace {
|
|||||||
return Object;
|
return Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON parse_array( const string &str, size_t &offset ) {
|
static JSON parse_array( const std::string &str, size_t &offset ) {
|
||||||
JSON Array = JSON::Make( JSON::Class::Array );
|
JSON Array( JSON::Class::Array );
|
||||||
unsigned index = 0;
|
size_t index = 0;
|
||||||
|
|
||||||
++offset;
|
++offset;
|
||||||
consume_ws( str, offset );
|
consume_ws( str, offset );
|
||||||
@ -510,8 +528,8 @@ namespace {
|
|||||||
return Array;
|
return Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON parse_string( const string &str, size_t &offset ) {
|
static JSON parse_string( const std::string &str, size_t &offset ) {
|
||||||
string val;
|
std::string val;
|
||||||
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) {
|
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) {
|
||||||
if( c == '\\' ) {
|
if( c == '\\' ) {
|
||||||
switch( str[ ++offset ] ) {
|
switch( str[ ++offset ] ) {
|
||||||
@ -525,11 +543,11 @@ namespace {
|
|||||||
case 't' : val += '\t'; break;
|
case 't' : val += '\t'; break;
|
||||||
case 'u' : {
|
case 'u' : {
|
||||||
val += "\\u" ;
|
val += "\\u" ;
|
||||||
for( unsigned i = 1; i <= 4; ++i ) {
|
for( size_t i = 1; i <= 4; ++i ) {
|
||||||
c = str[offset+i];
|
c = str[offset+i];
|
||||||
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
|
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) {
|
||||||
val += c;
|
val += c;
|
||||||
else {
|
} else {
|
||||||
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -537,80 +555,87 @@ namespace {
|
|||||||
} break;
|
} break;
|
||||||
default : val += '\\'; break;
|
default : val += '\\'; break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
val += c;
|
val += c;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
++offset;
|
++offset;
|
||||||
return JSON(val);
|
return JSON(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON parse_number( const string &str, size_t &offset ) {
|
static JSON parse_number( const std::string &str, size_t &offset ) {
|
||||||
JSON Number;
|
std::string val, exp_str;
|
||||||
string val, exp_str;
|
|
||||||
char c = '\0';
|
char c = '\0';
|
||||||
bool isDouble = false;
|
bool isDouble = false;
|
||||||
|
bool isNegative = false;
|
||||||
long exp = 0;
|
long exp = 0;
|
||||||
|
if( offset < str.size() && str[offset] == '-' ) {
|
||||||
|
isNegative = true;
|
||||||
|
++offset;
|
||||||
|
}
|
||||||
for (; offset < str.size() ;) {
|
for (; offset < str.size() ;) {
|
||||||
c = str[offset++];
|
c = str[offset++];
|
||||||
if( (c == '-') || (c >= '0' && c <= '9') )
|
if( c >= '0' && c <= '9' ) {
|
||||||
val += c;
|
val += c;
|
||||||
else if( c == '.' ) {
|
} else if( c == '.' && !isDouble ) {
|
||||||
val += c;
|
val += c;
|
||||||
isDouble = true;
|
isDouble = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if( offset < str.size() && (c == 'E' || c == 'e' )) {
|
if( offset < str.size() && (c == 'E' || c == 'e' )) {
|
||||||
c = str[ offset++ ];
|
c = str[ offset++ ];
|
||||||
if( c == '-' ) { exp_str += '-';}
|
if( c == '-' ) {
|
||||||
else if( c == '+' ) { }
|
exp_str += '-';
|
||||||
else --offset;
|
} else if( c == '+' ) {
|
||||||
|
// do nothing
|
||||||
|
} else {
|
||||||
|
--offset;
|
||||||
|
}
|
||||||
|
|
||||||
for (; offset < str.size() ;) {
|
for (; offset < str.size() ;) {
|
||||||
c = str[ offset++ ];
|
c = str[ offset++ ];
|
||||||
if( c >= '0' && c <= '9' )
|
if( c >= '0' && c <= '9' ) {
|
||||||
exp_str += c;
|
exp_str += c;
|
||||||
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
} else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||||
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
|
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
exp = std::stol( exp_str );
|
}
|
||||||
|
exp = chaiscript::parse_num<long>( exp_str );
|
||||||
}
|
}
|
||||||
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
||||||
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
||||||
}
|
}
|
||||||
--offset;
|
--offset;
|
||||||
|
|
||||||
if( isDouble )
|
if( isDouble ) {
|
||||||
Number = std::stod( val ) * std::pow( 10, exp );
|
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||||
else {
|
} else {
|
||||||
if( !exp_str.empty() )
|
if( !exp_str.empty() ) {
|
||||||
Number = std::stol( val ) * std::pow( 10, exp );
|
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp ));
|
||||||
else
|
} else {
|
||||||
Number = std::stol( val );
|
return JSON((isNegative?-1:1) * chaiscript::parse_num<long>( val ));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON parse_bool( const string &str, size_t &offset ) {
|
static JSON parse_bool( const std::string &str, size_t &offset ) {
|
||||||
JSON Bool;
|
|
||||||
if( str.substr( offset, 4 ) == "true" ) {
|
if( str.substr( offset, 4 ) == "true" ) {
|
||||||
offset += 4;
|
offset += 4;
|
||||||
Bool = true;
|
return JSON(true);
|
||||||
} else if( str.substr( offset, 5 ) == "false" ) {
|
} else if( str.substr( offset, 5 ) == "false" ) {
|
||||||
offset += 5;
|
offset += 5;
|
||||||
Bool = false;
|
return JSON(false);
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'");
|
throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'");
|
||||||
}
|
}
|
||||||
return Bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON parse_null( const string &str, size_t &offset ) {
|
static JSON parse_null( const std::string &str, size_t &offset ) {
|
||||||
if( str.substr( offset, 4 ) != "null" ) {
|
if( str.substr( offset, 4 ) != "null" ) {
|
||||||
throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'");
|
throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'");
|
||||||
}
|
}
|
||||||
@ -618,7 +643,7 @@ namespace {
|
|||||||
return JSON();
|
return JSON();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON parse_next( const string &str, size_t &offset ) {
|
static JSON parse_next( const std::string &str, size_t &offset ) {
|
||||||
char value;
|
char value;
|
||||||
consume_ws( str, offset );
|
consume_ws( str, offset );
|
||||||
value = str[offset];
|
value = str[offset];
|
||||||
@ -629,16 +654,18 @@ namespace {
|
|||||||
case 't' :
|
case 't' :
|
||||||
case 'f' : return parse_bool( str, offset );
|
case 'f' : return parse_bool( str, offset );
|
||||||
case 'n' : return parse_null( str, offset );
|
case 'n' : return parse_null( str, offset );
|
||||||
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
|
default : if( ( value <= '9' && value >= '0' ) || value == '-' ) {
|
||||||
return parse_number( str, offset );
|
return parse_number( str, offset );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
|
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline JSON JSON::Load( const string &str ) {
|
};
|
||||||
|
|
||||||
|
inline JSON JSON::Load( const std::string &str ) {
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
return parse_next( str, offset );
|
return JSONParser::parse_next( str, offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End Namespace json
|
} // End Namespace json
|
||||||
|
@ -9,11 +9,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static ModulePtr library(ModulePtr m = std::make_shared<Module>())
|
static Module& library(Module& m)
|
||||||
{
|
{
|
||||||
|
|
||||||
m->add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
||||||
m->add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
std::map<std::string, Boxed_Value> m;
|
std::map<std::string, Boxed_Value> m;
|
||||||
|
|
||||||
for (const auto &p : t_json.ObjectRange())
|
for (const auto &p : t_json.object_range())
|
||||||
{
|
{
|
||||||
m.insert(std::make_pair(p.first, from_json(p.second)));
|
m.insert(std::make_pair(p.first, from_json(p.second)));
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
std::vector<Boxed_Value> vec;
|
std::vector<Boxed_Value> vec;
|
||||||
|
|
||||||
for (const auto &p : t_json.ArrayRange())
|
for (const auto &p : t_json.array_range())
|
||||||
{
|
{
|
||||||
vec.emplace_back(from_json(p));
|
vec.emplace_back(from_json(p));
|
||||||
}
|
}
|
||||||
@ -49,13 +49,13 @@ namespace chaiscript
|
|||||||
return Boxed_Value(vec);
|
return Boxed_Value(vec);
|
||||||
}
|
}
|
||||||
case json::JSON::Class::String:
|
case json::JSON::Class::String:
|
||||||
return Boxed_Value(t_json.ToString());
|
return Boxed_Value(t_json.to_string());
|
||||||
case json::JSON::Class::Floating:
|
case json::JSON::Class::Floating:
|
||||||
return Boxed_Value(t_json.ToFloat());
|
return Boxed_Value(t_json.to_float());
|
||||||
case json::JSON::Class::Integral:
|
case json::JSON::Class::Integral:
|
||||||
return Boxed_Value(t_json.ToInt());
|
return Boxed_Value(t_json.to_int());
|
||||||
case json::JSON::Class::Boolean:
|
case json::JSON::Class::Boolean:
|
||||||
return Boxed_Value(t_json.ToBool());
|
return Boxed_Value(t_json.to_bool());
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("Unknown JSON type");
|
throw std::runtime_error("Unknown JSON type");
|
||||||
@ -102,32 +102,24 @@ namespace chaiscript
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Boxed_Number bn(t_bv);
|
Boxed_Number bn(t_bv);
|
||||||
json::JSON obj;
|
|
||||||
if (Boxed_Number::is_floating_point(t_bv))
|
if (Boxed_Number::is_floating_point(t_bv))
|
||||||
{
|
{
|
||||||
obj = bn.get_as<double>();
|
return json::JSON(bn.get_as<double>());
|
||||||
} else {
|
} else {
|
||||||
obj = bn.get_as<long>();
|
return json::JSON(bn.get_as<long>());
|
||||||
}
|
}
|
||||||
return obj;
|
|
||||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
// not a number
|
// not a number
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bool b = boxed_cast<bool>(t_bv);
|
return json::JSON(boxed_cast<bool>(t_bv));
|
||||||
json::JSON obj;
|
|
||||||
obj = b;
|
|
||||||
return obj;
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
// not a bool
|
// not a bool
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string s = boxed_cast<std::string>(t_bv);
|
return json::JSON(boxed_cast<std::string>(t_bv));
|
||||||
json::JSON obj;
|
|
||||||
obj = s;
|
|
||||||
return obj;
|
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
// not a string
|
// not a string
|
||||||
}
|
}
|
||||||
|
37
include/chaiscript/utility/static_string.hpp
Normal file
37
include/chaiscript/utility/static_string.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||||
|
#define CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
namespace utility
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Static_String
|
||||||
|
{
|
||||||
|
template<size_t N>
|
||||||
|
constexpr Static_String(const char (&str)[N])
|
||||||
|
: m_size(N-1), data(&str[0])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t size() const {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char *c_str() const {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t m_size;
|
||||||
|
const char *data = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||||
|
|
||||||
@ -12,9 +16,8 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../chaiscript.hpp"
|
#include "../language/chaiscript_common.hpp"
|
||||||
#include "../dispatchkit/proxy_functions.hpp"
|
#include "../dispatchkit/register_function.hpp"
|
||||||
#include "../dispatchkit/type_info.hpp"
|
|
||||||
#include "../dispatchkit/operators.hpp"
|
#include "../dispatchkit/operators.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -69,27 +72,50 @@ namespace chaiscript
|
|||||||
typename std::enable_if<std::is_enum<Enum>::value, void>::type
|
typename std::enable_if<std::is_enum<Enum>::value, void>::type
|
||||||
add_class(ModuleType &t_module,
|
add_class(ModuleType &t_module,
|
||||||
const std::string &t_class_name,
|
const std::string &t_class_name,
|
||||||
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants)
|
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::user_type<Enum>(), t_class_name);
|
||||||
|
|
||||||
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
|
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
|
||||||
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
|
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
|
||||||
|
|
||||||
t_module.add([](){
|
|
||||||
// add some comparison and assignment operators
|
|
||||||
using namespace chaiscript::bootstrap::operators;
|
using namespace chaiscript::bootstrap::operators;
|
||||||
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
|
equal<Enum>(t_module);
|
||||||
}());
|
not_equal<Enum>(t_module);
|
||||||
|
assign<Enum>(t_module);
|
||||||
|
|
||||||
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
|
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
|
||||||
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
|
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
|
||||||
|
|
||||||
for (const auto &constant : t_constants)
|
for (const auto &constant : t_constants)
|
||||||
{
|
{
|
||||||
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
|
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename EnumClass, typename ModuleType>
|
||||||
|
typename std::enable_if<std::is_enum<EnumClass>::value, void>::type
|
||||||
|
add_class(ModuleType &t_module,
|
||||||
|
const std::string &t_class_name,
|
||||||
|
const std::vector<std::pair<EnumClass, std::string>> &t_constants
|
||||||
|
)
|
||||||
|
{
|
||||||
|
t_module.add(chaiscript::user_type<EnumClass>(), t_class_name);
|
||||||
|
|
||||||
|
t_module.add(chaiscript::constructor<EnumClass()>(), t_class_name);
|
||||||
|
t_module.add(chaiscript::constructor<EnumClass(const EnumClass &)>(), t_class_name);
|
||||||
|
|
||||||
|
using namespace chaiscript::bootstrap::operators;
|
||||||
|
equal<EnumClass>(t_module);
|
||||||
|
not_equal<EnumClass>(t_module);
|
||||||
|
assign<EnumClass>(t_module);
|
||||||
|
|
||||||
|
for (const auto &constant : t_constants)
|
||||||
|
{
|
||||||
|
t_module.add_global_const(chaiscript::const_var(EnumClass(constant.first)), constant.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright 2009-2015 Jason Turner
|
Copyright 2009-2016 Jason Turner
|
||||||
Copyright 2009-2012 Jonathan Turner.
|
Copyright 2009-2012 Jonathan Turner.
|
||||||
|
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
readme.md
43
readme.md
@ -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)
|
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)
|
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
|
http://www.chaiscript.com
|
||||||
|
|
||||||
(c) 2009-2012 Jonathan Turner
|
(c) 2009-2012 Jonathan Turner
|
||||||
(c) 2009-2015 Jason Turner
|
(c) 2009-2017 Jason Turner
|
||||||
|
|
||||||
Release under the BSD license, see "license.txt" for details.
|
Release under the BSD license, see "license.txt" for details.
|
||||||
|
|
||||||
@ -38,10 +43,9 @@ languages:
|
|||||||
Requirements
|
Requirements
|
||||||
============
|
============
|
||||||
|
|
||||||
ChaiScript requires a C++11 compiler to build with support for variadic
|
ChaiScript requires a C++14 compiler to build with support for variadic
|
||||||
templates. It has been tested with gcc 4.6 and clang 3.1 (with libcxx). MacOS
|
templates. It has been tested with gcc 4.9 and clang 3.6 (with libcxx).
|
||||||
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
|
For more information see the build
|
||||||
clang 4.0. MSVC 2013 or newer is supports also. For more information see the build
|
|
||||||
[dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html).
|
[dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html).
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
@ -75,7 +79,7 @@ directory, and for more in-depth look at the language, the unit tests in the
|
|||||||
"unittests" directory cover the most ground.
|
"unittests" directory cover the most ground.
|
||||||
|
|
||||||
For examples of how to register parts of your C++ application, see
|
For examples of how to register parts of your C++ application, see
|
||||||
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
|
"example.cpp" in the "samples" directory. Example.cpp is verbose and shows every
|
||||||
possible way of working with the library. For further documentation generate
|
possible way of working with the library. For further documentation generate
|
||||||
the doxygen documentation in the build folder or see the website
|
the doxygen documentation in the build folder or see the website
|
||||||
http://www.chaiscript.com.
|
http://www.chaiscript.com.
|
||||||
@ -83,6 +87,7 @@ http://www.chaiscript.com.
|
|||||||
|
|
||||||
The shortest complete example possible follows:
|
The shortest complete example possible follows:
|
||||||
|
|
||||||
|
```C++
|
||||||
/// main.cpp
|
/// main.cpp
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
@ -99,28 +104,4 @@ The shortest complete example possible follows:
|
|||||||
|
|
||||||
double d = chai.eval<double>("function(3, 4.75);");
|
double d = chai.eval<double>("function(3, 4.75);");
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Or, if you want to compile the std lib into your code, which reduces
|
|
||||||
runtime requirements.
|
|
||||||
|
|
||||||
/// main.cpp
|
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
|
||||||
|
|
||||||
double function(int i, double j)
|
|
||||||
{
|
|
||||||
return i * j;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
|
||||||
chai.add(chaiscript::fun(&function), "function");
|
|
||||||
|
|
||||||
double d = chai.eval<double>("function(3, 4.75);");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,99 @@
|
|||||||
Notes:
|
Notes:
|
||||||
=======
|
=======
|
||||||
Current Version: 5.7.1
|
Current Version: 6.0.0
|
||||||
|
|
||||||
|
### Changes since 5.8.6
|
||||||
|
|
||||||
|
*6.0.0 is a massive rework compared to 5.x. It now requires a C++14 enabled compiler*
|
||||||
|
|
||||||
|
#### Compiler Requirements
|
||||||
|
|
||||||
|
* MSVC 2015 or greater
|
||||||
|
* g++ 4.9 or greater
|
||||||
|
* clang 3.6 or greater
|
||||||
|
|
||||||
|
#### Breaking Changes
|
||||||
|
|
||||||
|
* Instantiating a ChaiScript object now, by default, builds the stdlib in
|
||||||
|
* This was done to address the most common support issues of loading stdlib dynamically at runtime
|
||||||
|
* If you want the old behavior, use include/chaiscript/chaiscript_basic.hpp
|
||||||
|
* Headers have been reorganized to fully separate stdlib/parser/engine from each other (some faster builds)
|
||||||
|
* Bootstrap functions no longer return a reference to the module added to (compile time savings)
|
||||||
|
* It's now no longer possible modify AST_Nodes (compile time, runtime efficiency)
|
||||||
|
* Function annotations no longer exist (simplifies code, reduces compile time, compile size)
|
||||||
|
|
||||||
|
#### New Features Added
|
||||||
|
|
||||||
|
* Modular optimization system; this can be accessed via the ChaiScript_Basic interface
|
||||||
|
* Execution tracing capability; also accessed via ChaiScript_Basic interface
|
||||||
|
* range-based for loops `for( id : container ) { }` (much better performance than other loop types)
|
||||||
|
* If-init expressions (ala C++17)
|
||||||
|
* Support for passing r-value references to functions
|
||||||
|
* Support for containing unique_ptr
|
||||||
|
* Add helpers for exposing enum classes to ChaiScript
|
||||||
|
* Allow typed ChaiScript defined functions to perform conversions on call #303
|
||||||
|
|
||||||
|
#### Improvements
|
||||||
|
|
||||||
|
* Compile time improvements
|
||||||
|
* Compile size improvements
|
||||||
|
* Significant runtime improvements (see "Modular optimization system")
|
||||||
|
* Significant parser improvements, both with parse-time and parser initialization time (Thanks @niXman)
|
||||||
|
* Fix type conversion to bool in conditionals
|
||||||
|
|
||||||
|
#### Improvements Still Need To Be Made
|
||||||
|
|
||||||
|
* File location tracking has been rewritten; this currently means error location reporting is not as good as it was
|
||||||
|
* Tracing capability needs to be tested and vetted
|
||||||
|
|
||||||
|
### Changes since 5.8.5
|
||||||
|
* Optimize away `return` statements in lambdas also
|
||||||
|
* Allow conversions to bool in conditionals
|
||||||
|
* Don't allow `class` statements inside of scopes
|
||||||
|
* Properly error when a dynamic object non-function member is called
|
||||||
|
|
||||||
|
### Changes since 5.8.4
|
||||||
|
* Fix order of operations for prefix operators
|
||||||
|
* Make sure atomics are initialized properly
|
||||||
|
* Remove parsing of unused prefix `&` operator
|
||||||
|
|
||||||
|
### Changes since 5.8.3
|
||||||
|
* Fix case with some numeric conversions mixed with numerics that do not need conversion
|
||||||
|
|
||||||
|
### Changes since 5.8.2
|
||||||
|
* Add support for reference of pointer return types
|
||||||
|
|
||||||
|
### Changes since 5.8.1
|
||||||
|
* Allow casting to non-const & std::shared_ptr<T>
|
||||||
|
|
||||||
|
|
||||||
|
### Changes since 5.8.0
|
||||||
|
* Fix parsing of floats to be locale independent #250
|
||||||
|
* Various warning fixes on various platforms
|
||||||
|
|
||||||
|
|
||||||
|
### Changes since 5.7.1
|
||||||
|
* Make all parser iterator operations range checked
|
||||||
|
* Parse in-string eval statements once, not once for each execution
|
||||||
|
* Fix parsing of operators (ie 1<-1 now parses)
|
||||||
|
* Fix variable scoping for functors
|
||||||
|
* Exception reduction
|
||||||
|
* Various object lifetime fixes
|
||||||
|
* Add JSON support for load / save #207
|
||||||
|
* Numeric overload resolution fixes #209
|
||||||
|
* Fix long long #208
|
||||||
|
* Add octal escapes in strings #211
|
||||||
|
* Fixed sizing of binary literals #213
|
||||||
|
* Added support for != with bool values #217
|
||||||
|
* Various value assignment vector fixes
|
||||||
|
* Fixed broken hex escape sequences from @ChristianKaeser
|
||||||
|
* Multiply defined symbols fixes #232 @RaptorFactor
|
||||||
|
* Add add_class<Enum> helper #233 @vrennert
|
||||||
|
* Cheatsheet fixes #235 @mlamby
|
||||||
|
* Fix parsing of strings inside of in-string eval statements
|
||||||
|
* Allow lower-case global keyword
|
||||||
|
* Enable thread-local on MSVC (should be significant performance boost)
|
||||||
|
|
||||||
|
|
||||||
### Changes since 5.7.0
|
### Changes since 5.7.0
|
||||||
* Build time reduction
|
* Build time reduction
|
||||||
|
@ -73,7 +73,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
|
|
||||||
//Create a new system object and share it with the chaiscript engine
|
//Create a new system object and share it with the chaiscript engine
|
||||||
System system;
|
System system;
|
||||||
chai.add(var(&system), "system");
|
chai.add_global(var(&system), "system");
|
||||||
|
|
||||||
//Add a bound callback method
|
//Add a bound callback method
|
||||||
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
|
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
|
||||||
@ -108,9 +108,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
// A shortcut to using eval is just to use the chai operator()
|
// A shortcut to using eval is just to use the chai operator()
|
||||||
chai("log(\"Test Module\", \"Test Message\");");
|
chai("log(\"Test Module\", \"Test Message\");");
|
||||||
|
|
||||||
//Finally, it is possible to register any std::function as a system function, in this
|
//Finally, it is possible to register a lambda as a system function, in this
|
||||||
//way, we can, for instance add a bound member function to the system
|
//way, we can, for instance add a bound member function to the system
|
||||||
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
|
chai.add(fun([&system](){ return system.do_callbacks("Bound Test"); }), "do_callbacks");
|
||||||
|
|
||||||
//Call bound version of do_callbacks
|
//Call bound version of do_callbacks
|
||||||
chai("do_callbacks()");
|
chai("do_callbacks()");
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
|
||||||
|
|
||||||
class Entity
|
class Entity
|
||||||
{
|
{
|
||||||
@ -57,7 +56,7 @@ class Factory
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&Entity::width), "width");
|
chai.add(chaiscript::fun(&Entity::width), "width");
|
||||||
chai.add(chaiscript::fun(&Entity::height), "height");
|
chai.add(chaiscript::fun(&Entity::height), "height");
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@ -13,7 +17,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
@ -65,6 +68,7 @@ std::vector<std::string> default_search_paths()
|
|||||||
{
|
{
|
||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||||
CHAR path[4096];
|
CHAR path[4096];
|
||||||
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
||||||
@ -89,24 +93,24 @@ std::vector<std::string> default_search_paths()
|
|||||||
std::vector<char> buf(2048);
|
std::vector<char> buf(2048);
|
||||||
ssize_t size = -1;
|
ssize_t size = -1;
|
||||||
|
|
||||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) > 0)
|
||||||
{
|
{
|
||||||
exepath = std::string(&buf.front(), size);
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty())
|
||||||
{
|
{
|
||||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) > 0)
|
||||||
{
|
{
|
||||||
exepath = std::string(&buf.front(), size);
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exepath.empty())
|
if (exepath.empty())
|
||||||
{
|
{
|
||||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) > 0)
|
||||||
{
|
{
|
||||||
exepath = std::string(&buf.front(), size);
|
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +138,7 @@ std::vector<std::string> default_search_paths()
|
|||||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
|
||||||
|
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
@ -291,7 +296,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths);
|
chaiscript::ChaiScript chai(usepaths);
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&myexit), "exit");
|
chai.add(chaiscript::fun(&myexit), "exit");
|
||||||
chai.add(chaiscript::fun(&myexit), "quit");
|
chai.add(chaiscript::fun(&myexit), "quit");
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
|
||||||
|
|
||||||
class BaseClass
|
class BaseClass
|
||||||
{
|
{
|
||||||
@ -44,14 +43,14 @@ class ChaiScriptDerived : public BaseClass
|
|||||||
tie(t_funcs.at(1), m_validateValueImpl);
|
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);
|
assert(m_doSomethingImpl);
|
||||||
return m_doSomethingImpl(*this, f, d);
|
return m_doSomethingImpl(*this, f, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
|
bool validateValue(const std::string &t_val) override
|
||||||
{
|
{
|
||||||
assert(m_validateValueImpl);
|
assert(m_validateValueImpl);
|
||||||
return m_validateValueImpl(*this, t_val);
|
return m_validateValueImpl(*this, t_val);
|
||||||
@ -70,7 +69,7 @@ class ChaiScriptDerived : public BaseClass
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
chaiscript::ChaiScript chai;
|
||||||
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
||||||
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
||||||
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
|
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
@ -32,16 +31,9 @@ void function(void)
|
|||||||
class test
|
class test
|
||||||
{
|
{
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
chaiscript::ChaiScript::State backupState;
|
chaiscript::ChaiScript::State backupState = chai.get_state();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
test()
|
|
||||||
: chai(chaiscript::Std_Lib::library())
|
|
||||||
{
|
|
||||||
backupState = chai.get_state();
|
|
||||||
}
|
|
||||||
~test(){}
|
|
||||||
|
|
||||||
void ResetState()
|
void ResetState()
|
||||||
{
|
{
|
||||||
chai.set_state(backupState);
|
chai.set_state(backupState);
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
|
||||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||||
|
|
||||||
int main( int /*argc*/ , char * /*argv*/[] )
|
int main( int /*argc*/ , char * /*argv*/[] )
|
||||||
{
|
{
|
||||||
chaiscript::ChaiScript ch( chaiscript::Std_Lib::library( ) );
|
chaiscript::ChaiScript ch;
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
static const char script[ ] =
|
static const char script[ ] =
|
||||||
R""(
|
R""(
|
||||||
|
|
||||||
@ -19,8 +21,7 @@ int main( int /*argc*/ , char * /*argv*/[] )
|
|||||||
|
|
||||||
)"";
|
)"";
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ch.eval( script );
|
ch.eval( script );
|
||||||
}
|
}
|
||||||
catch ( const std::exception &e )
|
catch ( const std::exception &e )
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user