mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-06 08:46:53 +08:00
Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop
This commit is contained in:
commit
a9fc1d492e
0
.buckconfig
Normal file
0
.buckconfig
Normal file
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/buck-out/
|
||||
/.buckd/
|
||||
/buckaroo/
|
||||
.buckconfig.local
|
||||
BUCKAROO_DEPS
|
||||
84
.travis.yml
84
.travis.yml
@ -1,33 +1,67 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
env:
|
||||
matrix:
|
||||
- GCC_VER="4.9"
|
||||
- GCC_VER="5"
|
||||
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
- g++-5
|
||||
- g++-6
|
||||
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 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
|
||||
compiler: gcc
|
||||
- os: linux
|
||||
sudo: false
|
||||
env: GCC_VER="6" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode8
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode8
|
||||
env: CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
- secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM="
|
||||
|
||||
before_install:
|
||||
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
|
||||
- if [ "$GCC_VER" = "5" ]; then export COVERAGE=1 CPPCHECK=1; fi
|
||||
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
|
||||
- sudo pip install cpp-coveralls
|
||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -qq g++-$GCC_VER
|
||||
- if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi
|
||||
- pip install --user cpp-coveralls
|
||||
|
||||
script:
|
||||
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi
|
||||
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi
|
||||
- make test
|
||||
- if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
|
||||
- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $CMAKE_OPTIONS .
|
||||
- cmake --build . -- -j2
|
||||
- if [ "${BUILD_ONLY}" != "1" ]; then ctest; fi
|
||||
- if [ "${COVERAGE}" = "1" ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
|
||||
|
||||
after_script:
|
||||
- if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
|
||||
#after_script:
|
||||
# - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi
|
||||
|
||||
|
||||
notifications:
|
||||
@ -42,15 +76,3 @@ notifications:
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
on_failure: always # options: [always|never|change] default: always
|
||||
on_start: false # default: false
|
||||
|
||||
addons:
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "ChaiScript/ChaiScript"
|
||||
description: "Build submitted via Travis CI"
|
||||
notification_email: jason@emptycrate.com
|
||||
build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . "
|
||||
build_command: "cmake --build . -- -j2"
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
|
||||
|
||||
11
BUCK
Normal file
11
BUCK
Normal file
@ -0,0 +1,11 @@
|
||||
prebuilt_cxx_library(
|
||||
name = 'chaiscript',
|
||||
header_only = True,
|
||||
header_namespace = 'chaiscript',
|
||||
exported_headers = subdir_glob([
|
||||
('include/chaiscript', '**/*.hpp'),
|
||||
]),
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
||||
@ -14,6 +14,7 @@ ELSE()
|
||||
project(chaiscript)
|
||||
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||
option(DYNLOAD_ENABLED "Dynamic Loading Support Enabled" TRUE)
|
||||
|
||||
|
||||
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
||||
@ -21,6 +22,7 @@ option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
|
||||
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
||||
option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE)
|
||||
option(BUILD_IN_CPP17_MODE "Build with C++17 flags" FALSE)
|
||||
|
||||
mark_as_advanced(USE_STD_MAKE_SHARED)
|
||||
|
||||
@ -149,12 +151,20 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
|
||||
if(GCC_VERSION VERSION_LESS 4.9)
|
||||
set(CPP11_FLAG "-std=c++1y")
|
||||
set(CPP14_FLAG "-std=c++1y")
|
||||
else()
|
||||
set(CPP11_FLAG "-std=c++14")
|
||||
if (BUILD_IN_CPP17_MODE)
|
||||
set(CPP14_FLAG "-std=c++1z")
|
||||
else()
|
||||
set(CPP14_FLAG "-std=c++14")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(CPP11_FLAG "-std=c++14")
|
||||
if (BUILD_IN_CPP17_MODE)
|
||||
set(CPP14_FLAG "-std=c++1z")
|
||||
else()
|
||||
set(CPP14_FLAG "-std=c++14")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
@ -178,7 +188,7 @@ if(MSVC)
|
||||
# how to workaround or fix the error. So I'm disabling it globally.
|
||||
add_definitions(/wd4503)
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wconversion -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 ${CPP14_FLAG})
|
||||
|
||||
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-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command)
|
||||
@ -196,12 +206,12 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
|
||||
if(USE_LIBCXX)
|
||||
add_definitions(-stdlib=libc++)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG} -stdlib=libc++")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG} -stdlib=libc++")
|
||||
else()
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG}")
|
||||
endif()
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG}")
|
||||
endif()
|
||||
|
||||
# limitations in MinGW require us to make an optimized build
|
||||
@ -221,9 +231,15 @@ if(NOT MULTITHREAD_SUPPORT_ENABLED)
|
||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||
endif()
|
||||
|
||||
if(NOT DYNLOAD_ENABLED)
|
||||
add_definitions(-DCHAISCRIPT_NO_DYNLOAD)
|
||||
endif()
|
||||
|
||||
if(CMAKE_HOST_UNIX)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
list(APPEND LIBS "dl")
|
||||
if(DYNLOAD_ENABLED)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||
list(APPEND LIBS "dl")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MULTITHREAD_SUPPORT_ENABLED)
|
||||
@ -298,32 +314,17 @@ if (RUN_FUZZY_TESTS)
|
||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2017-07-20.tar.bz2
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
|
||||
)
|
||||
|
||||
|
||||
file(GLOB FUZZY_CRASH_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/id*)
|
||||
list(SORT FUZZY_CRASH_TESTS)
|
||||
file(GLOB FUZZY_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/MINIMIZED/*)
|
||||
list(SORT FUZZY_TESTS)
|
||||
|
||||
file(GLOB FUZZY_EXCEPTION_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/id*)
|
||||
list(SORT FUZZY_EXCEPTION_TESTS)
|
||||
|
||||
|
||||
foreach(filename ${FUZZY_CRASH_TESTS})
|
||||
foreach(filename ${FUZZY_TESTS})
|
||||
message(STATUS "Adding test ${filename}")
|
||||
add_test(${filename} chai "-e" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
|
||||
endforeach()
|
||||
|
||||
set_property(TEST ${FUZZY_CRASH_TESTS}
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_BINARY_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
|
||||
foreach(filename ${FUZZY_EXCEPTION_TESTS})
|
||||
message(STATUS "Adding test ${filename}")
|
||||
add_test(${filename} chai "--exception" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
|
||||
add_test(fuzz.${filename} chai "-e" "--exception" "--any-exception" ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzz_unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
|
||||
endforeach()
|
||||
|
||||
set_property(TEST ${FUZZY_EXCEPTION_TESTS}
|
||||
@ -427,6 +428,9 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS})
|
||||
ADD_CATCH_TESTS(compiled_tests)
|
||||
|
||||
add_executable(static_chaiscript_test unittests/static_chaiscript.cpp)
|
||||
target_link_libraries(static_chaiscript_test ${LIBS})
|
||||
add_test(NAME Static_ChaiScript_Test COMMAND static_chaiscript_test)
|
||||
|
||||
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
|
||||
target_link_libraries(boxed_cast_test ${LIBS})
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
version: 5.8.x.{build}
|
||||
os: Visual Studio 2015
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
environment:
|
||||
matrix:
|
||||
- {}
|
||||
- VS_VERSION: "Visual Studio 14"
|
||||
- VS_VERSION: "Visual Studio 15"
|
||||
build_script:
|
||||
- cmd: >-
|
||||
mkdir build
|
||||
|
||||
cd build
|
||||
|
||||
cmake c:\Projects\chaiscript -G "Visual Studio 14"
|
||||
cmake c:\Projects\chaiscript -G "%VS_VERSION%"
|
||||
|
||||
cmake --build . --config Debug
|
||||
test_script:
|
||||
|
||||
3
buckaroo.json
Normal file
3
buckaroo.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "ChaiScript"
|
||||
}
|
||||
@ -15,6 +15,9 @@ chaiscript::ChaiScript chai; // loads stdlib from loadable module on file system
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdlib
|
||||
```
|
||||
|
||||
Note that ChaiScript cannot be used as a global / static object unless it is being compiled with `CHAISCRIPT_NO_THREADS`.
|
||||
|
||||
|
||||
# Adding Things To The Engine
|
||||
|
||||
## Adding a Function / Method / Member
|
||||
@ -91,6 +94,49 @@ chai.add(chaiscript::user_type<MyClass>(), "MyClass");
|
||||
|
||||
User defined type conversions are possible, defined in either script or in C++.
|
||||
|
||||
|
||||
|
||||
### ChaiScript Defined Conversions
|
||||
|
||||
Function objects (including lambdas) can be used to add type conversions
|
||||
from inside of ChaiScript:
|
||||
|
||||
```
|
||||
add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); });
|
||||
```
|
||||
|
||||
### C++ Defined Conversions
|
||||
|
||||
Invoking a C++ type conversion possible with `static_cast`
|
||||
|
||||
```
|
||||
chai.add(chaiscript::type_conversion<T, bool>());
|
||||
```
|
||||
|
||||
Calling a user defined type conversion that takes a lambda
|
||||
|
||||
```
|
||||
chai.add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { /* return converted thing */ }));
|
||||
```
|
||||
|
||||
### Class Hierarchies
|
||||
|
||||
If you want objects to be convertable between base and derived classes, you must tell ChaiScritp about the relationship.
|
||||
|
||||
```
|
||||
chai.add(chaiscript::base_class<Base, Derived>());
|
||||
```
|
||||
|
||||
If you have multiple classes in your inheritance graph, you will probably want to tell ChaiScript about all relationships.
|
||||
|
||||
```
|
||||
chai.add(chaiscript::base_class<Base, Derived>());
|
||||
chai.add(chaiscript::base_class<Derived, MoreDerived>());
|
||||
chai.add(chaiscript::base_class<Base, MoreDerived>());
|
||||
```
|
||||
|
||||
### Helpers
|
||||
|
||||
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
|
||||
|
||||
```
|
||||
@ -104,6 +150,7 @@ chai.add(chaiscript::map_conversion<std::map<std::string, int>>());
|
||||
```
|
||||
|
||||
|
||||
|
||||
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
|
||||
|
||||
## Adding Objects
|
||||
@ -211,7 +258,7 @@ Conversion to `std::shared_ptr<T> &` is supported for function calls, but if you
|
||||
```cpp
|
||||
// ok this is supported, you can register it with chaiscript engine
|
||||
void nullify_shared_ptr(std::shared_ptr<int> &t) {
|
||||
t == nullptr
|
||||
t = nullptr
|
||||
}
|
||||
```
|
||||
|
||||
@ -318,6 +365,15 @@ while (some_condition()) { /* do something */ }
|
||||
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
|
||||
|
||||
```
|
||||
@ -502,9 +558,33 @@ the contained function.
|
||||
|
||||
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
|
||||
|
||||
## Context
|
||||
|
||||
* `__LINE__` Current file line number
|
||||
* `__FILE__` Full path of current file
|
||||
* `__CLASS__` Name of current class
|
||||
* `__FUNC__` Mame of current function
|
||||
|
||||
|
||||
# Built In Functions
|
||||
|
||||
## Disabling Built-Ins
|
||||
|
||||
When constructing a ChaiScript object, a vector of parameters can be passed in to disable or enable various built-in methods.
|
||||
|
||||
Current options:
|
||||
|
||||
```
|
||||
enum class Options
|
||||
{
|
||||
Load_Modules,
|
||||
No_Load_Modules,
|
||||
External_Scripts,
|
||||
No_External_Scripts
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
## Evaluation
|
||||
|
||||
```
|
||||
@ -516,4 +596,7 @@ use("filename") // evals file exactly once and returns value of last statement
|
||||
|
||||
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor
|
||||
|
||||
## JSON
|
||||
|
||||
* `from_json` converts a JSON string into its strongly typed (map, vector, int, double, string) representations
|
||||
* `to_json` converts a ChaiScript object (either a `Object` or one of map, vector, int, double, string) tree into its JSON string representation
|
||||
|
||||
@ -4,7 +4,7 @@ pushd ..
|
||||
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
|
||||
tar -xvf cppcheck-1.66.tar.bz2
|
||||
cd cppcheck-1.66
|
||||
CXX=g++-4.8 make -j2
|
||||
make -j2
|
||||
popd
|
||||
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
|
||||
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
|
||||
|
||||
@ -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.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_HPP_
|
||||
#define CHAISCRIPT_HPP_
|
||||
|
||||
@ -65,7 +69,7 @@
|
||||
/// int main()
|
||||
/// {
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(&function, "function");
|
||||
/// chai.add(chaiscript::fun(&function), "function");
|
||||
///
|
||||
/// double d = chai.eval<double>("function(3, 4.75);");
|
||||
/// }
|
||||
@ -827,11 +831,12 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
||||
std::vector<std::string> t_usepaths = {})
|
||||
std::vector<std::string> t_usepaths = {},
|
||||
const std::vector<Options> &t_opts = chaiscript::default_options())
|
||||
: ChaiScript_Basic(
|
||||
chaiscript::Std_Lib::library(),
|
||||
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
||||
t_modulepaths, t_usepaths)
|
||||
t_modulepaths, t_usepaths, t_opts)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BASIC_HPP_
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||
@ -9,9 +9,13 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CHAISCRIPT_STRINGIZE(x) "" #x
|
||||
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
|
||||
#define CHAISCRIPT_STRINGIZE_EXPANDED(x) CHAISCRIPT_STRINGIZE(x)
|
||||
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE_EXPANDED(_MSC_FULL_VER)
|
||||
#define CHAISCRIPT_MSVC _MSC_VER
|
||||
#define CHAISCRIPT_HAS_DECLSPEC
|
||||
|
||||
static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later required");
|
||||
|
||||
#else
|
||||
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
|
||||
#endif
|
||||
@ -44,10 +48,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
||||
/// \todo Make this support other compilers when possible
|
||||
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
#if defined(__llvm__)
|
||||
#define CHAISCRIPT_CLANG
|
||||
@ -93,6 +93,16 @@ namespace chaiscript {
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename B, typename D, typename ...Arg>
|
||||
inline std::unique_ptr<B> make_unique(Arg && ... arg)
|
||||
{
|
||||
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||
return std::make_unique<D>(std::forward<Arg>(arg)...);
|
||||
#else
|
||||
return std::unique_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Build_Info {
|
||||
static int version_major()
|
||||
{
|
||||
@ -145,7 +155,7 @@ namespace chaiscript {
|
||||
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||
{
|
||||
T t = 0;
|
||||
for (char c = *t_str; (c = *t_str); ++t_str) {
|
||||
for (char c = *t_str; (c = *t_str) != 0; ++t_str) {
|
||||
if (c < '0' || c > '9') {
|
||||
return t;
|
||||
}
|
||||
@ -206,6 +216,22 @@ namespace chaiscript {
|
||||
return parse_num<T>(t_str.c_str());
|
||||
}
|
||||
|
||||
enum class Options
|
||||
{
|
||||
No_Load_Modules,
|
||||
Load_Modules,
|
||||
No_External_Scripts,
|
||||
External_Scripts
|
||||
};
|
||||
|
||||
static inline std::vector<Options> default_options()
|
||||
{
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
return {Options::No_Load_Modules, Options::External_Scripts};
|
||||
#else
|
||||
return {Options::Load_Modules, Options::External_Scripts};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||
#define CHAISCRIPT_THREADING_HPP_
|
||||
|
||||
@ -57,118 +61,54 @@ namespace chaiscript
|
||||
|
||||
using std::recursive_mutex;
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
|
||||
explicit Thread_Storage(void *t_key)
|
||||
: m_key(t_key)
|
||||
{
|
||||
}
|
||||
Thread_Storage() = default;
|
||||
Thread_Storage(const Thread_Storage &) = delete;
|
||||
Thread_Storage(Thread_Storage &&) = delete;
|
||||
Thread_Storage &operator=(const Thread_Storage &) = delete;
|
||||
Thread_Storage &operator=(Thread_Storage &&) = delete;
|
||||
|
||||
~Thread_Storage()
|
||||
{
|
||||
t().erase(m_key);
|
||||
t().erase(this);
|
||||
}
|
||||
|
||||
inline const T *operator->() const
|
||||
{
|
||||
return &(t()[m_key]);
|
||||
return &(t()[this]);
|
||||
}
|
||||
|
||||
inline const T &operator*() const
|
||||
{
|
||||
return t()[m_key];
|
||||
return t()[this];
|
||||
}
|
||||
|
||||
inline T *operator->()
|
||||
{
|
||||
return &(t()[m_key]);
|
||||
return &(t()[this]);
|
||||
}
|
||||
|
||||
inline T &operator*()
|
||||
{
|
||||
return t()[m_key];
|
||||
return t()[this];
|
||||
}
|
||||
|
||||
|
||||
void *m_key;
|
||||
|
||||
private:
|
||||
static std::unordered_map<void*, T> &t()
|
||||
static std::unordered_map<const void*, T> &t()
|
||||
{
|
||||
thread_local static std::unordered_map<void *, T> my_t;
|
||||
thread_local std::unordered_map<const void *, T> my_t;
|
||||
return my_t;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#pragma message ("Threading without thread_local support is not well supported.")
|
||||
|
||||
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
///
|
||||
/// This version is used if the compiler does not support thread_local
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
|
||||
explicit Thread_Storage(void *)
|
||||
{
|
||||
}
|
||||
|
||||
inline const T *operator->() const
|
||||
{
|
||||
return get_tls().get();
|
||||
}
|
||||
|
||||
inline const T &operator*() const
|
||||
{
|
||||
return *get_tls();
|
||||
}
|
||||
|
||||
inline T *operator->()
|
||||
{
|
||||
return get_tls().get();
|
||||
}
|
||||
|
||||
inline T &operator*()
|
||||
{
|
||||
return *get_tls();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/// \todo this leaks thread instances. It needs to be culled from time to time
|
||||
std::shared_ptr<T> get_tls() const
|
||||
{
|
||||
unique_lock<mutex> lock(m_mutex);
|
||||
|
||||
const auto id = std::this_thread::get_id();
|
||||
auto itr = m_instances.find(id);
|
||||
|
||||
if (itr != m_instances.end()) { return itr->second; }
|
||||
|
||||
std::shared_ptr<T> new_instance(std::make_shared<T>());
|
||||
|
||||
m_instances.insert(std::make_pair(id, new_instance));
|
||||
|
||||
return new_instance;
|
||||
}
|
||||
|
||||
|
||||
mutable mutex m_mutex;
|
||||
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
|
||||
};
|
||||
#endif // threading enabled but no tls
|
||||
|
||||
#else // threading disabled
|
||||
template<typename T>
|
||||
class unique_lock
|
||||
@ -204,7 +144,7 @@ namespace chaiscript
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
explicit Thread_Storage(void *)
|
||||
explicit Thread_Storage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ namespace chaiscript {
|
||||
{
|
||||
}
|
||||
|
||||
virtual void *data() override
|
||||
void *data() override
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
|
||||
@ -31,12 +35,12 @@ namespace chaiscript
|
||||
public:
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
std::string t_what) noexcept
|
||||
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
|
||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
|
||||
{
|
||||
}
|
||||
|
||||
@ -46,10 +50,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bad_boxed_cast(const bad_boxed_cast &) = default;
|
||||
virtual ~bad_boxed_cast() noexcept = default;
|
||||
~bad_boxed_cast() noexcept override = default;
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const noexcept override
|
||||
const char * what() const noexcept override
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||
#define CHAISCRIPT_BIND_FIRST_HPP_
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
|
||||
@ -301,13 +305,13 @@ namespace chaiscript
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return pf && pf->get_parse_tree();
|
||||
return bool(pf);
|
||||
}
|
||||
|
||||
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf && pf->get_parse_tree())
|
||||
if (pf)
|
||||
{
|
||||
return pf->get_parse_tree();
|
||||
} else {
|
||||
@ -541,7 +545,7 @@ namespace chaiscript
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
|
||||
&chaiscript::var<const chaiscript::AST_Node_Trace &>);
|
||||
return retval;
|
||||
}), "call_stack"} }
|
||||
);
|
||||
@ -570,7 +574,7 @@ namespace chaiscript
|
||||
const auto children = t_node.get_children();
|
||||
std::transform(children.begin(), children.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
|
||||
&chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
|
||||
return retval;
|
||||
}), "children"}
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
/// \file
|
||||
/// This file contains utility functions for registration of STL container
|
||||
/// classes. The methodology used is based on the SGI STL concepts.
|
||||
@ -37,7 +41,7 @@ namespace chaiscript
|
||||
/// Bidir_Range, based on the D concept of ranges.
|
||||
/// \todo Update the Range code to base its capabilities on
|
||||
/// the user_typetraits of the iterator passed in
|
||||
template<typename Container>
|
||||
template<typename Container, typename IterType>
|
||||
struct Bidir_Range
|
||||
{
|
||||
typedef Container container_type;
|
||||
@ -79,64 +83,6 @@ namespace chaiscript
|
||||
return (*m_begin);
|
||||
}
|
||||
|
||||
decltype(auto) back() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
typename Container::iterator pos = m_end;
|
||||
--pos;
|
||||
return (*(pos));
|
||||
}
|
||||
|
||||
typename Container::iterator m_begin;
|
||||
typename Container::iterator m_end;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct Const_Bidir_Range
|
||||
{
|
||||
typedef const Container container_type;
|
||||
typedef typename std::iterator_traits<typename Container::const_iterator>::reference const_reference_type;
|
||||
|
||||
Const_Bidir_Range(const Container &c)
|
||||
: m_begin(c.begin()), m_end(c.end())
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_begin == m_end;
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
++m_begin;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
--m_end;
|
||||
}
|
||||
|
||||
decltype(auto) front() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
throw std::range_error("Range empty");
|
||||
}
|
||||
return (*m_begin);
|
||||
}
|
||||
|
||||
decltype(auto) back() const
|
||||
{
|
||||
if (empty())
|
||||
@ -148,8 +94,8 @@ namespace chaiscript
|
||||
return (*(pos));
|
||||
}
|
||||
|
||||
typename Container::const_iterator m_begin;
|
||||
typename Container::const_iterator m_end;
|
||||
IterType m_begin;
|
||||
IterType m_end;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -229,8 +175,8 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
void input_range_type(const std::string &type, Module& m)
|
||||
{
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
|
||||
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType, typename ContainerType::iterator> >(type,m);
|
||||
detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator> >("Const_" + type,m);
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr input_range_type(const std::string &type)
|
||||
@ -389,9 +335,24 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
void back_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
m.add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.back());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "back");
|
||||
m.add(fun([](const ContainerType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.back());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "back");
|
||||
|
||||
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
@ -434,13 +395,29 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
void front_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
||||
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*pop_ptr)();
|
||||
|
||||
m.add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
|
||||
m.add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
|
||||
m.add(fun([](const ContainerType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
|
||||
|
||||
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
[&]()->std::string{
|
||||
@ -631,11 +608,27 @@ namespace chaiscript
|
||||
{
|
||||
m.add(user_type<VectorType>(), type);
|
||||
|
||||
typedef typename VectorType::reference (VectorType::*frontptr)();
|
||||
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
|
||||
m.add(fun([](VectorType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
|
||||
m.add(fun([](const VectorType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
throw std::range_error("Container empty");
|
||||
} else {
|
||||
return (container.front());
|
||||
}
|
||||
}
|
||||
)
|
||||
, "front");
|
||||
|
||||
|
||||
m.add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||
m.add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||
|
||||
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
|
||||
@ -25,7 +29,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
T* throw_if_null(T *t)
|
||||
{
|
||||
if (t) return t;
|
||||
if (t) { return t; }
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
}
|
||||
|
||||
@ -135,6 +139,50 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a && type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &&>
|
||||
{
|
||||
static Result&& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
|
||||
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
|
||||
{
|
||||
static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
||||
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::unique_ptr<Result> &>
|
||||
{
|
||||
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
|
||||
/// \todo Fix the fact that this has to be in a shared_ptr for now
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::unique_ptr<Result> &>
|
||||
{
|
||||
static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||
|
||||
@ -28,9 +31,9 @@ namespace chaiscript
|
||||
{
|
||||
struct arithmetic_error : std::runtime_error
|
||||
{
|
||||
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||
explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||
arithmetic_error(const arithmetic_error &) = default;
|
||||
virtual ~arithmetic_error() noexcept = default;
|
||||
~arithmetic_error() noexcept override = default;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -585,6 +588,67 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
template<typename Source, typename Target>
|
||||
static void check_type()
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// MSVC complains about this being redundant / tautologica l
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127 6287)
|
||||
#endif
|
||||
if (sizeof(Source) != sizeof(Target)
|
||||
|| std::is_signed<Source>() != std::is_signed<Target>()
|
||||
|| std::is_floating_point<Source>() != std::is_floating_point<Target>())
|
||||
{
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Target> Target get_as_checked() const
|
||||
{
|
||||
switch (get_common_type(bv)) {
|
||||
case Common_Types::t_int32:
|
||||
check_type<int32_t, Target>();
|
||||
return get_as_aux<Target, int32_t>(bv);
|
||||
case Common_Types::t_uint8:
|
||||
check_type<uint8_t, Target>();
|
||||
return get_as_aux<Target, uint8_t>(bv);
|
||||
case Common_Types::t_int8:
|
||||
check_type<int8_t, Target>();
|
||||
return get_as_aux<Target, int8_t>(bv);
|
||||
case Common_Types::t_uint16:
|
||||
check_type<uint16_t, Target>();
|
||||
return get_as_aux<Target, uint16_t>(bv);
|
||||
case Common_Types::t_int16:
|
||||
check_type<int16_t, Target>();
|
||||
return get_as_aux<Target, int16_t>(bv);
|
||||
case Common_Types::t_uint32:
|
||||
check_type<uint32_t, Target>();
|
||||
return get_as_aux<Target, uint32_t>(bv);
|
||||
case Common_Types::t_uint64:
|
||||
check_type<uint64_t, Target>();
|
||||
return get_as_aux<Target, uint64_t>(bv);
|
||||
case Common_Types::t_int64:
|
||||
check_type<int64_t, Target>();
|
||||
return get_as_aux<Target, int64_t>(bv);
|
||||
case Common_Types::t_double:
|
||||
check_type<double, Target>();
|
||||
return get_as_aux<Target, double>(bv);
|
||||
case Common_Types::t_float:
|
||||
check_type<float, Target>();
|
||||
return get_as_aux<Target, float>(bv);
|
||||
case Common_Types::t_long_double:
|
||||
check_type<long double, Target>();
|
||||
return get_as_aux<Target, long double>(bv);
|
||||
}
|
||||
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
|
||||
template<typename Target> Target get_as() const
|
||||
{
|
||||
switch (get_common_type(bv)) {
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
|
||||
@ -35,11 +39,11 @@ namespace chaiscript
|
||||
{
|
||||
Data(const Type_Info &ti,
|
||||
chaiscript::detail::Any to,
|
||||
bool tr,
|
||||
bool is_ref,
|
||||
const void *t_void_ptr,
|
||||
bool t_return_value)
|
||||
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
m_is_ref(tr), m_return_value(t_return_value)
|
||||
m_is_ref(is_ref), m_return_value(t_return_value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -54,7 +58,7 @@ namespace chaiscript
|
||||
|
||||
if (rhs.m_attrs)
|
||||
{
|
||||
m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*rhs.m_attrs));
|
||||
m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*rhs.m_attrs);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -119,6 +123,8 @@ namespace chaiscript
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
static auto get(T *t, bool t_return_value)
|
||||
{
|
||||
@ -145,6 +151,19 @@ namespace chaiscript
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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)
|
||||
{
|
||||
@ -236,8 +255,9 @@ namespace chaiscript
|
||||
~Sentinel()
|
||||
{
|
||||
// save new pointer data
|
||||
m_data.get().m_data_ptr = m_ptr.get().get();
|
||||
m_data.get().m_const_data_ptr = m_ptr.get().get();
|
||||
const auto ptr_ = m_ptr.get().get();
|
||||
m_data.get().m_data_ptr = ptr_;
|
||||
m_data.get().m_const_data_ptr = ptr_;
|
||||
}
|
||||
|
||||
Sentinel& operator=(Sentinel&&s) = default;
|
||||
@ -302,7 +322,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data->m_attrs)
|
||||
{
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>());
|
||||
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>();
|
||||
}
|
||||
|
||||
auto &attr = (*m_data->m_attrs)[t_name];
|
||||
@ -319,7 +339,7 @@ namespace chaiscript
|
||||
{
|
||||
if (t_obj.m_data->m_attrs)
|
||||
{
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*t_obj.m_data->m_attrs));
|
||||
m_data->m_attrs = std::make_unique<std::map<std::string, std::shared_ptr<Data>>>(*t_obj.m_data->m_attrs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -342,8 +362,8 @@ namespace chaiscript
|
||||
// necessary to avoid hitting the templated && constructor of Boxed_Value
|
||||
struct Internal_Construction{};
|
||||
|
||||
Boxed_Value(const std::shared_ptr<Data> &t_data, Internal_Construction)
|
||||
: m_data(t_data) {
|
||||
Boxed_Value(std::shared_ptr<Data> t_data, Internal_Construction)
|
||||
: m_data(std::move(t_data)) {
|
||||
}
|
||||
|
||||
std::shared_ptr<Data> m_data = Object_Data::get();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
|
||||
@ -25,7 +25,7 @@ namespace chaiscript {
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
struct Const_Caller
|
||||
{
|
||||
Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
||||
explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(const Class &o, Inner&& ... inner) const {
|
||||
@ -38,7 +38,7 @@ namespace chaiscript {
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Fun_Caller
|
||||
{
|
||||
Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
||||
explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(Inner&& ... inner) const {
|
||||
@ -51,7 +51,7 @@ namespace chaiscript {
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
struct Caller
|
||||
{
|
||||
Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
||||
explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(Class &o, Inner&& ... inner) const {
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
|
||||
#define CHAISCRIPT_DISPATCHKIT_HPP_
|
||||
|
||||
@ -67,7 +71,7 @@ namespace chaiscript
|
||||
|
||||
reserved_word_error(const reserved_word_error &) = default;
|
||||
|
||||
virtual ~reserved_word_error() noexcept = default;
|
||||
~reserved_word_error() noexcept override = default;
|
||||
|
||||
std::string word() const
|
||||
{
|
||||
@ -89,7 +93,7 @@ namespace chaiscript
|
||||
|
||||
illegal_name_error(const illegal_name_error &) = default;
|
||||
|
||||
virtual ~illegal_name_error() noexcept = default;
|
||||
~illegal_name_error() noexcept override = default;
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@ -112,7 +116,7 @@ namespace chaiscript
|
||||
|
||||
name_conflict_error(const name_conflict_error &) = default;
|
||||
|
||||
virtual ~name_conflict_error() noexcept = default;
|
||||
~name_conflict_error() noexcept override = default;
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@ -135,7 +139,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
global_non_const(const global_non_const &) = default;
|
||||
virtual ~global_non_const() noexcept = default;
|
||||
~global_non_const() noexcept override = default;
|
||||
};
|
||||
}
|
||||
|
||||
@ -147,7 +151,7 @@ namespace chaiscript
|
||||
public:
|
||||
Module &add(Type_Info ti, std::string name)
|
||||
{
|
||||
m_typeinfos.emplace_back(std::move(ti), std::move(name));
|
||||
m_typeinfos.emplace_back(ti, std::move(name));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -266,7 +270,7 @@ namespace chaiscript
|
||||
class Dispatch_Function final : public dispatch::Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
||||
explicit Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
|
||||
m_funcs(std::move(t_funcs))
|
||||
{
|
||||
@ -356,7 +360,7 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
|
||||
assert(type_infos.size() > 0 && " type_info vector size is < 0, this is only possible if something else is broken");
|
||||
assert(!type_infos.empty() && " type_info vector size is < 0, this is only possible if something else is broken");
|
||||
|
||||
if (size_mismatch)
|
||||
{
|
||||
@ -447,8 +451,8 @@ namespace chaiscript
|
||||
Type_Name_Map m_types;
|
||||
};
|
||||
|
||||
Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
|
||||
: m_stack_holder(this),
|
||||
explicit Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
|
||||
: m_stack_holder(),
|
||||
m_parser(parser)
|
||||
{
|
||||
}
|
||||
@ -681,7 +685,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
t_loc = static_cast<uint_fast32_t>(Loc::located);
|
||||
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
|
||||
} else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) {
|
||||
auto &stack = get_stack_data(t_holder);
|
||||
|
||||
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
|
||||
@ -698,9 +702,9 @@ namespace chaiscript
|
||||
|
||||
// no? is it a function object?
|
||||
auto obj = get_function_object_int(name, loc);
|
||||
if (obj.first != loc) t_loc = uint_fast32_t(obj.first);
|
||||
return obj.second;
|
||||
if (obj.first != loc) { t_loc = uint_fast32_t(obj.first); }
|
||||
|
||||
return obj.second;
|
||||
|
||||
}
|
||||
|
||||
@ -763,7 +767,10 @@ namespace chaiscript
|
||||
{
|
||||
uint_fast32_t method_missing_loc = m_method_missing_loc;
|
||||
auto method_missing_funs = get_function("method_missing", method_missing_loc);
|
||||
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
|
||||
if (method_missing_funs.first != method_missing_loc) {
|
||||
m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
|
||||
}
|
||||
|
||||
return std::move(method_missing_funs.second);
|
||||
}
|
||||
|
||||
@ -954,7 +961,7 @@ namespace chaiscript
|
||||
{
|
||||
uint_fast32_t loc = t_loc;
|
||||
const auto funs = get_function(t_name, loc);
|
||||
if (funs.first != loc) t_loc = uint_fast32_t(funs.first);
|
||||
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first); }
|
||||
|
||||
const auto do_attribute_call =
|
||||
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
|
||||
@ -977,14 +984,21 @@ namespace chaiscript
|
||||
|
||||
This_Foist fi(*this, l_params.front());
|
||||
|
||||
auto func = boxed_cast<const dispatch::Proxy_Function_Base *>(bv);
|
||||
try {
|
||||
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
|
||||
auto func = boxed_cast<const dispatch::Proxy_Function_Base *>(bv);
|
||||
try {
|
||||
return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
} catch (const chaiscript::exception::arity_error &) {
|
||||
} catch (const chaiscript::exception::guard_error &) {
|
||||
}
|
||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
||||
std::vector<Const_Proxy_Function>{boxed_cast<Const_Proxy_Function>(bv)});
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||
} catch (const chaiscript::exception::arity_error &) {
|
||||
} catch (const chaiscript::exception::guard_error &) {
|
||||
// unable to convert bv into a Proxy_Function_Base
|
||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
||||
std::vector<Const_Proxy_Function>(l_funs.begin(), l_funs.end()));
|
||||
}
|
||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector<Const_Proxy_Function>{boxed_cast<Const_Proxy_Function>(bv)});
|
||||
} else {
|
||||
return bv;
|
||||
}
|
||||
@ -1067,7 +1081,8 @@ namespace chaiscript
|
||||
{
|
||||
uint_fast32_t loc = t_loc;
|
||||
const auto funs = get_function(t_name, loc);
|
||||
if (funs.first != loc) t_loc = uint_fast32_t(funs.first);
|
||||
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first);
|
||||
}
|
||||
return dispatch::dispatch(*funs.second, params, t_conversions);
|
||||
}
|
||||
|
||||
@ -1191,7 +1206,7 @@ namespace chaiscript
|
||||
|
||||
static void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(t_params));
|
||||
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params);
|
||||
}
|
||||
|
||||
static void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
|
||||
@ -1209,7 +1224,7 @@ namespace chaiscript
|
||||
|
||||
void save_function_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
save_function_params(*m_stack_holder, std::move(t_params));
|
||||
save_function_params(*m_stack_holder, t_params);
|
||||
}
|
||||
|
||||
void save_function_params(std::vector<Boxed_Value> &&t_params)
|
||||
@ -1505,7 +1520,7 @@ namespace chaiscript
|
||||
class Dispatch_State
|
||||
{
|
||||
public:
|
||||
Dispatch_State(Dispatch_Engine &t_engine)
|
||||
explicit Dispatch_State(Dispatch_Engine &t_engine)
|
||||
: m_engine(t_engine),
|
||||
m_stack_holder(t_engine.get_stack_holder()),
|
||||
m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves())
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
@ -25,7 +29,7 @@ namespace chaiscript
|
||||
namespace dispatch
|
||||
{
|
||||
struct option_explicit_set : std::runtime_error {
|
||||
option_explicit_set(const std::string &t_param_name)
|
||||
explicit option_explicit_set(const std::string &t_param_name)
|
||||
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
|
||||
{
|
||||
|
||||
@ -33,13 +37,13 @@ namespace chaiscript
|
||||
|
||||
option_explicit_set(const option_explicit_set &) = default;
|
||||
|
||||
virtual ~option_explicit_set() noexcept = default;
|
||||
~option_explicit_set() noexcept override = default;
|
||||
};
|
||||
|
||||
class Dynamic_Object
|
||||
{
|
||||
public:
|
||||
Dynamic_Object(std::string t_type_name)
|
||||
explicit Dynamic_Object(std::string t_type_name)
|
||||
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
||||
@ -99,7 +99,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const 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))
|
||||
{
|
||||
@ -109,7 +109,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
|
||||
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
@ -151,7 +151,7 @@ namespace chaiscript
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
if (!bvs.empty())
|
||||
{
|
||||
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||
} else {
|
||||
@ -202,7 +202,7 @@ namespace chaiscript
|
||||
bool operator==(const Proxy_Function_Base &f) const override
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
}
|
||||
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
|
||||
@ -33,7 +37,7 @@ namespace chaiscript
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (t_conversions) {
|
||||
if (t_conversions != nullptr) {
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
@ -52,7 +56,7 @@ namespace chaiscript
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (t_conversions) {
|
||||
if (t_conversions != nullptr) {
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
@ -72,7 +76,7 @@ namespace chaiscript
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (t_conversions) {
|
||||
if (t_conversions != nullptr) {
|
||||
dispatch::dispatch(t_funcs, params, *t_conversions);
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
#define CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
|
||||
@ -27,9 +31,7 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
/// Used internally for handling a return value from a Proxy_Function call
|
||||
template<typename Ret>
|
||||
struct Handle_Return
|
||||
{
|
||||
@ -155,6 +157,18 @@ namespace chaiscript
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::unique_ptr<Ret>> : Handle_Return<std::unique_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(std::unique_ptr<Ret> &&r)
|
||||
{
|
||||
return Boxed_Value(std::move(r), true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret &>
|
||||
{
|
||||
@ -167,9 +181,9 @@ namespace chaiscript
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret>
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
static Boxed_Value handle(Ret r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
return Boxed_Value(std::move(r));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
#define CHAISCRIPT_OPERATORS_HPP_
|
||||
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
||||
@ -38,7 +41,7 @@ namespace chaiscript
|
||||
class Boxed_Number;
|
||||
struct AST_Node;
|
||||
|
||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::unique_ptr<AST_Node> AST_NodePtr;
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
@ -53,7 +56,7 @@ namespace chaiscript
|
||||
m_doti(user_type<Dynamic_Object>())
|
||||
{}
|
||||
|
||||
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
|
||||
explicit Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
|
||||
: m_types(std::move(t_types)),
|
||||
m_has_types(false),
|
||||
m_doti(user_type<Dynamic_Object>())
|
||||
@ -63,7 +66,7 @@ namespace chaiscript
|
||||
|
||||
void push_front(std::string t_name, Type_Info t_ti)
|
||||
{
|
||||
m_types.emplace(m_types.begin(), std::move(t_name), std::move(t_ti));
|
||||
m_types.emplace(m_types.begin(), std::move(t_name), t_ti);
|
||||
update_has_types();
|
||||
}
|
||||
|
||||
@ -72,10 +75,51 @@ namespace chaiscript
|
||||
return m_types == t_rhs.m_types;
|
||||
}
|
||||
|
||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
std::vector<Boxed_Value> convert(std::vector<Boxed_Value> vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (!m_has_types) return true;
|
||||
if (vals.size() != m_types.size()) return false;
|
||||
for (size_t i = 0; i < vals.size(); ++i)
|
||||
{
|
||||
const auto &name = m_types[i].first;
|
||||
if (!name.empty()) {
|
||||
const auto &bv = vals[i];
|
||||
|
||||
if (!bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
const auto &ti = m_types[i].second;
|
||||
if (!ti.is_undef())
|
||||
{
|
||||
if (!bv.get_type_info().bare_equal(ti)) {
|
||||
if (t_conversions->converts(ti, bv.get_type_info())) {
|
||||
try {
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
vals[i] = t_conversions->boxed_type_conversion(m_types[i].second, t_conversions.saves(), vals[i]);
|
||||
} catch (...) {
|
||||
try {
|
||||
// try going the other way
|
||||
vals[i] = t_conversions->boxed_type_down_conversion(m_types[i].second, t_conversions.saves(), vals[i]);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), *m_types[i].second.bare_type_info());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vals;
|
||||
}
|
||||
|
||||
// first result: is a match
|
||||
// second result: needs conversions
|
||||
std::pair<bool, bool> match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
bool needs_conversion = false;
|
||||
|
||||
if (!m_has_types) { return std::make_pair(true, needs_conversion); }
|
||||
if (vals.size() != m_types.size()) { return std::make_pair(false, needs_conversion); }
|
||||
|
||||
for (size_t i = 0; i < vals.size(); ++i)
|
||||
{
|
||||
@ -87,25 +131,31 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
||||
if (!(name == "Dynamic_Object" || d.get_type_name() == name)) {
|
||||
return std::make_pair(false, false);
|
||||
}
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
return std::make_pair(false, false);
|
||||
}
|
||||
} else {
|
||||
const auto &ti = m_types[i].second;
|
||||
if (!ti.is_undef())
|
||||
{
|
||||
if (!bv.get_type_info().bare_equal(ti)) {
|
||||
return false;
|
||||
if (!t_conversions->converts(ti, bv.get_type_info())) {
|
||||
return std::make_pair(false, false);
|
||||
} else {
|
||||
needs_conversion = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
return std::make_pair(false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return std::make_pair(true, needs_conversion);
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, Type_Info>> &types() const
|
||||
@ -282,7 +332,7 @@ namespace chaiscript
|
||||
|
||||
guard_error(const guard_error &) = default;
|
||||
|
||||
virtual ~guard_error() noexcept = default;
|
||||
~guard_error() noexcept override = default;
|
||||
};
|
||||
}
|
||||
|
||||
@ -296,32 +346,32 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dynamic_Proxy_Function(
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
const int t_arity,
|
||||
std::shared_ptr<AST_Node> t_parsenode,
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
||||
m_param_types(std::move(t_param_types)),
|
||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||
{
|
||||
// assert(t_parsenode);
|
||||
}
|
||||
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &rhs) const override
|
||||
bool operator==(const Proxy_Function_Base &rhs) const override
|
||||
{
|
||||
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||
|
||||
return this == &rhs
|
||||
|| (prhs
|
||||
|| ((prhs != nullptr)
|
||||
&& this->m_arity == prhs->m_arity
|
||||
&& !this->m_guard && !prhs->m_guard
|
||||
&& this->m_param_types == prhs->m_param_types);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
|
||||
&& test_guard(vals, t_conversions);
|
||||
return call_match_internal(vals, t_conversions).first;
|
||||
}
|
||||
|
||||
|
||||
@ -330,9 +380,17 @@ namespace chaiscript
|
||||
return m_guard;
|
||||
}
|
||||
|
||||
AST_NodePtr get_parse_tree() const
|
||||
bool has_parse_tree() const {
|
||||
return static_cast<bool>(m_parsenode);
|
||||
}
|
||||
|
||||
const AST_Node &get_parse_tree() const
|
||||
{
|
||||
return m_parsenode;
|
||||
if (m_parsenode) {
|
||||
return *m_parsenode;
|
||||
} else {
|
||||
throw std::runtime_error("Dynamic_Proxy_Function does not have parse_tree");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -353,6 +411,26 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
// first result: is a match
|
||||
// second result: needs conversions
|
||||
std::pair<bool, bool> call_match_internal(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
const auto comparison_result = [&](){
|
||||
if (m_arity < 0) {
|
||||
return std::make_pair(true, false);
|
||||
} else if (vals.size() == size_t(m_arity)) {
|
||||
return m_param_types.match(vals, t_conversions);
|
||||
} else {
|
||||
return std::make_pair(false, false);
|
||||
}
|
||||
}();
|
||||
|
||||
return std::make_pair(
|
||||
comparison_result.first && test_guard(vals, t_conversions),
|
||||
comparison_result.second
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
|
||||
{
|
||||
@ -371,9 +449,12 @@ namespace chaiscript
|
||||
return types;
|
||||
}
|
||||
|
||||
protected:
|
||||
Param_Types m_param_types;
|
||||
|
||||
private:
|
||||
Proxy_Function m_guard;
|
||||
AST_NodePtr m_parsenode;
|
||||
std::shared_ptr<AST_Node> m_parsenode;
|
||||
};
|
||||
|
||||
|
||||
@ -385,7 +466,7 @@ namespace chaiscript
|
||||
Dynamic_Proxy_Function_Impl(
|
||||
Callable t_f,
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
std::shared_ptr<AST_Node> t_parsenode = AST_NodePtr(),
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Dynamic_Proxy_Function(
|
||||
@ -402,9 +483,14 @@ namespace chaiscript
|
||||
protected:
|
||||
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)
|
||||
{
|
||||
return m_f(params);
|
||||
if (match_results.second) {
|
||||
return m_f(m_param_types.convert(params, t_conversions));
|
||||
} else {
|
||||
return m_f(params);
|
||||
}
|
||||
} else {
|
||||
throw exception::guard_error();
|
||||
}
|
||||
@ -516,7 +602,7 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const 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);
|
||||
}
|
||||
@ -529,7 +615,7 @@ namespace chaiscript
|
||||
class Proxy_Function_Impl_Base : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||
explicit Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
||||
{
|
||||
}
|
||||
@ -550,7 +636,7 @@ namespace chaiscript
|
||||
class Proxy_Function_Callable_Impl final : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Callable_Impl(Callable f)
|
||||
explicit Proxy_Function_Callable_Impl(Callable f)
|
||||
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
||||
m_f(std::move(f))
|
||||
{
|
||||
@ -581,7 +667,7 @@ namespace chaiscript
|
||||
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
|
||||
explicit Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Impl_Base(t_types)
|
||||
{
|
||||
}
|
||||
@ -637,7 +723,7 @@ namespace chaiscript
|
||||
class Attribute_Access final : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
explicit Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types(), 1),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
@ -742,7 +828,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
dispatch_error(const dispatch_error &) = default;
|
||||
virtual ~dispatch_error() noexcept = default;
|
||||
~dispatch_error() noexcept override = default;
|
||||
|
||||
std::vector<Boxed_Value> parameters;
|
||||
std::vector<Const_Proxy_Function> functions;
|
||||
@ -759,7 +845,7 @@ namespace chaiscript
|
||||
{
|
||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||
|
||||
if (t_func->get_arity() == -1) return false;
|
||||
if (t_func->get_arity() == -1) { return false; }
|
||||
|
||||
assert(plist.size() == types.size() - 1);
|
||||
|
||||
@ -843,11 +929,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
/// Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
/// each function against the set of parameters, in order, until a matching
|
||||
/// function is found or throw dispatch_error if no matching function is found
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
|
||||
@ -44,7 +48,7 @@ namespace chaiscript
|
||||
|
||||
arity_error(const arity_error &) = default;
|
||||
|
||||
virtual ~arity_error() noexcept {}
|
||||
~arity_error() noexcept override = default;
|
||||
|
||||
int got;
|
||||
int expected;
|
||||
@ -115,7 +119,15 @@ namespace chaiscript
|
||||
const std::vector<Boxed_Value> ¶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
|
||||
// MSVC is reporting that this is unreachable code - and it's wrong.
|
||||
return Handle_Return<void>::handle();
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
|
||||
@ -44,6 +48,7 @@ namespace chaiscript
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
|
||||
}
|
||||
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function fun(Ret (*func)(Param...))
|
||||
{
|
||||
@ -73,13 +78,45 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
|
||||
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
|
||||
{
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<T, Class>>(m));
|
||||
}
|
||||
|
||||
// only compile this bit if noexcept is part of the type system
|
||||
//
|
||||
#if __cpp_noexcept_function_type >= 201510
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function fun(Ret (*func)(Param...) noexcept)
|
||||
{
|
||||
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
|
||||
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) const noexcept)
|
||||
{
|
||||
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) noexcept)
|
||||
{
|
||||
auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@ -107,31 +144,6 @@ namespace chaiscript
|
||||
return fun(detail::bind_first(std::forward<T>(t), q));
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
|
||||
/// \param[in] t Function / member to expose
|
||||
/// \param[in] q Value to bind to first parameter
|
||||
/// \param[in] r Value to bind to second parameter
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct MyClass
|
||||
/// {
|
||||
/// void memberfunction(int);
|
||||
/// };
|
||||
///
|
||||
/// MyClass obj;
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
|
||||
/// // memberfunction() will be equivalent to obj.memberfunction(1)
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T, typename Q, typename R>
|
||||
Proxy_Function fun(T &&t, Q &&q, R &&r)
|
||||
{
|
||||
return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -84,12 +84,14 @@ 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;
|
||||
n = align_up(n);
|
||||
if (p + n == ptr_) {
|
||||
ptr_ = p;
|
||||
}
|
||||
}
|
||||
else {
|
||||
::operator delete(p);
|
||||
}
|
||||
else
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||
@ -108,13 +110,13 @@ public:
|
||||
short_alloc(const short_alloc&) = default;
|
||||
short_alloc& operator=(const short_alloc&) = delete;
|
||||
|
||||
short_alloc(arena_type& a) noexcept : a_(a)
|
||||
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>
|
||||
short_alloc(const short_alloc<U, N, alignment>& a) noexcept
|
||||
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>;};
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
@ -39,14 +43,14 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
explicit bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() noexcept = default;
|
||||
~bad_boxed_dynamic_cast() noexcept override = default;
|
||||
};
|
||||
|
||||
class bad_boxed_type_cast : public bad_boxed_cast
|
||||
@ -63,14 +67,14 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const std::string &w) noexcept
|
||||
explicit bad_boxed_type_cast(const std::string &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
|
||||
|
||||
virtual ~bad_boxed_type_cast() noexcept = default;
|
||||
~bad_boxed_type_cast() noexcept override = default;
|
||||
};
|
||||
}
|
||||
|
||||
@ -100,8 +104,8 @@ namespace chaiscript
|
||||
virtual ~Type_Conversion_Base() = default;
|
||||
|
||||
protected:
|
||||
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
|
||||
: m_to(t_to), m_from(t_from)
|
||||
Type_Conversion_Base(Type_Info t_to, Type_Info t_from)
|
||||
: m_to(std::move(t_to)), m_from(std::move(t_from))
|
||||
{
|
||||
}
|
||||
|
||||
@ -286,7 +290,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
||||
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
|
||||
: Type_Conversion_Base(t_to, t_from),
|
||||
m_func(std::move(t_func))
|
||||
{
|
||||
}
|
||||
@ -302,7 +306,7 @@ namespace chaiscript
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
virtual bool bidir() const override
|
||||
bool bidir() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -334,21 +338,15 @@ namespace chaiscript
|
||||
: m_mutex(),
|
||||
m_conversions(),
|
||||
m_convertableTypes(),
|
||||
m_num_types(0),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
m_num_types(0)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Conversions(const Type_Conversions &t_other)
|
||||
: m_mutex(),
|
||||
m_conversions(t_other.get_conversions()),
|
||||
m_convertableTypes(t_other.m_convertableTypes),
|
||||
m_num_types(m_conversions.size()),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
{
|
||||
}
|
||||
Type_Conversions(const Type_Conversions &t_other) = delete;
|
||||
Type_Conversions(Type_Conversions &&) = default;
|
||||
|
||||
Type_Conversions &operator=(const Type_Conversions &) = delete;
|
||||
Type_Conversions &operator=(Type_Conversions &&) = default;
|
||||
|
||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
||||
{
|
||||
@ -397,28 +395,39 @@ namespace chaiscript
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
||||
if (t_saves.enabled) t_saves.saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
return boxed_type_conversion(user_type<To>(), t_saves, from);
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||
{
|
||||
return boxed_type_down_conversion(user_type<From>(), t_saves, to);
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
||||
if (t_saves.enabled) t_saves.saves.push_back(ret);
|
||||
Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from);
|
||||
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to);
|
||||
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||
#define CHAISCRIPT_TYPE_INFO_HPP_
|
||||
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include "../utility/fnv1a.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace chaiscript
|
||||
@ -51,76 +57,48 @@ namespace chaiscript
|
||||
|
||||
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
||||
{
|
||||
if (t_str == "==")
|
||||
{
|
||||
return Opers::equals;
|
||||
} else if (t_str == "<") {
|
||||
return Opers::less_than;
|
||||
} else if (t_str == ">") {
|
||||
return Opers::greater_than;
|
||||
} else if (t_str == "<=") {
|
||||
return Opers::less_than_equal;
|
||||
} else if (t_str == ">=") {
|
||||
return Opers::greater_than_equal;
|
||||
} else if (t_str == "!=") {
|
||||
return Opers::not_equal;
|
||||
} else if (t_str == "=") {
|
||||
return Opers::assign;
|
||||
} else if (t_str == "++") {
|
||||
return Opers::pre_increment;
|
||||
} else if (t_str == "--") {
|
||||
return Opers::pre_decrement;
|
||||
} else if (t_str == "*=") {
|
||||
return Opers::assign_product;
|
||||
} else if (t_str == "+=") {
|
||||
return Opers::assign_sum;
|
||||
} else if (t_str == "-=") {
|
||||
return Opers::assign_difference;
|
||||
} else if (t_str == "&=") {
|
||||
return Opers::assign_bitwise_and;
|
||||
} else if (t_str == "|=") {
|
||||
return Opers::assign_bitwise_or;
|
||||
} else if (t_str == "<<=") {
|
||||
return Opers::assign_shift_left;
|
||||
} else if (t_str == ">>=") {
|
||||
return Opers::assign_shift_right;
|
||||
} else if (t_str == "%=") {
|
||||
return Opers::assign_remainder;
|
||||
} else if (t_str == "^=") {
|
||||
return Opers::assign_bitwise_xor;
|
||||
} else if (t_str == "<<") {
|
||||
return Opers::shift_left;
|
||||
} else if (t_str == ">>") {
|
||||
return Opers::shift_right;
|
||||
} else if (t_str == "%") {
|
||||
return Opers::remainder;
|
||||
} else if (t_str == "&") {
|
||||
return Opers::bitwise_and;
|
||||
} else if (t_str == "|") {
|
||||
return Opers::bitwise_or;
|
||||
} else if (t_str == "^") {
|
||||
return Opers::bitwise_xor;
|
||||
} else if (t_str == "~") {
|
||||
return Opers::bitwise_complement;
|
||||
} else if (t_str == "+") {
|
||||
if (t_is_unary) {
|
||||
return Opers::unary_plus;
|
||||
} else {
|
||||
return Opers::sum;
|
||||
}
|
||||
} else if (t_str == "-") {
|
||||
if (t_is_unary) {
|
||||
return Opers::unary_minus;
|
||||
} else {
|
||||
return Opers::difference;
|
||||
}
|
||||
} else if (t_str == "/") {
|
||||
return Opers::quotient;
|
||||
} else if (t_str == "*") {
|
||||
return Opers::product;
|
||||
} else {
|
||||
return Opers::invalid;
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4307)
|
||||
#endif
|
||||
|
||||
const auto op_hash = utility::fnv1a_32(t_str.c_str());
|
||||
switch (op_hash) {
|
||||
case utility::fnv1a_32("=="): { return Opers::equals; }
|
||||
case utility::fnv1a_32("<"): { return Opers::less_than; }
|
||||
case utility::fnv1a_32(">"): { return Opers::greater_than; }
|
||||
case utility::fnv1a_32("<="): { return Opers::less_than_equal; }
|
||||
case utility::fnv1a_32(">="): { return Opers::greater_than_equal; }
|
||||
case utility::fnv1a_32("!="): { return Opers::not_equal; }
|
||||
case utility::fnv1a_32("="): { return Opers::assign; }
|
||||
case utility::fnv1a_32("++"): { return Opers::pre_increment; }
|
||||
case utility::fnv1a_32("--"): { return Opers::pre_decrement; }
|
||||
case utility::fnv1a_32("*="): { return Opers::assign_product; }
|
||||
case utility::fnv1a_32("+="): { return Opers::assign_sum; }
|
||||
case utility::fnv1a_32("-="): { return Opers::assign_difference; }
|
||||
case utility::fnv1a_32("&="): { return Opers::assign_bitwise_and; }
|
||||
case utility::fnv1a_32("|="): { return Opers::assign_bitwise_or; }
|
||||
case utility::fnv1a_32("<<="): { return Opers::assign_shift_left; }
|
||||
case utility::fnv1a_32(">>="): { return Opers::assign_shift_right; }
|
||||
case utility::fnv1a_32("%="): { return Opers::assign_remainder; }
|
||||
case utility::fnv1a_32("^="): { return Opers::assign_bitwise_xor; }
|
||||
case utility::fnv1a_32("<<"): { return Opers::shift_left; }
|
||||
case utility::fnv1a_32(">>"): { return Opers::shift_right; }
|
||||
case utility::fnv1a_32("%"): { return Opers::remainder; }
|
||||
case utility::fnv1a_32("&"): { return Opers::bitwise_and; }
|
||||
case utility::fnv1a_32("|"): { return Opers::bitwise_or; }
|
||||
case utility::fnv1a_32("^"): { return Opers::bitwise_xor; }
|
||||
case utility::fnv1a_32("~"): { return Opers::bitwise_complement; }
|
||||
case utility::fnv1a_32("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
|
||||
case utility::fnv1a_32("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
|
||||
case utility::fnv1a_32("/"): { return Opers::quotient; }
|
||||
case utility::fnv1a_32("*"): { return Opers::product; }
|
||||
default: { return Opers::invalid; }
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
#define CHAISCRIPT_COMMON_HPP_
|
||||
|
||||
@ -31,7 +35,8 @@ namespace chaiscript
|
||||
{
|
||||
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", "_"};
|
||||
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_",
|
||||
"__LINE__", "__FILE__", "__FUNC__", "__CLASS__"};
|
||||
return m_reserved_words.count(name) > 0;
|
||||
}
|
||||
|
||||
@ -61,7 +66,7 @@ namespace chaiscript
|
||||
Array_Call, Dot_Access,
|
||||
Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
|
||||
};
|
||||
|
||||
enum class Operator_Precidence { Ternary_Cond, Logical_Or,
|
||||
@ -71,12 +76,12 @@ namespace chaiscript
|
||||
namespace
|
||||
{
|
||||
/// Helper lookup to get the name of each node type
|
||||
const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
|
||||
inline const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
|
||||
static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl",
|
||||
"Array_Call", "Dot_Access",
|
||||
"Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||
|
||||
return ast_node_types[static_cast<int>(ast_node_type)];
|
||||
}
|
||||
@ -119,8 +124,10 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<const AST_Node> AST_NodePtr_Const;
|
||||
typedef std::unique_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::unique_ptr<const AST_Node> AST_NodePtr_Const;
|
||||
|
||||
struct AST_Node_Trace;
|
||||
|
||||
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
@ -129,7 +136,7 @@ namespace chaiscript
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &t_reason) noexcept
|
||||
explicit load_module_error(const std::string &t_reason) noexcept
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
@ -140,7 +147,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
virtual ~load_module_error() noexcept = default;
|
||||
~load_module_error() noexcept override = default;
|
||||
|
||||
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
{
|
||||
@ -163,7 +170,7 @@ namespace chaiscript
|
||||
File_Position start_position;
|
||||
std::string filename;
|
||||
std::string detail;
|
||||
std::vector<AST_NodePtr_Const> call_stack;
|
||||
std::vector<AST_Node_Trace> call_stack;
|
||||
|
||||
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,
|
||||
@ -187,7 +194,7 @@ namespace chaiscript
|
||||
reason(t_why), start_position(t_where), filename(t_fname)
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why) noexcept
|
||||
explicit eval_error(const std::string &t_why) noexcept
|
||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||
reason(t_why)
|
||||
{}
|
||||
@ -199,7 +206,7 @@ namespace chaiscript
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << what();
|
||||
if (call_stack.size() > 0) {
|
||||
if (!call_stack.empty()) {
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
||||
ss << '\n' << detail << '\n';
|
||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||
@ -216,33 +223,33 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual ~eval_error() noexcept = default;
|
||||
~eval_error() noexcept override = default;
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static AST_Node_Type id(const T& t)
|
||||
{
|
||||
return t->identifier;
|
||||
return t.identifier;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string pretty(const T& t)
|
||||
{
|
||||
return t->pretty_print();
|
||||
return t.pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static const std::string &fname(const T& t)
|
||||
{
|
||||
return t->filename();
|
||||
return t.filename();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string startpos(const T& t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << t->start().line << ", " << t->start().column;
|
||||
oss << t.start().line << ", " << t.start().column;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@ -255,6 +262,7 @@ namespace chaiscript
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
assert(t_func);
|
||||
int arity = t_func->get_arity();
|
||||
std::vector<Type_Info> types = t_func->get_param_types();
|
||||
|
||||
@ -303,20 +311,20 @@ namespace chaiscript
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||
|
||||
if (dynfun)
|
||||
if (dynfun && dynfun->has_parse_tree())
|
||||
{
|
||||
Proxy_Function f = dynfun->get_guard();
|
||||
|
||||
if (f)
|
||||
{
|
||||
auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||
if (dynfunguard)
|
||||
if (dynfunguard && dynfunguard->has_parse_tree())
|
||||
{
|
||||
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||
}
|
||||
}
|
||||
|
||||
retval += "\n Defined at " + format_location(dynfun->get_parse_tree());
|
||||
retval += "\n Defined at " + format_location(dynfun->get_parse_tree());
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -325,20 +333,15 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
static std::string format_guard(const T &t)
|
||||
{
|
||||
return t->pretty_print();
|
||||
return t.pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_location(const T &t)
|
||||
{
|
||||
if (t) {
|
||||
std::ostringstream oss;
|
||||
oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
|
||||
return oss.str();
|
||||
} else {
|
||||
return "(internal)";
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
@ -348,6 +351,7 @@ namespace chaiscript
|
||||
std::stringstream ss;
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
assert(t_functions[0]);
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:\n";
|
||||
@ -475,19 +479,19 @@ namespace chaiscript
|
||||
|
||||
/// Errors generated when loading a file
|
||||
struct file_not_found_error : std::runtime_error {
|
||||
file_not_found_error(const std::string &t_filename) noexcept
|
||||
explicit file_not_found_error(const std::string &t_filename) noexcept
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
{ }
|
||||
|
||||
file_not_found_error(const file_not_found_error &) = default;
|
||||
virtual ~file_not_found_error() noexcept {}
|
||||
~file_not_found_error() noexcept override = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// \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 {
|
||||
public:
|
||||
const AST_Node_Type identifier;
|
||||
const std::string text;
|
||||
@ -511,14 +515,14 @@ namespace chaiscript
|
||||
|
||||
oss << text;
|
||||
|
||||
for (auto & elem : this->get_children()) {
|
||||
oss << elem->pretty_print() << ' ';
|
||||
for (auto & elem : get_children()) {
|
||||
oss << elem.get().pretty_print() << ' ';
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
virtual std::vector<AST_NodePtr> get_children() const = 0;
|
||||
virtual std::vector<std::reference_wrapper<AST_Node>> get_children() const = 0;
|
||||
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
|
||||
|
||||
|
||||
@ -529,16 +533,16 @@ namespace chaiscript
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
||||
|
||||
for (auto & elem : this->get_children()) {
|
||||
oss << elem->to_string(t_prepend + " ");
|
||||
for (auto & elem : get_children()) {
|
||||
oss << elem.get().to_string(t_prepend + " ");
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv) {
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
try {
|
||||
return boxed_cast<bool>(t_bv);
|
||||
return t_ss->boxed_cast<bool>(t_bv);
|
||||
}
|
||||
catch (const exception::bad_boxed_cast &) {
|
||||
throw exception::eval_error("Condition not boolean");
|
||||
@ -563,12 +567,60 @@ namespace chaiscript
|
||||
|
||||
};
|
||||
|
||||
struct AST_Node_Trace
|
||||
{
|
||||
const AST_Node_Type identifier;
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
|
||||
const std::string &filename() const {
|
||||
return *location.filename;
|
||||
}
|
||||
|
||||
const File_Position &start() const {
|
||||
return location.start;
|
||||
}
|
||||
|
||||
const File_Position &end() const {
|
||||
return location.end;
|
||||
}
|
||||
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
for (const auto & elem : children) {
|
||||
oss << elem.pretty_print() << ' ';
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::vector<AST_Node_Trace> get_children(const AST_Node &node)
|
||||
{
|
||||
const auto node_children = node.get_children();
|
||||
return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
|
||||
}
|
||||
|
||||
AST_Node_Trace(const AST_Node &node)
|
||||
: identifier(node.identifier), text(node.text),
|
||||
location(node.location), children(get_children(node))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::vector<AST_Node_Trace> children;
|
||||
|
||||
};
|
||||
|
||||
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 debug_print(const AST_Node &t, std::string prepend = "") const = 0;
|
||||
virtual void *get_tracer_ptr() = 0;
|
||||
virtual ~ChaiScript_Parser_Base() = default;
|
||||
ChaiScript_Parser_Base() = default;
|
||||
@ -596,19 +648,19 @@ namespace chaiscript
|
||||
struct Return_Value {
|
||||
Boxed_Value retval;
|
||||
|
||||
Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
|
||||
explicit Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
|
||||
};
|
||||
|
||||
|
||||
/// Special type indicating a call to 'break'
|
||||
struct Break_Loop {
|
||||
Break_Loop() { }
|
||||
Break_Loop() = default;
|
||||
};
|
||||
|
||||
|
||||
/// Special type indicating a call to 'continue'
|
||||
struct Continue_Loop {
|
||||
Continue_Loop() { }
|
||||
Continue_Loop() = default;
|
||||
};
|
||||
|
||||
|
||||
@ -620,7 +672,7 @@ namespace chaiscript
|
||||
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
|
||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
||||
|
||||
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
explicit Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds->new_scope(m_ds.stack_holder());
|
||||
@ -644,7 +696,7 @@ namespace chaiscript
|
||||
Function_Push_Pop(const Function_Push_Pop &) = delete;
|
||||
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
||||
|
||||
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
explicit Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
@ -662,7 +714,7 @@ namespace chaiscript
|
||||
|
||||
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
m_ds->save_function_params(std::move(t_params));
|
||||
m_ds->save_function_params(t_params);
|
||||
}
|
||||
|
||||
|
||||
@ -678,7 +730,7 @@ namespace chaiscript
|
||||
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
|
||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
||||
|
||||
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
explicit Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds->new_stack(m_ds.stack_holder());
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||
#define CHAISCRIPT_ENGINE_HPP_
|
||||
|
||||
@ -32,12 +36,13 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#if defined(CHAISCRIPT_NO_DYNLOAD)
|
||||
#include "chaiscript_unknown.hpp"
|
||||
#elif defined(CHAISCRIPT_WINDOWS)
|
||||
#include "chaiscript_windows.hpp"
|
||||
#elif _POSIX_VERSION
|
||||
#include "chaiscript_posix.hpp"
|
||||
@ -94,7 +99,7 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
const auto p = m_parser->parse(t_input, t_filename);
|
||||
return p->eval(m_engine);
|
||||
return p->eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||
}
|
||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
@ -139,7 +144,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
void build_eval_system(const ModulePtr &t_lib) {
|
||||
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
|
||||
if (t_lib)
|
||||
{
|
||||
add(t_lib);
|
||||
@ -160,9 +165,6 @@ namespace chaiscript
|
||||
})
|
||||
, "call_exists");
|
||||
|
||||
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
//
|
||||
//
|
||||
|
||||
m_engine.add(fun(
|
||||
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
|
||||
@ -184,13 +186,22 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
|
||||
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
|
||||
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end()
|
||||
&& std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end())
|
||||
{
|
||||
m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
|
||||
m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
|
||||
}
|
||||
|
||||
if (std::find(t_opts.begin(), t_opts.end(), Options::No_External_Scripts) == t_opts.end()
|
||||
&& std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end())
|
||||
{
|
||||
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
|
||||
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
|
||||
}
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
|
||||
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
|
||||
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
||||
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
||||
m_engine.add(fun([this](const AST_Node &t_ast){ return eval(t_ast); }), "eval");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
||||
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
|
||||
@ -228,59 +239,29 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths)
|
||||
{
|
||||
if (paths.empty()) { return {""}; }
|
||||
else { return paths; }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Constructor for ChaiScript
|
||||
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript_Basic(const ModulePtr &t_lib,
|
||||
std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_modulepaths = {},
|
||||
std::vector<std::string> t_usepaths = {})
|
||||
: m_module_paths(std::move(t_modulepaths)),
|
||||
m_use_paths(std::move(t_usepaths)),
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))),
|
||||
m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths))),
|
||||
m_parser(std::move(parser)),
|
||||
m_engine(*m_parser)
|
||||
{
|
||||
if (m_module_paths.empty())
|
||||
{
|
||||
m_module_paths.push_back("");
|
||||
}
|
||||
|
||||
if (m_use_paths.empty())
|
||||
{
|
||||
m_use_paths.push_back("");
|
||||
}
|
||||
|
||||
build_eval_system(t_lib);
|
||||
}
|
||||
|
||||
/// \brief Constructor for ChaiScript.
|
||||
///
|
||||
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
||||
/// at runtime generates an error if it cannot be found.
|
||||
///
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_modulepaths = {},
|
||||
std::vector<std::string> t_usepaths = {})
|
||||
: m_module_paths(std::move(t_modulepaths)),
|
||||
m_use_paths(std::move(t_usepaths)),
|
||||
m_parser(std::move(parser)),
|
||||
m_engine(*m_parser)
|
||||
{
|
||||
if (m_module_paths.empty())
|
||||
{
|
||||
m_module_paths.push_back("");
|
||||
}
|
||||
|
||||
if (m_use_paths.empty())
|
||||
{
|
||||
m_use_paths.push_back("");
|
||||
}
|
||||
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
// If on Unix, add the path of the current executable to the module search path
|
||||
// as windows would do
|
||||
|
||||
@ -294,7 +275,7 @@ namespace chaiscript
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
cast_union u;
|
||||
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);
|
||||
const size_t lastslash = dllpath.rfind('/');
|
||||
if (lastslash != std::string::npos)
|
||||
@ -313,8 +294,23 @@ namespace chaiscript
|
||||
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
|
||||
}
|
||||
#endif
|
||||
build_eval_system(t_lib, t_opts);
|
||||
}
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
/// \brief Constructor for ChaiScript.
|
||||
///
|
||||
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
||||
/// at runtime generates an error if it cannot be found.
|
||||
///
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||
: ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts)
|
||||
{
|
||||
try {
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib-" + Build_Info::version());
|
||||
@ -330,15 +326,23 @@ namespace chaiscript
|
||||
<< 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
|
||||
|
||||
build_eval_system(ModulePtr());
|
||||
parser::ChaiScript_Parser_Base &get_parser()
|
||||
{
|
||||
return *m_parser;
|
||||
}
|
||||
|
||||
|
||||
const Boxed_Value eval(const AST_NodePtr &t_ast)
|
||||
const Boxed_Value eval(const AST_Node &t_ast)
|
||||
{
|
||||
try {
|
||||
return t_ast->eval(m_engine);
|
||||
return t_ast.eval(chaiscript::detail::Dispatch_State(m_engine));
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
throw Boxed_Value(t_ee);
|
||||
}
|
||||
@ -346,9 +350,9 @@ namespace chaiscript
|
||||
|
||||
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
||||
{
|
||||
const auto ast = m_parser->parse(t_input, "PARSE");
|
||||
auto ast = m_parser->parse(t_input, "PARSE");
|
||||
if (t_debug_print) {
|
||||
m_parser->debug_print(ast);
|
||||
m_parser->debug_print(*ast);
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
@ -570,6 +574,10 @@ namespace chaiscript
|
||||
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
|
||||
std::string load_module(const std::string &t_module_name)
|
||||
{
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
(void)t_module_name; // -Wunused-parameter
|
||||
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||
#else
|
||||
std::vector<exception::load_module_error> errors;
|
||||
std::string version_stripped_name = t_module_name;
|
||||
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
|
||||
@ -603,6 +611,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
throw chaiscript::exception::load_module_error(t_module_name, errors);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_EVAL_HPP_
|
||||
#define CHAISCRIPT_EVAL_HPP_
|
||||
|
||||
@ -43,13 +47,13 @@ namespace chaiscript
|
||||
{
|
||||
template<typename T> struct AST_Node_Impl;
|
||||
|
||||
template<typename T> using AST_Node_Impl_Ptr = typename std::shared_ptr<AST_Node_Impl<T>>;
|
||||
template<typename T> using AST_Node_Impl_Ptr = typename std::unique_ptr<AST_Node_Impl<T>>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Helper function that will set up the scope around a function call, including handling the named function parameters
|
||||
template<typename T>
|
||||
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr) {
|
||||
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
|
||||
chaiscript::detail::Dispatch_State state(t_ss);
|
||||
|
||||
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
|
||||
@ -64,7 +68,7 @@ namespace chaiscript
|
||||
}();
|
||||
|
||||
chaiscript::eval::detail::Stack_Push_Pop tpp(state);
|
||||
if (thisobj) state.add_object("this", *thisobj);
|
||||
if (thisobj && !has_this_capture) { state.add_object("this", *thisobj); }
|
||||
|
||||
if (t_locals) {
|
||||
for (const auto &local : *t_locals) {
|
||||
@ -79,7 +83,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
try {
|
||||
return t_node->eval(state);
|
||||
return t_node.eval(state);
|
||||
} catch (detail::Return_Value &rv) {
|
||||
return std::move(rv.retval);
|
||||
}
|
||||
@ -91,14 +95,25 @@ namespace chaiscript
|
||||
{
|
||||
AST_Node_Impl(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc,
|
||||
std::vector<AST_Node_Impl_Ptr<T>> t_children = std::vector<AST_Node_Impl_Ptr<T>>())
|
||||
: AST_Node(std::move(t_ast_node_text), std::move(t_id), std::move(t_loc)),
|
||||
: AST_Node(std::move(t_ast_node_text), t_id, std::move(t_loc)),
|
||||
children(std::move(t_children))
|
||||
{
|
||||
}
|
||||
|
||||
static bool get_scoped_bool_condition(const AST_Node_Impl<T> &node, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||
return get_bool_condition(node.eval(t_ss), t_ss);
|
||||
}
|
||||
|
||||
std::vector<AST_NodePtr> get_children() const final {
|
||||
return {children.begin(), children.end()};
|
||||
|
||||
std::vector<std::reference_wrapper<AST_Node>> get_children() const final {
|
||||
std::vector<std::reference_wrapper<AST_Node>> retval;
|
||||
retval.reserve(children.size());
|
||||
for (auto &&child : children) {
|
||||
retval.emplace_back(*child);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final
|
||||
@ -107,7 +122,7 @@ namespace chaiscript
|
||||
T::trace(t_e, this);
|
||||
return eval_internal(t_e);
|
||||
} catch (exception::eval_error &ee) {
|
||||
ee.call_stack.push_back(shared_from_this());
|
||||
ee.call_stack.push_back(*this);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -238,7 +253,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Constant_AST_Node(Boxed_Value t_value)
|
||||
explicit Constant_AST_Node(Boxed_Value t_value)
|
||||
: AST_Node_Impl<T>("", AST_Node_Type::Constant, Parse_Location()),
|
||||
m_value(std::move(t_value))
|
||||
{
|
||||
@ -270,60 +285,15 @@ namespace chaiscript
|
||||
mutable std::atomic_uint_fast32_t m_loc = {0};
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Unused_Return_Fun_Call_AST_Node final : AST_Node_Impl<T> {
|
||||
Unused_Return_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Unused_Return_Fun_Call, std::move(t_loc), std::move(t_children)) { }
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
{
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
|
||||
std::vector<Boxed_Value> params;
|
||||
|
||||
params.reserve(this->children[1]->children.size());
|
||||
for (const auto &child : this->children[1]->children) {
|
||||
params.push_back(child->eval(t_ss));
|
||||
}
|
||||
|
||||
Boxed_Value fn(this->children[0]->eval(t_ss));
|
||||
|
||||
try {
|
||||
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(params, t_ss.conversions());
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
|
||||
}
|
||||
catch(const exception::bad_boxed_cast &){
|
||||
try {
|
||||
Const_Proxy_Function f = t_ss->boxed_cast<const Const_Proxy_Function &>(fn);
|
||||
// handle the case where there is only 1 function to try to call and dispatch fails on it
|
||||
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss);
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
|
||||
}
|
||||
}
|
||||
catch(const exception::arity_error &e){
|
||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||
}
|
||||
catch(const exception::guard_error &e){
|
||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||
}
|
||||
catch(detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Fun_Call_AST_Node final : AST_Node_Impl<T> {
|
||||
struct Fun_Call_AST_Node : AST_Node_Impl<T> {
|
||||
Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { }
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) {
|
||||
assert(!this->children.empty());
|
||||
}
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
template<bool Save_Params>
|
||||
Boxed_Value do_eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const
|
||||
{
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
|
||||
@ -334,7 +304,9 @@ namespace chaiscript
|
||||
params.push_back(child->eval(t_ss));
|
||||
}
|
||||
|
||||
fpp.save_params(params);
|
||||
if (Save_Params) {
|
||||
fpp.save_params(params);
|
||||
}
|
||||
|
||||
Boxed_Value fn(this->children[0]->eval(t_ss));
|
||||
|
||||
@ -364,10 +336,28 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
{
|
||||
return do_eval_internal<true>(t_ss);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Unused_Return_Fun_Call_AST_Node final : Fun_Call_AST_Node<T> {
|
||||
Unused_Return_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
Fun_Call_AST_Node<T>(std::move(t_ast_node_text), std::move(t_loc), std::move(t_children)) { }
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
{
|
||||
return this->template do_eval_internal<false>(t_ss);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Arg_AST_Node final : AST_Node_Impl<T> {
|
||||
@ -382,44 +372,44 @@ namespace chaiscript
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
|
||||
|
||||
|
||||
static std::string get_arg_name(const AST_Node_Impl_Ptr<T> &t_node) {
|
||||
if (t_node->children.empty())
|
||||
static std::string get_arg_name(const AST_Node_Impl<T> &t_node) {
|
||||
if (t_node.children.empty())
|
||||
{
|
||||
return t_node->text;
|
||||
} else if (t_node->children.size() == 1) {
|
||||
return t_node->children[0]->text;
|
||||
return t_node.text;
|
||||
} else if (t_node.children.size() == 1) {
|
||||
return t_node.children[0]->text;
|
||||
} else {
|
||||
return t_node->children[1]->text;
|
||||
return t_node.children[1]->text;
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> get_arg_names(const AST_Node_Impl_Ptr<T> &t_node) {
|
||||
static std::vector<std::string> get_arg_names(const AST_Node_Impl<T> &t_node) {
|
||||
std::vector<std::string> retval;
|
||||
|
||||
for (const auto &node : t_node->children)
|
||||
for (const auto &node : t_node.children)
|
||||
{
|
||||
retval.push_back(get_arg_name(node));
|
||||
retval.push_back(get_arg_name(*node));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static std::pair<std::string, Type_Info> get_arg_type(const AST_Node_Impl_Ptr<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss)
|
||||
static std::pair<std::string, Type_Info> get_arg_type(const AST_Node_Impl<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss)
|
||||
{
|
||||
if (t_node->children.size() < 2)
|
||||
if (t_node.children.size() < 2)
|
||||
{
|
||||
return {};
|
||||
} else {
|
||||
return {t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)};
|
||||
return {t_node.children[0]->text, t_ss->get_type(t_node.children[0]->text, false)};
|
||||
}
|
||||
}
|
||||
|
||||
static dispatch::Param_Types get_arg_types(const AST_Node_Impl_Ptr<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
static dispatch::Param_Types get_arg_types(const AST_Node_Impl<T> &t_node, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
std::vector<std::pair<std::string, Type_Info>> retval;
|
||||
|
||||
for (const auto &child : t_node->children)
|
||||
for (const auto &child : t_node.children)
|
||||
{
|
||||
retval.push_back(get_arg_type(child, t_ss));
|
||||
retval.push_back(get_arg_type(*child, t_ss));
|
||||
}
|
||||
|
||||
return dispatch::Param_Types(std::move(retval));
|
||||
@ -455,13 +445,13 @@ namespace chaiscript
|
||||
try {
|
||||
|
||||
if (lhs.is_undef()) {
|
||||
if ((!this->children.empty()
|
||||
if (!this->children.empty()
|
||||
&& ((this->children[0]->identifier == AST_Node_Type::Reference)
|
||||
|| (!this->children[0]->children.empty()
|
||||
&& this->children[0]->children[0]->identifier == AST_Node_Type::Reference)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
{
|
||||
/// \todo This does not handle the case of an unassigned reference variable
|
||||
/// being assigned outside of its declaration
|
||||
@ -639,8 +629,16 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Lambda_AST_Node final : AST_Node_Impl<T> {
|
||||
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
AST_Node_Impl<T>(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)),
|
||||
m_param_names(Arg_List_AST_Node<T>::get_arg_names(this->children[1])) { }
|
||||
AST_Node_Impl<T>(t_ast_node_text,
|
||||
AST_Node_Type::Lambda,
|
||||
std::move(t_loc),
|
||||
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
||||
std::make_move_iterator(std::prev(t_children.end())))
|
||||
),
|
||||
m_param_names(Arg_List_AST_Node<T>::get_arg_names(*this->children[1])),
|
||||
m_this_capture(has_this_capture(this->children[0]->children)),
|
||||
m_lambda_node(std::move(t_children.back()))
|
||||
{ }
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
||||
|
||||
@ -653,25 +651,34 @@ namespace chaiscript
|
||||
}();
|
||||
|
||||
const auto numparams = this->children[1]->children.size();
|
||||
const auto param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[1], t_ss);
|
||||
const auto param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[1], t_ss);
|
||||
|
||||
const auto &lambda_node = this->children.back();
|
||||
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
||||
|
||||
return Boxed_Value(
|
||||
dispatch::make_dynamic_proxy_function(
|
||||
[engine, lambda_node, param_names = this->m_param_names, captures](const std::vector<Boxed_Value> &t_params)
|
||||
[engine, lambda_node = this->m_lambda_node, param_names = this->m_param_names, captures,
|
||||
this_capture = this->m_this_capture] (const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
return detail::eval_function(engine, lambda_node, param_names, t_params, &captures);
|
||||
return detail::eval_function(engine, *lambda_node, param_names, t_params, &captures, this_capture);
|
||||
},
|
||||
static_cast<int>(numparams), lambda_node, param_types
|
||||
static_cast<int>(numparams), m_lambda_node, param_types
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static bool has_this_capture(const std::vector<AST_Node_Impl_Ptr<T>> &children) {
|
||||
return std::any_of(std::begin(children), std::end(children),
|
||||
[](const auto &child){
|
||||
return child->children[0]->text == "this";
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<std::string> m_param_names;
|
||||
|
||||
const bool m_this_capture = false;
|
||||
const std::shared_ptr<AST_Node_Impl<T>> m_lambda_node;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -706,55 +713,81 @@ namespace chaiscript
|
||||
|
||||
template<typename T>
|
||||
struct Def_AST_Node final : AST_Node_Impl<T> {
|
||||
|
||||
std::shared_ptr<AST_Node_Impl<T>> m_body_node;
|
||||
std::shared_ptr<AST_Node_Impl<T>> m_guard_node;
|
||||
|
||||
Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { }
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc),
|
||||
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
||||
std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children, 1)?2:1)))
|
||||
),
|
||||
m_body_node(get_body_node(std::move(t_children))),
|
||||
m_guard_node(get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
|
||||
|
||||
{ }
|
||||
|
||||
static std::shared_ptr<AST_Node_Impl<T>> get_guard_node(std::vector<AST_Node_Impl_Ptr<T>> &&vec, bool has_guard)
|
||||
{
|
||||
if (has_guard) {
|
||||
return std::move(*std::prev(vec.end(), 2));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<AST_Node_Impl<T>> get_body_node(std::vector<AST_Node_Impl_Ptr<T>> &&vec)
|
||||
{
|
||||
return std::move(vec.back());
|
||||
}
|
||||
|
||||
static bool has_guard(const std::vector<AST_Node_Impl_Ptr<T>> &t_children, const std::size_t offset)
|
||||
{
|
||||
if ((t_children.size() > 2 + offset) && (t_children[1+offset]->identifier == AST_Node_Type::Arg_List)) {
|
||||
if (t_children.size() > 3 + offset) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (t_children.size() > 2 + offset) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||
std::vector<std::string> t_param_names;
|
||||
size_t numparams = 0;
|
||||
AST_Node_Impl_Ptr<T> guardnode;
|
||||
|
||||
dispatch::Param_Types param_types;
|
||||
|
||||
if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
||||
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
||||
numparams = this->children[1]->children.size();
|
||||
t_param_names = Arg_List_AST_Node<T>::get_arg_names(this->children[1]);
|
||||
param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[1], t_ss);
|
||||
|
||||
if (this->children.size() > 3) {
|
||||
guardnode = this->children[2];
|
||||
}
|
||||
}
|
||||
else {
|
||||
//no parameters
|
||||
numparams = 0;
|
||||
|
||||
if (this->children.size() > 2) {
|
||||
guardnode = this->children[1];
|
||||
}
|
||||
t_param_names = Arg_List_AST_Node<T>::get_arg_names(*this->children[1]);
|
||||
param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[1], t_ss);
|
||||
}
|
||||
|
||||
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
||||
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
|
||||
if (guardnode) {
|
||||
if (m_guard_node) {
|
||||
guard = dispatch::make_dynamic_proxy_function(
|
||||
[engine, guardnode, t_param_names](const std::vector<Boxed_Value> &t_params)
|
||||
[engine, guardnode = m_guard_node, t_param_names](const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
return detail::eval_function(engine, guardnode, t_param_names, t_params);
|
||||
return detail::eval_function(engine, *guardnode, t_param_names, t_params);
|
||||
},
|
||||
static_cast<int>(numparams), guardnode);
|
||||
static_cast<int>(numparams), m_guard_node);
|
||||
}
|
||||
|
||||
try {
|
||||
const std::string & l_function_name = this->children[0]->text;
|
||||
const auto & func_node = this->children.back();
|
||||
t_ss->add(
|
||||
dispatch::make_dynamic_proxy_function(
|
||||
[engine, guardnode, func_node, t_param_names](const std::vector<Boxed_Value> &t_params)
|
||||
[engine, func_node = m_body_node, t_param_names](const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
return detail::eval_function(engine, func_node, t_param_names, t_params);
|
||||
return detail::eval_function(engine, *func_node, t_param_names, t_params);
|
||||
},
|
||||
static_cast<int>(numparams), this->children.back(),
|
||||
static_cast<int>(numparams), m_body_node,
|
||||
param_types, guard), l_function_name);
|
||||
} catch (const exception::name_conflict_error &e) {
|
||||
throw exception::eval_error("Function redefined '" + e.name() + "'");
|
||||
@ -773,7 +806,7 @@ namespace chaiscript
|
||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||
|
||||
try {
|
||||
while (this->get_bool_condition(this->children[0]->eval(t_ss))) {
|
||||
while (this->get_scoped_bool_condition(*this->children[0], t_ss)) {
|
||||
try {
|
||||
this->children[1]->eval(t_ss);
|
||||
} catch (detail::Continue_Loop &) {
|
||||
@ -808,22 +841,6 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Ternary_Cond_AST_Node final : AST_Node_Impl<T> {
|
||||
Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Ternary_Cond, std::move(t_loc), std::move(t_children))
|
||||
{ assert(this->children.size() == 3); }
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
||||
if (this->get_bool_condition(this->children[0]->eval(t_ss))) {
|
||||
return this->children[1]->eval(t_ss);
|
||||
} else {
|
||||
return this->children[2]->eval(t_ss);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct If_AST_Node final : AST_Node_Impl<T> {
|
||||
@ -834,7 +851,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
||||
if (this->get_bool_condition(this->children[0]->eval(t_ss))) {
|
||||
if (this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)) {
|
||||
return this->children[1]->eval(t_ss);
|
||||
} else {
|
||||
return this->children[2]->eval(t_ss);
|
||||
@ -852,7 +869,7 @@ namespace chaiscript
|
||||
const auto get_function = [&t_ss](const std::string &t_name, auto &t_hint){
|
||||
uint_fast32_t hint = t_hint;
|
||||
auto funs = t_ss->get_function(t_name, hint);
|
||||
if (funs.first != hint) t_hint = uint_fast32_t(funs.first);
|
||||
if (funs.first != hint) { t_hint = uint_fast32_t(funs.first); }
|
||||
return std::move(funs.second);
|
||||
};
|
||||
|
||||
@ -932,7 +949,7 @@ namespace chaiscript
|
||||
try {
|
||||
for (
|
||||
this->children[0]->eval(t_ss);
|
||||
this->get_bool_condition(this->children[1]->eval(t_ss));
|
||||
this->get_scoped_bool_condition(*this->children[1], t_ss);
|
||||
this->children[2]->eval(t_ss)
|
||||
) {
|
||||
try {
|
||||
@ -1253,32 +1270,32 @@ namespace chaiscript
|
||||
}
|
||||
for (size_t i = 1; i < end_point; ++i) {
|
||||
chaiscript::eval::detail::Scope_Push_Pop catch_scope(t_ss);
|
||||
AST_Node_Impl_Ptr<T> catch_block = this->children[i];
|
||||
auto &catch_block = *this->children[i];
|
||||
|
||||
if (catch_block->children.size() == 1) {
|
||||
if (catch_block.children.size() == 1) {
|
||||
//No variable capture, no guards
|
||||
retval = catch_block->children[0]->eval(t_ss);
|
||||
retval = catch_block.children[0]->eval(t_ss);
|
||||
break;
|
||||
} else if (catch_block->children.size() == 2 || catch_block->children.size() == 3) {
|
||||
const auto name = Arg_List_AST_Node<T>::get_arg_name(catch_block->children[0]);
|
||||
} else if (catch_block.children.size() == 2 || catch_block.children.size() == 3) {
|
||||
const auto name = Arg_List_AST_Node<T>::get_arg_name(*catch_block.children[0]);
|
||||
|
||||
if (dispatch::Param_Types(
|
||||
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(catch_block->children[0], t_ss)}
|
||||
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()))
|
||||
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(*catch_block.children[0], t_ss)}
|
||||
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()).first)
|
||||
{
|
||||
t_ss.add_object(name, t_except);
|
||||
|
||||
if (catch_block->children.size() == 2) {
|
||||
if (catch_block.children.size() == 2) {
|
||||
//Variable capture, no guards
|
||||
retval = catch_block->children[1]->eval(t_ss);
|
||||
retval = catch_block.children[1]->eval(t_ss);
|
||||
break;
|
||||
}
|
||||
else if (catch_block->children.size() == 3) {
|
||||
else if (catch_block.children.size() == 3) {
|
||||
//Variable capture, guards
|
||||
|
||||
bool guard = false;
|
||||
try {
|
||||
guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss));
|
||||
guard = boxed_cast<bool>(catch_block.children[1]->eval(t_ss));
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
if (this->children.back()->identifier == AST_Node_Type::Finally) {
|
||||
this->children.back()->children[0]->eval(t_ss);
|
||||
@ -1286,7 +1303,7 @@ namespace chaiscript
|
||||
throw exception::eval_error("Guard condition not boolean");
|
||||
}
|
||||
if (guard) {
|
||||
retval = catch_block->children[2]->eval(t_ss);
|
||||
retval = catch_block.children[2]->eval(t_ss);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1312,11 +1329,8 @@ namespace chaiscript
|
||||
try {
|
||||
retval = this->children[0]->eval(t_ss);
|
||||
}
|
||||
catch (exception::eval_error &) {
|
||||
if (this->children.back()->identifier == AST_Node_Type::Finally) {
|
||||
this->children.back()->children[0]->eval(t_ss);
|
||||
}
|
||||
throw;
|
||||
catch (const exception::eval_error &e) {
|
||||
retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
|
||||
}
|
||||
catch (const std::runtime_error &e) {
|
||||
retval = handle_exception(t_ss, Boxed_Value(std::ref(e)));
|
||||
@ -1361,55 +1375,50 @@ namespace chaiscript
|
||||
|
||||
template<typename T>
|
||||
struct Method_AST_Node final : AST_Node_Impl<T> {
|
||||
std::shared_ptr<AST_Node_Impl<T>> m_body_node;
|
||||
std::shared_ptr<AST_Node_Impl<T>> m_guard_node;
|
||||
|
||||
Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { }
|
||||
AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc),
|
||||
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
||||
std::make_move_iterator(std::prev(t_children.end(), Def_AST_Node<T>::has_guard(t_children, 1)?2:1)))
|
||||
),
|
||||
m_body_node(Def_AST_Node<T>::get_body_node(std::move(t_children))),
|
||||
m_guard_node(Def_AST_Node<T>::get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
|
||||
{
|
||||
}
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||
|
||||
AST_Node_Impl_Ptr<T> guardnode;
|
||||
|
||||
const auto d = t_ss->get_parent_locals();
|
||||
const auto itr = d.find("_current_class_name");
|
||||
const auto class_offset = (itr != d.end())?-1:0;
|
||||
const std::string & class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
|
||||
const std::string & class_name = this->children[0]->text;
|
||||
|
||||
//The first param of a method is always the implied this ptr.
|
||||
std::vector<std::string> t_param_names{"this"};
|
||||
dispatch::Param_Types param_types;
|
||||
|
||||
if ((this->children.size() > static_cast<size_t>(3 + class_offset))
|
||||
&& (this->children[static_cast<size_t>(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) {
|
||||
auto args = Arg_List_AST_Node<T>::get_arg_names(this->children[static_cast<size_t>(2 + class_offset)]);
|
||||
if ((this->children.size() > 2)
|
||||
&& (this->children[2]->identifier == AST_Node_Type::Arg_List)) {
|
||||
auto args = Arg_List_AST_Node<T>::get_arg_names(*this->children[2]);
|
||||
t_param_names.insert(t_param_names.end(), args.begin(), args.end());
|
||||
param_types = Arg_List_AST_Node<T>::get_arg_types(this->children[static_cast<size_t>(2 + class_offset)], t_ss);
|
||||
|
||||
if (this->children.size() > static_cast<size_t>(4 + class_offset)) {
|
||||
guardnode = this->children[static_cast<size_t>(3 + class_offset)];
|
||||
}
|
||||
}
|
||||
else {
|
||||
//no parameters
|
||||
|
||||
if (this->children.size() > static_cast<size_t>(3 + class_offset)) {
|
||||
guardnode = this->children[static_cast<size_t>(2 + class_offset)];
|
||||
}
|
||||
param_types = Arg_List_AST_Node<T>::get_arg_types(*this->children[2], t_ss);
|
||||
}
|
||||
|
||||
const size_t numparams = t_param_names.size();
|
||||
|
||||
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
|
||||
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
|
||||
if (guardnode) {
|
||||
if (m_guard_node) {
|
||||
guard = dispatch::make_dynamic_proxy_function(
|
||||
[engine, t_param_names, guardnode](const std::vector<Boxed_Value> &t_params) {
|
||||
return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params);
|
||||
[engine, t_param_names, guardnode = m_guard_node](const std::vector<Boxed_Value> &t_params) {
|
||||
return chaiscript::eval::detail::eval_function(engine, *guardnode, t_param_names, t_params);
|
||||
},
|
||||
static_cast<int>(numparams), guardnode);
|
||||
static_cast<int>(numparams), m_guard_node);
|
||||
}
|
||||
|
||||
try {
|
||||
const std::string & function_name = this->children[static_cast<size_t>(1 + class_offset)]->text;
|
||||
auto node = this->children.back();
|
||||
const std::string & function_name = this->children[1]->text;
|
||||
|
||||
if (function_name == class_name) {
|
||||
param_types.push_front(class_name, Type_Info());
|
||||
@ -1417,10 +1426,10 @@ namespace chaiscript
|
||||
t_ss->add(
|
||||
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
|
||||
dispatch::make_dynamic_proxy_function(
|
||||
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
|
||||
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
|
||||
[engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
|
||||
return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
|
||||
},
|
||||
static_cast<int>(numparams), node, param_types, guard
|
||||
static_cast<int>(numparams), m_body_node, param_types, guard
|
||||
)
|
||||
),
|
||||
function_name);
|
||||
@ -1431,15 +1440,17 @@ namespace chaiscript
|
||||
auto type = t_ss->get_type(class_name, false);
|
||||
param_types.push_front(class_name, type);
|
||||
|
||||
t_ss->add(std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
|
||||
t_ss->add(
|
||||
std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
|
||||
dispatch::make_dynamic_proxy_function(
|
||||
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
|
||||
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
|
||||
[engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
|
||||
return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
|
||||
},
|
||||
static_cast<int>(numparams), node, param_types, guard), type),
|
||||
static_cast<int>(numparams), m_body_node, param_types, guard), type),
|
||||
function_name);
|
||||
}
|
||||
} catch (const exception::name_conflict_error &e) {
|
||||
std::cout << "Method!!" << std::endl;
|
||||
throw exception::eval_error("Method redefined '" + e.name() + "'");
|
||||
}
|
||||
return void_var();
|
||||
@ -1454,13 +1465,10 @@ namespace chaiscript
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
{
|
||||
const auto &d = t_ss->get_parent_locals();
|
||||
const auto itr = d.find("_current_class_name");
|
||||
const auto class_offset = (itr != d.end())?-1:0;
|
||||
std::string class_name = (itr != d.end())?std::string(boxed_cast<std::string>(itr->second)):this->children[0]->text;
|
||||
std::string class_name = this->children[0]->text;
|
||||
|
||||
try {
|
||||
std::string attr_name = this->children[static_cast<size_t>(1 + class_offset)]->text;
|
||||
std::string attr_name = this->children[1]->text;
|
||||
|
||||
t_ss->add(
|
||||
std::make_shared<dispatch::detail::Dynamic_Object_Function>(
|
||||
@ -1470,7 +1478,7 @@ namespace chaiscript
|
||||
}),
|
||||
true
|
||||
|
||||
), this->children[static_cast<size_t>(1 + class_offset)]->text);
|
||||
), this->children[1]->text);
|
||||
} catch (const exception::name_conflict_error &e) {
|
||||
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
|
||||
}
|
||||
@ -1488,8 +1496,8 @@ namespace chaiscript
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
{
|
||||
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss))
|
||||
&& this->get_bool_condition(this->children[1]->eval(t_ss)));
|
||||
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)
|
||||
&& this->get_bool_condition(this->children[1]->eval(t_ss), t_ss));
|
||||
}
|
||||
|
||||
};
|
||||
@ -1502,8 +1510,8 @@ namespace chaiscript
|
||||
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
|
||||
{
|
||||
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss))
|
||||
|| this->get_bool_condition(this->children[1]->eval(t_ss)));
|
||||
return const_var(this->get_bool_condition(this->children[0]->eval(t_ss), t_ss)
|
||||
|| this->get_bool_condition(this->children[1]->eval(t_ss), t_ss));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
|
||||
@ -17,24 +17,33 @@ namespace chaiscript {
|
||||
struct Optimizer : T...
|
||||
{
|
||||
Optimizer() = default;
|
||||
Optimizer(T ... t)
|
||||
explicit Optimizer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Tracer>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
||||
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(p), 0)... };
|
||||
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(std::move(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;
|
||||
eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) {
|
||||
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||
return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||
} else {
|
||||
return node->children[offset];
|
||||
return *node.children[offset];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<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];
|
||||
}
|
||||
|
||||
|
||||
@ -48,24 +57,24 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
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();
|
||||
auto child_count(const eval::AST_Node_Impl<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();
|
||||
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)
|
||||
auto make_compiled_node(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));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node), std::move(children), std::move(callable));
|
||||
}
|
||||
|
||||
|
||||
struct Return {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> p)
|
||||
{
|
||||
if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
|
||||
&& !p->children.empty())
|
||||
@ -75,7 +84,7 @@ namespace chaiscript {
|
||||
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];
|
||||
last_child->children.back() = std::move(block_last_child->children[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,9 +95,9 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool contains_var_decl_in_scope(const T &node)
|
||||
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node)
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Var_Decl) {
|
||||
if (node.identifier == AST_Node_Type::Var_Decl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -96,8 +105,8 @@ namespace chaiscript {
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
const auto &child = child_at(node, i);
|
||||
if (child->identifier != AST_Node_Type::Block
|
||||
&& child->identifier != AST_Node_Type::For
|
||||
if (child.identifier != AST_Node_Type::Block
|
||||
&& child.identifier != AST_Node_Type::For
|
||||
&& contains_var_decl_in_scope(child)) {
|
||||
return true;
|
||||
}
|
||||
@ -108,15 +117,16 @@ namespace chaiscript {
|
||||
|
||||
struct Block {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if (node->identifier == AST_Node_Type::Block)
|
||||
{
|
||||
if (!contains_var_decl_in_scope(node))
|
||||
if (!contains_var_decl_in_scope(*node))
|
||||
{
|
||||
if (node->children.size() == 1) {
|
||||
return node->children[0];
|
||||
return std::move(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 chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location,
|
||||
std::move(node->children));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,7 +137,7 @@ namespace chaiscript {
|
||||
|
||||
struct Dead_Code {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if (node->identifier == AST_Node_Type::Block)
|
||||
{
|
||||
std::vector<size_t> keepers;
|
||||
@ -135,10 +145,10 @@ namespace chaiscript {
|
||||
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)
|
||||
const 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);
|
||||
}
|
||||
@ -147,12 +157,16 @@ namespace chaiscript {
|
||||
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);
|
||||
const auto new_children = [&](){
|
||||
std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
|
||||
for (const auto x : keepers)
|
||||
{
|
||||
retval.push_back(std::move(node->children[x]));
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children());
|
||||
}
|
||||
} else {
|
||||
return node;
|
||||
@ -162,29 +176,30 @@ namespace chaiscript {
|
||||
|
||||
struct Unused_Return {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
if ((node->identifier == AST_Node_Type::Block
|
||||
|| node->identifier == AST_Node_Type::Scopeless_Block)
|
||||
&& node->children.size() > 0)
|
||||
&& !node->children.empty())
|
||||
{
|
||||
for (size_t i = 0; i < node->children.size()-1; ++i) {
|
||||
auto child = node->children[i];
|
||||
auto child = node->children[i].get();
|
||||
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));
|
||||
node->children[i] = chaiscript::make_unique<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)
|
||||
&& 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));
|
||||
auto &sub_child = child_at(child, i);
|
||||
if (sub_child.identifier == AST_Node_Type::Fun_Call) {
|
||||
child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child.text, sub_child.location, std::move(sub_child.children));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,17 +210,17 @@ namespace chaiscript {
|
||||
|
||||
struct If {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if ((node->identifier == AST_Node_Type::If || node->identifier == AST_Node_Type::Ternary_Cond)
|
||||
auto optimize(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;
|
||||
const auto condition = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[0].get())->m_value;
|
||||
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||
if (boxed_cast<bool>(condition)) {
|
||||
return node->children[1];
|
||||
return std::move(node->children[1]);
|
||||
} else if (node->children.size() == 3) {
|
||||
return node->children[2];
|
||||
return std::move(node->children[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,7 +231,7 @@ namespace chaiscript {
|
||||
|
||||
struct Partial_Fold {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
|
||||
// Fold right side
|
||||
if (node->identifier == AST_Node_Type::Binary
|
||||
@ -228,9 +243,10 @@ namespace chaiscript {
|
||||
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;
|
||||
const auto rhs = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[1].get())->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);
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location,
|
||||
std::move(node->children), rhs);
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
@ -244,7 +260,7 @@ namespace chaiscript {
|
||||
|
||||
struct Constant_Fold {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
|
||||
|
||||
if (node->identifier == AST_Node_Type::Prefix
|
||||
&& node->children.size() == 1
|
||||
@ -253,14 +269,14 @@ namespace chaiscript {
|
||||
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 lhs = dynamic_cast<const eval::Constant_AST_Node<T> *>(node->children[0].get())->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));
|
||||
return chaiscript::make_unique<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)));
|
||||
return chaiscript::make_unique<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
|
||||
@ -271,8 +287,8 @@ namespace chaiscript {
|
||||
&& 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;
|
||||
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
||||
const auto rhs = dynamic_cast<const 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] {
|
||||
@ -280,7 +296,7 @@ namespace chaiscript {
|
||||
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));
|
||||
return chaiscript::make_unique<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
|
||||
@ -294,12 +310,12 @@ namespace chaiscript {
|
||||
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;
|
||||
const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
|
||||
const auto rhs = dynamic_cast<const 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));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
@ -312,13 +328,13 @@ namespace chaiscript {
|
||||
&& 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;
|
||||
const auto arg = dynamic_cast<const 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));
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
||||
};
|
||||
|
||||
if (fun_name == "double") {
|
||||
@ -344,35 +360,36 @@ namespace chaiscript {
|
||||
|
||||
struct For_Loop {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &for_node) {
|
||||
auto optimize(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);
|
||||
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
|
||||
if (child_count(*for_node) == 4
|
||||
&& 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_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_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)
|
||||
&& 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;
|
||||
const Boxed_Value &begin = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(eq_node, 1)).m_value;
|
||||
const Boxed_Value &end = dynamic_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>())) {
|
||||
@ -380,9 +397,14 @@ namespace chaiscript {
|
||||
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},
|
||||
// note that we are moving the last element out, then popping the empty shared_ptr
|
||||
// from the vector
|
||||
std::vector<eval::AST_Node_Impl_Ptr<T>> body_vector;
|
||||
auto body_child = std::move(for_node->children[3]);
|
||||
for_node->children.pop_back();
|
||||
body_vector.emplace_back(std::move(body_child));
|
||||
|
||||
return make_compiled_node(std::move(for_node), std::move(body_vector),
|
||||
[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);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||
@ -15,10 +15,10 @@ namespace chaiscript
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
explicit DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (!m_data)
|
||||
if (m_data == nullptr)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// and 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||
@ -10,10 +10,11 @@
|
||||
namespace chaiscript {
|
||||
namespace eval {
|
||||
|
||||
struct Noop_Tracer
|
||||
|
||||
struct Noop_Tracer_Detail
|
||||
{
|
||||
template<typename T>
|
||||
static void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
|
||||
void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -22,13 +23,13 @@ namespace chaiscript {
|
||||
struct Tracer : T...
|
||||
{
|
||||
Tracer() = default;
|
||||
Tracer(T ... t)
|
||||
explicit Tracer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
}
|
||||
|
||||
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
(void)std::initializer_list<int>{ (T::trace(ds, node), 0)... };
|
||||
(void)std::initializer_list<int>{ (static_cast<T&>(*this).trace(ds, node), 0)... };
|
||||
}
|
||||
|
||||
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
@ -36,6 +37,8 @@ namespace chaiscript {
|
||||
}
|
||||
};
|
||||
|
||||
typedef Tracer<Noop_Tracer_Detail> Noop_Tracer;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||
@ -16,7 +16,11 @@ namespace chaiscript
|
||||
{
|
||||
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;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_WINDOWS_HPP_
|
||||
@ -80,7 +80,7 @@ namespace chaiscript
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
explicit DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
|
||||
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
|
||||
@ -386,12 +386,12 @@ class JSON
|
||||
return "null";
|
||||
case Class::Object: {
|
||||
std::string pad = "";
|
||||
for( long i = 0; i < depth; ++i, pad += tab );
|
||||
for( long i = 0; i < depth; ++i, pad += tab ) { }
|
||||
|
||||
std::string s = "{\n";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.Map ) {
|
||||
if( !skip ) s += ",\n";
|
||||
if( !skip ) { s += ",\n"; }
|
||||
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||
skip = false;
|
||||
}
|
||||
@ -402,7 +402,7 @@ class JSON
|
||||
std::string s = "[";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.List ) {
|
||||
if( !skip ) s += ", ";
|
||||
if( !skip ) { s += ", "; }
|
||||
s += p.dump( depth + 1, tab );
|
||||
skip = false;
|
||||
}
|
||||
@ -426,8 +426,8 @@ class JSON
|
||||
private:
|
||||
static std::string json_escape( const std::string &str ) {
|
||||
std::string output;
|
||||
for( size_t i = 0; i < str.length(); ++i )
|
||||
switch( str[i] ) {
|
||||
for(char i : str) {
|
||||
switch( i ) {
|
||||
case '\"': output += "\\\""; break;
|
||||
case '\\': output += "\\\\"; break;
|
||||
case '\b': output += "\\b"; break;
|
||||
@ -435,8 +435,9 @@ class JSON
|
||||
case '\n': output += "\\n"; break;
|
||||
case '\r': output += "\\r"; break;
|
||||
case '\t': output += "\\t"; break;
|
||||
default : output += str[i]; break;
|
||||
default : output += i; break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -462,7 +463,7 @@ struct JSONParser {
|
||||
}
|
||||
|
||||
static void consume_ws( const std::string &str, size_t &offset ) {
|
||||
while( isspace( str[offset] ) && offset <= str.size() ) ++offset;
|
||||
while( isspace( str.at(offset) ) && offset <= str.size() ) { ++offset; }
|
||||
}
|
||||
|
||||
static JSON parse_object( const std::string &str, size_t &offset ) {
|
||||
@ -470,29 +471,29 @@ struct JSONParser {
|
||||
|
||||
++offset;
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] == '}' ) {
|
||||
if( str.at(offset) == '}' ) {
|
||||
++offset; return Object;
|
||||
}
|
||||
|
||||
for (;offset<str.size();) {
|
||||
JSON Key = parse_next( str, offset );
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] != ':' ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str[offset] + "'\n");
|
||||
if( str.at(offset) != ':' ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str.at(offset) + "'\n");
|
||||
}
|
||||
consume_ws( str, ++offset );
|
||||
JSON Value = parse_next( str, offset );
|
||||
Object[Key.to_string()] = Value;
|
||||
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] == ',' ) {
|
||||
if( str.at(offset) == ',' ) {
|
||||
++offset; continue;
|
||||
}
|
||||
else if( str[offset] == '}' ) {
|
||||
else if( str.at(offset) == '}' ) {
|
||||
++offset; break;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str[offset] + "'\n");
|
||||
throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str.at(offset) + "'\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,7 +506,7 @@ struct JSONParser {
|
||||
|
||||
++offset;
|
||||
consume_ws( str, offset );
|
||||
if( str[offset] == ']' ) {
|
||||
if( str.at(offset) == ']' ) {
|
||||
++offset; return Array;
|
||||
}
|
||||
|
||||
@ -513,14 +514,14 @@ struct JSONParser {
|
||||
Array[index++] = parse_next( str, offset );
|
||||
consume_ws( str, offset );
|
||||
|
||||
if( str[offset] == ',' ) {
|
||||
if( str.at(offset) == ',' ) {
|
||||
++offset; continue;
|
||||
}
|
||||
else if( str[offset] == ']' ) {
|
||||
else if( str.at(offset) == ']' ) {
|
||||
++offset; break;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str[offset] + "'\n");
|
||||
throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str.at(offset) + "'\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,9 +530,9 @@ struct JSONParser {
|
||||
|
||||
static JSON parse_string( const std::string &str, size_t &offset ) {
|
||||
std::string val;
|
||||
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) {
|
||||
for( char c = str.at(++offset); c != '\"' ; c = str.at(++offset) ) {
|
||||
if( c == '\\' ) {
|
||||
switch( str[ ++offset ] ) {
|
||||
switch( str.at(++offset) ) {
|
||||
case '\"': val += '\"'; break;
|
||||
case '\\': val += '\\'; break;
|
||||
case '/' : val += '/' ; break;
|
||||
@ -543,10 +544,10 @@ struct JSONParser {
|
||||
case 'u' : {
|
||||
val += "\\u" ;
|
||||
for( size_t i = 1; i <= 4; ++i ) {
|
||||
c = str[offset+i];
|
||||
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
|
||||
c = str.at(offset+i);
|
||||
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) {
|
||||
val += c;
|
||||
else {
|
||||
} else {
|
||||
throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
||||
}
|
||||
}
|
||||
@ -554,9 +555,9 @@ struct JSONParser {
|
||||
} break;
|
||||
default : val += '\\'; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
val += c;
|
||||
}
|
||||
}
|
||||
++offset;
|
||||
return JSON(val);
|
||||
@ -566,33 +567,43 @@ struct JSONParser {
|
||||
std::string val, exp_str;
|
||||
char c = '\0';
|
||||
bool isDouble = false;
|
||||
bool isNegative = false;
|
||||
long exp = 0;
|
||||
if( offset < str.size() && str.at(offset) == '-' ) {
|
||||
isNegative = true;
|
||||
++offset;
|
||||
}
|
||||
for (; offset < str.size() ;) {
|
||||
c = str[offset++];
|
||||
if( (c == '-') || (c >= '0' && c <= '9') )
|
||||
c = str.at(offset++);
|
||||
if( c >= '0' && c <= '9' ) {
|
||||
val += c;
|
||||
else if( c == '.' ) {
|
||||
} else if( c == '.' && !isDouble ) {
|
||||
val += c;
|
||||
isDouble = true;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( offset < str.size() && (c == 'E' || c == 'e' )) {
|
||||
c = str[ offset++ ];
|
||||
if( c == '-' ) { exp_str += '-';}
|
||||
else if( c == '+' ) { }
|
||||
else --offset;
|
||||
c = str.at(offset++);
|
||||
if( c == '-' ) {
|
||||
exp_str += '-';
|
||||
} else if( c == '+' ) {
|
||||
// do nothing
|
||||
} else {
|
||||
--offset;
|
||||
}
|
||||
|
||||
for (; offset < str.size() ;) {
|
||||
c = str[ offset++ ];
|
||||
if( c >= '0' && c <= '9' )
|
||||
c = str.at(offset++);
|
||||
if( c >= '0' && c <= '9' ) {
|
||||
exp_str += c;
|
||||
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||
} else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'");
|
||||
}
|
||||
else
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
exp = chaiscript::parse_num<long>( exp_str );
|
||||
}
|
||||
@ -602,12 +613,12 @@ struct JSONParser {
|
||||
--offset;
|
||||
|
||||
if( isDouble ) {
|
||||
return JSON(chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||
} else {
|
||||
if( !exp_str.empty() ) {
|
||||
return JSON(static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp ));
|
||||
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp ));
|
||||
} else {
|
||||
return JSON(chaiscript::parse_num<long>( val ));
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<long>( val ));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -635,7 +646,7 @@ struct JSONParser {
|
||||
static JSON parse_next( const std::string &str, size_t &offset ) {
|
||||
char value;
|
||||
consume_ws( str, offset );
|
||||
value = str[offset];
|
||||
value = str.at(offset);
|
||||
switch( value ) {
|
||||
case '[' : return parse_array( str, offset );
|
||||
case '{' : return parse_object( str, offset );
|
||||
@ -643,8 +654,9 @@ struct JSONParser {
|
||||
case 't' :
|
||||
case 'f' : return parse_bool( str, offset );
|
||||
case 'n' : return parse_null( str, offset );
|
||||
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
|
||||
default : if( ( value <= '9' && value >= '0' ) || value == '-' ) {
|
||||
return parse_number( str, offset );
|
||||
}
|
||||
}
|
||||
throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'");
|
||||
}
|
||||
|
||||
@ -63,7 +63,11 @@ namespace chaiscript
|
||||
|
||||
static Boxed_Value from_json(const std::string &t_json)
|
||||
{
|
||||
return from_json( json::JSON::Load(t_json) );
|
||||
try {
|
||||
return from_json( json::JSON::Load(t_json) );
|
||||
} catch (const std::out_of_range& ) {
|
||||
throw std::runtime_error("Unparsed JSON input");
|
||||
}
|
||||
}
|
||||
|
||||
static std::string to_json(const Boxed_Value &t_bv)
|
||||
|
||||
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.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
|
||||
@ -89,6 +93,29 @@ namespace chaiscript
|
||||
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename EnumClass, typename ModuleType>
|
||||
typename std::enable_if<std::is_enum<EnumClass>::value, void>::type
|
||||
add_class(ModuleType &t_module,
|
||||
const std::string &t_class_name,
|
||||
const std::vector<std::pair<EnumClass, std::string>> &t_constants
|
||||
)
|
||||
{
|
||||
t_module.add(chaiscript::user_type<EnumClass>(), t_class_name);
|
||||
|
||||
t_module.add(chaiscript::constructor<EnumClass()>(), t_class_name);
|
||||
t_module.add(chaiscript::constructor<EnumClass(const EnumClass &)>(), t_class_name);
|
||||
|
||||
using namespace chaiscript::bootstrap::operators;
|
||||
equal<EnumClass>(t_module);
|
||||
not_equal<EnumClass>(t_module);
|
||||
assign<EnumClass>(t_module);
|
||||
|
||||
for (const auto &constant : t_constants)
|
||||
{
|
||||
t_module.add_global_const(chaiscript::const_var(EnumClass(constant.first)), constant.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
55
readme.md
55
readme.md
@ -17,7 +17,7 @@ ChaiScript
|
||||
http://www.chaiscript.com
|
||||
|
||||
(c) 2009-2012 Jonathan Turner
|
||||
(c) 2009-2016 Jason Turner
|
||||
(c) 2009-2017 Jason Turner
|
||||
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
@ -79,7 +79,7 @@ directory, and for more in-depth look at the language, the unit tests in the
|
||||
"unittests" directory cover the most ground.
|
||||
|
||||
For examples of how to register parts of your C++ application, see
|
||||
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
|
||||
"example.cpp" in the "samples" directory. Example.cpp is verbose and shows every
|
||||
possible way of working with the library. For further documentation generate
|
||||
the doxygen documentation in the build folder or see the website
|
||||
http://www.chaiscript.com.
|
||||
@ -87,44 +87,21 @@ http://www.chaiscript.com.
|
||||
|
||||
The shortest complete example possible follows:
|
||||
|
||||
/// main.cpp
|
||||
```C++
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Or, if you want to compile the std lib into your code, which reduces
|
||||
runtime requirements.
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
||||
```
|
||||
|
||||
@ -26,13 +26,20 @@ Current Version: 6.0.0
|
||||
|
||||
* 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 ) { }`
|
||||
* 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
|
||||
|
||||
@ -41,6 +48,9 @@ Current Version: 6.0.0
|
||||
|
||||
### 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
|
||||
|
||||
12
samples/BUCK
Normal file
12
samples/BUCK
Normal file
@ -0,0 +1,12 @@
|
||||
cxx_binary(
|
||||
name = 'example',
|
||||
srcs = [
|
||||
'example.cpp',
|
||||
],
|
||||
compiler_flags = [
|
||||
'-std=c++14',
|
||||
],
|
||||
deps = [
|
||||
'//:chaiscript',
|
||||
],
|
||||
)
|
||||
@ -108,9 +108,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
// A shortcut to using eval is just to use the chai operator()
|
||||
chai("log(\"Test Module\", \"Test Message\");");
|
||||
|
||||
//Finally, it is possible to register any std::function as a system function, in this
|
||||
//Finally, it is possible to register a lambda as a system function, in this
|
||||
//way, we can, for instance add a bound member function to the system
|
||||
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
chai.add(fun([&system](){ return system.do_callbacks("Bound Test"); }), "do_callbacks");
|
||||
|
||||
//Call bound version of do_callbacks
|
||||
chai("do_callbacks()");
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
@ -64,6 +68,7 @@ std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
||||
@ -133,6 +138,7 @@ std::vector<std::string> default_search_paths()
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
|
||||
return paths;
|
||||
}
|
||||
@ -246,7 +252,7 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
342
src/libfuzzer_client.cpp
Normal file
342
src/libfuzzer_client.cpp
Normal file
@ -0,0 +1,342 @@
|
||||
// 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
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include "../static_libs/chaiscript_parser.hpp"
|
||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
|
||||
char *mystrdup (const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
if (d == nullptr) { return nullptr; } // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len+1, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d,s,len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
std::string retval;
|
||||
std::cout << p ;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char* /*unused*/){}
|
||||
void using_history(){}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string> (*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
std::vector<std::string> (*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = t_path;
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
|
||||
}
|
||||
#else
|
||||
|
||||
std::string exepath;
|
||||
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
|
||||
{
|
||||
exepath = std::string(&buf.front(), static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
exepath = std::string(rInfo.dli_fname);
|
||||
}
|
||||
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash+1));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void help(int n) {
|
||||
if ( n >= 0 ) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
|
||||
std::cout << "Additionally, you can inspect the runtime system using:\n";
|
||||
std::cout << " dump_system() - outputs all functions registered to the system\n";
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||
} else {
|
||||
std::cout << "usage : chai [option]+\n";
|
||||
std::cout << "option:" << '\n';
|
||||
std::cout << " -h | --help" << '\n';
|
||||
std::cout << " -i | --interactive" << '\n';
|
||||
std::cout << " -c | --command cmd" << '\n';
|
||||
std::cout << " -v | --version" << '\n';
|
||||
std::cout << " - --stdin" << '\n';
|
||||
std::cout << " filepath" << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
} catch (...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
} catch (const chaiscript::exception::eval_error &e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
throw std::runtime_error("no exception throw");
|
||||
}
|
||||
|
||||
std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if ( ! std::cin.eof() ) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if ( input_raw != nullptr ) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos+1, std::string::npos);
|
||||
}
|
||||
|
||||
retval = val;
|
||||
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if( retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// We have to wrap exit with our own because Clang has a hard time with
|
||||
// function pointers to functions with special attributes (system exit being marked NORETURN)
|
||||
void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript_Basic& chai)
|
||||
{
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
std::string input = get_next_command();
|
||||
try {
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if ( !ee.call_stack.empty() ) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double now()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto now = high_resolution_clock::now();
|
||||
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.eval( R"chaiscript(
|
||||
def assert_equal(x, y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
// Passes
|
||||
} else {
|
||||
// Fails
|
||||
print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_false(f)
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
print("assert_false failure");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_true(f)
|
||||
{
|
||||
if (!f)
|
||||
{
|
||||
print("assert_true failure");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_not_equal(x, y)
|
||||
{
|
||||
if (!(x == y))
|
||||
{
|
||||
// Passes
|
||||
} else {
|
||||
// Fails
|
||||
print("assert_not_equal failure: got " + to_string(y) + " which was not expected.");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_throws(desc, x)
|
||||
{
|
||||
if (throws_exception(x))
|
||||
{
|
||||
// Passes
|
||||
} else {
|
||||
// Fails
|
||||
print("assert_throws failure, function did not throw exception: " + to_string(desc));
|
||||
// exit(-1);
|
||||
}
|
||||
})chaiscript");
|
||||
|
||||
try {
|
||||
chai.eval(std::string(reinterpret_cast<const char *>(data), size));
|
||||
} catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << '\n';
|
||||
} catch (const chaiscript::Boxed_Value &e) {
|
||||
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << "unhandled unknown exception: " << e.what() << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
51
src/main.cpp
51
src/main.cpp
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
@ -25,7 +29,7 @@
|
||||
char *mystrdup (const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
if (d == nullptr) { return nullptr; } // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len+1, s); // Copy the characters
|
||||
#else
|
||||
@ -44,7 +48,7 @@ char* readline(const char* p)
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char*){}
|
||||
void add_history(const char* /*unused*/){}
|
||||
void using_history(){}
|
||||
#endif
|
||||
|
||||
@ -67,6 +71,7 @@ std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
|
||||
@ -116,7 +121,7 @@ std::vector<std::string> default_search_paths()
|
||||
{
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
if ( !dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname ) {
|
||||
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
@ -136,6 +141,7 @@ std::vector<std::string> default_search_paths()
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
|
||||
return paths;
|
||||
}
|
||||
@ -184,7 +190,7 @@ std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if ( ! std::cin.eof() ) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if ( input_raw ) {
|
||||
if ( input_raw != nullptr ) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
@ -240,8 +246,8 @@ void interactive(chaiscript::ChaiScript_Basic& chai)
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
|
||||
if ( !ee.call_stack.empty() ) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
@ -277,7 +283,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.push_back("");
|
||||
if (usepath)
|
||||
if (usepath != nullptr)
|
||||
{
|
||||
usepaths.push_back(usepath);
|
||||
}
|
||||
@ -286,7 +292,7 @@ int main(int argc, char *argv[])
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
if (modulepath != nullptr)
|
||||
{
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
@ -302,13 +308,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
bool eval_error_ok = false;
|
||||
bool boxed_exception_ok = false;
|
||||
bool any_exception_ok = false;
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if ( i == 0 && argc > 1 ) {
|
||||
++i;
|
||||
}
|
||||
|
||||
std::string arg( i ? argv[i] : "--interactive" );
|
||||
std::string arg( i != 0 ? argv[i] : "--interactive" );
|
||||
|
||||
enum { eInteractive
|
||||
, eCommand
|
||||
@ -319,9 +326,9 @@ int main(int argc, char *argv[])
|
||||
if ( (i+1) >= argc ) {
|
||||
std::cout << "insufficient input following " << arg << '\n';
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
}
|
||||
arg = argv[++i];
|
||||
}
|
||||
|
||||
} else if ( arg == "-" || arg == "--stdin" ) {
|
||||
arg = "" ;
|
||||
std::string line;
|
||||
@ -338,6 +345,9 @@ int main(int argc, char *argv[])
|
||||
} else if ( arg == "--exception" ) {
|
||||
boxed_exception_ok = true;
|
||||
continue;
|
||||
} else if ( arg == "--any-exception" ) {
|
||||
any_exception_ok = true;
|
||||
continue;
|
||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
||||
mode = eInteractive ;
|
||||
} else if ( arg.find('-') == 0 ) {
|
||||
@ -377,11 +387,18 @@ int main(int argc, char *argv[])
|
||||
catch (const chaiscript::exception::load_module_error &e) {
|
||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
||||
}
|
||||
|
||||
// catch (std::exception &e) {
|
||||
// std::cout << e.what() << '\n';
|
||||
// return EXIT_FAILURE;
|
||||
// }
|
||||
catch (std::exception &e) {
|
||||
std::cout << "Unhandled standard exception: " << e.what() << '\n';
|
||||
if (!any_exception_ok) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
std::cout << "Unhandled unknown exception" << '\n';
|
||||
if (!any_exception_ok) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <list>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Catch v1.3.5
|
||||
* Generated: 2016-02-29 08:16:42.342094
|
||||
* Catch v1.5.7
|
||||
* Generated: 2016-09-27 10:45:46.824849
|
||||
* ----------------------------------------------------------
|
||||
* This file has been merged from multiple headers. Please don't edit it directly
|
||||
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
||||
@ -62,7 +62,11 @@
|
||||
|
||||
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
|
||||
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
|
||||
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
||||
#ifdef CATCH_CONFIG_COUNTER
|
||||
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
|
||||
#else
|
||||
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
||||
#endif
|
||||
|
||||
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
|
||||
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
|
||||
@ -89,7 +93,7 @@
|
||||
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
|
||||
|
||||
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
|
||||
|
||||
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
|
||||
// ****************
|
||||
// Note to maintainers: if new toggles are added please document them
|
||||
// in configuration.md, too
|
||||
@ -102,8 +106,16 @@
|
||||
|
||||
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
# define CATCH_CPP11_OR_GREATER
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if __cplusplus >= 201103L
|
||||
# define CATCH_CPP11_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if __cplusplus >= 201402L
|
||||
# define CATCH_CPP14_OR_GREATER
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
@ -185,6 +197,15 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Use __COUNTER__ if the compiler supports it
|
||||
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
|
||||
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
|
||||
( defined __clang__ && __clang_major__ >= 3 )
|
||||
|
||||
#define CATCH_INTERNAL_CONFIG_COUNTER
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// C++ language feature support
|
||||
|
||||
@ -256,6 +277,9 @@
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||
# define CATCH_CONFIG_COUNTER
|
||||
#endif
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||
@ -686,24 +710,28 @@ void registerTestCaseFunction
|
||||
|
||||
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||
static void TestName(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
||||
namespace{ \
|
||||
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
|
||||
struct TestName : ClassName{ \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
|
||||
} \
|
||||
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
|
||||
void TestName::test()
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
||||
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
||||
@ -711,24 +739,28 @@ void registerTestCaseFunction
|
||||
|
||||
#else
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
|
||||
static void TestName(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
|
||||
namespace{ \
|
||||
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
|
||||
struct TestCaseName : ClassName{ \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
|
||||
} \
|
||||
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
|
||||
void TestCaseName::test()
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
|
||||
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
|
||||
@ -2041,7 +2073,7 @@ namespace Catch {
|
||||
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
|
||||
} \
|
||||
INTERNAL_CATCH_REACT( __catchResult ) \
|
||||
} while( Catch::isTrue( false && static_cast<bool>(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
|
||||
} while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
|
||||
@ -2578,10 +2610,12 @@ namespace Catch {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
|
||||
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
|
||||
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
|
||||
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
|
||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
|
||||
static std::string translatorName( signature ); \
|
||||
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
|
||||
static std::string translatorName( signature )
|
||||
|
||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
|
||||
|
||||
// #included from: internal/catch_approx.hpp
|
||||
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
||||
@ -3189,10 +3223,11 @@ namespace Catch {
|
||||
|
||||
bool matches( TestCaseInfo const& testCase ) const {
|
||||
// All patterns in a filter must match for the filter to be a match
|
||||
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
|
||||
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
|
||||
if( !(*it)->matches( testCase ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -3424,7 +3459,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
class DebugOutStream : public IStream {
|
||||
std::auto_ptr<StreamBufBase> m_streamBuf;
|
||||
CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
|
||||
mutable std::ostream m_os;
|
||||
public:
|
||||
DebugOutStream();
|
||||
@ -3572,7 +3607,7 @@ namespace Catch {
|
||||
}
|
||||
ConfigData m_data;
|
||||
|
||||
std::auto_ptr<IStream const> m_stream;
|
||||
CATCH_AUTO_PTR( IStream const ) m_stream;
|
||||
TestSpec m_testSpec;
|
||||
};
|
||||
|
||||
@ -3592,7 +3627,7 @@ namespace Catch {
|
||||
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
|
||||
// #included from: ../external/clara.h
|
||||
|
||||
// Version 0.0.1.1
|
||||
// Version 0.0.2.4
|
||||
|
||||
// Only use header guard if we are not using an outer namespace
|
||||
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
|
||||
@ -3908,6 +3943,10 @@ namespace Tbc {
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
||||
#define CLARA_PLATFORM_WINDOWS
|
||||
#endif
|
||||
|
||||
// Use optional outer namespace
|
||||
#ifdef STITCH_CLARA_OPEN_NAMESPACE
|
||||
STITCH_CLARA_OPEN_NAMESPACE
|
||||
@ -3931,9 +3970,6 @@ namespace Clara {
|
||||
const unsigned int consoleWidth = 80;
|
||||
#endif
|
||||
|
||||
// Use this to try and stop compiler from warning about unreachable code
|
||||
inline bool isTrue( bool value ) { return value; }
|
||||
|
||||
using namespace Tbc;
|
||||
|
||||
inline bool startsWith( std::string const& str, std::string const& prefix ) {
|
||||
@ -3969,14 +4005,6 @@ namespace Clara {
|
||||
else
|
||||
throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
|
||||
}
|
||||
inline void convertInto( bool _source, bool& _dest ) {
|
||||
_dest = _source;
|
||||
}
|
||||
template<typename T>
|
||||
inline void convertInto( bool, T& ) {
|
||||
if( isTrue( true ) )
|
||||
throw std::runtime_error( "Invalid conversion" );
|
||||
}
|
||||
|
||||
template<typename ConfigT>
|
||||
struct IArgFunction {
|
||||
@ -3986,7 +4014,6 @@ namespace Clara {
|
||||
IArgFunction( IArgFunction const& ) = default;
|
||||
#endif
|
||||
virtual void set( ConfigT& config, std::string const& value ) const = 0;
|
||||
virtual void setFlag( ConfigT& config ) const = 0;
|
||||
virtual bool takesArg() const = 0;
|
||||
virtual IArgFunction* clone() const = 0;
|
||||
};
|
||||
@ -4008,9 +4035,6 @@ namespace Clara {
|
||||
void set( ConfigT& config, std::string const& value ) const {
|
||||
functionObj->set( config, value );
|
||||
}
|
||||
void setFlag( ConfigT& config ) const {
|
||||
functionObj->setFlag( config );
|
||||
}
|
||||
bool takesArg() const { return functionObj->takesArg(); }
|
||||
|
||||
bool isSet() const {
|
||||
@ -4023,7 +4047,6 @@ namespace Clara {
|
||||
template<typename C>
|
||||
struct NullBinder : IArgFunction<C>{
|
||||
virtual void set( C&, std::string const& ) const {}
|
||||
virtual void setFlag( C& ) const {}
|
||||
virtual bool takesArg() const { return true; }
|
||||
virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
|
||||
};
|
||||
@ -4034,9 +4057,6 @@ namespace Clara {
|
||||
virtual void set( C& p, std::string const& stringValue ) const {
|
||||
convertInto( stringValue, p.*member );
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
convertInto( true, p.*member );
|
||||
}
|
||||
virtual bool takesArg() const { return !IsBool<M>::value; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
|
||||
M C::* member;
|
||||
@ -4049,11 +4069,6 @@ namespace Clara {
|
||||
convertInto( stringValue, value );
|
||||
(p.*member)( value );
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
typename RemoveConstRef<M>::type value;
|
||||
convertInto( true, value );
|
||||
(p.*member)( value );
|
||||
}
|
||||
virtual bool takesArg() const { return !IsBool<M>::value; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
|
||||
void (C::*member)( M );
|
||||
@ -4067,9 +4082,6 @@ namespace Clara {
|
||||
if( value )
|
||||
(p.*member)();
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
(p.*member)();
|
||||
}
|
||||
virtual bool takesArg() const { return false; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
|
||||
void (C::*member)();
|
||||
@ -4084,9 +4096,6 @@ namespace Clara {
|
||||
if( value )
|
||||
function( obj );
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
function( p );
|
||||
}
|
||||
virtual bool takesArg() const { return false; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
|
||||
void (*function)( C& );
|
||||
@ -4100,11 +4109,6 @@ namespace Clara {
|
||||
convertInto( stringValue, value );
|
||||
function( obj, value );
|
||||
}
|
||||
virtual void setFlag( C& obj ) const {
|
||||
typename RemoveConstRef<T>::type value;
|
||||
convertInto( true, value );
|
||||
function( obj, value );
|
||||
}
|
||||
virtual bool takesArg() const { return !IsBool<T>::value; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
|
||||
void (*function)( C&, T );
|
||||
@ -4112,8 +4116,20 @@ namespace Clara {
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
struct Parser {
|
||||
Parser() : separators( " \t=:" ) {}
|
||||
inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
|
||||
std::vector<std::string> args( static_cast<std::size_t>( argc ) );
|
||||
for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
|
||||
args[i] = argv[i];
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
class Parser {
|
||||
enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
|
||||
Mode mode;
|
||||
std::size_t from;
|
||||
bool inQuotes;
|
||||
public:
|
||||
|
||||
struct Token {
|
||||
enum Type { Positional, ShortOpt, LongOpt };
|
||||
@ -4122,38 +4138,75 @@ namespace Clara {
|
||||
std::string data;
|
||||
};
|
||||
|
||||
void parseIntoTokens( int argc, char const* const argv[], std::vector<Parser::Token>& tokens ) const {
|
||||
Parser() : mode( None ), from( 0 ), inQuotes( false ){}
|
||||
|
||||
void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
|
||||
const std::string doubleDash = "--";
|
||||
for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
|
||||
parseIntoTokens( argv[i] , tokens);
|
||||
for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
|
||||
parseIntoTokens( args[i], tokens);
|
||||
}
|
||||
void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
|
||||
while( !arg.empty() ) {
|
||||
Parser::Token token( Parser::Token::Positional, arg );
|
||||
arg = "";
|
||||
if( token.data[0] == '-' ) {
|
||||
if( token.data.size() > 1 && token.data[1] == '-' ) {
|
||||
token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
|
||||
}
|
||||
else {
|
||||
token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
|
||||
if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
|
||||
arg = "-" + token.data.substr( 1 );
|
||||
token.data = token.data.substr( 0, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( token.type != Parser::Token::Positional ) {
|
||||
std::size_t pos = token.data.find_first_of( separators );
|
||||
if( pos != std::string::npos ) {
|
||||
arg = token.data.substr( pos+1 );
|
||||
token.data = token.data.substr( 0, pos );
|
||||
}
|
||||
}
|
||||
tokens.push_back( token );
|
||||
|
||||
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
|
||||
for( std::size_t i = 0; i <= arg.size(); ++i ) {
|
||||
char c = arg[i];
|
||||
if( c == '"' )
|
||||
inQuotes = !inQuotes;
|
||||
mode = handleMode( i, c, arg, tokens );
|
||||
}
|
||||
}
|
||||
std::string separators;
|
||||
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
|
||||
switch( mode ) {
|
||||
case None: return handleNone( i, c );
|
||||
case MaybeShortOpt: return handleMaybeShortOpt( i, c );
|
||||
case ShortOpt:
|
||||
case LongOpt:
|
||||
case SlashOpt: return handleOpt( i, c, arg, tokens );
|
||||
case Positional: return handlePositional( i, c, arg, tokens );
|
||||
default: throw std::logic_error( "Unknown mode" );
|
||||
}
|
||||
}
|
||||
|
||||
Mode handleNone( std::size_t i, char c ) {
|
||||
if( inQuotes ) {
|
||||
from = i;
|
||||
return Positional;
|
||||
}
|
||||
switch( c ) {
|
||||
case '-': return MaybeShortOpt;
|
||||
#ifdef CLARA_PLATFORM_WINDOWS
|
||||
case '/': from = i+1; return SlashOpt;
|
||||
#endif
|
||||
default: from = i; return Positional;
|
||||
}
|
||||
}
|
||||
Mode handleMaybeShortOpt( std::size_t i, char c ) {
|
||||
switch( c ) {
|
||||
case '-': from = i+1; return LongOpt;
|
||||
default: from = i; return ShortOpt;
|
||||
}
|
||||
}
|
||||
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
|
||||
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
|
||||
return mode;
|
||||
|
||||
std::string optName = arg.substr( from, i-from );
|
||||
if( mode == ShortOpt )
|
||||
for( std::size_t j = 0; j < optName.size(); ++j )
|
||||
tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
|
||||
else if( mode == SlashOpt && optName.size() == 1 )
|
||||
tokens.push_back( Token( Token::ShortOpt, optName ) );
|
||||
else
|
||||
tokens.push_back( Token( Token::LongOpt, optName ) );
|
||||
return None;
|
||||
}
|
||||
Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
|
||||
if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
|
||||
return mode;
|
||||
|
||||
std::string data = arg.substr( from, i-from );
|
||||
tokens.push_back( Token( Token::Positional, data ) );
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ConfigT>
|
||||
@ -4456,21 +4509,21 @@ namespace Clara {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
ConfigT parse( int argc, char const* const argv[] ) const {
|
||||
ConfigT parse( std::vector<std::string> const& args ) const {
|
||||
ConfigT config;
|
||||
parseInto( argc, argv, config );
|
||||
parseInto( args, config );
|
||||
return config;
|
||||
}
|
||||
|
||||
std::vector<Parser::Token> parseInto( int argc, char const* argv[], ConfigT& config ) const {
|
||||
std::string processName = argv[0];
|
||||
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
|
||||
std::string processName = args[0];
|
||||
std::size_t lastSlash = processName.find_last_of( "/\\" );
|
||||
if( lastSlash != std::string::npos )
|
||||
processName = processName.substr( lastSlash+1 );
|
||||
m_boundProcessName.set( config, processName );
|
||||
std::vector<Parser::Token> tokens;
|
||||
Parser parser;
|
||||
parser.parseIntoTokens( argc, argv, tokens );
|
||||
parser.parseIntoTokens( args, tokens );
|
||||
return populate( tokens, config );
|
||||
}
|
||||
|
||||
@ -4501,7 +4554,7 @@ namespace Clara {
|
||||
arg.boundField.set( config, tokens[++i].data );
|
||||
}
|
||||
else {
|
||||
arg.boundField.setFlag( config );
|
||||
arg.boundField.set( config, "true" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4667,8 +4720,11 @@ namespace Catch {
|
||||
std::string line;
|
||||
while( std::getline( f, line ) ) {
|
||||
line = trim(line);
|
||||
if( !line.empty() && !startsWith( line, "#" ) )
|
||||
addTestOrTags( config, "\"" + line + "\"," );
|
||||
if( !line.empty() && !startsWith( line, "#" ) ) {
|
||||
if( !startsWith( line, "\"" ) )
|
||||
line = "\"" + line + "\"";
|
||||
addTestOrTags( config, line + "," );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5209,6 +5265,8 @@ namespace Catch
|
||||
bool aborting;
|
||||
};
|
||||
|
||||
class MultipleReporters;
|
||||
|
||||
struct IStreamingReporter : IShared {
|
||||
virtual ~IStreamingReporter();
|
||||
|
||||
@ -5236,6 +5294,8 @@ namespace Catch
|
||||
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
|
||||
|
||||
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
|
||||
};
|
||||
|
||||
struct IReporterFactory : IShared {
|
||||
@ -5312,7 +5372,10 @@ namespace Catch {
|
||||
++it ) {
|
||||
matchedTests++;
|
||||
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
||||
Catch::cout() << testCaseInfo.name << std::endl;
|
||||
if( startsWith( testCaseInfo.name, "#" ) )
|
||||
Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
|
||||
else
|
||||
Catch::cout() << testCaseInfo.name << std::endl;
|
||||
}
|
||||
return matchedTests;
|
||||
}
|
||||
@ -5453,6 +5516,10 @@ namespace TestCaseTracking {
|
||||
virtual void addChild( Ptr<ITracker> const& child ) = 0;
|
||||
virtual ITracker* findChild( std::string const& name ) = 0;
|
||||
virtual void openChild() = 0;
|
||||
|
||||
// Debug/ checking
|
||||
virtual bool isSectionTracker() const = 0;
|
||||
virtual bool isIndexTracker() const = 0;
|
||||
};
|
||||
|
||||
class TrackerContext {
|
||||
@ -5577,6 +5644,10 @@ namespace TestCaseTracking {
|
||||
m_parent->openChild();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
|
||||
virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
|
||||
|
||||
void open() {
|
||||
m_runState = Executing;
|
||||
moveToThis();
|
||||
@ -5640,13 +5711,16 @@ namespace TestCaseTracking {
|
||||
{}
|
||||
virtual ~SectionTracker();
|
||||
|
||||
virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
|
||||
|
||||
static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
|
||||
SectionTracker* section = CATCH_NULL;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
if( ITracker* childTracker = currentTracker.findChild( name ) ) {
|
||||
section = dynamic_cast<SectionTracker*>( childTracker );
|
||||
assert( section );
|
||||
assert( childTracker );
|
||||
assert( childTracker->isSectionTracker() );
|
||||
section = static_cast<SectionTracker*>( childTracker );
|
||||
}
|
||||
else {
|
||||
section = new SectionTracker( name, ctx, ¤tTracker );
|
||||
@ -5671,13 +5745,16 @@ namespace TestCaseTracking {
|
||||
{}
|
||||
virtual ~IndexTracker();
|
||||
|
||||
virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
|
||||
|
||||
static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
|
||||
IndexTracker* tracker = CATCH_NULL;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
if( ITracker* childTracker = currentTracker.findChild( name ) ) {
|
||||
tracker = dynamic_cast<IndexTracker*>( childTracker );
|
||||
assert( tracker );
|
||||
assert( childTracker );
|
||||
assert( childTracker->isIndexTracker() );
|
||||
tracker = static_cast<IndexTracker*>( childTracker );
|
||||
}
|
||||
else {
|
||||
tracker = new IndexTracker( name, ctx, ¤tTracker, size );
|
||||
@ -5884,6 +5961,11 @@ namespace Catch {
|
||||
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
|
||||
|
||||
Totals deltaTotals = m_totals.delta( prevTotals );
|
||||
if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
|
||||
deltaTotals.assertions.failed++;
|
||||
deltaTotals.testCases.passed--;
|
||||
deltaTotals.testCases.failed++;
|
||||
}
|
||||
m_totals.testCases += deltaTotals.testCases;
|
||||
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||
deltaTotals,
|
||||
@ -6275,10 +6357,10 @@ namespace Catch {
|
||||
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
|
||||
}
|
||||
|
||||
int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
|
||||
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
|
||||
try {
|
||||
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
|
||||
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
|
||||
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
|
||||
if( m_configData.showHelp )
|
||||
showHelp( m_configData.processName );
|
||||
m_config.reset();
|
||||
@ -6302,16 +6384,13 @@ namespace Catch {
|
||||
m_config.reset();
|
||||
}
|
||||
|
||||
int run( int argc, char const* argv[] ) {
|
||||
int run( int argc, char const* const* const argv ) {
|
||||
|
||||
int returnCode = applyCommandLine( argc, argv );
|
||||
if( returnCode == 0 )
|
||||
returnCode = run();
|
||||
return returnCode;
|
||||
}
|
||||
int run( int argc, char* argv[] ) {
|
||||
return run( argc, const_cast<char const**>( argv ) );
|
||||
}
|
||||
|
||||
int run() {
|
||||
if( m_configData.showHelp )
|
||||
@ -6375,13 +6454,31 @@ namespace Catch {
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef CATCH_CPP14_OR_GREATER
|
||||
#include <random>
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct LexSort {
|
||||
bool operator() (TestCase i,TestCase j) const { return (i<j);}
|
||||
};
|
||||
struct RandomNumberGenerator {
|
||||
int operator()( int n ) const { return std::rand() % n; }
|
||||
typedef int result_type;
|
||||
|
||||
result_type operator()( result_type n ) const { return std::rand() % n; }
|
||||
|
||||
#ifdef CATCH_CPP14_OR_GREATER
|
||||
static constexpr result_type min() { return 0; }
|
||||
static constexpr result_type max() { return 1000000; }
|
||||
result_type operator()() const { return std::rand() % max(); }
|
||||
#endif
|
||||
template<typename V>
|
||||
static void shuffle( V& vector ) {
|
||||
RandomNumberGenerator rng;
|
||||
#ifdef CATCH_CPP14_OR_GREATER
|
||||
std::shuffle( vector.begin(), vector.end(), rng );
|
||||
#else
|
||||
std::random_shuffle( vector.begin(), vector.end(), rng );
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
|
||||
@ -6390,14 +6487,12 @@ namespace Catch {
|
||||
|
||||
switch( config.runOrder() ) {
|
||||
case RunTests::InLexicographicalOrder:
|
||||
std::sort( sorted.begin(), sorted.end(), LexSort() );
|
||||
std::sort( sorted.begin(), sorted.end() );
|
||||
break;
|
||||
case RunTests::InRandomOrder:
|
||||
{
|
||||
seedRng( config );
|
||||
|
||||
RandomNumberGenerator rng;
|
||||
std::random_shuffle( sorted.begin(), sorted.end(), rng );
|
||||
RandomNumberGenerator::shuffle( sorted );
|
||||
}
|
||||
break;
|
||||
case RunTests::InDeclarationOrder:
|
||||
@ -6416,13 +6511,15 @@ namespace Catch {
|
||||
it != itEnd;
|
||||
++it ) {
|
||||
std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
|
||||
if( !prev.second ){
|
||||
Catch::cerr()
|
||||
<< Colour( Colour::Red )
|
||||
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
|
||||
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
|
||||
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
|
||||
exit(1);
|
||||
if( !prev.second ) {
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << Colour( Colour::Red )
|
||||
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
|
||||
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
|
||||
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
|
||||
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7481,7 +7578,7 @@ namespace Catch {
|
||||
return os;
|
||||
}
|
||||
|
||||
Version libraryVersion( 1, 3, 5, "", 0 );
|
||||
Version libraryVersion( 1, 5, 7, "", 0 );
|
||||
|
||||
}
|
||||
|
||||
@ -8460,13 +8557,18 @@ public: // IStreamingReporter
|
||||
++it )
|
||||
(*it)->skipTest( testInfo );
|
||||
}
|
||||
|
||||
virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
|
||||
Ptr<IStreamingReporter> resultingReporter;
|
||||
|
||||
if( existingReporter ) {
|
||||
MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() );
|
||||
MultipleReporters* multi = existingReporter->tryAsMulti();
|
||||
if( !multi ) {
|
||||
multi = new MultipleReporters;
|
||||
resultingReporter = Ptr<IStreamingReporter>( multi );
|
||||
@ -8646,7 +8748,7 @@ namespace Catch {
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
|
||||
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
||||
assert( !m_sectionStack.empty() );
|
||||
SectionNode& sectionNode = *m_sectionStack.back();
|
||||
sectionNode.assertions.push_back( assertionStats );
|
||||
@ -8856,9 +8958,10 @@ namespace Catch {
|
||||
break;
|
||||
|
||||
default:
|
||||
// Escape control chars - based on contribution by @espenalb in PR #465
|
||||
// Escape control chars - based on contribution by @espenalb in PR #465 and
|
||||
// by @mrpi PR #588
|
||||
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
|
||||
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
|
||||
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
|
||||
else
|
||||
os << c;
|
||||
}
|
||||
@ -8913,13 +9016,20 @@ namespace Catch {
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( &Catch::cout() )
|
||||
{}
|
||||
{
|
||||
// We encode control characters, which requires
|
||||
// XML 1.1
|
||||
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
|
||||
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
|
||||
}
|
||||
|
||||
XmlWriter( std::ostream& os )
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( &os )
|
||||
{}
|
||||
{
|
||||
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
|
||||
}
|
||||
|
||||
~XmlWriter() {
|
||||
while( !m_tags.empty() )
|
||||
@ -9086,7 +9196,7 @@ namespace Catch {
|
||||
|
||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||
StreamingReporterBase::testCaseStarting(testInfo);
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
m_testCaseTimer.start();
|
||||
@ -9777,7 +9887,7 @@ namespace Catch {
|
||||
if( totals.testCases.total() == 0 ) {
|
||||
stream << Colour( Colour::Warning ) << "No tests ran\n";
|
||||
}
|
||||
else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
|
||||
else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
|
||||
stream << Colour( Colour::ResultSuccess ) << "All tests passed";
|
||||
stream << " ("
|
||||
<< pluralise( totals.assertions.passed, "assertion" ) << " in "
|
||||
|
||||
8
unittests/class_inside_scope.chai
Normal file
8
unittests/class_inside_scope.chai
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
try {
|
||||
parse("{ class C { var data; def C() {} } }")
|
||||
assert_false(true)
|
||||
} catch (e) {
|
||||
assert_true(true)
|
||||
}
|
||||
@ -12,9 +12,12 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
// This one is necessary for the const return non-reference test
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#endif
|
||||
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
@ -197,7 +200,7 @@ TEST_CASE("Throw int or double")
|
||||
chai.eval("throw(1.0)", chaiscript::exception_specification<int, double>());
|
||||
REQUIRE(false);
|
||||
} catch (const double e) {
|
||||
CHECK(e == 1.0);
|
||||
CHECK(e == Approx(1.0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -982,4 +985,341 @@ TEST_CASE("type_conversion to bool")
|
||||
module->add(chaiscript::type_conversion<T, bool>());
|
||||
}
|
||||
|
||||
TEST_CASE("Make sure ChaiScript object still compiles / executes")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
}
|
||||
|
||||
struct Count_Tracer
|
||||
{
|
||||
int count = 0;
|
||||
template<typename T>
|
||||
void trace(const chaiscript::detail::Dispatch_State &, const chaiscript::eval::AST_Node_Impl<T> *)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_CASE("Test count tracer")
|
||||
{
|
||||
typedef chaiscript::parser::ChaiScript_Parser< chaiscript::eval::Tracer<Count_Tracer>, chaiscript::optimizer::Optimizer_Default > Parser_Type;
|
||||
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library(),
|
||||
std::make_unique<Parser_Type>());
|
||||
|
||||
Parser_Type &parser = dynamic_cast<Parser_Type &>(chai.get_parser());
|
||||
|
||||
const auto count = parser.get_tracer().count;
|
||||
|
||||
chai.eval("");
|
||||
|
||||
CHECK(parser.get_tracer().count > count);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Test stdlib options")
|
||||
{
|
||||
const auto test_has_external_scripts = [](chaiscript::ChaiScript_Basic &chai) {
|
||||
CHECK_NOTHROW(chai.eval("`use`"));
|
||||
CHECK_NOTHROW(chai.eval("`eval_file`"));
|
||||
};
|
||||
|
||||
const auto test_no_external_scripts = [](chaiscript::ChaiScript_Basic &chai) {
|
||||
CHECK_THROWS(chai.eval("`use`"));
|
||||
CHECK_THROWS(chai.eval("`eval_file`"));
|
||||
};
|
||||
|
||||
const auto test_has_load_modules = [](chaiscript::ChaiScript_Basic &chai) {
|
||||
CHECK_NOTHROW(chai.eval("`load_module`"));
|
||||
};
|
||||
|
||||
const auto test_no_load_modules = [](chaiscript::ChaiScript_Basic &chai) {
|
||||
CHECK_THROWS(chai.eval("`load_module`"));
|
||||
};
|
||||
|
||||
SECTION( "Defaults" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
test_has_external_scripts(chai);
|
||||
test_has_load_modules(chai);
|
||||
}
|
||||
|
||||
SECTION( "Load_Modules, External_Scripts" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
|
||||
{chaiscript::Options::Load_Modules, chaiscript::Options::External_Scripts} );
|
||||
test_has_external_scripts(chai);
|
||||
test_has_load_modules(chai);
|
||||
}
|
||||
|
||||
SECTION( "No_Load_Modules, No_External_Scripts" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts} );
|
||||
test_no_external_scripts(chai);
|
||||
test_no_load_modules(chai);
|
||||
}
|
||||
|
||||
SECTION( "No_Load_Modules, Load_Modules" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::Load_Modules} );
|
||||
test_no_external_scripts(chai);
|
||||
test_no_load_modules(chai);
|
||||
}
|
||||
|
||||
SECTION( "No_External_Scripts, External_Scripts" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
|
||||
{chaiscript::Options::No_External_Scripts, chaiscript::Options::External_Scripts} );
|
||||
test_no_external_scripts(chai);
|
||||
test_no_load_modules(chai);
|
||||
}
|
||||
|
||||
SECTION( "No_External_Scripts, Load_Modules" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
|
||||
{chaiscript::Options::No_External_Scripts, chaiscript::Options::Load_Modules} );
|
||||
test_no_external_scripts(chai);
|
||||
test_has_load_modules(chai);
|
||||
}
|
||||
|
||||
SECTION( "External_Scripts, No_Load_Modules" ) {
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {},
|
||||
{chaiscript::Options::External_Scripts, chaiscript::Options::No_Load_Modules} );
|
||||
test_has_external_scripts(chai);
|
||||
test_no_load_modules(chai);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uservalueref(int &&)
|
||||
{
|
||||
}
|
||||
|
||||
void usemoveonlytype(std::unique_ptr<int> &&)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Pass r-value reference to func")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
|
||||
chai.add(chaiscript::fun(&uservalueref), "uservalueref");
|
||||
chai.add(chaiscript::fun(&usemoveonlytype), "usemoveonlytype");
|
||||
|
||||
chai.add(chaiscript::var(std::make_unique<int>(1)), "iptr");
|
||||
chai.eval("usemoveonlytype(iptr)");
|
||||
}
|
||||
|
||||
TEST_CASE("Use unique_ptr")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
|
||||
chai.add(chaiscript::fun([](int &i){ ++i; }), "inci");
|
||||
chai.add(chaiscript::fun([](int i){ ++i; }), "copyi");
|
||||
chai.add(chaiscript::fun([](int *i){ ++(*i); }), "derefi");
|
||||
chai.add(chaiscript::fun([](const std::unique_ptr<int> &i){ ++(*i); }), "constrefuniqptri");
|
||||
chai.add(chaiscript::fun([](std::unique_ptr<int> &i){ ++(*i); }), "refuniqptri");
|
||||
chai.add(chaiscript::fun([](std::unique_ptr<int> &&i){ ++(*i); }), "rvaluniqptri");
|
||||
chai.add(chaiscript::var(std::make_unique<int>(1)), "iptr");
|
||||
|
||||
|
||||
CHECK(chai.eval<int>("iptr") == 1);
|
||||
chai.eval("inci(iptr)");
|
||||
CHECK(chai.eval<int>("iptr") == 2);
|
||||
chai.eval("copyi(iptr)");
|
||||
CHECK(chai.eval<int>("iptr") == 2);
|
||||
chai.eval("derefi(iptr)");
|
||||
CHECK(chai.eval<int>("iptr") == 3);
|
||||
chai.eval("constrefuniqptri(iptr)");
|
||||
CHECK(chai.eval<int>("iptr") == 4);
|
||||
chai.eval("refuniqptri(iptr)");
|
||||
CHECK(chai.eval<int>("iptr") == 5);
|
||||
chai.eval("rvaluniqptri(iptr)");
|
||||
CHECK(chai.eval<int>("iptr") == 6);
|
||||
}
|
||||
|
||||
|
||||
class Unique_Ptr_Test_Class
|
||||
{
|
||||
public:
|
||||
Unique_Ptr_Test_Class() = default;
|
||||
Unique_Ptr_Test_Class(const Unique_Ptr_Test_Class&) = default;
|
||||
Unique_Ptr_Test_Class(Unique_Ptr_Test_Class &&) = default;
|
||||
Unique_Ptr_Test_Class &operator=(const Unique_Ptr_Test_Class&) = default;
|
||||
Unique_Ptr_Test_Class &operator=(Unique_Ptr_Test_Class&&) = default;
|
||||
virtual ~Unique_Ptr_Test_Class() = default;
|
||||
|
||||
int getI() const {return 5;}
|
||||
};
|
||||
|
||||
|
||||
std::unique_ptr<Unique_Ptr_Test_Class> make_Unique_Ptr_Test_Class()
|
||||
{
|
||||
return std::make_unique<Unique_Ptr_Test_Class>();
|
||||
}
|
||||
|
||||
TEST_CASE("Call methods through unique_ptr")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
|
||||
chai.add(chaiscript::var(std::make_unique<Unique_Ptr_Test_Class>()), "uptr");
|
||||
chai.add(chaiscript::fun(make_Unique_Ptr_Test_Class), "make_Unique_Ptr_Test_Class");
|
||||
chai.add(chaiscript::fun(&Unique_Ptr_Test_Class::getI), "getI");
|
||||
CHECK(chai.eval<int>("uptr.getI()") == 5);
|
||||
CHECK(chai.eval<int>("var uptr2 = make_Unique_Ptr_Test_Class(); uptr2.getI()") == 5);
|
||||
}
|
||||
|
||||
|
||||
class Unique_Ptr_Test_Base_Class
|
||||
{
|
||||
public:
|
||||
int getI() const {return 5;}
|
||||
};
|
||||
|
||||
class Unique_Ptr_Test_Derived_Class : public Unique_Ptr_Test_Base_Class
|
||||
{};
|
||||
|
||||
std::unique_ptr<Unique_Ptr_Test_Derived_Class> make_Unique_Ptr_Test_Derived_Class()
|
||||
{
|
||||
return std::make_unique<Unique_Ptr_Test_Derived_Class>();
|
||||
}
|
||||
|
||||
TEST_CASE("Call methods on base class through unique_ptr<derived>")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
|
||||
chai.add(chaiscript::var(std::make_unique<Unique_Ptr_Test_Derived_Class>()), "uptr");
|
||||
chai.add(chaiscript::fun(make_Unique_Ptr_Test_Derived_Class), "make_Unique_Ptr_Test_Derived_Class");
|
||||
chai.add(chaiscript::fun(&Unique_Ptr_Test_Base_Class::getI), "getI");
|
||||
chai.add(chaiscript::base_class<Unique_Ptr_Test_Base_Class, Unique_Ptr_Test_Derived_Class>());
|
||||
CHECK(chai.eval<int>("uptr.getI()") == 5);
|
||||
CHECK(chai.eval<int>("var uptr2 = make_Unique_Ptr_Test_Derived_Class(); uptr2.getI()") == 5);
|
||||
}
|
||||
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
A() = default;
|
||||
A(const A&) = default;
|
||||
A(A &&) = default;
|
||||
A &operator=(const A&) = default;
|
||||
A &operator=(A&&) = default;
|
||||
virtual ~A() = default;
|
||||
};
|
||||
|
||||
class B : public A
|
||||
{
|
||||
public:
|
||||
B() = default;
|
||||
};
|
||||
|
||||
TEST_CASE("Test typed chaiscript functions to perform conversions")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
chai.add(chaiscript::user_type<A>(), "A");
|
||||
|
||||
chai.add(chaiscript::user_type<B>(), "B");
|
||||
chai.add(chaiscript::base_class<A, B>());
|
||||
|
||||
chai.add(chaiscript::fun([](const B &)
|
||||
{
|
||||
}), "CppFunctWithBArg");
|
||||
|
||||
chai.add(chaiscript::fun([]() -> std::shared_ptr<A>
|
||||
{
|
||||
return (std::shared_ptr<A>(new B()));
|
||||
}), "Create");
|
||||
|
||||
chai.eval(R"(
|
||||
var inst = Create() // A*
|
||||
|
||||
// it prints "A"
|
||||
inst.type_name().print()
|
||||
|
||||
// Ok it is casted using conversion
|
||||
CppFunctWithBArg(inst)
|
||||
|
||||
// Define a function with B as argument
|
||||
def ChaiFuncWithBArg(B inst)
|
||||
{
|
||||
print("ok")
|
||||
}
|
||||
|
||||
// don't work
|
||||
ChaiFuncWithBArg(inst)
|
||||
)");
|
||||
}
|
||||
|
||||
struct Reference_MyClass
|
||||
{
|
||||
Reference_MyClass(double& t_x) : x(t_x) {}
|
||||
double& x;
|
||||
};
|
||||
|
||||
TEST_CASE("Test reference member being registered")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
// Note, C++ will not allow us to do this:
|
||||
// chai.add(chaiscript::fun(&Reference_MyClass::x) , "x");
|
||||
chai.add(chaiscript::fun([](Reference_MyClass &r) -> decltype(auto) { return (r.x); }), "x");
|
||||
chai.add(chaiscript::fun([](const Reference_MyClass &r) -> decltype(auto) { return (r.x); }), "x");
|
||||
double d;
|
||||
chai.add(chaiscript::var(Reference_MyClass(d)), "ref");
|
||||
chai.eval("ref.x = 2.3");
|
||||
CHECK(d == Approx(2.3));
|
||||
}
|
||||
|
||||
|
||||
const int add_3(const int &i)
|
||||
{
|
||||
return i + 3;
|
||||
}
|
||||
|
||||
TEST_CASE("Test returning by const non-reference")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
// Note, C++ will not allow us to do this:
|
||||
// chai.add(chaiscript::fun(&Reference_MyClass::x) , "x");
|
||||
chai.add(chaiscript::fun(&add_3), "add_3");
|
||||
auto v = chai.eval<int>("add_3(12)");
|
||||
CHECK(v == 15);
|
||||
}
|
||||
|
||||
|
||||
struct MyException : std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
int value = 5;
|
||||
};
|
||||
|
||||
void throws_a_thing()
|
||||
{
|
||||
throw MyException("Hello World");
|
||||
}
|
||||
|
||||
TEST_CASE("Test throwing and catching custom exception")
|
||||
{
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
chai.add(chaiscript::user_type<MyException>(), "MyException");
|
||||
chai.add(chaiscript::base_class<std::runtime_error, MyException>()); // be sure to register base class relationship
|
||||
chai.add(chaiscript::fun(&throws_a_thing), "throws_a_thing");
|
||||
chai.add(chaiscript::fun(&MyException::value), "value");
|
||||
|
||||
const auto s = chai.eval<std::string>("fun(){ try { throws_a_thing(); } catch (MyException ex) { return ex.what(); } }()");
|
||||
CHECK(s == "Hello World");
|
||||
|
||||
// this has an explicit clone to prevent returning a pointer to the `value` from inside of MyException
|
||||
const auto i = chai.eval<int>("fun(){ try { throws_a_thing(); } catch (MyException ex) { var v = clone(ex.value); print(v); return v; } }()");
|
||||
CHECK(i == 5);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Test ability to get 'use' function from default construction")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
const auto use_function = chai.eval<std::function<chaiscript::Boxed_Value (const std::string &)>>("use");
|
||||
}
|
||||
|
||||
|
||||
|
||||
23
unittests/conversion_to_bool.chai
Normal file
23
unittests/conversion_to_bool.chai
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
// all we care is that this executes, really
|
||||
|
||||
add_type_conversion(type("int"), type("bool"), fun(int i) { return i != 0; });
|
||||
|
||||
if (0) {
|
||||
assert_true(false);
|
||||
}
|
||||
|
||||
if (!0) {
|
||||
assert_true(true);
|
||||
} else {
|
||||
assert_true(false);
|
||||
}
|
||||
|
||||
while (0) {
|
||||
assert_true(false);
|
||||
}
|
||||
|
||||
for (; 0; ) {
|
||||
assert_true(false);
|
||||
}
|
||||
|
||||
42
unittests/execution_context.chai
Normal file
42
unittests/execution_context.chai
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
|
||||
assert_equal(__LINE__, 3)
|
||||
|
||||
def f() {
|
||||
[__LINE__, __CLASS__, __FUNC__]
|
||||
}
|
||||
|
||||
var res = f()
|
||||
|
||||
assert_equal(res[0], 6)
|
||||
assert_equal(res[1], "NOT_IN_CLASS")
|
||||
assert_equal(res[2], "f")
|
||||
|
||||
assert_equal(__CLASS__, "NOT_IN_CLASS")
|
||||
assert_equal(__FUNC__, "NOT_IN_FUNCTION")
|
||||
|
||||
class C
|
||||
{
|
||||
def C() {}
|
||||
def member() { [__LINE__, __CLASS__, __FUNC__]; }
|
||||
}
|
||||
|
||||
var c = C();
|
||||
|
||||
var res2 = c.member();
|
||||
|
||||
assert_equal(res2[0], 21)
|
||||
assert_equal(res2[1], "C")
|
||||
assert_equal(res2[2], "member")
|
||||
|
||||
def C::member2() { [__LINE__, __CLASS__, __FUNC__]; }
|
||||
|
||||
var res3 = c.member2();
|
||||
|
||||
assert_equal(res3[0], 32)
|
||||
assert_equal(res3[1], "C")
|
||||
assert_equal(res3[2], "member2")
|
||||
|
||||
assert_true(__FILE__.find("execution_context.chai") != -1)
|
||||
|
||||
|
||||
26
unittests/explicit_this_capture.chai
Normal file
26
unittests/explicit_this_capture.chai
Normal file
@ -0,0 +1,26 @@
|
||||
class Test
|
||||
{
|
||||
def Test()
|
||||
{}
|
||||
|
||||
def a(Function f)
|
||||
{
|
||||
f("test");
|
||||
// f();
|
||||
}
|
||||
|
||||
def b()
|
||||
{
|
||||
var l = fun [this](x) { this.thing(); }
|
||||
this.a(l)
|
||||
}
|
||||
|
||||
def thing()
|
||||
{
|
||||
print("hello world");
|
||||
}
|
||||
}
|
||||
var t = Test()
|
||||
t.b()
|
||||
|
||||
|
||||
53
unittests/fuzz_unit_test.inc
Normal file
53
unittests/fuzz_unit_test.inc
Normal file
@ -0,0 +1,53 @@
|
||||
def assert_equal(x, y)
|
||||
{
|
||||
if (x == y)
|
||||
{
|
||||
// Passes
|
||||
} else {
|
||||
// Fails
|
||||
print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_false(f)
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
print("assert_false failure");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_true(f)
|
||||
{
|
||||
if (!f)
|
||||
{
|
||||
print("assert_true failure");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_not_equal(x, y)
|
||||
{
|
||||
if (!(x == y))
|
||||
{
|
||||
// Passes
|
||||
} else {
|
||||
// Fails
|
||||
print("assert_not_equal failure: got " + to_string(y) + " which was not expected.");
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
def assert_throws(desc, x)
|
||||
{
|
||||
if (throws_exception(x))
|
||||
{
|
||||
// Passes
|
||||
} else {
|
||||
// Fails
|
||||
print("assert_throws failure, function did not throw exception: " + to_string(desc));
|
||||
// exit(-1);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
BIN
unittests/fuzzy_tests-2017-07-20.tar.bz2
Normal file
BIN
unittests/fuzzy_tests-2017-07-20.tar.bz2
Normal file
Binary file not shown.
@ -1,12 +1,12 @@
|
||||
// Test global
|
||||
|
||||
GLOBAL g = 3;
|
||||
global g = 3;
|
||||
assert_true(g == 3);
|
||||
|
||||
var v := g;
|
||||
assert_true(v == 3);
|
||||
|
||||
GLOBAL g = 2;
|
||||
global g = 2;
|
||||
assert_true(g == 2);
|
||||
assert_true(v == 2);
|
||||
|
||||
|
||||
@ -3,123 +3,282 @@
|
||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// ignore errors about negative unsigned integer literals
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_LITERAL(v) test_literal(v, #v)
|
||||
#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true)
|
||||
|
||||
template<typename T>
|
||||
bool test_literal(T val, const std::string &str)
|
||||
bool test_literal(T val, const std::string &str, bool use_boxed_number = false)
|
||||
{
|
||||
std::cout << "Comparing : " << val;
|
||||
std::cout << '(' << str << ") Comparing : C++ '" << val;
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||
T val2 = chai.eval<T>(str);
|
||||
std::cout << " " << val2 << '\n';
|
||||
|
||||
// Note, after applying the `-` it's possible that chaiscript has internally converted
|
||||
// between two equivalently sized types (ie, unsigned long and unsigned long long on a 64bit system)
|
||||
// so we're going to allow some leeway with the signed tests
|
||||
T val2 = [&](){
|
||||
if (!use_boxed_number) {
|
||||
return chai.eval<T>(str);
|
||||
} else {
|
||||
return chai.eval<chaiscript::Boxed_Number>(str).get_as_checked<T>();
|
||||
}
|
||||
}();
|
||||
|
||||
std::cout << "' chai '" << val2 << "'\n";
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if( TEST_LITERAL(0xF)
|
||||
&& TEST_LITERAL(0xFF)
|
||||
&& TEST_LITERAL(0xFFF)
|
||||
&& TEST_LITERAL(0xFFFF)
|
||||
&& TEST_LITERAL(0xFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
|
||||
&& TEST_LITERAL(01)
|
||||
&& TEST_LITERAL(017)
|
||||
&& TEST_LITERAL(0177)
|
||||
&& TEST_LITERAL(01777)
|
||||
&& TEST_LITERAL(017777)
|
||||
&& TEST_LITERAL(0177777)
|
||||
&& TEST_LITERAL(01777777)
|
||||
&& TEST_LITERAL(017777777)
|
||||
&& TEST_LITERAL(0177777777)
|
||||
&& TEST_LITERAL(01777777777)
|
||||
&& TEST_LITERAL(017777777777)
|
||||
&& TEST_LITERAL(0177777777777)
|
||||
&& TEST_LITERAL(01777777777777)
|
||||
&& TEST_LITERAL(017777777777777)
|
||||
&& TEST_LITERAL(0177777777777777)
|
||||
&& TEST_LITERAL(01777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777777)
|
||||
if(
|
||||
TEST_LITERAL(0xF)
|
||||
&& TEST_LITERAL(0xFF)
|
||||
&& TEST_LITERAL(0xFFF)
|
||||
&& TEST_LITERAL(0xFFFF)
|
||||
&& TEST_LITERAL(0xFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
&& TEST_LITERAL(1)
|
||||
&& TEST_LITERAL(17)
|
||||
&& TEST_LITERAL(177)
|
||||
&& TEST_LITERAL(1777)
|
||||
&& TEST_LITERAL(17777)
|
||||
&& TEST_LITERAL(177777)
|
||||
&& TEST_LITERAL(1777777)
|
||||
&& TEST_LITERAL(17777777)
|
||||
&& TEST_LITERAL(177777777)
|
||||
&& TEST_LITERAL(1777777777)
|
||||
&& TEST_LITERAL(17777777777)
|
||||
&& TEST_LITERAL(177777777777)
|
||||
&& TEST_LITERAL(1777777777777)
|
||||
&& TEST_LITERAL(17777777777777)
|
||||
&& TEST_LITERAL(177777777777777)
|
||||
&& TEST_LITERAL(1777777777777777)
|
||||
&& TEST_LITERAL(17777777777777777)
|
||||
&& TEST_LITERAL(177777777777777777)
|
||||
&& TEST_LITERAL(1777777777777777777)
|
||||
|
||||
&& test_literal(0xF, "0b1111")
|
||||
&& test_literal(0xFF, "0b11111111")
|
||||
&& test_literal(0xFFF, "0b111111111111")
|
||||
&& test_literal(0xFFFF, "0b1111111111111111")
|
||||
&& test_literal(0xFFFFF, "0b11111111111111111111")
|
||||
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
|
||||
&& TEST_LITERAL(01)
|
||||
&& TEST_LITERAL(017)
|
||||
&& TEST_LITERAL(0177)
|
||||
&& TEST_LITERAL(01777)
|
||||
&& TEST_LITERAL(017777)
|
||||
&& TEST_LITERAL(0177777)
|
||||
&& TEST_LITERAL(01777777)
|
||||
&& TEST_LITERAL(017777777)
|
||||
&& TEST_LITERAL(0177777777)
|
||||
&& TEST_LITERAL(01777777777)
|
||||
&& TEST_LITERAL(017777777777)
|
||||
&& TEST_LITERAL(0177777777777)
|
||||
&& TEST_LITERAL(01777777777777)
|
||||
&& TEST_LITERAL(017777777777777)
|
||||
&& TEST_LITERAL(0177777777777777)
|
||||
&& TEST_LITERAL(01777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777)
|
||||
&& TEST_LITERAL(017777777777777777777)
|
||||
&& TEST_LITERAL(0177777777777777777777)
|
||||
&& TEST_LITERAL(01777777777777777777777)
|
||||
|
||||
&& test_literal(0x7, "0b111")
|
||||
&& test_literal(0x7F, "0b1111111")
|
||||
&& test_literal(0x7FF, "0b11111111111")
|
||||
&& test_literal(0x7FFF, "0b111111111111111")
|
||||
&& test_literal(0x7FFFF, "0b1111111111111111111")
|
||||
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
|
||||
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
|
||||
)
|
||||
&& TEST_LITERAL(1)
|
||||
&& TEST_LITERAL(17)
|
||||
&& TEST_LITERAL(177)
|
||||
&& TEST_LITERAL(1777)
|
||||
&& TEST_LITERAL(17777)
|
||||
&& TEST_LITERAL(177777)
|
||||
&& TEST_LITERAL(1777777)
|
||||
&& TEST_LITERAL(17777777)
|
||||
&& TEST_LITERAL(177777777)
|
||||
&& TEST_LITERAL(1777777777)
|
||||
&& TEST_LITERAL(17777777777)
|
||||
&& TEST_LITERAL(177777777777)
|
||||
&& TEST_LITERAL(1777777777777)
|
||||
&& TEST_LITERAL(17777777777777)
|
||||
&& TEST_LITERAL(177777777777777)
|
||||
&& TEST_LITERAL(1777777777777777)
|
||||
&& TEST_LITERAL(17777777777777777)
|
||||
&& TEST_LITERAL(177777777777777777)
|
||||
&& TEST_LITERAL(1777777777777777777)
|
||||
|
||||
&& test_literal(0xF, "0b1111")
|
||||
&& test_literal(0xFF, "0b11111111")
|
||||
&& test_literal(0xFFF, "0b111111111111")
|
||||
&& test_literal(0xFFFF, "0b1111111111111111")
|
||||
&& test_literal(0xFFFFF, "0b11111111111111111111")
|
||||
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
|
||||
|
||||
&& test_literal(0x7, "0b111")
|
||||
&& test_literal(0x7F, "0b1111111")
|
||||
&& test_literal(0x7FF, "0b11111111111")
|
||||
&& test_literal(0x7FFF, "0b111111111111111")
|
||||
&& test_literal(0x7FFFF, "0b1111111111111111111")
|
||||
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
|
||||
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
|
||||
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
|
||||
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-0xF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFF)
|
||||
&& TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-01)
|
||||
&& TEST_LITERAL_SIGNED(-017)
|
||||
&& TEST_LITERAL_SIGNED(-0177)
|
||||
&& TEST_LITERAL_SIGNED(-01777)
|
||||
&& TEST_LITERAL_SIGNED(-017777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-017777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-0177777777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-01777777777777777777777)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-1)
|
||||
&& TEST_LITERAL_SIGNED(-17)
|
||||
&& TEST_LITERAL_SIGNED(-177)
|
||||
&& TEST_LITERAL_SIGNED(-1777)
|
||||
&& TEST_LITERAL_SIGNED(-17777)
|
||||
&& TEST_LITERAL_SIGNED(-177777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-17777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-177777777777777777)
|
||||
&& TEST_LITERAL_SIGNED(-1777777777777777777)
|
||||
|
||||
// Test 8/16/24/32 bit boundaries for various types
|
||||
|
||||
&& TEST_LITERAL(255)
|
||||
&& TEST_LITERAL(65535)
|
||||
&& TEST_LITERAL(16777215)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL(4294967295)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255)
|
||||
&& TEST_LITERAL_SIGNED(-65535)
|
||||
&& TEST_LITERAL_SIGNED(-16777215)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL_SIGNED(-4294967295)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL(255u)
|
||||
&& TEST_LITERAL(65535u)
|
||||
&& TEST_LITERAL(16777215u)
|
||||
&& TEST_LITERAL(4294967295u)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255u)
|
||||
&& TEST_LITERAL_SIGNED(-65535u)
|
||||
&& TEST_LITERAL_SIGNED(-16777215u)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295u)
|
||||
|
||||
&& TEST_LITERAL(255l)
|
||||
&& TEST_LITERAL(65535l)
|
||||
&& TEST_LITERAL(16777215l)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL(4294967295l)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255l)
|
||||
&& TEST_LITERAL_SIGNED(-65535l)
|
||||
&& TEST_LITERAL_SIGNED(-16777215l)
|
||||
#ifndef CHAISCRIPT_MSVC
|
||||
// bug in cl.exe causes this to be incorrectly parsed as an unsigned
|
||||
&& TEST_LITERAL_SIGNED(-4294967295l)
|
||||
#endif
|
||||
|
||||
&& TEST_LITERAL(255ul)
|
||||
&& TEST_LITERAL(65535ul)
|
||||
&& TEST_LITERAL(16777215ul)
|
||||
&& TEST_LITERAL(4294967295ul)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255ul)
|
||||
&& TEST_LITERAL_SIGNED(-65535ul)
|
||||
&& TEST_LITERAL_SIGNED(-16777215ul)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295ul)
|
||||
|
||||
&& TEST_LITERAL(255ull)
|
||||
&& TEST_LITERAL(65535ull)
|
||||
&& TEST_LITERAL(16777215ull)
|
||||
&& TEST_LITERAL(4294967295ull)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255ull)
|
||||
&& TEST_LITERAL_SIGNED(-65535ull)
|
||||
&& TEST_LITERAL_SIGNED(-16777215ull)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295ull)
|
||||
|
||||
&& TEST_LITERAL(255ll)
|
||||
&& TEST_LITERAL(65535ll)
|
||||
&& TEST_LITERAL(16777215ll)
|
||||
&& TEST_LITERAL(4294967295ll)
|
||||
|
||||
&& TEST_LITERAL_SIGNED(-255ll)
|
||||
&& TEST_LITERAL_SIGNED(-65535ll)
|
||||
&& TEST_LITERAL_SIGNED(-16777215ll)
|
||||
&& TEST_LITERAL_SIGNED(-4294967295ll)
|
||||
|
||||
|
||||
)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@ -1 +1,2 @@
|
||||
assert_equal(from_json("100"), 100)
|
||||
assert_equal(from_json("-100"), -100)
|
||||
|
||||
@ -1 +1,22 @@
|
||||
assert_equal(from_json("1.234"), 1.234)
|
||||
assert_equal(from_json("-1.234"), -1.234)
|
||||
|
||||
auto caught = false;
|
||||
try {
|
||||
from_json("-1-5.3");
|
||||
}
|
||||
catch(e) {
|
||||
assert_equal("JSON ERROR: Number: unexpected character '-'", e.what());
|
||||
caught = true;
|
||||
}
|
||||
assert_equal(caught, true);
|
||||
|
||||
caught = false;
|
||||
try {
|
||||
from_json("-15.3.2");
|
||||
}
|
||||
catch(e) {
|
||||
assert_equal("JSON ERROR: Number: unexpected character '.'", e.what());
|
||||
caught = true;
|
||||
}
|
||||
assert_equal(caught, true);
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
assert_equal(from_json("[1,2,3]"), [1,2,3])
|
||||
assert_equal(from_json("[1,-2,3]"), [1,-2,3])
|
||||
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#endif
|
||||
#include <chaiscript/chaiscript_basic.hpp>
|
||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||
|
||||
@ -57,18 +60,22 @@ int main()
|
||||
}
|
||||
|
||||
std::vector<std::string> modulepaths;
|
||||
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
chaiscript::ChaiScript chai(/* unused */modulepaths, usepaths);
|
||||
#else
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
|
||||
|
||||
// For this test we are going to load the dynamic stdlib
|
||||
// to make sure it continues to work
|
||||
chaiscript::ChaiScript_Basic chai(
|
||||
std::make_unique<chaiscript::parser::ChaiScript_Parser<chaiscript::eval::Noop_Tracer, chaiscript::optimizer::Optimizer_Default>>(),
|
||||
modulepaths,usepaths);
|
||||
#endif
|
||||
|
||||
std::vector<std::shared_ptr<std::thread> > threads;
|
||||
|
||||
|
||||
12
unittests/negative_numbers.chai
Normal file
12
unittests/negative_numbers.chai
Normal file
@ -0,0 +1,12 @@
|
||||
def numFunc(x)
|
||||
{
|
||||
return x + 10;
|
||||
}
|
||||
|
||||
|
||||
// Note that unary prefix `-` has lower precedence than `.`
|
||||
// this is why these values are correct, even if counterintuitive
|
||||
|
||||
assert_true(-5.numFunc() == -15);
|
||||
assert_true((-5).numFunc() == 5);
|
||||
|
||||
11
unittests/static_chaiscript.cpp
Normal file
11
unittests/static_chaiscript.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
#define CHAISCRIPT_NO_THREADS
|
||||
|
||||
/// ChaiScript as a static is unsupported with thread support enabled
|
||||
///
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
static chaiscript::ChaiScript chai;
|
||||
|
||||
int main() {}
|
||||
Loading…
x
Reference in New Issue
Block a user