mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-02-09 03:06:50 +08:00
Merge branch 'develop' into best_practices
This commit is contained in:
commit
a880319db8
@ -24,10 +24,10 @@ matrix:
|
|||||||
sudo: false
|
sudo: false
|
||||||
env: GCC_VER="4.9"
|
env: GCC_VER="4.9"
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
- os: linux
|
# - os: linux
|
||||||
sudo: false
|
#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
|
#env: GCC_VER="6" 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
|
#compiler: gcc
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: false
|
sudo: false
|
||||||
env: GCC_VER="5" CPPCHECK=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
|
env: GCC_VER="5" CPPCHECK=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
|
||||||
|
|||||||
@ -4,13 +4,6 @@ if(NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
|
|||||||
cmake_policy(SET CMP0054 NEW)
|
cmake_policy(SET CMP0054 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
IF(BIICODE)
|
|
||||||
INIT_BIICODE_BLOCK()
|
|
||||||
ADD_BIICODE_TARGETS()
|
|
||||||
ELSE()
|
|
||||||
# Your regular CMakeLists configuration here
|
|
||||||
|
|
||||||
|
|
||||||
project(chaiscript)
|
project(chaiscript)
|
||||||
|
|
||||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||||
@ -49,6 +42,8 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|||||||
if(ENABLE_ADDRESS_SANITIZER)
|
if(ENABLE_ADDRESS_SANITIZER)
|
||||||
add_definitions(-fsanitize=address -g)
|
add_definitions(-fsanitize=address -g)
|
||||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
|
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
|
||||||
|
|
||||||
|
option(BUILD_LIBFUZZ_TESTER "Build libfuzzer tool" FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE)
|
option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE)
|
||||||
@ -102,7 +97,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
|||||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR 6)
|
set(CPACK_PACKAGE_VERSION_MAJOR 7)
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||||
|
|
||||||
@ -123,6 +118,7 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
|||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
include(cmake/Catch.cmake)
|
||||||
|
|
||||||
if(NOT MINGW)
|
if(NOT MINGW)
|
||||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||||
@ -155,6 +151,9 @@ endif()
|
|||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_definitions(/std:c++latest /W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
|
add_definitions(/std:c++latest /W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
|
||||||
|
|
||||||
|
add_definitions(/std:c++17)
|
||||||
|
|
||||||
|
|
||||||
if (MSVC_VERSION STREQUAL "1800")
|
if (MSVC_VERSION STREQUAL "1800")
|
||||||
# VS2013 doesn't have magic statics
|
# VS2013 doesn't have magic statics
|
||||||
add_definitions(/w44640)
|
add_definitions(/w44640)
|
||||||
@ -163,7 +162,7 @@ if(MSVC)
|
|||||||
add_definitions(/w34062)
|
add_definitions(/w34062)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(/bigobj)
|
add_definitions(/bigobj /permissive-)
|
||||||
# Note on MSVC compiler flags.
|
# Note on MSVC compiler flags.
|
||||||
# The code base selective disables warnings as necessary when the compiler is complaining too much
|
# The code base selective disables warnings as necessary when the compiler is complaining too much
|
||||||
# about something that is perfectly valid, or there is simply no technical way around it
|
# about something that is perfectly valid, or there is simply no technical way around it
|
||||||
@ -262,8 +261,8 @@ add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
|||||||
target_link_libraries(chai ${LIBS} ${CHAISCRIPT_LIBS})
|
target_link_libraries(chai ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
|
|
||||||
if(BUILD_SAMPLES)
|
if(BUILD_SAMPLES)
|
||||||
add_executable(example samples/example.cpp)
|
add_executable(sanity_checks src/sanity_checks.cpp)
|
||||||
target_link_libraries(example ${LIBS})
|
target_link_libraries(sanity_checks ${LIBS})
|
||||||
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
|
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
|
||||||
target_link_libraries(test_num_exceptions ${LIBS} ${CHAISCRIPT_LIBS})
|
target_link_libraries(test_num_exceptions ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||||
@ -287,6 +286,7 @@ if(BUILD_MODULES)
|
|||||||
set(MODULES stl_extra)
|
set(MODULES stl_extra)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||||
list(SORT UNIT_TESTS)
|
list(SORT UNIT_TESTS)
|
||||||
|
|
||||||
@ -411,7 +411,7 @@ if(BUILD_TESTING)
|
|||||||
if(NOT UNIT_TEST_LIGHT)
|
if(NOT UNIT_TEST_LIGHT)
|
||||||
add_executable(compiled_tests unittests/compiled_tests.cpp)
|
add_executable(compiled_tests unittests/compiled_tests.cpp)
|
||||||
target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS})
|
target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS})
|
||||||
ADD_CATCH_TESTS(compiled_tests)
|
catch_discover_tests(compiled_tests TEST_PREFIX "compiled.")
|
||||||
|
|
||||||
add_executable(static_chaiscript_test unittests/static_chaiscript.cpp)
|
add_executable(static_chaiscript_test unittests/static_chaiscript.cpp)
|
||||||
target_link_libraries(static_chaiscript_test ${LIBS})
|
target_link_libraries(static_chaiscript_test ${LIBS})
|
||||||
@ -458,6 +458,15 @@ if(BUILD_TESTING)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(BUILD_LIBFUZZ_TESTER)
|
||||||
|
add_executable(fuzzer src/libfuzzer_client.cpp src/sha3.cpp)
|
||||||
|
target_compile_options(fuzzer PRIVATE "-fsanitize=fuzzer,address")
|
||||||
|
target_link_libraries(fuzzer PRIVATE ${LIBS} "-fsanitize=fuzzer,address")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
install(TARGETS chai chaiscript_stdlib-${CHAI_VERSION} ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
install(TARGETS chai chaiscript_stdlib-${CHAI_VERSION} ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||||
|
|
||||||
install(DIRECTORY include/chaiscript DESTINATION include
|
install(DIRECTORY include/chaiscript DESTINATION include
|
||||||
@ -482,5 +491,3 @@ install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
|
|||||||
DESTINATION lib/pkgconfig)
|
DESTINATION lib/pkgconfig)
|
||||||
|
|
||||||
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
|
|||||||
4
LICENSE
4
LICENSE
@ -1,4 +1,6 @@
|
|||||||
Copyright 2009-2016 Jason Turner
|
BSD-3-Clause License
|
||||||
|
|
||||||
|
Copyright 2009-2018 Jason Turner
|
||||||
Copyright 2009-2012 Jonathan Turner.
|
Copyright 2009-2012 Jonathan Turner.
|
||||||
|
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
version: 5.8.x.{build}
|
version: 6.1.x.{build}
|
||||||
image:
|
image:
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
environment:
|
environment:
|
||||||
@ -11,7 +11,7 @@ build_script:
|
|||||||
|
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
cmake c:\Projects\chaiscript -G "%VS_VERSION%"
|
cmake c:\Projects\chaiscript -G "%VS_VERSION%" -DBUILD_TESTING:BOOL=ON -DBUILD_MODULES:BOOL=ON
|
||||||
|
|
||||||
cmake --build . --config Debug
|
cmake --build . --config Debug
|
||||||
test_script:
|
test_script:
|
||||||
|
|||||||
@ -370,6 +370,25 @@ if (expression) { }
|
|||||||
if (statement; expression) { }
|
if (statement; expression) { }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Switch Statements
|
||||||
|
|
||||||
|
``` chaiscript
|
||||||
|
var myvalue = 2
|
||||||
|
switch (myvalue) {
|
||||||
|
case (1) {
|
||||||
|
print("My Value is 1");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (2) {
|
||||||
|
print("My Value is 2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
print("My Value is something else.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Built in Types
|
## Built in Types
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
175
cmake/Catch.cmake
Normal file
175
cmake/Catch.cmake
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
Catch
|
||||||
|
-----
|
||||||
|
|
||||||
|
This module defines a function to help use the Catch test framework.
|
||||||
|
|
||||||
|
The :command:`catch_discover_tests` discovers tests by asking the compiled test
|
||||||
|
executable to enumerate its tests. This does not require CMake to be re-run
|
||||||
|
when tests change. However, it may not work in a cross-compiling environment,
|
||||||
|
and setting test properties is less convenient.
|
||||||
|
|
||||||
|
This command is intended to replace use of :command:`add_test` to register
|
||||||
|
tests, and will create a separate CTest test for each Catch test case. Note
|
||||||
|
that this is in some cases less efficient, as common set-up and tear-down logic
|
||||||
|
cannot be shared by multiple test cases executing in the same instance.
|
||||||
|
However, it provides more fine-grained pass/fail information to CTest, which is
|
||||||
|
usually considered as more beneficial. By default, the CTest test name is the
|
||||||
|
same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
|
||||||
|
|
||||||
|
.. command:: catch_discover_tests
|
||||||
|
|
||||||
|
Automatically add tests with CTest by querying the compiled test executable
|
||||||
|
for available tests::
|
||||||
|
|
||||||
|
catch_discover_tests(target
|
||||||
|
[TEST_SPEC arg1...]
|
||||||
|
[EXTRA_ARGS arg1...]
|
||||||
|
[WORKING_DIRECTORY dir]
|
||||||
|
[TEST_PREFIX prefix]
|
||||||
|
[TEST_SUFFIX suffix]
|
||||||
|
[PROPERTIES name1 value1...]
|
||||||
|
[TEST_LIST var]
|
||||||
|
)
|
||||||
|
|
||||||
|
``catch_discover_tests`` sets up a post-build command on the test executable
|
||||||
|
that generates the list of tests by parsing the output from running the test
|
||||||
|
with the ``--list-test-names-only`` argument. This ensures that the full
|
||||||
|
list of tests is obtained. Since test discovery occurs at build time, it is
|
||||||
|
not necessary to re-run CMake when the list of tests changes.
|
||||||
|
However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
|
||||||
|
in order to function in a cross-compiling environment.
|
||||||
|
|
||||||
|
Additionally, setting properties on tests is somewhat less convenient, since
|
||||||
|
the tests are not available at CMake time. Additional test properties may be
|
||||||
|
assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
|
||||||
|
more fine-grained test control is needed, custom content may be provided
|
||||||
|
through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
|
||||||
|
directory property. The set of discovered tests is made accessible to such a
|
||||||
|
script via the ``<target>_TESTS`` variable.
|
||||||
|
|
||||||
|
The options are:
|
||||||
|
|
||||||
|
``target``
|
||||||
|
Specifies the Catch executable, which must be a known CMake executable
|
||||||
|
target. CMake will substitute the location of the built executable when
|
||||||
|
running the test.
|
||||||
|
|
||||||
|
``TEST_SPEC arg1...``
|
||||||
|
Specifies test cases, wildcarded test cases, tags and tag expressions to
|
||||||
|
pass to the Catch executable with the ``--list-test-names-only`` argument.
|
||||||
|
|
||||||
|
``EXTRA_ARGS arg1...``
|
||||||
|
Any extra arguments to pass on the command line to each test case.
|
||||||
|
|
||||||
|
``WORKING_DIRECTORY dir``
|
||||||
|
Specifies the directory in which to run the discovered test cases. If this
|
||||||
|
option is not provided, the current binary directory is used.
|
||||||
|
|
||||||
|
``TEST_PREFIX prefix``
|
||||||
|
Specifies a ``prefix`` to be prepended to the name of each discovered test
|
||||||
|
case. This can be useful when the same test executable is being used in
|
||||||
|
multiple calls to ``catch_discover_tests()`` but with different
|
||||||
|
``TEST_SPEC`` or ``EXTRA_ARGS``.
|
||||||
|
|
||||||
|
``TEST_SUFFIX suffix``
|
||||||
|
Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
|
||||||
|
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
|
||||||
|
be specified.
|
||||||
|
|
||||||
|
``PROPERTIES name1 value1...``
|
||||||
|
Specifies additional properties to be set on all tests discovered by this
|
||||||
|
invocation of ``catch_discover_tests``.
|
||||||
|
|
||||||
|
``TEST_LIST var``
|
||||||
|
Make the list of tests available in the variable ``var``, rather than the
|
||||||
|
default ``<target>_TESTS``. This can be useful when the same test
|
||||||
|
executable is being used in multiple calls to ``catch_discover_tests()``.
|
||||||
|
Note that this variable is only available in CTest.
|
||||||
|
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
function(catch_discover_tests TARGET)
|
||||||
|
cmake_parse_arguments(
|
||||||
|
""
|
||||||
|
""
|
||||||
|
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST"
|
||||||
|
"TEST_SPEC;EXTRA_ARGS;PROPERTIES"
|
||||||
|
${ARGN}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _WORKING_DIRECTORY)
|
||||||
|
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
endif()
|
||||||
|
if(NOT _TEST_LIST)
|
||||||
|
set(_TEST_LIST ${TARGET}_TESTS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
## Generate a unique name based on the extra arguments
|
||||||
|
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}")
|
||||||
|
string(SUBSTRING ${args_hash} 0 7 args_hash)
|
||||||
|
|
||||||
|
# Define rule to generate test list for aforementioned test executable
|
||||||
|
set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
|
||||||
|
set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
|
||||||
|
get_property(crosscompiling_emulator
|
||||||
|
TARGET ${TARGET}
|
||||||
|
PROPERTY CROSSCOMPILING_EMULATOR
|
||||||
|
)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${TARGET} POST_BUILD
|
||||||
|
BYPRODUCTS "${ctest_tests_file}"
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
-D "TEST_TARGET=${TARGET}"
|
||||||
|
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
|
||||||
|
-D "TEST_EXECUTOR=${crosscompiling_emulator}"
|
||||||
|
-D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
|
||||||
|
-D "TEST_SPEC=${_TEST_SPEC}"
|
||||||
|
-D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
|
||||||
|
-D "TEST_PROPERTIES=${_PROPERTIES}"
|
||||||
|
-D "TEST_PREFIX=${_TEST_PREFIX}"
|
||||||
|
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
|
||||||
|
-D "TEST_LIST=${_TEST_LIST}"
|
||||||
|
-D "CTEST_FILE=${ctest_tests_file}"
|
||||||
|
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
file(WRITE "${ctest_include_file}"
|
||||||
|
"if(EXISTS \"${ctest_tests_file}\")\n"
|
||||||
|
" include(\"${ctest_tests_file}\")\n"
|
||||||
|
"else()\n"
|
||||||
|
" add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
|
||||||
|
"endif()\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
|
||||||
|
# Add discovered tests to directory TEST_INCLUDE_FILES
|
||||||
|
set_property(DIRECTORY
|
||||||
|
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# Add discovered tests as directory TEST_INCLUDE_FILE if possible
|
||||||
|
get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
|
||||||
|
if (NOT ${test_include_file_set})
|
||||||
|
set_property(DIRECTORY
|
||||||
|
PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Cannot set more than one TEST_INCLUDE_FILE"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
set(_CATCH_DISCOVER_TESTS_SCRIPT
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
|
||||||
|
)
|
||||||
76
cmake/CatchAddTests.cmake
Normal file
76
cmake/CatchAddTests.cmake
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
set(prefix "${TEST_PREFIX}")
|
||||||
|
set(suffix "${TEST_SUFFIX}")
|
||||||
|
set(spec ${TEST_SPEC})
|
||||||
|
set(extra_args ${TEST_EXTRA_ARGS})
|
||||||
|
set(properties ${TEST_PROPERTIES})
|
||||||
|
set(script)
|
||||||
|
set(suite)
|
||||||
|
set(tests)
|
||||||
|
|
||||||
|
function(add_command NAME)
|
||||||
|
set(_args "")
|
||||||
|
foreach(_arg ${ARGN})
|
||||||
|
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
|
||||||
|
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
|
||||||
|
else()
|
||||||
|
set(_args "${_args} ${_arg}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Run test executable to get list of available tests
|
||||||
|
if(NOT EXISTS "${TEST_EXECUTABLE}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
|
||||||
|
OUTPUT_VARIABLE output
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
)
|
||||||
|
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
|
||||||
|
if(${result} EQUAL 0)
|
||||||
|
message(WARNING
|
||||||
|
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
|
||||||
|
)
|
||||||
|
elseif(${result} LESS 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Error running test executable '${TEST_EXECUTABLE}':\n"
|
||||||
|
" Result: ${result}\n"
|
||||||
|
" Output: ${output}\n"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(REPLACE "\n" ";" output "${output}")
|
||||||
|
|
||||||
|
# Parse output
|
||||||
|
foreach(line ${output})
|
||||||
|
set(test ${line})
|
||||||
|
# ...and add to script
|
||||||
|
add_command(add_test
|
||||||
|
"${prefix}${test}${suffix}"
|
||||||
|
${TEST_EXECUTOR}
|
||||||
|
"${TEST_EXECUTABLE}"
|
||||||
|
${test}
|
||||||
|
${extra_args}
|
||||||
|
)
|
||||||
|
add_command(set_tests_properties
|
||||||
|
"${prefix}${test}${suffix}"
|
||||||
|
PROPERTIES
|
||||||
|
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
|
||||||
|
${properties}
|
||||||
|
)
|
||||||
|
list(APPEND tests "${prefix}${test}${suffix}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Create a list of all discovered tests, which users may use to e.g. set
|
||||||
|
# properties on the tests
|
||||||
|
add_command(set ${TEST_LIST} ${tests})
|
||||||
|
|
||||||
|
# Write CTest script
|
||||||
|
file(WRITE "${CTEST_FILE}" "${script}")
|
||||||
185
cmake/ParseAndAddCatchTests.cmake
Normal file
185
cmake/ParseAndAddCatchTests.cmake
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#==================================================================================================#
|
||||||
|
# supported macros #
|
||||||
|
# - TEST_CASE, #
|
||||||
|
# - SCENARIO, #
|
||||||
|
# - TEST_CASE_METHOD, #
|
||||||
|
# - CATCH_TEST_CASE, #
|
||||||
|
# - CATCH_SCENARIO, #
|
||||||
|
# - CATCH_TEST_CASE_METHOD. #
|
||||||
|
# #
|
||||||
|
# Usage #
|
||||||
|
# 1. make sure this module is in the path or add this otherwise: #
|
||||||
|
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||||
|
# 2. make sure that you've enabled testing option for the project by the call: #
|
||||||
|
# enable_testing() #
|
||||||
|
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
|
||||||
|
# project(testing_target) #
|
||||||
|
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||||
|
# enable_testing() #
|
||||||
|
# #
|
||||||
|
# find_path(CATCH_INCLUDE_DIR "catch.hpp") #
|
||||||
|
# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) #
|
||||||
|
# #
|
||||||
|
# file(GLOB SOURCE_FILES "*.cpp") #
|
||||||
|
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
|
||||||
|
# #
|
||||||
|
# include(ParseAndAddCatchTests) #
|
||||||
|
# ParseAndAddCatchTests(${PROJECT_NAME}) #
|
||||||
|
# #
|
||||||
|
# The following variables affect the behavior of the script: #
|
||||||
|
# #
|
||||||
|
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
|
||||||
|
# -- enables debug messages #
|
||||||
|
# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) #
|
||||||
|
# -- excludes tests marked with [!hide], [.] or [.foo] tags #
|
||||||
|
# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) #
|
||||||
|
# -- adds fixture class name to the test name #
|
||||||
|
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
||||||
|
# -- adds cmake target name to the test name #
|
||||||
|
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
|
||||||
|
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
|
||||||
|
# #
|
||||||
|
#==================================================================================================#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8.8)
|
||||||
|
|
||||||
|
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
|
||||||
|
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
||||||
|
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
||||||
|
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
||||||
|
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
|
||||||
|
|
||||||
|
function(PrintDebugMessage)
|
||||||
|
if(PARSE_CATCH_TESTS_VERBOSE)
|
||||||
|
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# This removes the contents between
|
||||||
|
# - block comments (i.e. /* ... */)
|
||||||
|
# - full line comments (i.e. // ... )
|
||||||
|
# contents have been read into '${CppCode}'.
|
||||||
|
# !keep partial line comments
|
||||||
|
function(RemoveComments CppCode)
|
||||||
|
string(ASCII 2 CMakeBeginBlockComment)
|
||||||
|
string(ASCII 3 CMakeEndBlockComment)
|
||||||
|
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
|
||||||
|
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
|
||||||
|
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
|
||||||
|
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
|
||||||
|
|
||||||
|
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Worker function
|
||||||
|
function(ParseFile SourceFile TestTarget)
|
||||||
|
# According to CMake docs EXISTS behavior is well-defined only for full paths.
|
||||||
|
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
|
||||||
|
if(NOT EXISTS ${SourceFile})
|
||||||
|
message(WARNING "Cannot find source file: ${SourceFile}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
PrintDebugMessage("parsing ${SourceFile}")
|
||||||
|
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
|
||||||
|
|
||||||
|
# Remove block and fullline comments
|
||||||
|
RemoveComments(Contents)
|
||||||
|
|
||||||
|
# Find definition of test names
|
||||||
|
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
||||||
|
|
||||||
|
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
|
||||||
|
PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
|
||||||
|
set_property(
|
||||||
|
DIRECTORY
|
||||||
|
APPEND
|
||||||
|
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
foreach(TestName ${Tests})
|
||||||
|
# Strip newlines
|
||||||
|
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
||||||
|
|
||||||
|
# Get test type and fixture if applicable
|
||||||
|
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
|
||||||
|
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
|
||||||
|
string(REPLACE "${TestType}(" "" TestFixture "${TestTypeAndFixture}")
|
||||||
|
|
||||||
|
# Get string parts of test definition
|
||||||
|
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
|
||||||
|
|
||||||
|
# Strip wrapping quotation marks
|
||||||
|
string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}")
|
||||||
|
string(REPLACE "\";\"" ";" TestStrings "${TestStrings}")
|
||||||
|
|
||||||
|
# Validate that a test name and tags have been provided
|
||||||
|
list(LENGTH TestStrings TestStringsLength)
|
||||||
|
if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1)
|
||||||
|
message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Assign name and tags
|
||||||
|
list(GET TestStrings 0 Name)
|
||||||
|
if("${TestType}" STREQUAL "SCENARIO")
|
||||||
|
set(Name "Scenario: ${Name}")
|
||||||
|
endif()
|
||||||
|
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
|
||||||
|
set(CTestName "${TestFixture}:${Name}")
|
||||||
|
else()
|
||||||
|
set(CTestName "${Name}")
|
||||||
|
endif()
|
||||||
|
if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME)
|
||||||
|
set(CTestName "${TestTarget}:${CTestName}")
|
||||||
|
endif()
|
||||||
|
# add target to labels to enable running all tests added from this target
|
||||||
|
set(Labels ${TestTarget})
|
||||||
|
if(TestStringsLength EQUAL 2)
|
||||||
|
list(GET TestStrings 1 Tags)
|
||||||
|
string(TOLOWER "${Tags}" Tags)
|
||||||
|
# remove target from labels if the test is hidden
|
||||||
|
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
|
||||||
|
list(REMOVE_ITEM Labels ${TestTarget})
|
||||||
|
endif()
|
||||||
|
string(REPLACE "]" ";" Tags "${Tags}")
|
||||||
|
string(REPLACE "[" "" Tags "${Tags}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND Labels ${Tags})
|
||||||
|
|
||||||
|
list(FIND Labels "!hide" IndexOfHideLabel)
|
||||||
|
set(HiddenTagFound OFF)
|
||||||
|
foreach(label ${Labels})
|
||||||
|
string(REGEX MATCH "^!hide|^\\." result ${label})
|
||||||
|
if(result)
|
||||||
|
set(HiddenTagFound ON)
|
||||||
|
break()
|
||||||
|
endif(result)
|
||||||
|
endforeach(label)
|
||||||
|
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound})
|
||||||
|
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
||||||
|
else()
|
||||||
|
PrintDebugMessage("Adding test \"${CTestName}\"")
|
||||||
|
if(Labels)
|
||||||
|
PrintDebugMessage("Setting labels to ${Labels}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add the test and set its properties
|
||||||
|
add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters})
|
||||||
|
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||||
|
LABELS "${Labels}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# entry point
|
||||||
|
function(ParseAndAddCatchTests TestTarget)
|
||||||
|
PrintDebugMessage("Started parsing ${TestTarget}")
|
||||||
|
get_target_property(SourceFiles ${TestTarget} SOURCES)
|
||||||
|
PrintDebugMessage("Found the following sources: ${SourceFiles}")
|
||||||
|
foreach(SourceFile ${SourceFiles})
|
||||||
|
ParseFile(${SourceFile} ${TestTarget})
|
||||||
|
endforeach()
|
||||||
|
PrintDebugMessage("Finished parsing ${TestTarget}")
|
||||||
|
endfunction()
|
||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BASIC_HPP_
|
#ifndef CHAISCRIPT_BASIC_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||||
@ -76,7 +76,7 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace chaiscript {
|
namespace chaiscript {
|
||||||
constexpr static const int version_major = 6;
|
constexpr static const int version_major = 7;
|
||||||
constexpr static const int version_minor = 0;
|
constexpr static const int version_minor = 0;
|
||||||
constexpr static const int version_patch = 0;
|
constexpr static const int version_patch = 0;
|
||||||
|
|
||||||
@ -153,8 +153,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] constexpr auto parse_num(const std::string_view &t_str) noexcept
|
[[nodiscard]] constexpr auto parse_num(const std::string_view t_str) noexcept -> typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||||
-> typename std::enable_if<std::is_integral<T>::value, T>::type
|
|
||||||
{
|
{
|
||||||
T t = 0;
|
T t = 0;
|
||||||
for (const auto c : t_str) {
|
for (const auto c : t_str) {
|
||||||
@ -168,60 +167,15 @@ namespace chaiscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
[[nodiscard]] auto parse_num(const std::string_view &t_str) noexcept
|
|
||||||
-> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
|
||||||
{
|
|
||||||
T t = 0;
|
|
||||||
T base = 0;
|
|
||||||
T decimal_place = 0;
|
|
||||||
bool exponent = false;
|
|
||||||
bool neg_exponent = false;
|
|
||||||
|
|
||||||
const auto final_value = [](const T val, const T baseval, const bool hasexp, const bool negexp) -> T {
|
|
||||||
if (!hasexp) {
|
|
||||||
return val;
|
|
||||||
} else {
|
|
||||||
return baseval * std::pow(T(10), val*T(negexp?-1:1));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto c : t_str) {
|
|
||||||
if (c == '.') {
|
|
||||||
decimal_place = 10;
|
|
||||||
} else if (c == 'e' || c == 'E') {
|
|
||||||
exponent = true;
|
|
||||||
decimal_place = 0;
|
|
||||||
base = t;
|
|
||||||
t = 0;
|
|
||||||
} else if (c == '-' && exponent) {
|
|
||||||
neg_exponent = true;
|
|
||||||
} else if (c == '+' && exponent) {
|
|
||||||
neg_exponent = false;
|
|
||||||
} else if (c < '0' || c > '9') {
|
|
||||||
return final_value(t, base, exponent, neg_exponent);
|
|
||||||
} else if (decimal_place < T(10)) {
|
|
||||||
t *= T(10);
|
|
||||||
t += T(c - '0');
|
|
||||||
} else {
|
|
||||||
t += (T(c - '0') / (T(decimal_place)));
|
|
||||||
decimal_place *= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return final_value(t, base, exponent, neg_exponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
[[nodiscard]] auto parse_num(const std::string_view t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
||||||
{
|
{
|
||||||
T t = 0;
|
T t = 0;
|
||||||
T base;
|
T base{};
|
||||||
T decimal_place = 0;
|
T decimal_place = 0;
|
||||||
int exponent = 0;
|
int exponent = 0;
|
||||||
|
|
||||||
for (char c;; ++t_str) {
|
for (const auto c : t_str) {
|
||||||
c = *t_str;
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case '.':
|
case '.':
|
||||||
@ -251,17 +205,18 @@ namespace chaiscript {
|
|||||||
case '9':
|
case '9':
|
||||||
if (decimal_place < 10) {
|
if (decimal_place < 10) {
|
||||||
t *= 10;
|
t *= 10;
|
||||||
t += c - '0';
|
t += static_cast<T>(c - '0');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
t += (c - '0') / decimal_place;
|
t += static_cast<T>(c - '0') / decimal_place;
|
||||||
decimal_place *= 10;
|
decimal_place *= 10;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return exponent ? base * std::pow(T(10), t * exponent) : t;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return exponent ? base * std::pow(T(10), t * static_cast<T>(exponent)) : t;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct str_equal {
|
struct str_equal {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -135,6 +135,7 @@ namespace chaiscript
|
|||||||
construct_pod<T>(name, m);
|
construct_pod<T>(name, m);
|
||||||
|
|
||||||
m.add(fun(&parse_string<T>), "to_" + name);
|
m.add(fun(&parse_string<T>), "to_" + name);
|
||||||
|
m.add(fun([](const T t){ return t; }), "to_" + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -454,7 +455,7 @@ namespace chaiscript
|
|||||||
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
||||||
m.add(fun(&Boxed_Number::to_string), "to_string");
|
m.add(fun(&Boxed_Number::to_string), "to_string");
|
||||||
|
|
||||||
|
|
||||||
bootstrap_pod_type<double>("double", m);
|
bootstrap_pod_type<double>("double", m);
|
||||||
bootstrap_pod_type<long double>("long_double", m);
|
bootstrap_pod_type<long double>("long_double", m);
|
||||||
bootstrap_pod_type<float>("float", m);
|
bootstrap_pod_type<float>("float", m);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
107
include/chaiscript/dispatchkit/callable_traits.hpp
Normal file
107
include/chaiscript/dispatchkit/callable_traits.hpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_
|
||||||
|
#define CHAISCRIPT_CALLABLE_TRAITS_HPP_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace chaiscript {
|
||||||
|
namespace dispatch {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename Class, typename ... Param>
|
||||||
|
struct Constructor
|
||||||
|
{
|
||||||
|
template<typename ... Inner>
|
||||||
|
std::shared_ptr<Class> operator()(Inner&& ... inner) const {
|
||||||
|
return std::make_shared<Class>(std::forward<Inner>(inner)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret, typename Class, typename ... Param>
|
||||||
|
struct Const_Caller
|
||||||
|
{
|
||||||
|
explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
||||||
|
|
||||||
|
template<typename ... Inner>
|
||||||
|
Ret operator()(const Class &o, Inner&& ... inner) const {
|
||||||
|
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret (Class::*m_func)(Param...) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret, typename ... Param>
|
||||||
|
struct Fun_Caller
|
||||||
|
{
|
||||||
|
explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
||||||
|
|
||||||
|
template<typename ... Inner>
|
||||||
|
Ret operator()(Inner&& ... inner) const {
|
||||||
|
return (m_func)(std::forward<Inner>(inner)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret(*m_func)(Param...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret, typename Class, typename ... Param>
|
||||||
|
struct Caller
|
||||||
|
{
|
||||||
|
explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
||||||
|
|
||||||
|
template<typename ... Inner>
|
||||||
|
Ret operator()(Class &o, Inner&& ... inner) const {
|
||||||
|
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret (Class::*m_func)(Param...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Arity
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret, typename ... Params>
|
||||||
|
struct Arity<Ret (Params...)>
|
||||||
|
{
|
||||||
|
static const size_t arity = sizeof...(Params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Function_Signature
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret, typename ... Params>
|
||||||
|
struct Function_Signature<Ret (Params...)>
|
||||||
|
{
|
||||||
|
typedef Ret Return_Type;
|
||||||
|
typedef Ret (Signature)(Params...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret, typename T, typename ... Params>
|
||||||
|
struct Function_Signature<Ret (T::*)(Params...) const>
|
||||||
|
{
|
||||||
|
typedef Ret Return_Type;
|
||||||
|
typedef Ret (Signature)(Params...);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Callable_Traits
|
||||||
|
{
|
||||||
|
typedef typename Function_Signature<decltype(&T::operator())>::Signature Signature;
|
||||||
|
typedef typename Function_Signature<decltype(&T::operator())>::Return_Type Return_Type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -682,7 +682,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the type info for a named type
|
/// Returns the type info for a named type
|
||||||
Type_Info get_type(const std::string_view &name, bool t_throw = true) const
|
Type_Info get_type(std::string_view name, bool t_throw = true) const
|
||||||
{
|
{
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (t_throw) {
|
if (t_throw) {
|
||||||
throw std::range_error("Type Not Known");
|
throw std::range_error("Type Not Known: " + std::string(name));
|
||||||
} else {
|
} else {
|
||||||
return Type_Info();
|
return Type_Info();
|
||||||
}
|
}
|
||||||
@ -730,8 +730,8 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
uint_fast32_t method_missing_loc = m_method_missing_loc;
|
uint_fast32_t method_missing_loc = m_method_missing_loc;
|
||||||
auto method_missing_funs = get_function("method_missing", method_missing_loc);
|
auto method_missing_funs = get_function("method_missing", method_missing_loc);
|
||||||
if (method_missing_funs.first != method_missing_loc) {
|
if (method_missing_funs.first != method_missing_loc) {
|
||||||
m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
|
m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(method_missing_funs.second);
|
return std::move(method_missing_funs.second);
|
||||||
@ -837,7 +837,7 @@ namespace chaiscript
|
|||||||
for (auto itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
for (auto itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||||
{
|
{
|
||||||
retval.insert(itr->begin(), itr->end());
|
retval.insert(itr->begin(), itr->end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the global values
|
// add the global values
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
@ -950,11 +950,11 @@ namespace chaiscript
|
|||||||
} catch (const chaiscript::exception::arity_error &) {
|
} catch (const chaiscript::exception::arity_error &) {
|
||||||
} catch (const chaiscript::exception::guard_error &) {
|
} catch (const chaiscript::exception::guard_error &) {
|
||||||
}
|
}
|
||||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
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)});
|
std::vector<Const_Proxy_Function>{boxed_cast<Const_Proxy_Function>(bv)});
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
// unable to convert bv into a Proxy_Function_Base
|
// unable to convert bv into a Proxy_Function_Base
|
||||||
throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
|
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()));
|
std::vector<Const_Proxy_Function>(l_funs.begin(), l_funs.end()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1011,7 +1011,7 @@ namespace chaiscript
|
|||||||
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
||||||
return do_attribute_call(2, Function_Params(tmp_params), functions, t_conversions);
|
return do_attribute_call(2, Function_Params(tmp_params), functions, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
std::array p{params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))};
|
std::array<Boxed_Value, 3> p{params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))};
|
||||||
return dispatch::dispatch(functions, Function_Params{p}, t_conversions);
|
return dispatch::dispatch(functions, Function_Params{p}, t_conversions);
|
||||||
}
|
}
|
||||||
} catch (const dispatch::option_explicit_set &e) {
|
} catch (const dispatch::option_explicit_set &e) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -46,9 +46,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
constexpr Type_Info() noexcept = default;
|
constexpr Type_Info() noexcept = default;
|
||||||
|
|
||||||
constexpr bool operator<(const Type_Info &ti) const noexcept
|
bool operator<(const Type_Info &ti) const noexcept
|
||||||
{
|
{
|
||||||
return m_type_info < ti.m_type_info;
|
return m_type_info->before(*ti.m_type_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool operator!=(const Type_Info &ti) const noexcept
|
constexpr bool operator!=(const Type_Info &ti) const noexcept
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -506,11 +506,14 @@ namespace chaiscript
|
|||||||
/// Errors generated when loading a file
|
/// Errors generated when loading a file
|
||||||
struct file_not_found_error : std::runtime_error {
|
struct file_not_found_error : std::runtime_error {
|
||||||
explicit file_not_found_error(const std::string &t_filename)
|
explicit file_not_found_error(const std::string &t_filename)
|
||||||
: std::runtime_error("File Not Found: " + t_filename)
|
: std::runtime_error("File Not Found: " + t_filename),
|
||||||
|
filename(t_filename)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
file_not_found_error(const file_not_found_error &) = default;
|
file_not_found_error(const file_not_found_error &) = default;
|
||||||
~file_not_found_error() noexcept override = default;
|
~file_not_found_error() noexcept override = default;
|
||||||
|
|
||||||
|
std::string filename;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -673,9 +676,6 @@ namespace chaiscript
|
|||||||
/// Special type for returned values
|
/// Special type for returned values
|
||||||
struct Return_Value {
|
struct Return_Value {
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
|
|
||||||
explicit Return_Value(Boxed_Value &&t_return_value) : retval(std::move(t_return_value)) { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -54,8 +54,8 @@
|
|||||||
#include "../dispatchkit/exception_specification.hpp"
|
#include "../dispatchkit/exception_specification.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/// Namespace alias to provide cleaner and more explicit syntax to users.
|
/// Namespace alias to provide cleaner and more explicit syntax to users.
|
||||||
using Namespace = dispatch::Dynamic_Object;
|
using Namespace = dispatch::Dynamic_Object;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -200,11 +200,32 @@ namespace chaiscript
|
|||||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
||||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
|
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
|
||||||
|
|
||||||
// why this unused parameter to Namesapce?
|
// why this unused parameter to Namespace?
|
||||||
m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([](Namespace& ) {}, t_namespace_name); import(t_namespace_name); }), "namespace");
|
m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([](Namespace& /*space*/) {}, t_namespace_name); import(t_namespace_name); }), "namespace");
|
||||||
m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
|
m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Skip BOM at the beginning of file
|
||||||
|
static bool skip_bom(std::ifstream &infile) {
|
||||||
|
size_t bytes_needed = 3;
|
||||||
|
char buffer[3];
|
||||||
|
|
||||||
|
memset(buffer, '\0', bytes_needed);
|
||||||
|
|
||||||
|
infile.read(buffer, static_cast<std::streamsize>(bytes_needed));
|
||||||
|
|
||||||
|
if ((buffer[0] == '\xef')
|
||||||
|
&& (buffer[1] == '\xbb')
|
||||||
|
&& (buffer[2] == '\xbf')) {
|
||||||
|
|
||||||
|
infile.seekg(3);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
infile.seekg(0);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function for loading a file
|
/// Helper function for loading a file
|
||||||
static std::string load_file(const std::string &t_filename) {
|
static std::string load_file(const std::string &t_filename) {
|
||||||
@ -214,17 +235,22 @@ namespace chaiscript
|
|||||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto size = infile.tellg();
|
auto size = infile.tellg();
|
||||||
infile.seekg(0, std::ios::beg);
|
infile.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
assert(size >= 0);
|
assert(size >= 0);
|
||||||
|
|
||||||
|
if (skip_bom(infile)) {
|
||||||
|
size-=3; // decrement the BOM size from file size, otherwise we'll get parsing errors
|
||||||
|
assert(size >= 0); //and check if there's more text
|
||||||
|
}
|
||||||
|
|
||||||
if (size == std::streampos(0))
|
if (size == std::streampos(0))
|
||||||
{
|
{
|
||||||
return std::string();
|
return std::string();
|
||||||
} else {
|
} else {
|
||||||
std::vector<char> v(static_cast<size_t>(size));
|
std::vector<char> v(static_cast<size_t>(size));
|
||||||
infile.read(&v[0], size);
|
infile.read(&v[0], static_cast<std::streamsize>(size));
|
||||||
return std::string(v.begin(), v.end());
|
return std::string(v.begin(), v.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,8 +395,8 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
for (const auto &path : m_use_paths)
|
for (const auto &path : m_use_paths)
|
||||||
{
|
{
|
||||||
|
const auto appendedpath = path + t_filename;
|
||||||
try {
|
try {
|
||||||
const auto appendedpath = path + t_filename;
|
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
@ -386,7 +412,11 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
return retval; // return, we loaded it, or it was already loaded
|
return retval; // return, we loaded it, or it was already loaded
|
||||||
} catch (const exception::file_not_found_error &) {
|
} catch (const exception::file_not_found_error &e) {
|
||||||
|
if (e.filename != appendedpath) {
|
||||||
|
// a nested file include failed
|
||||||
|
throw;
|
||||||
|
}
|
||||||
// failed to load, try the next path
|
// failed to load, try the next path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -711,39 +741,39 @@ namespace chaiscript
|
|||||||
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
|
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Imports a namespace object into the global scope of this ChaiScript instance.
|
/// \brief Imports a namespace object into the global scope of this ChaiScript instance.
|
||||||
/// \param[in] t_namespace_name Name of the namespace to import.
|
/// \param[in] t_namespace_name Name of the namespace to import.
|
||||||
/// \throw std::runtime_error In the case that the namespace name was never registered.
|
/// \throw std::runtime_error In the case that the namespace name was never registered.
|
||||||
void import(const std::string& t_namespace_name)
|
void import(const std::string& t_namespace_name)
|
||||||
{
|
{
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
|
|
||||||
if (m_engine.get_scripting_objects().count(t_namespace_name)) {
|
if (m_engine.get_scripting_objects().count(t_namespace_name)) {
|
||||||
throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined");
|
throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined");
|
||||||
}
|
}
|
||||||
else if (m_namespace_generators.count(t_namespace_name)) {
|
else if (m_namespace_generators.count(t_namespace_name)) {
|
||||||
m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name);
|
m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw std::runtime_error("No registered namespace: " + t_namespace_name);
|
throw std::runtime_error("No registered namespace: " + t_namespace_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never used.
|
/// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never used.
|
||||||
/// \param[in] t_namespace_generator Namespace generator function.
|
/// \param[in] t_namespace_generator Namespace generator function.
|
||||||
/// \param[in] t_namespace_name Name of the Namespace function being registered.
|
/// \param[in] t_namespace_name Name of the Namespace function being registered.
|
||||||
/// \throw std::runtime_error In the case that the namespace name was already registered.
|
/// \throw std::runtime_error In the case that the namespace name was already registered.
|
||||||
void register_namespace(const std::function<void(Namespace&)>& t_namespace_generator, const std::string& t_namespace_name)
|
void register_namespace(const std::function<void(Namespace&)>& t_namespace_generator, const std::string& t_namespace_name)
|
||||||
{
|
{
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
|
|
||||||
if (!m_namespace_generators.count(t_namespace_name)) {
|
if (!m_namespace_generators.count(t_namespace_name)) {
|
||||||
// contain the namespace object memory within the m_namespace_generators map
|
// contain the namespace object memory within the m_namespace_generators map
|
||||||
m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace& { t_namespace_generator(space); return space; }));
|
m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace& { t_namespace_generator(space); return space; }));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
|
throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -99,7 +99,7 @@ namespace chaiscript
|
|||||||
} else if (incoming.get_type_info().bare_equal_type_info(typeid(std::string))) {
|
} else if (incoming.get_type_info().bare_equal_type_info(typeid(std::string))) {
|
||||||
return Boxed_Value(*static_cast<const std::string *>(incoming.get_const_ptr()));
|
return Boxed_Value(*static_cast<const std::string *>(incoming.get_const_ptr()));
|
||||||
} else {
|
} else {
|
||||||
std::array params{std::move(incoming)};
|
std::array<Boxed_Value, 1> params{std::move(incoming)};
|
||||||
return t_ss->call_function("clone", t_loc, Function_Params{params}, t_ss.conversions());
|
return t_ss->call_function("clone", t_loc, Function_Params{params}, t_ss.conversions());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -203,7 +203,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
std::array params{t_lhs, m_rhs};
|
std::array<Boxed_Value, 2> params{t_lhs, m_rhs};
|
||||||
fpp.save_params(Function_Params{params});
|
fpp.save_params(Function_Params{params});
|
||||||
return t_ss->call_function(t_oper_string, m_loc, Function_Params{params}, t_ss.conversions());
|
return t_ss->call_function(t_oper_string, m_loc, Function_Params{params}, t_ss.conversions());
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
std::array params{t_lhs, t_rhs};
|
std::array<Boxed_Value, 2> params{t_lhs, t_rhs};
|
||||||
fpp.save_params(Function_Params(params));
|
fpp.save_params(Function_Params(params));
|
||||||
return t_ss->call_function(t_oper_string, m_loc, Function_Params(params), t_ss.conversions());
|
return t_ss->call_function(t_oper_string, m_loc, Function_Params(params), t_ss.conversions());
|
||||||
}
|
}
|
||||||
@ -331,6 +331,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
Boxed_Value fn(this->children[0]->eval(t_ss));
|
Boxed_Value fn(this->children[0]->eval(t_ss));
|
||||||
|
|
||||||
|
using ConstFunctionTypePtr = const dispatch::Proxy_Function_Base *;
|
||||||
try {
|
try {
|
||||||
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(Function_Params{params}, t_ss.conversions());
|
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(Function_Params{params}, t_ss.conversions());
|
||||||
}
|
}
|
||||||
@ -339,7 +340,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
catch(const exception::bad_boxed_cast &){
|
catch(const exception::bad_boxed_cast &){
|
||||||
try {
|
try {
|
||||||
Const_Proxy_Function f = t_ss->boxed_cast<const Const_Proxy_Function &>(fn);
|
using ConstFunctionTypeRef = const Const_Proxy_Function &;
|
||||||
|
Const_Proxy_Function f = t_ss->boxed_cast<ConstFunctionTypeRef>(fn);
|
||||||
// handle the case where there is only 1 function to try to call and dispatch fails on it
|
// 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, make_vector(f), false, *t_ss);
|
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, make_vector(f), false, *t_ss);
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
@ -455,10 +457,16 @@ namespace chaiscript
|
|||||||
// for the RHS
|
// for the RHS
|
||||||
auto rhs = this->children[1]->eval(t_ss);
|
auto rhs = this->children[1]->eval(t_ss);
|
||||||
auto lhs = this->children[0]->eval(t_ss);
|
auto lhs = this->children[0]->eval(t_ss);
|
||||||
std::array p{std::move(lhs), std::move(rhs)};
|
std::array<Boxed_Value, 2> p{std::move(lhs), std::move(rhs)};
|
||||||
return p;
|
return p;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
if (params[0].is_return_value()) {
|
||||||
|
throw exception::eval_error("Error, cannot assign to temporary value.");
|
||||||
|
} else if (params[0].is_const()) {
|
||||||
|
throw exception::eval_error("Error, cannot assign to constant value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_oper != Operators::Opers::invalid && params[0].get_type_info().is_arithmetic() &&
|
if (m_oper != Operators::Opers::invalid && params[0].get_type_info().is_arithmetic() &&
|
||||||
params[1].get_type_info().is_arithmetic())
|
params[1].get_type_info().is_arithmetic())
|
||||||
@ -466,13 +474,9 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
return Boxed_Number::do_oper(m_oper, params[0], params[1]);
|
return Boxed_Number::do_oper(m_oper, params[0], params[1]);
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
throw exception::eval_error("Error with unsupported arithmetic assignment operation");
|
throw exception::eval_error("Error with unsupported arithmetic assignment operation.");
|
||||||
}
|
}
|
||||||
} else if (m_oper == Operators::Opers::assign) {
|
} else if (m_oper == Operators::Opers::assign) {
|
||||||
if (params[0].is_return_value()) {
|
|
||||||
throw exception::eval_error("Error, cannot assign to temporary value.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (params[0].is_undef()) {
|
if (params[0].is_undef()) {
|
||||||
@ -599,7 +603,7 @@ namespace chaiscript
|
|||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
|
||||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
|
|
||||||
std::array params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)};
|
std::array<Boxed_Value, 2> params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fpp.save_params(Function_Params{params});
|
fpp.save_params(Function_Params{params});
|
||||||
@ -657,7 +661,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (this->children[1]->identifier == AST_Node_Type::Array_Call) {
|
if (this->children[1]->identifier == AST_Node_Type::Array_Call) {
|
||||||
try {
|
try {
|
||||||
std::array p{retval, this->children[1]->children[1]->eval(t_ss)};
|
std::array<Boxed_Value, 2> p{retval, this->children[1]->children[1]->eval(t_ss)};
|
||||||
retval = t_ss->call_function("[]", m_array_loc, Function_Params{p}, t_ss.conversions());
|
retval = t_ss->call_function("[]", m_array_loc, Function_Params{p}, t_ss.conversions());
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
@ -771,6 +775,8 @@ namespace chaiscript
|
|||||||
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
|
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)))
|
std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children, 1)?2:1)))
|
||||||
),
|
),
|
||||||
|
// This apparent use after move is safe because we are only moving out the specific elements we need
|
||||||
|
// on each operation.
|
||||||
m_body_node(get_body_node(std::move(t_children))),
|
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))
|
m_guard_node(get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))
|
||||||
|
|
||||||
@ -933,10 +939,16 @@ namespace chaiscript
|
|||||||
|
|
||||||
const auto do_loop = [&loop_var_name, &t_ss, this](const auto &ranged_thing){
|
const auto do_loop = [&loop_var_name, &t_ss, this](const auto &ranged_thing){
|
||||||
try {
|
try {
|
||||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
for (auto &&loop_var : ranged_thing) {
|
||||||
Boxed_Value &obj = t_ss.add_get_object(loop_var_name, void_var());
|
// This scope push and pop might not be the best thing for perf
|
||||||
for (auto loop_var : ranged_thing) {
|
// but we know it's 100% correct
|
||||||
obj = Boxed_Value(std::move(loop_var));
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
/// to-do make this if-constexpr with C++17 branch
|
||||||
|
if (!std::is_same<std::decay_t<decltype(loop_var)>, Boxed_Value>::value) {
|
||||||
|
t_ss.add_get_object(loop_var_name, Boxed_Value(std::ref(loop_var)));
|
||||||
|
} else {
|
||||||
|
t_ss.add_get_object(loop_var_name, Boxed_Value(loop_var));
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
this->children[2]->eval(t_ss);
|
this->children[2]->eval(t_ss);
|
||||||
} catch (detail::Continue_Loop &) {
|
} catch (detail::Continue_Loop &) {
|
||||||
@ -960,10 +972,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const auto range_obj = call_function(range_funcs, range_expression_result);
|
const auto range_obj = call_function(range_funcs, range_expression_result);
|
||||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
|
||||||
Boxed_Value &obj = t_ss.add_get_object(loop_var_name, void_var());
|
|
||||||
while (!boxed_cast<bool>(call_function(empty_funcs, range_obj))) {
|
while (!boxed_cast<bool>(call_function(empty_funcs, range_obj))) {
|
||||||
obj = call_function(front_funcs, range_obj);
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
t_ss.add_get_object(loop_var_name, call_function(front_funcs, range_obj));
|
||||||
try {
|
try {
|
||||||
this->children[2]->eval(t_ss);
|
this->children[2]->eval(t_ss);
|
||||||
} catch (detail::Continue_Loop &) {
|
} catch (detail::Continue_Loop &) {
|
||||||
@ -1039,7 +1050,7 @@ namespace chaiscript
|
|||||||
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
|
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
|
||||||
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
|
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
|
||||||
try {
|
try {
|
||||||
std::array p{match_value, this->children[currentCase]->children[0]->eval(t_ss)};
|
std::array<Boxed_Value, 2> p{match_value, this->children[currentCase]->children[0]->eval(t_ss)};
|
||||||
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, Function_Params{p}, t_ss.conversions()))) {
|
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, Function_Params{p}, t_ss.conversions()))) {
|
||||||
this->children[currentCase]->eval(t_ss);
|
this->children[currentCase]->eval(t_ss);
|
||||||
hasMatched = true;
|
hasMatched = true;
|
||||||
@ -1154,10 +1165,10 @@ namespace chaiscript
|
|||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||||
if (!this->children.empty()) {
|
if (!this->children.empty()) {
|
||||||
throw detail::Return_Value(this->children[0]->eval(t_ss));
|
throw detail::Return_Value{this->children[0]->eval(t_ss)};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw detail::Return_Value(void_var());
|
throw detail::Return_Value{void_var()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1214,6 +1225,10 @@ namespace chaiscript
|
|||||||
// short circuit arithmetic operations
|
// short circuit arithmetic operations
|
||||||
if (m_oper != Operators::Opers::invalid && m_oper != Operators::Opers::bitwise_and && bv.get_type_info().is_arithmetic())
|
if (m_oper != Operators::Opers::invalid && m_oper != Operators::Opers::bitwise_and && bv.get_type_info().is_arithmetic())
|
||||||
{
|
{
|
||||||
|
if ((m_oper == Operators::Opers::pre_increment || m_oper == Operators::Opers::pre_decrement) && bv.is_const())
|
||||||
|
{
|
||||||
|
throw exception::eval_error("Error with prefix operator evaluation: cannot modify constant value.");
|
||||||
|
}
|
||||||
return Boxed_Number::do_oper(m_oper, bv);
|
return Boxed_Number::do_oper(m_oper, bv);
|
||||||
} else {
|
} else {
|
||||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
@ -1283,7 +1298,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||||
try {
|
try {
|
||||||
std::array params{
|
std::array<Boxed_Value, 2> params{
|
||||||
this->children[0]->children[0]->children[0]->eval(t_ss),
|
this->children[0]->children[0]->children[0]->eval(t_ss),
|
||||||
this->children[0]->children[0]->children[1]->eval(t_ss)
|
this->children[0]->children[0]->children[1]->eval(t_ss)
|
||||||
};
|
};
|
||||||
@ -1408,7 +1423,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
|
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),
|
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::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)))
|
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_body_node(Def_AST_Node<T>::get_body_node(std::move(t_children))),
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
|
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
|
||||||
@ -356,7 +356,7 @@ namespace chaiscript {
|
|||||||
|
|
||||||
const auto make_constant = [&node, &fun_name](auto val){
|
const auto make_constant = [&node, &fun_name](auto val){
|
||||||
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||||
return chaiscript::make_unique<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, const_var(val));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fun_name == "double") {
|
if (fun_name == "double") {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -118,12 +118,34 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Tracer, typename Optimizer>
|
template<typename Tracer, typename Optimizer, std::size_t Parse_Depth=512>
|
||||||
class ChaiScript_Parser final : public ChaiScript_Parser_Base {
|
class ChaiScript_Parser final : public ChaiScript_Parser_Base {
|
||||||
void *get_tracer_ptr() noexcept override {
|
void *get_tracer_ptr() noexcept override {
|
||||||
return &m_tracer;
|
return &m_tracer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t m_current_parse_depth = 0;
|
||||||
|
|
||||||
|
struct Depth_Counter
|
||||||
|
{
|
||||||
|
static const auto max_depth = Parse_Depth;
|
||||||
|
Depth_Counter(ChaiScript_Parser *t_parser) : parser(t_parser)
|
||||||
|
{
|
||||||
|
++parser->m_current_parse_depth;
|
||||||
|
if (parser->m_current_parse_depth > max_depth) {
|
||||||
|
throw exception::eval_error("Maximum parse depth exceeded",
|
||||||
|
File_Position(parser->m_position.line, parser->m_position.col), *(parser->m_filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Depth_Counter() noexcept
|
||||||
|
{
|
||||||
|
--parser->m_current_parse_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChaiScript_Parser *parser;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Array2D, typename First, typename Second>
|
template<typename Array2D, typename First, typename Second>
|
||||||
constexpr static void set_alphabet(Array2D &array, const First first, const Second second) noexcept
|
constexpr static void set_alphabet(Array2D &array, const First first, const Second second) noexcept
|
||||||
{
|
{
|
||||||
@ -552,10 +574,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Skips ChaiScript whitespace, which means space and tab, but not cr/lf
|
/// Skips ChaiScript whitespace, which means space and tab, but not cr/lf
|
||||||
/// jespada: Modified SkipWS to skip optionally CR ('\n') and/or LF+CR ("\r\n")
|
/// jespada: Modified SkipWS to skip optionally CR ('\n') and/or LF+CR ("\r\n")
|
||||||
|
/// AlekMosingiewicz: Added exception when illegal character detected
|
||||||
bool SkipWS(bool skip_cr=false) {
|
bool SkipWS(bool skip_cr=false) {
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
while (m_position.has_more()) {
|
while (m_position.has_more()) {
|
||||||
|
if(static_cast<unsigned char>(*m_position) > 0x7e) {
|
||||||
|
throw exception::eval_error("Illegal character", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
|
}
|
||||||
auto end_line = (*m_position != 0) && ((*m_position == '\n') || (*m_position == '\r' && *(m_position+1) == '\n'));
|
auto end_line = (*m_position != 0) && ((*m_position == '\n') || (*m_position == '\r' && *(m_position+1) == '\n'));
|
||||||
|
|
||||||
if ( char_in_alphabet(*m_position,detail::white_alphabet) || (skip_cr && end_line)) {
|
if ( char_in_alphabet(*m_position,detail::white_alphabet) || (skip_cr && end_line)) {
|
||||||
@ -766,6 +792,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
#ifdef CHAISCRIPT_CLANG
|
#ifdef CHAISCRIPT_CLANG
|
||||||
#pragma GCC diagnostic ignored "-Wtautological-compare"
|
#pragma GCC diagnostic ignored "-Wtautological-compare"
|
||||||
|
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -781,7 +808,10 @@ namespace chaiscript
|
|||||||
return const_var(static_cast<unsigned int>(u));
|
return const_var(static_cast<unsigned int>(u));
|
||||||
} else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long>::min() && u <= std::numeric_limits<long>::max()) {
|
} else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long>::min() && u <= std::numeric_limits<long>::max()) {
|
||||||
return const_var(static_cast<long>(u));
|
return const_var(static_cast<long>(u));
|
||||||
} else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
|
} else if ((unsigned_ || base != 10) && !longlong_
|
||||||
|
|
||||||
|
&& u >= std::numeric_limits<unsigned long>::min()
|
||||||
|
&& u <= std::numeric_limits<unsigned long>::max()) {
|
||||||
return const_var(static_cast<unsigned long>(u));
|
return const_var(static_cast<unsigned long>(u));
|
||||||
} else if (!unsigned_ && u >= std::numeric_limits<long long>::min() && u <= std::numeric_limits<long long>::max()) {
|
} else if (!unsigned_ && u >= std::numeric_limits<long long>::min() && u <= std::numeric_limits<long long>::max()) {
|
||||||
return const_var(static_cast<long long>(u));
|
return const_var(static_cast<long long>(u));
|
||||||
@ -948,7 +978,7 @@ namespace chaiscript
|
|||||||
} break;
|
} break;
|
||||||
case utility::hash("__FUNC__"): {
|
case utility::hash("__FUNC__"): {
|
||||||
std::string fun_name = "NOT_IN_FUNCTION";
|
std::string fun_name = "NOT_IN_FUNCTION";
|
||||||
for (size_t idx = m_match_stack.size() - 1; idx > 0; --idx)
|
for (size_t idx = m_match_stack.empty() ? 0 : m_match_stack.size() - 1; idx > 0; --idx)
|
||||||
{
|
{
|
||||||
if (m_match_stack[idx-1]->identifier == AST_Node_Type::Id
|
if (m_match_stack[idx-1]->identifier == AST_Node_Type::Id
|
||||||
&& m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) {
|
&& m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) {
|
||||||
@ -961,7 +991,7 @@ namespace chaiscript
|
|||||||
} break;
|
} break;
|
||||||
case utility::hash("__CLASS__"): {
|
case utility::hash("__CLASS__"): {
|
||||||
std::string fun_name = "NOT_IN_CLASS";
|
std::string fun_name = "NOT_IN_CLASS";
|
||||||
for (size_t idx = m_match_stack.size() - 1; idx > 1; --idx)
|
for (size_t idx = m_match_stack.empty() ? 0 : m_match_stack.size() - 1; idx > 1; --idx)
|
||||||
{
|
{
|
||||||
if (m_match_stack[idx-2]->identifier == AST_Node_Type::Id
|
if (m_match_stack[idx-2]->identifier == AST_Node_Type::Id
|
||||||
&& m_match_stack[idx-1]->identifier == AST_Node_Type::Id
|
&& m_match_stack[idx-1]->identifier == AST_Node_Type::Id
|
||||||
@ -1071,7 +1101,7 @@ namespace chaiscript
|
|||||||
bool saw_interpolation_marker = false;
|
bool saw_interpolation_marker = false;
|
||||||
bool is_octal = false;
|
bool is_octal = false;
|
||||||
bool is_hex = false;
|
bool is_hex = false;
|
||||||
bool is_unicode = false;
|
std::size_t unicode_size = 0;
|
||||||
const bool interpolation_allowed;
|
const bool interpolation_allowed;
|
||||||
|
|
||||||
string_type octal_matches;
|
string_type octal_matches;
|
||||||
@ -1095,12 +1125,12 @@ namespace chaiscript
|
|||||||
process_hex();
|
process_hex();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_unicode) {
|
if (unicode_size > 0) {
|
||||||
process_unicode();
|
process_unicode();
|
||||||
}
|
}
|
||||||
} catch (const std::invalid_argument &) {
|
} catch (const std::invalid_argument &) {
|
||||||
// escape sequence was invalid somehow, we'll pick this
|
} catch (const exception::eval_error &) {
|
||||||
// up in the next part of parsing
|
// Something happened with parsing, we'll catch it later?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,13 +1160,43 @@ namespace chaiscript
|
|||||||
|
|
||||||
void process_unicode()
|
void process_unicode()
|
||||||
{
|
{
|
||||||
if (!hex_matches.empty()) {
|
const auto ch = static_cast<uint32_t>(std::stoi(hex_matches, nullptr, 16));
|
||||||
auto val = stoll(hex_matches, nullptr, 16);
|
const auto match_size = hex_matches.size();
|
||||||
hex_matches.clear();
|
hex_matches.clear();
|
||||||
match += detail::Char_Parser_Helper<string_type>::str_from_ll(val);
|
|
||||||
}
|
|
||||||
is_escaped = false;
|
is_escaped = false;
|
||||||
is_unicode = false;
|
const auto u_size = unicode_size;
|
||||||
|
unicode_size = 0;
|
||||||
|
|
||||||
|
char buf[4];
|
||||||
|
if (u_size != match_size) {
|
||||||
|
throw exception::eval_error("Incomplete unicode escape sequence");
|
||||||
|
}
|
||||||
|
if (u_size == 4 && ch >= 0xD800 && ch <= 0xDFFF) {
|
||||||
|
throw exception::eval_error("Invalid 16 bit universal character");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ch < 0x80) {
|
||||||
|
match += static_cast<char>(ch);
|
||||||
|
} else if (ch < 0x800) {
|
||||||
|
buf[0] = static_cast<char>(0xC0 | (ch >> 6));
|
||||||
|
buf[1] = static_cast<char>(0x80 | (ch & 0x3F));
|
||||||
|
match.append(buf, 2);
|
||||||
|
} else if (ch < 0x10000) {
|
||||||
|
buf[0] = static_cast<char>(0xE0 | (ch >> 12));
|
||||||
|
buf[1] = static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
|
||||||
|
buf[2] = static_cast<char>(0x80 | (ch & 0x3F));
|
||||||
|
match.append(buf, 3);
|
||||||
|
} else if (ch < 0x200000) {
|
||||||
|
buf[0] = static_cast<char>(0xF0 | (ch >> 18));
|
||||||
|
buf[1] = static_cast<char>(0x80 | ((ch >> 12) & 0x3F));
|
||||||
|
buf[2] = static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
|
||||||
|
buf[3] = static_cast<char>(0x80 | (ch & 0x3F));
|
||||||
|
match.append(buf, 4);
|
||||||
|
} else {
|
||||||
|
// this must be an invalid escape sequence?
|
||||||
|
throw exception::eval_error("Invalid 32 bit universal character");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse(const char_type t_char, const int line, const int col, const std::string &filename) {
|
void parse(const char_type t_char, const int line, const int col, const std::string &filename) {
|
||||||
@ -1172,16 +1232,16 @@ namespace chaiscript
|
|||||||
} else {
|
} else {
|
||||||
process_hex();
|
process_hex();
|
||||||
}
|
}
|
||||||
} else if (is_unicode) {
|
} else if (unicode_size > 0) {
|
||||||
if (is_hex_char) {
|
if (is_hex_char) {
|
||||||
hex_matches.push_back(t_char);
|
hex_matches.push_back(t_char);
|
||||||
|
|
||||||
if(hex_matches.size() == 4) {
|
if(hex_matches.size() == unicode_size) {
|
||||||
// Format is specified to be 'slash'uABCD
|
// Format is specified to be 'slash'uABCD
|
||||||
// on collecting from A to D do parsing
|
// on collecting from A to D do parsing
|
||||||
process_unicode();
|
process_unicode();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Not a unicode anymore, try parsing any way
|
// Not a unicode anymore, try parsing any way
|
||||||
// May be someone used 'slash'uAA only
|
// May be someone used 'slash'uAA only
|
||||||
@ -1204,7 +1264,9 @@ namespace chaiscript
|
|||||||
} else if (t_char == 'x') {
|
} else if (t_char == 'x') {
|
||||||
is_hex = true;
|
is_hex = true;
|
||||||
} else if (t_char == 'u') {
|
} else if (t_char == 'u') {
|
||||||
is_unicode = true;
|
unicode_size = 4;
|
||||||
|
} else if (t_char == 'U') {
|
||||||
|
unicode_size = 8;
|
||||||
} else {
|
} else {
|
||||||
switch (t_char) {
|
switch (t_char) {
|
||||||
case ('\'') : match.push_back('\''); break;
|
case ('\'') : match.push_back('\''); break;
|
||||||
@ -1235,6 +1297,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads (and potentially captures) a quoted string from input. Translates escaped sequences.
|
/// Reads (and potentially captures) a quoted string from input. Translates escaped sequences.
|
||||||
bool Quoted_String() {
|
bool Quoted_String() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
const auto start = m_position;
|
const auto start = m_position;
|
||||||
@ -1350,6 +1413,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads (and potentially captures) a char group from input. Translates escaped sequences.
|
/// Reads (and potentially captures) a char group from input. Translates escaped sequences.
|
||||||
bool Single_Quoted_String() {
|
bool Single_Quoted_String() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
const auto start = m_position;
|
const auto start = m_position;
|
||||||
@ -1389,6 +1453,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads (and potentially captures) a char from input if it matches the parameter
|
/// Reads (and potentially captures) a char from input if it matches the parameter
|
||||||
bool Char(const char t_c) {
|
bool Char(const char t_c) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
return Char_(t_c);
|
return Char_(t_c);
|
||||||
}
|
}
|
||||||
@ -1413,6 +1478,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads (and potentially captures) a string from input if it matches the parameter
|
/// Reads (and potentially captures) a string from input if it matches the parameter
|
||||||
bool Keyword(const utility::Static_String &t_s) {
|
bool Keyword(const utility::Static_String &t_s) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
const auto start = m_position;
|
const auto start = m_position;
|
||||||
bool retval = Keyword_(t_s);
|
bool retval = Keyword_(t_s);
|
||||||
@ -1431,6 +1497,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads (and potentially captures) a symbol group from input if it matches the parameter
|
/// Reads (and potentially captures) a symbol group from input if it matches the parameter
|
||||||
bool Symbol(const utility::Static_String &t_s, const bool t_disallow_prevention=false) {
|
bool Symbol(const utility::Static_String &t_s, const bool t_disallow_prevention=false) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
const auto start = m_position;
|
const auto start = m_position;
|
||||||
bool retval = Symbol_(t_s);
|
bool retval = Symbol_(t_s);
|
||||||
@ -1465,6 +1532,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads until the end of the current statement
|
/// Reads until the end of the current statement
|
||||||
bool Eos() {
|
bool Eos() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
return Eol_(true);
|
return Eol_(true);
|
||||||
@ -1472,6 +1540,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads (and potentially captures) an end-of-line group from input
|
/// Reads (and potentially captures) an end-of-line group from input
|
||||||
bool Eol() {
|
bool Eol() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
return Eol_();
|
return Eol_();
|
||||||
@ -1479,6 +1548,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a comma-separated list of values from input. Id's only, no types allowed
|
/// Reads a comma-separated list of values from input. Id's only, no types allowed
|
||||||
bool Id_Arg_List() {
|
bool Id_Arg_List() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS(true);
|
SkipWS(true);
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
@ -1504,6 +1574,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a comma-separated list of values from input, for function declarations
|
/// Reads a comma-separated list of values from input, for function declarations
|
||||||
bool Decl_Arg_List() {
|
bool Decl_Arg_List() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS(true);
|
SkipWS(true);
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
@ -1530,6 +1601,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a comma-separated list of values from input
|
/// Reads a comma-separated list of values from input
|
||||||
bool Arg_List() {
|
bool Arg_List() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
SkipWS(true);
|
SkipWS(true);
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
@ -1555,6 +1627,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads possible special container values, including ranges and map_pairs
|
/// Reads possible special container values, including ranges and map_pairs
|
||||||
bool Container_Arg_List() {
|
bool Container_Arg_List() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
SkipWS(true);
|
SkipWS(true);
|
||||||
|
|
||||||
@ -1592,6 +1665,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a lambda (anonymous function) from input
|
/// Reads a lambda (anonymous function) from input
|
||||||
bool Lambda() {
|
bool Lambda() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1633,6 +1707,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a function definition from input
|
/// Reads a function definition from input
|
||||||
bool Def(const bool t_class_context = false, const std::string &t_class_name = "") {
|
bool Def(const bool t_class_context = false, const std::string &t_class_name = "") {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1692,6 +1767,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a function definition from input
|
/// Reads a function definition from input
|
||||||
bool Try() {
|
bool Try() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1746,6 +1822,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads an if/else if/else block from input
|
/// Reads an if/else if/else block from input
|
||||||
bool If() {
|
bool If() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1811,6 +1888,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a class block from input
|
/// Reads a class block from input
|
||||||
bool Class(const bool t_class_allowed) {
|
bool Class(const bool t_class_allowed) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
size_t prev_stack_top = m_match_stack.size();
|
size_t prev_stack_top = m_match_stack.size();
|
||||||
@ -1843,6 +1921,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a while block from input
|
/// Reads a while block from input
|
||||||
bool While() {
|
bool While() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1872,6 +1951,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads the ranged `for` conditions from input
|
/// Reads the ranged `for` conditions from input
|
||||||
bool Range_Expression() {
|
bool Range_Expression() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
// the first element will have already been captured by the For_Guards() call that preceeds it
|
// the first element will have already been captured by the For_Guards() call that preceeds it
|
||||||
return Char(':') && Equation();
|
return Char(':') && Equation();
|
||||||
}
|
}
|
||||||
@ -1879,6 +1959,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads the C-style `for` conditions from input
|
/// Reads the C-style `for` conditions from input
|
||||||
bool For_Guards() {
|
bool For_Guards() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
if (!(Equation() && Eol()))
|
if (!(Equation() && Eol()))
|
||||||
{
|
{
|
||||||
if (!Eol())
|
if (!Eol())
|
||||||
@ -1910,6 +1991,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a for block from input
|
/// Reads a for block from input
|
||||||
bool For() {
|
bool For() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1953,6 +2035,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a case block from input
|
/// Reads a case block from input
|
||||||
bool Case() {
|
bool Case() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -1993,6 +2076,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a switch statement from input
|
/// Reads a switch statement from input
|
||||||
bool Switch() {
|
bool Switch() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Keyword("switch")) {
|
if (Keyword("switch")) {
|
||||||
@ -2036,6 +2120,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a curly-brace C-style class block from input
|
/// Reads a curly-brace C-style class block from input
|
||||||
bool Class_Block(const std::string &t_class_name) {
|
bool Class_Block(const std::string &t_class_name) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -2060,6 +2145,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a curly-brace C-style block from input
|
/// Reads a curly-brace C-style block from input
|
||||||
bool Block() {
|
bool Block() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -2084,6 +2170,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a return statement from input
|
/// Reads a return statement from input
|
||||||
bool Return() {
|
bool Return() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Keyword("return")) {
|
if (Keyword("return")) {
|
||||||
@ -2097,6 +2184,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a break statement from input
|
/// Reads a break statement from input
|
||||||
bool Break() {
|
bool Break() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Keyword("break")) {
|
if (Keyword("break")) {
|
||||||
@ -2109,6 +2197,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a continue statement from input
|
/// Reads a continue statement from input
|
||||||
bool Continue() {
|
bool Continue() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Keyword("continue")) {
|
if (Keyword("continue")) {
|
||||||
@ -2121,6 +2210,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a dot expression(member access), then proceeds to check if it's a function or array call
|
/// Reads a dot expression(member access), then proceeds to check if it's a function or array call
|
||||||
bool Dot_Fun_Array() {
|
bool Dot_Fun_Array() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -2191,6 +2281,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a variable declaration from input
|
/// Reads a variable declaration from input
|
||||||
bool Var_Decl(const bool t_class_context = false, const std::string &t_class_name = "") {
|
bool Var_Decl(const bool t_class_context = false, const std::string &t_class_name = "") {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -2246,6 +2337,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads an expression surrounded by parentheses from input
|
/// Reads an expression surrounded by parentheses from input
|
||||||
bool Paren_Expression() {
|
bool Paren_Expression() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
if (Char('(')) {
|
if (Char('(')) {
|
||||||
if (!Operator()) {
|
if (!Operator()) {
|
||||||
throw exception::eval_error("Incomplete expression", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete expression", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
@ -2261,6 +2353,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads, and identifies, a short-form container initialization from input
|
/// Reads, and identifies, a short-form container initialization from input
|
||||||
bool Inline_Container() {
|
bool Inline_Container() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Char('[')) {
|
if (Char('[')) {
|
||||||
@ -2292,6 +2385,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Parses a variable specified with a & aka reference
|
/// Parses a variable specified with a & aka reference
|
||||||
bool Reference() {
|
bool Reference() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Symbol("&")) {
|
if (Symbol("&")) {
|
||||||
@ -2308,6 +2402,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a unary prefixed expression from input
|
/// Reads a unary prefixed expression from input
|
||||||
bool Prefix() {
|
bool Prefix() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
using SS = utility::Static_String;
|
using SS = utility::Static_String;
|
||||||
const std::array<utility::Static_String, 6> prefix_opers{{
|
const std::array<utility::Static_String, 6> prefix_opers{{
|
||||||
@ -2338,6 +2433,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Parses any of a group of 'value' style ast_node groups from input
|
/// Parses any of a group of 'value' style ast_node groups from input
|
||||||
bool Value() {
|
bool Value() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
return Var_Decl() || Dot_Fun_Array() || Prefix();
|
return Var_Decl() || Dot_Fun_Array() || Prefix();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2354,7 +2450,9 @@ namespace chaiscript
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Operator(const size_t t_precedence = 0) {
|
bool Operator(const size_t t_precedence = 0) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
@ -2419,6 +2517,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a pair of values used to create a map initialization from input
|
/// Reads a pair of values used to create a map initialization from input
|
||||||
bool Map_Pair() {
|
bool Map_Pair() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -2446,6 +2545,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Reads a pair of values used to create a range initialization from input
|
/// Reads a pair of values used to create a range initialization from input
|
||||||
bool Value_Range() {
|
bool Value_Range() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
@ -2473,6 +2573,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Parses a string of binary equation operators
|
/// Parses a string of binary equation operators
|
||||||
bool Equation() {
|
bool Equation() {
|
||||||
|
Depth_Counter dc{this};
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
using SS = utility::Static_String;
|
using SS = utility::Static_String;
|
||||||
@ -2498,6 +2599,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Parses statements allowed inside of a class block
|
/// Parses statements allowed inside of a class block
|
||||||
bool Class_Statements(const std::string &t_class_name) {
|
bool Class_Statements(const std::string &t_class_name) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
bool has_more = true;
|
bool has_more = true;
|
||||||
@ -2526,6 +2628,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Top level parser, starts parsing of all known parses
|
/// Top level parser, starts parsing of all known parses
|
||||||
bool Statements(const bool t_class_allowed = false) {
|
bool Statements(const bool t_class_allowed = false) {
|
||||||
|
Depth_Counter dc{this};
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
bool has_more = true;
|
bool has_more = true;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_POSIX_HPP_
|
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and 2009-2017, Jason Turner (jason@emptycrate.com)
|
// and 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_TRACER_HPP_
|
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_WINDOWS_HPP_
|
#ifndef CHAISCRIPT_WINDOWS_HPP_
|
||||||
|
|||||||
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-2018, 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
|
||||||
@ -50,7 +50,7 @@ class JSON
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
using Data = std::variant<std::nullptr_t, chaiscript::utility::QuickFlatMap<std::string, JSON>, std::vector<JSON>, std::string, double, int64_t, bool>;
|
using Data = std::variant<std::nullptr_t, chaiscript::utility::QuickFlatMap<std::string, JSON>, std::vector<JSON>, std::string, double, std::int64_t, bool>;
|
||||||
|
|
||||||
struct Internal
|
struct Internal
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ class JSON
|
|||||||
case Class::Array: return std::vector<JSON>{};
|
case Class::Array: return std::vector<JSON>{};
|
||||||
case Class::String: return std::string{};
|
case Class::String: return std::string{};
|
||||||
case Class::Floating: return double{};
|
case Class::Floating: return double{};
|
||||||
case Class::Integral: return int64_t{};
|
case Class::Integral: return std::int64_t{};
|
||||||
case Class::Boolean: return bool{};
|
case Class::Boolean: return bool{};
|
||||||
}
|
}
|
||||||
throw std::runtime_error("unknown type");
|
throw std::runtime_error("unknown type");
|
||||||
@ -191,7 +191,7 @@ class JSON
|
|||||||
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<bool>(b) ) {}
|
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<bool>(b) ) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
explicit JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<int64_t>(i) ) {}
|
explicit JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<std::int64_t>(i) ) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) noexcept : internal( static_cast<double>(f) ) {}
|
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) noexcept : internal( static_cast<double>(f) ) {}
|
||||||
@ -280,10 +280,10 @@ class JSON
|
|||||||
[](){ return double{}; }
|
[](){ return double{}; }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
int64_t to_int() const noexcept {
|
std::int64_t to_int() const noexcept {
|
||||||
return internal.visit_or<Class::Integral>(
|
return internal.visit_or<Class::Integral>(
|
||||||
[](const auto &o){ return o; },
|
[](const auto &o){ return o; },
|
||||||
[](){ return int64_t{}; }
|
[](){ return std::int64_t{}; }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
bool to_bool() const noexcept {
|
bool to_bool() const noexcept {
|
||||||
@ -321,7 +321,7 @@ class JSON
|
|||||||
bool skip = true;
|
bool skip = true;
|
||||||
for( auto &p : *internal.Map() ) {
|
for( auto &p : *internal.Map() ) {
|
||||||
if( !skip ) { s += ",\n"; }
|
if( !skip ) { s += ",\n"; }
|
||||||
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
|
s += ( pad + "\"" + json_escape(p.first) + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||||
skip = false;
|
skip = false;
|
||||||
}
|
}
|
||||||
s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ;
|
s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ;
|
||||||
@ -497,7 +497,7 @@ struct JSONParser {
|
|||||||
char c = '\0';
|
char c = '\0';
|
||||||
bool isDouble = false;
|
bool isDouble = false;
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
int64_t exp = 0;
|
std::int64_t exp = 0;
|
||||||
bool isExpNegative = false;
|
bool isExpNegative = false;
|
||||||
if( offset < str.size() && str.at(offset) == '-' ) {
|
if( offset < str.size() && str.at(offset) == '-' ) {
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
@ -535,7 +535,7 @@ struct JSONParser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exp = chaiscript::parse_num<int64_t>( exp_str ) * (isExpNegative?-1:1);
|
exp = chaiscript::parse_num<std::int64_t>( exp_str ) * (isExpNegative?-1:1);
|
||||||
}
|
}
|
||||||
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
||||||
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
||||||
@ -546,9 +546,9 @@ struct JSONParser {
|
|||||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||||
} else {
|
} else {
|
||||||
if( !exp_str.empty() ) {
|
if( !exp_str.empty() ) {
|
||||||
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<int64_t>( val )) * std::pow( 10, exp ));
|
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<std::int64_t>( val )) * std::pow( 10, exp ));
|
||||||
} else {
|
} else {
|
||||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<int64_t>( val ));
|
return JSON((isNegative?-1:1) * chaiscript::parse_num<std::int64_t>( val ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
const std::map<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(t_bv);
|
const std::map<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(t_bv);
|
||||||
|
|
||||||
json::JSON obj;
|
json::JSON obj(json::JSON::Class::Object);
|
||||||
for (const auto &o : m)
|
for (const auto &o : m)
|
||||||
{
|
{
|
||||||
obj[o.first] = to_json_object(o.second);
|
obj[o.first] = to_json_object(o.second);
|
||||||
@ -93,7 +93,7 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
|
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
|
||||||
|
|
||||||
json::JSON obj;
|
json::JSON obj(json::JSON::Class::Array);
|
||||||
for (size_t i = 0; i < v.size(); ++i)
|
for (size_t i = 0; i < v.size(); ++i)
|
||||||
{
|
{
|
||||||
obj[i] = to_json_object(v[i]);
|
obj[i] = to_json_object(v[i]);
|
||||||
@ -110,7 +110,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return json::JSON(bn.get_as<double>());
|
return json::JSON(bn.get_as<double>());
|
||||||
} else {
|
} else {
|
||||||
return json::JSON(bn.get_as<long>());
|
return json::JSON(bn.get_as<std::int64_t>());
|
||||||
}
|
}
|
||||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||||
// not a number
|
// not a number
|
||||||
@ -132,7 +132,7 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(t_bv);
|
const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(t_bv);
|
||||||
|
|
||||||
json::JSON obj;
|
json::JSON obj(json::JSON::Class::Object);
|
||||||
for (const auto &attr : o.get_attrs())
|
for (const auto &attr : o.get_attrs())
|
||||||
{
|
{
|
||||||
obj[attr.first] = to_json_object(attr.second);
|
obj[attr.first] = to_json_object(attr.second);
|
||||||
@ -142,6 +142,8 @@ namespace chaiscript
|
|||||||
// not a dynamic object
|
// not a dynamic object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t_bv.is_null()) return json::JSON(); // a null value
|
||||||
|
|
||||||
throw std::runtime_error("Unknown object type to convert to JSON");
|
throw std::runtime_error("Unknown object type to convert to JSON");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
Copyright 2009-2016 Jason Turner
|
BSD-3-Clause License
|
||||||
|
|
||||||
|
Copyright 2009-2018 Jason Turner
|
||||||
Copyright 2009-2012 Jonathan Turner.
|
Copyright 2009-2012 Jonathan Turner.
|
||||||
|
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|||||||
@ -1,6 +1,19 @@
|
|||||||
Notes:
|
Notes:
|
||||||
=======
|
=======
|
||||||
Current Version: 6.0.0
|
Current Version: 6.1.0
|
||||||
|
|
||||||
|
### Changes since 6.0.0
|
||||||
|
|
||||||
|
* Add namespacing support #290 @stephenberry
|
||||||
|
* Add utf parsing support
|
||||||
|
* cheatsheet.md updates
|
||||||
|
* `add_class` utility support for scoped enums #306 @StanEpp
|
||||||
|
* Parser optimizations #300 @niXman
|
||||||
|
* Various JSON fixes #377 #400 #409 #371 @totalgee @dinghram @arcoRocks
|
||||||
|
* Various cleanups, bugfixes and warning fixes and minor performance improvements
|
||||||
|
* Support for C++17 compilers!
|
||||||
|
* Support for UTF8 BOM #439 @AlekMosingiewicz @MarioLiebisch
|
||||||
|
|
||||||
|
|
||||||
### Changes since 5.8.6
|
### Changes since 5.8.6
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include "../static_libs/chaiscript_parser.hpp"
|
#include "../static_libs/chaiscript_parser.hpp"
|
||||||
#include "../static_libs/chaiscript_stdlib.hpp"
|
#include "../static_libs/chaiscript_stdlib.hpp"
|
||||||
|
|
||||||
|
#include "sha3.h"
|
||||||
|
|
||||||
#ifdef READLINE_AVAILABLE
|
#ifdef READLINE_AVAILABLE
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
@ -323,17 +324,28 @@ def assert_throws(desc, x)
|
|||||||
}
|
}
|
||||||
})chaiscript");
|
})chaiscript");
|
||||||
|
|
||||||
|
SHA3 sha3;
|
||||||
|
std::string sha = sha3(data, size);
|
||||||
|
|
||||||
|
std::string input(reinterpret_cast<const char *>(data), size);
|
||||||
try {
|
try {
|
||||||
chai.eval(std::string(reinterpret_cast<const char *>(data), size));
|
chai.eval(std::string(reinterpret_cast<const char *>(data), size));
|
||||||
} catch (const chaiscript::exception::eval_error &ee) {
|
std::ofstream ofs("VALID/" + sha);
|
||||||
std::cout << ee.pretty_print();
|
ofs << input;
|
||||||
std::cout << '\n';
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
} catch (const chaiscript::Boxed_Value &e) {
|
std::ofstream ofs("EVAL_ERROR/" + sha);
|
||||||
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
|
ofs << input;
|
||||||
|
} catch (const chaiscript::Boxed_Value &) {
|
||||||
|
std::ofstream ofs("BOXED_VALUE/" + sha);
|
||||||
|
ofs << input;
|
||||||
} catch (const chaiscript::exception::load_module_error &e) {
|
} catch (const chaiscript::exception::load_module_error &e) {
|
||||||
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
std::cout << "Unhandled module load error\n" << e.what() << '\n';
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &) {
|
||||||
std::cout << "unhandled unknown exception: " << e.what() << '\n';
|
std::ofstream ofs("STD_EXCEPTION/" + sha);
|
||||||
|
ofs << input;
|
||||||
|
} catch (...) {
|
||||||
|
std::ofstream ofs("UNKOWN_EXCEPTION/" + sha);
|
||||||
|
ofs << input;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
10
src/main.cpp
10
src/main.cpp
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
@ -164,15 +164,15 @@ void help(int n) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool throws_exception(const std::function<void ()> &f)
|
std::string throws_exception(const std::function<void ()> &f)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (...) {
|
} catch (const std::exception &e) {
|
||||||
return true;
|
return e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||||
|
|||||||
@ -4,6 +4,11 @@
|
|||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
|
||||||
|
// NOT TO BE USED AS A SOURCE OF BEST PRACTICES
|
||||||
|
// FOR CHAISCRIPT
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
@ -156,7 +161,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
|
|
||||||
//Ability to create our own container types when needed. std::vector and std::map are
|
//Ability to create our own container types when needed. std::vector and std::map are
|
||||||
//mostly supported currently
|
//mostly supported currently
|
||||||
chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
|
//chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
|
||||||
|
|
||||||
|
|
||||||
// Test ability to register a function that excepts a shared_ptr version of a type
|
// Test ability to register a function that excepts a shared_ptr version of a type
|
||||||
289
src/sha3.cpp
Normal file
289
src/sha3.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
// //////////////////////////////////////////////////////////
|
||||||
|
// sha3.cpp
|
||||||
|
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||||
|
// see http://create.stephan-brumme.com/disclaimer.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "sha3.h"
|
||||||
|
|
||||||
|
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <endian.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// same as reset()
|
||||||
|
SHA3::SHA3(Bits bits)
|
||||||
|
: m_blockSize(200 - 2 * (bits / 8)),
|
||||||
|
m_bits(bits)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// restart
|
||||||
|
void SHA3::reset()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < StateSize; i++)
|
||||||
|
m_hash[i] = 0;
|
||||||
|
|
||||||
|
m_numBytes = 0;
|
||||||
|
m_bufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// constants and local helper functions
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const unsigned int Rounds = 24;
|
||||||
|
const uint64_t XorMasks[Rounds] =
|
||||||
|
{
|
||||||
|
0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
|
||||||
|
0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
|
||||||
|
0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
|
||||||
|
0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
|
||||||
|
0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
|
||||||
|
0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
|
||||||
|
0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
|
||||||
|
0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/// rotate left and wrap around to the right
|
||||||
|
inline uint64_t rotateLeft(uint64_t x, uint8_t numBits)
|
||||||
|
{
|
||||||
|
return (x << numBits) | (x >> (64 - numBits));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// convert litte vs big endian
|
||||||
|
inline uint64_t swap(uint64_t x)
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_bswap64(x);
|
||||||
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_uint64(x);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (x >> 56) |
|
||||||
|
((x >> 40) & 0x000000000000FF00ULL) |
|
||||||
|
((x >> 24) & 0x0000000000FF0000ULL) |
|
||||||
|
((x >> 8) & 0x00000000FF000000ULL) |
|
||||||
|
((x << 8) & 0x000000FF00000000ULL) |
|
||||||
|
((x << 24) & 0x0000FF0000000000ULL) |
|
||||||
|
((x << 40) & 0x00FF000000000000ULL) |
|
||||||
|
(x << 56);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// return x % 5 for 0 <= x <= 9
|
||||||
|
unsigned int mod5(unsigned int x)
|
||||||
|
{
|
||||||
|
if (x < 5)
|
||||||
|
return x;
|
||||||
|
|
||||||
|
return x - 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// process a full block
|
||||||
|
void SHA3::processBlock(const void* data)
|
||||||
|
{
|
||||||
|
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
|
||||||
|
#define LITTLEENDIAN(x) swap(x)
|
||||||
|
#else
|
||||||
|
#define LITTLEENDIAN(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const uint64_t* data64 = (const uint64_t*) data;
|
||||||
|
// mix data into state
|
||||||
|
for (unsigned int i = 0; i < m_blockSize / 8; i++)
|
||||||
|
m_hash[i] ^= LITTLEENDIAN(data64[i]);
|
||||||
|
|
||||||
|
// re-compute state
|
||||||
|
for (unsigned int round = 0; round < Rounds; round++)
|
||||||
|
{
|
||||||
|
// Theta
|
||||||
|
uint64_t coefficients[5];
|
||||||
|
for (unsigned int i = 0; i < 5; i++)
|
||||||
|
coefficients[i] = m_hash[i] ^ m_hash[i + 5] ^ m_hash[i + 10] ^ m_hash[i + 15] ^ m_hash[i + 20];
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
uint64_t one = coefficients[mod5(i + 4)] ^ rotateLeft(coefficients[mod5(i + 1)], 1);
|
||||||
|
m_hash[i ] ^= one;
|
||||||
|
m_hash[i + 5] ^= one;
|
||||||
|
m_hash[i + 10] ^= one;
|
||||||
|
m_hash[i + 15] ^= one;
|
||||||
|
m_hash[i + 20] ^= one;
|
||||||
|
}
|
||||||
|
|
||||||
|
// temporary
|
||||||
|
uint64_t one;
|
||||||
|
|
||||||
|
// Rho Pi
|
||||||
|
uint64_t last = m_hash[1];
|
||||||
|
one = m_hash[10]; m_hash[10] = rotateLeft(last, 1); last = one;
|
||||||
|
one = m_hash[ 7]; m_hash[ 7] = rotateLeft(last, 3); last = one;
|
||||||
|
one = m_hash[11]; m_hash[11] = rotateLeft(last, 6); last = one;
|
||||||
|
one = m_hash[17]; m_hash[17] = rotateLeft(last, 10); last = one;
|
||||||
|
one = m_hash[18]; m_hash[18] = rotateLeft(last, 15); last = one;
|
||||||
|
one = m_hash[ 3]; m_hash[ 3] = rotateLeft(last, 21); last = one;
|
||||||
|
one = m_hash[ 5]; m_hash[ 5] = rotateLeft(last, 28); last = one;
|
||||||
|
one = m_hash[16]; m_hash[16] = rotateLeft(last, 36); last = one;
|
||||||
|
one = m_hash[ 8]; m_hash[ 8] = rotateLeft(last, 45); last = one;
|
||||||
|
one = m_hash[21]; m_hash[21] = rotateLeft(last, 55); last = one;
|
||||||
|
one = m_hash[24]; m_hash[24] = rotateLeft(last, 2); last = one;
|
||||||
|
one = m_hash[ 4]; m_hash[ 4] = rotateLeft(last, 14); last = one;
|
||||||
|
one = m_hash[15]; m_hash[15] = rotateLeft(last, 27); last = one;
|
||||||
|
one = m_hash[23]; m_hash[23] = rotateLeft(last, 41); last = one;
|
||||||
|
one = m_hash[19]; m_hash[19] = rotateLeft(last, 56); last = one;
|
||||||
|
one = m_hash[13]; m_hash[13] = rotateLeft(last, 8); last = one;
|
||||||
|
one = m_hash[12]; m_hash[12] = rotateLeft(last, 25); last = one;
|
||||||
|
one = m_hash[ 2]; m_hash[ 2] = rotateLeft(last, 43); last = one;
|
||||||
|
one = m_hash[20]; m_hash[20] = rotateLeft(last, 62); last = one;
|
||||||
|
one = m_hash[14]; m_hash[14] = rotateLeft(last, 18); last = one;
|
||||||
|
one = m_hash[22]; m_hash[22] = rotateLeft(last, 39); last = one;
|
||||||
|
one = m_hash[ 9]; m_hash[ 9] = rotateLeft(last, 61); last = one;
|
||||||
|
one = m_hash[ 6]; m_hash[ 6] = rotateLeft(last, 20); last = one;
|
||||||
|
m_hash[ 1] = rotateLeft(last, 44);
|
||||||
|
|
||||||
|
// Chi
|
||||||
|
for (unsigned int j = 0; j < 25; j += 5)
|
||||||
|
{
|
||||||
|
// temporaries
|
||||||
|
uint64_t one = m_hash[j];
|
||||||
|
uint64_t two = m_hash[j + 1];
|
||||||
|
|
||||||
|
m_hash[j] ^= m_hash[j + 2] & ~two;
|
||||||
|
m_hash[j + 1] ^= m_hash[j + 3] & ~m_hash[j + 2];
|
||||||
|
m_hash[j + 2] ^= m_hash[j + 4] & ~m_hash[j + 3];
|
||||||
|
m_hash[j + 3] ^= one & ~m_hash[j + 4];
|
||||||
|
m_hash[j + 4] ^= two & ~one;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iota
|
||||||
|
m_hash[0] ^= XorMasks[round];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// add arbitrary number of bytes
|
||||||
|
void SHA3::add(const void* data, size_t numBytes)
|
||||||
|
{
|
||||||
|
const uint8_t* current = (const uint8_t*) data;
|
||||||
|
|
||||||
|
// copy data to buffer
|
||||||
|
if (m_bufferSize > 0)
|
||||||
|
{
|
||||||
|
while (numBytes > 0 && m_bufferSize < m_blockSize)
|
||||||
|
{
|
||||||
|
m_buffer[m_bufferSize++] = *current++;
|
||||||
|
numBytes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// full buffer
|
||||||
|
if (m_bufferSize == m_blockSize)
|
||||||
|
{
|
||||||
|
processBlock((void*)m_buffer);
|
||||||
|
m_numBytes += m_blockSize;
|
||||||
|
m_bufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no more data ?
|
||||||
|
if (numBytes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// process full blocks
|
||||||
|
while (numBytes >= m_blockSize)
|
||||||
|
{
|
||||||
|
processBlock(current);
|
||||||
|
current += m_blockSize;
|
||||||
|
m_numBytes += m_blockSize;
|
||||||
|
numBytes -= m_blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep remaining bytes in buffer
|
||||||
|
while (numBytes > 0)
|
||||||
|
{
|
||||||
|
m_buffer[m_bufferSize++] = *current++;
|
||||||
|
numBytes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// process everything left in the internal buffer
|
||||||
|
void SHA3::processBuffer()
|
||||||
|
{
|
||||||
|
// add padding
|
||||||
|
size_t offset = m_bufferSize;
|
||||||
|
// add a "1" byte
|
||||||
|
m_buffer[offset++] = 0x06;
|
||||||
|
// fill with zeros
|
||||||
|
while (offset < m_blockSize)
|
||||||
|
m_buffer[offset++] = 0;
|
||||||
|
|
||||||
|
// and add a single set bit
|
||||||
|
m_buffer[offset - 1] |= 0x80;
|
||||||
|
|
||||||
|
processBlock(m_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// return latest hash as 16 hex characters
|
||||||
|
std::string SHA3::getHash()
|
||||||
|
{
|
||||||
|
// process remaining bytes
|
||||||
|
processBuffer();
|
||||||
|
|
||||||
|
// convert hash to string
|
||||||
|
static const char dec2hex[16 + 1] = "0123456789abcdef";
|
||||||
|
|
||||||
|
// number of significant elements in hash (uint64_t)
|
||||||
|
unsigned int hashLength = m_bits / 64;
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
result.reserve(m_bits / 4);
|
||||||
|
for (unsigned int i = 0; i < hashLength; i++)
|
||||||
|
for (unsigned int j = 0; j < 8; j++) // 64 bits => 8 bytes
|
||||||
|
{
|
||||||
|
// convert a byte to hex
|
||||||
|
unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j));
|
||||||
|
result += dec2hex[oneByte >> 4];
|
||||||
|
result += dec2hex[oneByte & 15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SHA3-224's last entry in m_hash provides only 32 bits instead of 64 bits
|
||||||
|
unsigned int remainder = m_bits - hashLength * 64;
|
||||||
|
unsigned int processed = 0;
|
||||||
|
while (processed < remainder)
|
||||||
|
{
|
||||||
|
// convert a byte to hex
|
||||||
|
unsigned char oneByte = (unsigned char) (m_hash[hashLength] >> processed);
|
||||||
|
result += dec2hex[oneByte >> 4];
|
||||||
|
result += dec2hex[oneByte & 15];
|
||||||
|
|
||||||
|
processed += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// compute SHA3 of a memory block
|
||||||
|
std::string SHA3::operator()(const void* data, size_t numBytes)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
add(data, numBytes);
|
||||||
|
return getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// compute SHA3 of a string, excluding final zero
|
||||||
|
std::string SHA3::operator()(const std::string& text)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
add(text.c_str(), text.size());
|
||||||
|
return getHash();
|
||||||
|
}
|
||||||
81
src/sha3.h
Normal file
81
src/sha3.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// //////////////////////////////////////////////////////////
|
||||||
|
// sha3.h
|
||||||
|
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||||
|
// see http://create.stephan-brumme.com/disclaimer.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//#include "hash.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// define fixed size integer types
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Windows
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
#else
|
||||||
|
// GCC
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// compute SHA3 hash
|
||||||
|
/** Usage:
|
||||||
|
SHA3 sha3;
|
||||||
|
std::string myHash = sha3("Hello World"); // std::string
|
||||||
|
std::string myHash2 = sha3("How are you", 11); // arbitrary data, 11 bytes
|
||||||
|
|
||||||
|
// or in a streaming fashion:
|
||||||
|
|
||||||
|
SHA3 sha3;
|
||||||
|
while (more data available)
|
||||||
|
sha3.add(pointer to fresh data, number of new bytes);
|
||||||
|
std::string myHash3 = sha3.getHash();
|
||||||
|
*/
|
||||||
|
class SHA3 //: public Hash
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// algorithm variants
|
||||||
|
enum Bits { Bits224 = 224, Bits256 = 256, Bits384 = 384, Bits512 = 512 };
|
||||||
|
|
||||||
|
/// same as reset()
|
||||||
|
explicit SHA3(Bits bits = Bits256);
|
||||||
|
|
||||||
|
/// compute hash of a memory block
|
||||||
|
std::string operator()(const void* data, size_t numBytes);
|
||||||
|
/// compute hash of a string, excluding final zero
|
||||||
|
std::string operator()(const std::string& text);
|
||||||
|
|
||||||
|
/// add arbitrary number of bytes
|
||||||
|
void add(const void* data, size_t numBytes);
|
||||||
|
|
||||||
|
/// return latest hash as hex characters
|
||||||
|
std::string getHash();
|
||||||
|
|
||||||
|
/// restart
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// process a full block
|
||||||
|
void processBlock(const void* data);
|
||||||
|
/// process everything left in the internal buffer
|
||||||
|
void processBuffer();
|
||||||
|
|
||||||
|
/// 1600 bits, stored as 25x64 bit, BlockSize is no more than 1152 bits (Keccak224)
|
||||||
|
enum { StateSize = 1600 / (8 * 8),
|
||||||
|
MaxBlockSize = 200 - 2 * (224 / 8) };
|
||||||
|
|
||||||
|
/// hash
|
||||||
|
uint64_t m_hash[StateSize];
|
||||||
|
/// size of processed data in bytes
|
||||||
|
uint64_t m_numBytes;
|
||||||
|
/// block size (less or equal to MaxBlockSize)
|
||||||
|
size_t m_blockSize;
|
||||||
|
/// valid bytes in m_buffer
|
||||||
|
size_t m_bufferSize;
|
||||||
|
/// bytes not processed yet
|
||||||
|
uint8_t m_buffer[MaxBlockSize];
|
||||||
|
/// variant
|
||||||
|
Bits m_bits;
|
||||||
|
};
|
||||||
@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 = 2 } );
|
||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 + 2 = 2 } );
|
||||||
|
|||||||
@ -66,10 +66,10 @@ var group = group_guard.get_contained_functions();
|
|||||||
assert_equal(true, group[0].has_guard())
|
assert_equal(true, group[0].has_guard())
|
||||||
assert_equal(false, group[1].has_guard())
|
assert_equal(false, group[1].has_guard())
|
||||||
|
|
||||||
assert_throws("Function does not have a guard", fun() { group[0].get_guard(); } );
|
assert_throws("Function does not have a guard", fun[group]() { group[1].get_guard(); } );
|
||||||
assert_throws("Function does not have a guard", fun() { without_guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[without_guard]() { without_guard.get_guard(); } );
|
||||||
|
|
||||||
var guard = with_guard.get_guard();
|
var guard = with_guard.get_guard();
|
||||||
|
|
||||||
assert_equal(false, guard.has_guard());
|
assert_equal(false, guard.has_guard());
|
||||||
assert_throws("Function does not have a guard", fun() { guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[guard]() { guard.get_guard(); } );
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
assert_throws("Illegal const function assignment", fun() { clone = `-` } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { clone = `-` } );
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
assert_throws("Invalid function reassignment", fun() { var x = 5; x = `-`; } );
|
assert_throws("Error: \"Unable to find appropriate'=' operator.\" With parameters: (int, const Function)", fun() { auto x = 5; x = `-`; } );
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,8 @@
|
|||||||
|
|
||||||
assert_throws("Parse failure", fun() { eval("[\"hello\":5,\"j\",\"k\"]") } );
|
try {
|
||||||
|
eval("[\"hello\":5,\"j\",\"k\"]");
|
||||||
|
assert_true(false);
|
||||||
|
} catch (eval_error ee) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,4 +13,4 @@ assert_equal(0, i -= i)
|
|||||||
assert_equal(3, j *= 1.5)
|
assert_equal(3, j *= 1.5)
|
||||||
assert_equal(1.5, j /= 2)
|
assert_equal(1.5, j /= 2)
|
||||||
assert_equal(2.5, j += 1)
|
assert_equal(2.5, j += 1)
|
||||||
assert_throws("No modulus for float", fun() { k % 2 } );
|
assert_throws("Error: \"Error with numeric operator calling: %\"", fun[k]() { k % 2 } );
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 = 2 } );
|
||||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 1 + 2 = 2 } );
|
||||||
|
|||||||
19562
unittests/catch.hpp
19562
unittests/catch.hpp
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4062 4242 4640 4702 6330 28251)
|
#pragma warning(disable : 4062 4242 4566 4640 4702 6330 28251)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -352,7 +352,29 @@ TEST_CASE("Functor cast")
|
|||||||
CHECK(d == 3 * 6);
|
CHECK(d == 3 * 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Non-ASCII characters in the middle of string")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||||
|
CHECK_THROWS_AS(chai.eval<std::string>("prin\xeft \"Hello World\""), chaiscript::exception::eval_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Non-ASCII characters in the beginning of string")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||||
|
CHECK_THROWS_AS(chai.eval<std::string>("\xefprint \"Hello World\""), chaiscript::exception::eval_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Non-ASCII characters in the end of string")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||||
|
CHECK_THROWS_AS(chai.eval<std::string>("print \"Hello World\"\xef"), chaiscript::exception::eval_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("BOM in string")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||||
|
CHECK_THROWS_AS(chai.eval<std::string>("\xef\xbb\xbfprint \"Hello World\""), chaiscript::exception::eval_error);
|
||||||
|
}
|
||||||
|
|
||||||
int set_state_test_myfun()
|
int set_state_test_myfun()
|
||||||
{
|
{
|
||||||
@ -382,7 +404,7 @@ TEST_CASE("Set and restore chai state")
|
|||||||
// set state should have reverted the state of the functions and dropped
|
// set state should have reverted the state of the functions and dropped
|
||||||
// the 'myfun'
|
// the 'myfun'
|
||||||
|
|
||||||
CHECK_THROWS_AS(chai.eval<int>("myfun()"), chaiscript::exception::eval_error &);
|
CHECK_THROWS_AS(chai.eval<int>("myfun()"), chaiscript::exception::eval_error);
|
||||||
|
|
||||||
// set state should not affect the local variables
|
// set state should not affect the local variables
|
||||||
CHECK(chai.eval<int>("i") == 1);
|
CHECK(chai.eval<int>("i") == 1);
|
||||||
@ -390,7 +412,7 @@ TEST_CASE("Set and restore chai state")
|
|||||||
// After resetting the locals we expect the 'i' to be gone
|
// After resetting the locals we expect the 'i' to be gone
|
||||||
chai.set_locals(locals);
|
chai.set_locals(locals);
|
||||||
|
|
||||||
CHECK_THROWS_AS(chai.eval<int>("i"), chaiscript::exception::eval_error &);
|
CHECK_THROWS_AS(chai.eval<int>("i"), chaiscript::exception::eval_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -468,8 +490,8 @@ TEST_CASE("Simultaneous ChaiScript tests")
|
|||||||
CHECK(chai.eval<int>("do_something(" + std::to_string(i) + ")") == i + 2);
|
CHECK(chai.eval<int>("do_something(" + std::to_string(i) + ")") == i + 2);
|
||||||
CHECK(chai2.eval<int>("do_something_else(" + std::to_string(i) + ")") == i * 2);
|
CHECK(chai2.eval<int>("do_something_else(" + std::to_string(i) + ")") == i * 2);
|
||||||
|
|
||||||
CHECK_THROWS_AS(chai2.eval("do_something(1)"), chaiscript::exception::eval_error &);
|
CHECK_THROWS_AS(chai2.eval("do_something(1)"), chaiscript::exception::eval_error);
|
||||||
CHECK_THROWS_AS(chai2.eval("i"), chaiscript::exception::eval_error &);
|
CHECK_THROWS_AS(chai2.eval("i"), chaiscript::exception::eval_error);
|
||||||
CHECK_NOTHROW(chai2.eval("do_something_else(1)"));
|
CHECK_NOTHROW(chai2.eval("do_something_else(1)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1271,6 +1293,16 @@ TEST_CASE("Test reference member being registered")
|
|||||||
CHECK(d == Approx(2.3));
|
CHECK(d == Approx(2.3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test unicode matches C++")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
|
||||||
|
CHECK(u8"\U000000AC" == chai.eval<std::string>(R"("\U000000AC")"));
|
||||||
|
CHECK("\xF0\x9F\x8D\x8C" == chai.eval<std::string>(R"("\xF0\x9F\x8D\x8C")"));
|
||||||
|
CHECK(u8"\U0001F34C" == chai.eval<std::string>(R"("\U0001F34C")"));
|
||||||
|
CHECK(u8"\u2022" == chai.eval<std::string>(R"("\u2022")"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const int add_3(const int &i)
|
const int add_3(const int &i)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,5 +10,7 @@ var o = MyClass();
|
|||||||
|
|
||||||
assert_true(o.is_explicit());
|
assert_true(o.is_explicit());
|
||||||
|
|
||||||
assert_throws("error", fun[o](){o.x = 2})
|
assert_throws("Error: \"'x' is not a function.\"", fun[o](){o.x = 2})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
unittests/eval_file_with_bom.chai
Normal file
2
unittests/eval_file_with_bom.chai
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
eval_file("file_with_bom.inc")
|
||||||
|
assert_true(alwaysTrue())
|
||||||
@ -40,3 +40,13 @@ assert_equal(res3[2], "member2")
|
|||||||
assert_true(__FILE__.find("execution_context.chai") != -1)
|
assert_true(__FILE__.find("execution_context.chai") != -1)
|
||||||
|
|
||||||
|
|
||||||
|
assert_equal(eval("__FILE__"), "__EVAL__")
|
||||||
|
assert_equal(eval("__LINE__"), 1)
|
||||||
|
assert_equal(eval("__FUNC__"), "NOT_IN_FUNCTION")
|
||||||
|
assert_equal(eval("__CLASS__"), "NOT_IN_CLASS")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
11
unittests/failed_deep_include.chai
Normal file
11
unittests/failed_deep_include.chai
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
use("failed_deep_include.inc")
|
||||||
|
assert_true(false);
|
||||||
|
} catch (e) {
|
||||||
|
puts("Caught exception while trying to use file");
|
||||||
|
assert_equal(e.what(), "File Not Found: totally_missing_file.inc");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
3
unittests/failed_deep_include.inc
Normal file
3
unittests/failed_deep_include.inc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
use("totally_missing_file.inc");
|
||||||
|
|
||||||
|
|
||||||
3
unittests/file_with_bom.inc
Normal file
3
unittests/file_with_bom.inc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
def alwaysTrue() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
@ -66,10 +66,10 @@ auto group = group_guard.get_contained_functions();
|
|||||||
assert_equal(true, group[0].has_guard())
|
assert_equal(true, group[0].has_guard())
|
||||||
assert_equal(false, group[1].has_guard())
|
assert_equal(false, group[1].has_guard())
|
||||||
|
|
||||||
assert_throws("Function does not have a guard", fun() { group[0].get_guard(); } );
|
assert_throws("Function does not have a guard", fun[group]() { group[1].get_guard(); } );
|
||||||
assert_throws("Function does not have a guard", fun() { without_guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[without_guard]() { without_guard.get_guard(); } );
|
||||||
|
|
||||||
auto guard = with_guard.get_guard();
|
auto guard = with_guard.get_guard();
|
||||||
|
|
||||||
assert_equal(false, guard.has_guard());
|
assert_equal(false, guard.has_guard());
|
||||||
assert_throws("Function does not have a guard", fun() { guard.get_guard(); } );
|
assert_throws("Function does not have a guard", fun[guard]() { guard.get_guard(); } );
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Function already defined", fun(){ def foo(x) { x + 1 }; def foo(x) { x + 1 } } );
|
assert_throws("Error: \"Function redefined 'foo'\"", fun(){ def foo(x) { x + 1 }; def foo(x) { x + 1 } } );
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
assert_throws("Illegal const function assignment", fun() { clone = `-` } );
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { clone = `-` } );
|
||||||
|
|||||||
@ -1 +1,4 @@
|
|||||||
assert_throws("Invalid function reassignment", fun() { auto x = 5; x = `-`; } );
|
assert_throws("Error: \"Unable to find appropriate'=' operator.\" With parameters: (int, const Function)", fun() { auto x = 5; x = `-`; } );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
19
unittests/json_15.chai
Normal file
19
unittests/json_15.chai
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Various to_json() tests
|
||||||
|
assert_equal(to_json(-13570), "-13570")
|
||||||
|
assert_equal(to_json(0.654321), "0.654321")
|
||||||
|
assert_equal(to_json("ChaiScript"), "\"ChaiScript\"")
|
||||||
|
assert_equal(to_json(true), "true")
|
||||||
|
assert_equal(to_json([1, 2, 3]), "[1, 2, 3]")
|
||||||
|
assert_equal(to_json(Vector()), "[]") // empty vector
|
||||||
|
assert_equal(to_json([]), "[]") // empty vector
|
||||||
|
assert_equal(to_json(Map()), "{\n\n}") // empty map
|
||||||
|
assert_equal(to_json(Dynamic_Object()), "{\n\n}") // empty object
|
||||||
|
|
||||||
|
// Round-trip JSON tests
|
||||||
|
assert_equal(from_json(to_json([])), [])
|
||||||
|
assert_equal(from_json(to_json(Map())), Map())
|
||||||
|
assert_equal(to_json(from_json("null")), "null")
|
||||||
|
assert_equal(from_json(to_json(["a": 5, "b": "stuff"])), ["a": 5, "b": "stuff"])
|
||||||
|
auto x = [3.5, true, false, "test", [], Vector(), Map()]
|
||||||
|
assert_equal(from_json(to_json(x)), x)
|
||||||
|
assert_equal(from_json(to_json(["aa\\zz":"aa\\zz"])), ["aa\\zz": "aa\\zz"])
|
||||||
@ -1,2 +1,3 @@
|
|||||||
assert_equal(from_json("100"), 100)
|
assert_equal(from_json("100"), 100)
|
||||||
assert_equal(from_json("-100"), -100)
|
assert_equal(from_json("-100"), -100)
|
||||||
|
assert_equal(to_json(4294967295), "4294967295")
|
||||||
|
|||||||
@ -1,2 +1,8 @@
|
|||||||
|
|
||||||
assert_throws("Parse failure", fun() { eval("[\"hello\":5,\"j\",\"k\"]") } );
|
try {
|
||||||
|
eval("[\"hello\":5,\"j\",\"k\"]");
|
||||||
|
assert_true(false);
|
||||||
|
} catch (eval_error ee) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,4 +13,6 @@ assert_equal(0, i -= i)
|
|||||||
assert_equal(3, j *= 1.5)
|
assert_equal(3, j *= 1.5)
|
||||||
assert_equal(1.5, j /= 2)
|
assert_equal(1.5, j /= 2)
|
||||||
assert_equal(2.5, j += 1)
|
assert_equal(2.5, j += 1)
|
||||||
assert_throws("No modulus for float", fun() { k % 2 } );
|
assert_throws("Error: \"Error with numeric operator calling: %\"", fun[k]() { k % 2 } );
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -29,3 +29,13 @@ assert_equal(2, j += 1);
|
|||||||
assert_equal(1, --j);
|
assert_equal(1, --j);
|
||||||
assert_equal(2, ++j);
|
assert_equal(2, ++j);
|
||||||
|
|
||||||
|
|
||||||
|
assert_throws("Error: \"Error with prefix operator evaluation: cannot modify constant value.\"", fun() { ++4; });
|
||||||
|
assert_throws("Error: \"Error with prefix operator evaluation: cannot modify constant value.\"", fun() { --4; });
|
||||||
|
|
||||||
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { 5 = 5; });
|
||||||
|
assert_throws("Error: \"Error, cannot assign to constant value.\"", fun() { int(5) = 5; });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
12
unittests/ranged_for_2.chai
Normal file
12
unittests/ranged_for_2.chai
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
def keys(map)
|
||||||
|
{
|
||||||
|
auto v = Vector(); // create empty vector
|
||||||
|
for( i : map )
|
||||||
|
{
|
||||||
|
v.push_back(i.first); // append key to the vector
|
||||||
|
}
|
||||||
|
v; // return the new vector
|
||||||
|
}
|
||||||
|
print(keys(["1a":111, "2b":222]));
|
||||||
|
|
||||||
|
|
||||||
@ -6,6 +6,20 @@ try {
|
|||||||
print("Caught Error: " + e.what());
|
print("Caught Error: " + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_value()
|
||||||
|
{
|
||||||
|
var i = 5;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_value_2()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO these should be fixed somehow
|
||||||
|
//assert_throws("Cannot assign to temporary", fun[](){ get_value() = 3; });
|
||||||
|
//assert_throws("Cannot assign to temporary", fun[](){ get_value_2() = 3; });
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
#define CHAISCRIPT_NO_THREADS
|
#define CHAISCRIPT_NO_THREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
/// ChaiScript as a static is unsupported with thread support enabled
|
/// ChaiScript as a static is unsupported with thread support enabled
|
||||||
///
|
///
|
||||||
|
|||||||
@ -1,11 +1,4 @@
|
|||||||
assert_equal('\u00aa', '\u00AA')
|
assert_equal("\u00aa", "\u00AA")
|
||||||
assert_equal('\u00bb', '\uBB')
|
assert_equal("\u00bb", "\xC2\xBB")
|
||||||
assert_equal('\ucc', '\u00CC')
|
|
||||||
assert_equal('\udd', '\uDD')
|
|
||||||
|
|
||||||
assert_equal('\u0ee', '\uEE')
|
|
||||||
assert_equal('\ue', '\u000E')
|
|
||||||
|
|
||||||
assert_equal("\u30\u31\u32", "012")
|
|
||||||
assert_equal("\u33Test", "3Test")
|
|
||||||
assert_equal("Test\u0040", "Test@")
|
assert_equal("Test\u0040", "Test@")
|
||||||
|
|||||||
@ -1,5 +1,16 @@
|
|||||||
assert_equal("\uc39c", "Ü")
|
assert_equal("\uc39c", "쎜")
|
||||||
assert_equal("U for \uc39cmlauts", "U for Ümlauts")
|
assert_equal("U for \u00dcmlauts", "U for Ümlauts")
|
||||||
assert_equal("More \uc39cml\uc3a4\uc3bcts", "More Ümläüts")
|
|
||||||
|
|
||||||
assert_equal("Thorn \uc3be sign", "Thorn þ sign")
|
assert_equal("Thorn \u00fe sign", "Thorn þ sign")
|
||||||
|
assert_equal("Test\u0020Me", "Test Me")
|
||||||
|
assert_equal("Test\u2022Me", "Test•Me")
|
||||||
|
|
||||||
|
assert_equal("\xF0\x9F\x8D\x8C", "🍌")
|
||||||
|
assert_equal("\U0001F34C", "🍌")
|
||||||
|
|
||||||
|
assert_throws("Error: \"Invalid 16 bit universal character\"", fun(){ parse("\"\\uD83C\""); });
|
||||||
|
assert_throws("Error: \"Incomplete unicode escape sequence\"", fun(){ parse("\"\\uD83 \""); });
|
||||||
|
|
||||||
|
assert_equal("\U00024B62", "𤭢")
|
||||||
|
|
||||||
|
assert_equal("Test\U0001F534Me", "Test🔴Me")
|
||||||
|
|||||||
@ -42,12 +42,14 @@ def assert_not_equal(x, y)
|
|||||||
|
|
||||||
def assert_throws(desc, x)
|
def assert_throws(desc, x)
|
||||||
{
|
{
|
||||||
if (throws_exception(x))
|
auto result = trim(throws_exception(x));
|
||||||
|
if (result == desc)
|
||||||
{
|
{
|
||||||
// Passes
|
// Passes
|
||||||
} else {
|
} else {
|
||||||
// Fails
|
// Fails
|
||||||
print("assert_throws failure, function did not throw exception: " + to_string(desc));
|
print("assert_throws failed: got '${result}' expected '${desc}'");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
assert_throws("Variable already defined", fun() { auto y = 10; auto y = 20; })
|
assert_throws("Error: \"Variable redefined 'y'\"", fun() { auto y = 10; auto y = 20; })
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user