Compare commits
1 Commits
v5.7.0
...
value_type
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c541c3d8e |
@@ -1,30 +1,13 @@
|
||||
compilers:
|
||||
- name: "clang"
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: "LibC++"
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: AddressSanitizer
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: ThreadSanitizer
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.8"
|
||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: cppcheck
|
||||
compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:cmake*" --suppress="*:unittests/catch.hpp" --force
|
||||
compiler_extra_flags: --enable=all -I include --inline-suppr
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
compilers:
|
||||
- name: clang
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
build_package_generator: TBZ2
|
||||
- name: clang
|
||||
build_type: Debug
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
skip_packaging: true
|
||||
|
||||
|
||||
@@ -2,19 +2,19 @@ compilers:
|
||||
- name: Visual Studio
|
||||
version: 14
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /analyze
|
||||
skip_packaging: true
|
||||
compiler_extra_flags: /ANALYZE
|
||||
- name: Visual Studio
|
||||
version: 14
|
||||
architecture: Win64
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /analyze
|
||||
skip_packaging: true
|
||||
compiler_extra_flags: /ANALYZE
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
architecture: Win64
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
|
||||
|
||||
@@ -26,14 +26,6 @@ notifications:
|
||||
- jason@emptycrate.com
|
||||
on_success: always
|
||||
on_failure: always
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/4be9a2720eaa1bb2a6c9
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
on_failure: always # options: [always|never|change] default: always
|
||||
on_start: false # default: false
|
||||
env:
|
||||
global:
|
||||
secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
|
||||
|
||||
|
||||
|
||||
172
CMakeLists.txt
172
CMakeLists.txt
@@ -1,30 +1,18 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
IF(BIICODE)
|
||||
INIT_BIICODE_BLOCK()
|
||||
ADD_BIICODE_TARGETS()
|
||||
ELSE()
|
||||
# Your regular CMakeLists configuration here
|
||||
|
||||
|
||||
project(chaiscript)
|
||||
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||
# MINGW does not yet support C++11's concurrency features
|
||||
if(MINGW)
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" FALSE)
|
||||
else()
|
||||
option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
||||
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
||||
|
||||
mark_as_advanced(USE_STD_MAKE_SHARED)
|
||||
|
||||
if(USE_STD_MAKE_SHARED)
|
||||
add_definitions(-DCHAISCRIPT_USE_STD_MAKE_SHARED)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
|
||||
@@ -48,38 +36,11 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_MEMORY_SANITIZER)
|
||||
add_definitions(-fsanitize=memory -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=memory")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNDEFINED_SANITIZER "Enable undefined behavior sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_UNDEFINED_SANITIZER)
|
||||
add_definitions(-fsanitize=undefined -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
option(ENABLE_LTO "Enable Link Time Optimization" FALSE)
|
||||
|
||||
if (ENABLE_LTO)
|
||||
add_definitions(-flto)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
|
||||
endif()
|
||||
|
||||
option(PROFILE_GENERATE "Generate profile data" FALSE)
|
||||
if (PROFILE_GENERATE)
|
||||
add_definitions(-fprofile-generate)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-generate")
|
||||
endif()
|
||||
|
||||
option(PROFILE_USE "Use profile data" FALSE)
|
||||
if (PROFILE_USE)
|
||||
add_definitions(-fprofile-use)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-use")
|
||||
endif()
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
@@ -93,7 +54,7 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 7)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 4)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
@@ -153,13 +114,7 @@ else()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(/W4)
|
||||
|
||||
# VS2013 doesn't have magic statics
|
||||
if (MSVC_VERSION STREQUAL "1800")
|
||||
add_definitions(/w44640)
|
||||
endif()
|
||||
|
||||
add_definitions(/W4 /w44640)
|
||||
add_definitions(/bigobj)
|
||||
# Note on MSVC compiler flags.
|
||||
# The code base selective disables warnings as necessary when the compiler is complaining too much
|
||||
@@ -170,13 +125,7 @@ if(MSVC)
|
||||
# how to workaround or fix the error. So I'm disabling it globally.
|
||||
add_definitions(/wd4503)
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG})
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
add_definitions(-Weverything -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors)
|
||||
else()
|
||||
add_definitions(-Wnoexcept)
|
||||
endif()
|
||||
add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic ${CPP11_FLAG})
|
||||
|
||||
if(APPLE)
|
||||
add_definitions(-Wno-sign-compare)
|
||||
@@ -184,7 +133,7 @@ else()
|
||||
endif()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
option(USE_LIBCXX "Use clang's libcxx" TRUE)
|
||||
option(USE_LIBCXX "Use clang's libcxx" FALSE)
|
||||
|
||||
if(USE_LIBCXX)
|
||||
add_definitions(-stdlib=libc++)
|
||||
@@ -205,7 +154,7 @@ endif()
|
||||
include_directories(include)
|
||||
|
||||
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
@@ -256,8 +205,6 @@ if(BUILD_SAMPLES)
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
add_executable(inheritance samples/inheritance.cpp)
|
||||
target_link_libraries(inheritance ${LIBS})
|
||||
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
||||
target_link_libraries(fun_call_performance ${LIBS})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -273,38 +220,6 @@ file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CUR
|
||||
list(SORT UNIT_TESTS)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
|
||||
# Add catch tests macro
|
||||
macro(ADD_CATCH_TESTS executable)
|
||||
if (MSVC)
|
||||
file(TO_NATIVE_PATH "${QT_LIBRARY_DIR}" QT_LIB_PATH)
|
||||
set(NEWPATH "${QT_LIB_PATH};$ENV{PATH}")
|
||||
else()
|
||||
set(NEWPATH $ENV{PATH})
|
||||
endif()
|
||||
|
||||
get_target_property(target_files ${executable} SOURCES)
|
||||
|
||||
foreach(source ${target_files})
|
||||
if(NOT "${source}" MATCHES "/moc_.*cxx")
|
||||
string(REGEX MATCH .*cpp source "${source}")
|
||||
if(source)
|
||||
file(READ "${source}" contents)
|
||||
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
|
||||
foreach(hit ${found_tests})
|
||||
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
|
||||
add_test(${test_name} "${executable}" ${test_name})
|
||||
set_tests_properties(${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
|
||||
|
||||
add_test(version_check chai -c "if(\"\\\${ version() };\\\${version_major()};\\\${version_minor()};\\\${version_patch()}\" != \"${CHAI_VERSION};${CPACK_PACKAGE_VERSION_MAJOR};${CPACK_PACKAGE_VERSION_MINOR};${CPACK_PACKAGE_VERSION_PATCH}\") { exit(-1) }")
|
||||
@@ -327,19 +242,71 @@ if(BUILD_TESTING)
|
||||
)
|
||||
|
||||
if(NOT UNIT_TEST_LIGHT)
|
||||
add_executable(compiled_tests unittests/compiled_tests.cpp)
|
||||
target_link_libraries(compiled_tests ${LIBS})
|
||||
ADD_CATCH_TESTS(compiled_tests)
|
||||
# commented out because uniform initializer syntax is not working properly in MSVC 2013
|
||||
add_executable(utility_test unittests/utility_test.cpp)
|
||||
target_link_libraries(utility_test ${LIBS})
|
||||
add_test(NAME Utility_Test COMMAND utility_test)
|
||||
|
||||
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
|
||||
target_link_libraries(dynamic_object_test ${LIBS})
|
||||
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
|
||||
|
||||
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
|
||||
target_link_libraries(functor_creation_test ${LIBS})
|
||||
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
|
||||
|
||||
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
|
||||
target_link_libraries(functor_cast_test ${LIBS})
|
||||
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
|
||||
|
||||
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
|
||||
target_link_libraries(boxed_cast_test ${LIBS})
|
||||
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
|
||||
|
||||
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
|
||||
target_link_libraries(object_lifetime_test ${LIBS})
|
||||
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
|
||||
|
||||
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
|
||||
target_link_libraries(function_ordering_test ${LIBS})
|
||||
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
|
||||
|
||||
add_executable(type_info_test unittests/type_info_test.cpp)
|
||||
target_link_libraries(type_info_test ${LIBS})
|
||||
add_test(NAME Type_Info_Test COMMAND type_info_test)
|
||||
|
||||
add_executable(type_name_test unittests/type_name_test.cpp)
|
||||
target_link_libraries(type_name_test ${LIBS})
|
||||
add_test(NAME Type_Name_Test COMMAND type_name_test)
|
||||
|
||||
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS})
|
||||
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
|
||||
|
||||
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
|
||||
target_link_libraries(short_comparison_test ${LIBS})
|
||||
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
|
||||
|
||||
add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp)
|
||||
target_link_libraries(cpp_lambda_test ${LIBS})
|
||||
add_test(NAME cpp_lambda_test COMMAND cpp_lambda_test)
|
||||
|
||||
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
|
||||
target_link_libraries(expected_eval_errors_test ${LIBS})
|
||||
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
|
||||
|
||||
add_executable(set_state_test unittests/set_state_test.cpp)
|
||||
target_link_libraries(set_state_test ${LIBS})
|
||||
add_test(NAME Set_State_Test COMMAND set_state_test)
|
||||
|
||||
add_executable(simultaneous_chaiscript_test unittests/simultaneous_chaiscript_test.cpp)
|
||||
target_link_libraries(simultaneous_chaiscript_test ${LIBS})
|
||||
add_test(NAME Simultaneous_ChaiScript_Test COMMAND simultaneous_chaiscript_test)
|
||||
|
||||
add_executable(heap_allocated_chaiscript_test unittests/heap_allocated_chaiscript_test.cpp)
|
||||
target_link_libraries(heap_allocated_chaiscript_test ${LIBS})
|
||||
add_test(NAME Heap_Allocated_ChaiScript_Test COMMAND heap_allocated_chaiscript_test)
|
||||
|
||||
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
|
||||
target_link_libraries(c_linkage_test ${LIBS})
|
||||
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
|
||||
@@ -348,6 +315,10 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(integer_literal_test ${LIBS})
|
||||
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
||||
|
||||
add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp)
|
||||
target_link_libraries(arithmetic_conversions_test ${LIBS})
|
||||
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test)
|
||||
|
||||
if(MULTITHREAD_SUPPORT_ENABLED)
|
||||
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
|
||||
target_link_libraries(multithreaded_test ${LIBS})
|
||||
@@ -399,6 +370,3 @@ configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @O
|
||||
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
|
||||
DESTINATION lib/pkgconfig)
|
||||
|
||||
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ PROJECT_NUMBER = ${CHAI_VERSION}
|
||||
# for a project that appears at the top of each page and should give viewer
|
||||
# a quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "An easy to use embedded scripting language for C++."
|
||||
PROJECT_BRIEF = ${CMAKE_BINARY_DIR}/docs
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify an logo or icon that is
|
||||
# included in the documentation. The maximum height of the logo should not
|
||||
|
||||
29
LICENSE
29
LICENSE
@@ -1,29 +0,0 @@
|
||||
Copyright 2009-2015 Jason Turner
|
||||
Copyright 2009-2012 Jonathan Turner.
|
||||
|
||||
All Rights Reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Jason Turner nor Jonathan Turner nor the
|
||||
name of contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,5 +0,0 @@
|
||||
[paths]
|
||||
include
|
||||
|
||||
[parent]
|
||||
ChaiScript/ChaiScript: 0
|
||||
334
cheatsheet.md
334
cheatsheet.md
@@ -1,334 +0,0 @@
|
||||
# Initializing ChaiScript
|
||||
|
||||
```
|
||||
chaiscript::ChaiScript chai; // loads stdlib from loadable module on file system
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdlib
|
||||
```
|
||||
|
||||
# Adding Things To The Engine
|
||||
|
||||
## Adding a Function / Method / Member
|
||||
|
||||
### General
|
||||
|
||||
```
|
||||
chai.add(chaiscript::fun(&function_name), "function_name");
|
||||
chai.add(chaiscript::fun(&Class::method_name), "method_name");
|
||||
chai.add(chaiscript::fun(&Class::member_name), "member_name");
|
||||
```
|
||||
|
||||
### With Overloads
|
||||
|
||||
#### Preferred
|
||||
|
||||
```
|
||||
chai.add(chaiscript::fun<ReturnType (ParamType1, ParamType2)>(&function_with_overloads), "function_name");
|
||||
```
|
||||
|
||||
#### Alternative
|
||||
|
||||
```
|
||||
chai.add(chaiscript::fun(std::static_cast<ReturnType (*)(ParamType1, ParamType2)>(&function_with_overloads)), "function_name");
|
||||
```
|
||||
|
||||
### Lambda
|
||||
|
||||
```
|
||||
chai.add(
|
||||
chaiscript::fun<std::string (bool)>(
|
||||
[](bool type) {
|
||||
if (type) { return "x"; }
|
||||
else { return "y"; }
|
||||
}), "function_name");
|
||||
```
|
||||
|
||||
### Constructors
|
||||
|
||||
```
|
||||
chai.add(chaiscript::constructor<MyType ()>(), "MyType");
|
||||
chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
|
||||
```
|
||||
|
||||
## Adding Types
|
||||
|
||||
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
|
||||
|
||||
```
|
||||
chai.add(chaiscript::user_type<MyClass>, "MyClass");
|
||||
```
|
||||
|
||||
## Adding Objects
|
||||
|
||||
```
|
||||
chai.add(chaiscript::var(somevar), "somevar"); // copied in
|
||||
chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared between C++ and chai
|
||||
auto shareddouble = std::make_shared<double>(4.3);
|
||||
chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai
|
||||
chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const
|
||||
chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const
|
||||
chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const
|
||||
```
|
||||
|
||||
# Executing Script
|
||||
|
||||
## General
|
||||
|
||||
```
|
||||
chai.eval("print(\"Hello World\")");
|
||||
chai.eval(R"(print("Hello World"))");
|
||||
```
|
||||
|
||||
## Unboxing Return Values
|
||||
|
||||
### Prefered
|
||||
|
||||
```
|
||||
chai.eval<double>("5.3 + 2.1"); // returns 7.4 as a C++ double
|
||||
```
|
||||
|
||||
### Alternative
|
||||
|
||||
```
|
||||
auto v = chai.eval("5.3 + 2.1");
|
||||
chai.boxed_cast<double>(v); // extracts double value from boxed_value and applies known conversions
|
||||
chaiscript::boxed_cast<double>(v); // free function version, does not know about conversions
|
||||
```
|
||||
|
||||
### Converting Between Algebraic Types
|
||||
|
||||
```
|
||||
chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with any number type
|
||||
// which is equivalent to, but much more automatic than:
|
||||
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
|
||||
```
|
||||
|
||||
## Sharing Values
|
||||
|
||||
```
|
||||
double &d = chai.eval("var i = 5.2; i"); // d is now a reference to i in the script
|
||||
std::shared_ptr<double> d = chai.eval("var i = 5.2; i"); // same result but reference counted
|
||||
|
||||
d = 3;
|
||||
chai.eval("print(i)"); // prints 3
|
||||
```
|
||||
|
||||
## Catching Eval Errors
|
||||
|
||||
```
|
||||
try {
|
||||
chai.eval("2.3 + \"String\"");
|
||||
} catch (const chaiscript::exception::eval_error &e) {
|
||||
std::cout << "Error\n" << e.pretty_print() << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
## Catching Errors Thrown From Script
|
||||
|
||||
```
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
} catch (const double e) {
|
||||
} catch (int) {
|
||||
} catch (float) {
|
||||
} catch (const std::string &) {
|
||||
} catch (const std::exception &e) {
|
||||
// This is the one what will be called in the specific throw() above
|
||||
}
|
||||
```
|
||||
|
||||
## Sharing Functions
|
||||
|
||||
|
||||
```
|
||||
auto p = chai.eval<std::function<std::string (double)>>("to_string");
|
||||
p(5); // calls chaiscript's 'to_string' function, returning std::string("5")
|
||||
```
|
||||
|
||||
Note: backtick treats operators as normal functions
|
||||
|
||||
```
|
||||
auto p = chai.eval<std::function<int (int, int)>>(`+`);
|
||||
p(5, 6); // calls chaiscript's '+' function, returning 11
|
||||
```
|
||||
|
||||
```
|
||||
auto p = chai.eval<std::function<std::string (int, double)>>(fun(x,y) { to_string(x) + to_string(y); });
|
||||
p(3,4.2); // evaluates the lambda function, returning the string "34.2" to C++
|
||||
```
|
||||
|
||||
# Language Reference
|
||||
|
||||
## Variables
|
||||
|
||||
```
|
||||
var i; // uninitialized variable, can take any value on first assignment;
|
||||
auto j; // equiv to var
|
||||
|
||||
var k = 5; // initialized to 5 (integer)
|
||||
var l := k; // reference to k
|
||||
auto &m = k; // reference to k
|
||||
|
||||
GLOBAL g = 5; // creates a global variable. If global already exists, it is not re-added
|
||||
GLOBAL g = 2; // global 'g' now equals 2
|
||||
|
||||
GLOBAL g2;
|
||||
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once
|
||||
```
|
||||
|
||||
## Built in Types
|
||||
|
||||
```
|
||||
var v = [1,2,3u,4ll,"16", `+`]; // creates vector of heterogenous values
|
||||
var m = ["a":1, "b":2]; // map of string:value pairs
|
||||
```
|
||||
|
||||
Floating point values default to `double` type and integers default to `int` type. All C++ suffixes
|
||||
such as `f`, `ll`, `u` as well as scientific notion is supported
|
||||
|
||||
```
|
||||
1.0 // double
|
||||
1.0f // float
|
||||
1.0l // long double
|
||||
1 // int
|
||||
1u // unsigned int
|
||||
1ul // unsigned long
|
||||
1ull // unsigned long long
|
||||
```
|
||||
|
||||
Literals are automatically sized, just as in C++. For example: `10000000000` is > 32bits and the appropriate type is used to hold it
|
||||
on your platform.
|
||||
|
||||
|
||||
## Functions
|
||||
|
||||
### General
|
||||
|
||||
```
|
||||
def myfun(x, y) { x + y; } // last statement in body is the return value
|
||||
def myfun(x, y) { return x + y; } // equiv
|
||||
```
|
||||
|
||||
### Optionally Typed
|
||||
|
||||
```
|
||||
def myfun(x, int y) { x + y; } // requires y to be an int
|
||||
```
|
||||
|
||||
### With Guards
|
||||
|
||||
```
|
||||
def myfun(x, int y) : y > 5 { x - y; } // only called if y > 5
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
Methods and functions are mostly equivalent
|
||||
|
||||
```
|
||||
def string::add(int y) { this + to_string(y); }
|
||||
def add(string s, int y) { s + to_string(y); } //equiv functionality
|
||||
|
||||
// calling new function/method
|
||||
"a".add(1); // returns a1
|
||||
add("a", 1); // returns a1, either calling syntax works with either def above
|
||||
```
|
||||
|
||||
### Lambdas
|
||||
|
||||
```
|
||||
var l = fun(x) { x * 15; }
|
||||
l(2) // returns 30
|
||||
|
||||
var a = 13
|
||||
var m = fun[a](x) { x * a; }
|
||||
m(3); // a was captured (by reference), returns 39
|
||||
|
||||
var n = bind(fun(x,y) { x * y; }, _, 10);
|
||||
n(2); // returns 20
|
||||
```
|
||||
|
||||
|
||||
|
||||
## ChaiScript Defined Types
|
||||
|
||||
Define a type called "MyType" with one member value "a" and a getter
|
||||
|
||||
### Preferred
|
||||
|
||||
```
|
||||
class MyType {
|
||||
var value;
|
||||
def MyType() { this.value = "a"; }
|
||||
def get_value() { "Value Is: " + this.value; }
|
||||
};
|
||||
```
|
||||
|
||||
### Alternative
|
||||
|
||||
```
|
||||
attr MyType::value;
|
||||
def MyType::MyType() { this.value = "a"; }
|
||||
def MyType::get_value() { "Value Is: " + this.value; }
|
||||
```
|
||||
|
||||
### Using
|
||||
|
||||
```
|
||||
var m = MyType(); // calls constructor
|
||||
print(m.get_value()); // prints "Value Is: a"
|
||||
print(get_value(m)); // prints "Value Is: a"
|
||||
```
|
||||
|
||||
## Dynamic Objects
|
||||
|
||||
All ChaiScript defined types and generic Dynamic_Object support dynamic parameters
|
||||
|
||||
```
|
||||
var o = Dynamic_Object();
|
||||
o.f = fun(x) { print(x); }
|
||||
o.f(3); // prints "3"
|
||||
```
|
||||
|
||||
Implicit 'this' is allowed:
|
||||
|
||||
```
|
||||
var o = Dynamic_Object();
|
||||
o.x = 3;
|
||||
o.f = fun(y) { print(this.x + y); }
|
||||
o.f(10); // prints 13
|
||||
```
|
||||
|
||||
## method_missing
|
||||
|
||||
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate
|
||||
method cannot be found
|
||||
|
||||
```
|
||||
def method_missing(int i, string name, Vector v) {
|
||||
print("method_missing(${i}, ${name}), ${v.size()} params");
|
||||
}
|
||||
|
||||
5.bob(1,2,3); // prints "method_missing(5, bob, 3 params)"
|
||||
```
|
||||
|
||||
`method_missing` signature can be either 2 parameters or 3 parameters. If the signature contains two parameters
|
||||
it is treated as a property. If the property contains a function then additional parameters are passed to
|
||||
the contained function.
|
||||
|
||||
If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins.
|
||||
|
||||
|
||||
# Built In Functions
|
||||
|
||||
## Evaluation
|
||||
|
||||
```
|
||||
eval("4 + 5") // dynamically eval script string and returns value of last statement
|
||||
eval_file("filename") // evals file and returns value of last statement
|
||||
use("filename") // evals file exactly once and returns value of last statement
|
||||
// if the file had already been 'used' nothing happens and undefined is returned
|
||||
```
|
||||
|
||||
Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor
|
||||
|
||||
|
||||
@@ -1,103 +1,103 @@
|
||||
# Checks for C++11 features
|
||||
# CXX11_FEATURE_LIST - a list containing all supported features
|
||||
# HAS_CXX11_AUTO - auto keyword
|
||||
# HAS_CXX11_NULLPTR - nullptr
|
||||
# HAS_CXX11_LAMBDA - lambdas
|
||||
# HAS_CXX11_STATIC_ASSERT - static_assert()
|
||||
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
|
||||
# HAS_CXX11_DECLTYPE - decltype keyword
|
||||
# HAS_CXX11_CSTDINT_H - cstdint header
|
||||
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
|
||||
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
|
||||
# HAS_CXX11_CONSTEXPR - constexpr keyword
|
||||
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
|
||||
# HAS_CXX11_FUNC - __func__ preprocessor constant
|
||||
#
|
||||
# Original script by Rolf Eike Beer
|
||||
# Modifications by Andreas Weis
|
||||
#
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
|
||||
SET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_CXX_FLAGS "-std=c++0x")
|
||||
endif()
|
||||
|
||||
MACRO(CXX11_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
|
||||
IF (NOT DEFINED ${RESULT_VAR})
|
||||
SET(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11/cxx11_${FEATURE_NAME}")
|
||||
|
||||
IF (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
|
||||
ELSE (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\"")
|
||||
ENDIF (${FEATURE_NUMBER})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME}")
|
||||
|
||||
SET(_SRCFILE "${_SRCFILE_BASE}.cpp")
|
||||
SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
IF (CROSS_COMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ELSE (CROSS_COMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}")
|
||||
IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ENDIF (CROSS_COMPILING)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
|
||||
IF (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ELSE (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ENDIF (_TMP_RESULT)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
|
||||
IF (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- works")
|
||||
LIST(APPEND CXX11_FEATURE_LIST ${RESULT_VAR})
|
||||
ELSE (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- not supported")
|
||||
ENDIF (${RESULT_VAR})
|
||||
SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
|
||||
ENDIF (NOT DEFINED ${RESULT_VAR})
|
||||
ENDMACRO(CXX11_CHECK_FEATURE)
|
||||
|
||||
CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)
|
||||
CXX11_CHECK_FEATURE("nullptr" 2431 HAS_CXX11_NULLPTR)
|
||||
CXX11_CHECK_FEATURE("lambda" 2927 HAS_CXX11_LAMBDA)
|
||||
CXX11_CHECK_FEATURE("static_assert" 1720 HAS_CXX11_STATIC_ASSERT)
|
||||
CXX11_CHECK_FEATURE("rvalue_references" 2118 HAS_CXX11_RVALUE_REFERENCES)
|
||||
CXX11_CHECK_FEATURE("decltype" 2343 HAS_CXX11_DECLTYPE)
|
||||
CXX11_CHECK_FEATURE("cstdint" "" HAS_CXX11_CSTDINT_H)
|
||||
CXX11_CHECK_FEATURE("long_long" 1811 HAS_CXX11_LONG_LONG)
|
||||
CXX11_CHECK_FEATURE("variadic_templates" 2555 HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
CXX11_CHECK_FEATURE("constexpr" 2235 HAS_CXX11_CONSTEXPR)
|
||||
CXX11_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX11_SIZEOF_MEMBER)
|
||||
CXX11_CHECK_FEATURE("__func__" 2340 HAS_CXX11_FUNC)
|
||||
|
||||
SET(CXX11_FEATURE_LIST ${CXX11_FEATURE_LIST} CACHE STRING "C++11 feature support list")
|
||||
MARK_AS_ADVANCED(FORCE CXX11_FEATURE_LIST)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS ${CHECK_CXX11_OLD_CMAKE_CXX_FLAGS})
|
||||
UNSET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS)
|
||||
|
||||
# Checks for C++11 features
|
||||
# CXX11_FEATURE_LIST - a list containing all supported features
|
||||
# HAS_CXX11_AUTO - auto keyword
|
||||
# HAS_CXX11_NULLPTR - nullptr
|
||||
# HAS_CXX11_LAMBDA - lambdas
|
||||
# HAS_CXX11_STATIC_ASSERT - static_assert()
|
||||
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
|
||||
# HAS_CXX11_DECLTYPE - decltype keyword
|
||||
# HAS_CXX11_CSTDINT_H - cstdint header
|
||||
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
|
||||
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
|
||||
# HAS_CXX11_CONSTEXPR - constexpr keyword
|
||||
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
|
||||
# HAS_CXX11_FUNC - __func__ preprocessor constant
|
||||
#
|
||||
# Original script by Rolf Eike Beer
|
||||
# Modifications by Andreas Weis
|
||||
#
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
|
||||
SET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_CXX_FLAGS "-std=c++0x")
|
||||
endif()
|
||||
|
||||
MACRO(CXX11_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
|
||||
IF (NOT DEFINED ${RESULT_VAR})
|
||||
SET(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11/cxx11_${FEATURE_NAME}")
|
||||
|
||||
IF (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
|
||||
ELSE (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\"")
|
||||
ENDIF (${FEATURE_NUMBER})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME}")
|
||||
|
||||
SET(_SRCFILE "${_SRCFILE_BASE}.cpp")
|
||||
SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
IF (CROSS_COMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ELSE (CROSS_COMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}")
|
||||
IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ENDIF (CROSS_COMPILING)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
|
||||
IF (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ELSE (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ENDIF (_TMP_RESULT)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
|
||||
IF (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- works")
|
||||
LIST(APPEND CXX11_FEATURE_LIST ${RESULT_VAR})
|
||||
ELSE (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- not supported")
|
||||
ENDIF (${RESULT_VAR})
|
||||
SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
|
||||
ENDIF (NOT DEFINED ${RESULT_VAR})
|
||||
ENDMACRO(CXX11_CHECK_FEATURE)
|
||||
|
||||
CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)
|
||||
CXX11_CHECK_FEATURE("nullptr" 2431 HAS_CXX11_NULLPTR)
|
||||
CXX11_CHECK_FEATURE("lambda" 2927 HAS_CXX11_LAMBDA)
|
||||
CXX11_CHECK_FEATURE("static_assert" 1720 HAS_CXX11_STATIC_ASSERT)
|
||||
CXX11_CHECK_FEATURE("rvalue_references" 2118 HAS_CXX11_RVALUE_REFERENCES)
|
||||
CXX11_CHECK_FEATURE("decltype" 2343 HAS_CXX11_DECLTYPE)
|
||||
CXX11_CHECK_FEATURE("cstdint" "" HAS_CXX11_CSTDINT_H)
|
||||
CXX11_CHECK_FEATURE("long_long" 1811 HAS_CXX11_LONG_LONG)
|
||||
CXX11_CHECK_FEATURE("variadic_templates" 2555 HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
CXX11_CHECK_FEATURE("constexpr" 2235 HAS_CXX11_CONSTEXPR)
|
||||
CXX11_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX11_SIZEOF_MEMBER)
|
||||
CXX11_CHECK_FEATURE("__func__" 2340 HAS_CXX11_FUNC)
|
||||
|
||||
SET(CXX11_FEATURE_LIST ${CXX11_FEATURE_LIST} CACHE STRING "C++11 feature support list")
|
||||
MARK_AS_ADVANCED(FORCE CXX11_FEATURE_LIST)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS ${CHECK_CXX11_OLD_CMAKE_CXX_FLAGS})
|
||||
UNSET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS)
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!__func__) { return 1; }
|
||||
if(std::strlen(__func__) <= 0) { return 1; }
|
||||
return 0;
|
||||
}
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!__func__) { return 1; }
|
||||
if(std::strlen(__func__) <= 0) { return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
auto i = 5;
|
||||
auto f = 3.14159f;
|
||||
auto d = 3.14159;
|
||||
bool ret = (
|
||||
(sizeof(f) < sizeof(d)) &&
|
||||
(sizeof(i) == sizeof(int))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto i = 5;
|
||||
auto f = 3.14159f;
|
||||
auto d = 3.14159;
|
||||
bool ret = (
|
||||
(sizeof(f) < sizeof(d)) &&
|
||||
(sizeof(i) == sizeof(int))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
constexpr int square(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
constexpr int the_answer()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int test_arr[square(3)];
|
||||
bool ret = (
|
||||
(square(the_answer()) == 1764) &&
|
||||
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
constexpr int square(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
constexpr int the_answer()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int test_arr[square(3)];
|
||||
bool ret = (
|
||||
(square(the_answer()) == 1764) &&
|
||||
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <cstdint>
|
||||
int main()
|
||||
{
|
||||
bool test =
|
||||
(sizeof(int8_t) == 1) &&
|
||||
(sizeof(int16_t) == 2) &&
|
||||
(sizeof(int32_t) == 4) &&
|
||||
(sizeof(int64_t) == 8);
|
||||
return test ? 0 : 1;
|
||||
}
|
||||
#include <cstdint>
|
||||
int main()
|
||||
{
|
||||
bool test =
|
||||
(sizeof(int8_t) == 1) &&
|
||||
(sizeof(int16_t) == 2) &&
|
||||
(sizeof(int32_t) == 4) &&
|
||||
(sizeof(int64_t) == 8);
|
||||
return test ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
bool check_size(int i)
|
||||
{
|
||||
return sizeof(int) == sizeof(decltype(i));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool ret = check_size(42);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
bool check_size(int i)
|
||||
{
|
||||
return sizeof(int) == sizeof(decltype(i));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool ret = check_size(42);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
return ([&ret]() -> int { return ret; })();
|
||||
}
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
return ([&ret]() -> int { return ret; })();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
int main(void)
|
||||
{
|
||||
long long l;
|
||||
unsigned long long ul;
|
||||
|
||||
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
|
||||
}
|
||||
int main(void)
|
||||
{
|
||||
long long l;
|
||||
unsigned long long ul;
|
||||
|
||||
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int* test = nullptr;
|
||||
return test ? 1 : 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
int* test = nullptr;
|
||||
return test ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int i = nullptr;
|
||||
return 1;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
int i = nullptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
int foo(int& lvalue)
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int foo(int&& rvalue)
|
||||
{
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 42;
|
||||
return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1;
|
||||
}
|
||||
int foo(int& lvalue)
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int foo(int&& rvalue)
|
||||
{
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 42;
|
||||
return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
struct foo {
|
||||
char bar;
|
||||
int baz;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool ret = (
|
||||
(sizeof(foo::bar) == 1) &&
|
||||
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
|
||||
(sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
struct foo {
|
||||
char bar;
|
||||
int baz;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool ret = (
|
||||
(sizeof(foo::bar) == 1) &&
|
||||
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
|
||||
(sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(0 < 1, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
static_assert(0 < 1, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(1 < 0, "this should fail");
|
||||
return 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
static_assert(1 < 0, "this should fail");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
int Accumulate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
int Accumulate(T v, Ts... vs)
|
||||
{
|
||||
return v + Accumulate(vs...);
|
||||
}
|
||||
|
||||
template<int... Is>
|
||||
int CountElements()
|
||||
{
|
||||
return sizeof...(Is);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int acc = Accumulate(1, 2, 3, 4, -5);
|
||||
int count = CountElements<1,2,3,4,5>();
|
||||
return ((acc == 5) && (count == 5)) ? 0 : 1;
|
||||
}
|
||||
int Accumulate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
int Accumulate(T v, Ts... vs)
|
||||
{
|
||||
return v + Accumulate(vs...);
|
||||
}
|
||||
|
||||
template<int... Is>
|
||||
int CountElements()
|
||||
{
|
||||
return sizeof...(Is);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int acc = Accumulate(1, 2, 3, 4, -5);
|
||||
int count = CountElements<1,2,3,4,5>();
|
||||
return ((acc == 5) && (count == 5)) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
|
||||
def go()
|
||||
var my_array=["1", 4, 6.6l, 10ul, "1000", 100, 10.9f ];
|
||||
|
||||
for (var j = 0; j < 10000; ++j)
|
||||
{
|
||||
var my_array=["1", 4, 6.6l, 10ul, "1000", 100, 10.9f ];
|
||||
|
||||
var q = 0;
|
||||
|
||||
for (var j = 0; j < 10000; ++j)
|
||||
for (var i = 0; i < 6; ++i)
|
||||
{
|
||||
for (var i = 0; i < 6; ++i)
|
||||
{
|
||||
to_string(my_array[i]);
|
||||
}
|
||||
|
||||
q += j;
|
||||
to_string(my_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
go();
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
load_module("test_module")
|
||||
|
||||
auto t := TestBaseType();
|
||||
|
||||
// This uses the TestBaseType to Type2 user type
|
||||
// conversion which was added in the module and then calls
|
||||
// "get_val()" which exists on the Type2 type
|
||||
//assert_equal(t.get_val(), 10);
|
||||
//print("Made it past test 1");
|
||||
|
||||
var t2 := Type2(t);
|
||||
|
||||
//dump_system();
|
||||
|
||||
for (var i = 0; i < 50000; ++i) {
|
||||
var str = string(get_str(t2));
|
||||
size(get_str(t2));
|
||||
t2.get_str().size();
|
||||
t.get_str().size();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# [PackageDev] target_format: plist, ext: tmLanguage
|
||||
---
|
||||
comment: 'ChaiScript Syntax: version 2.0'
|
||||
fileTypes: [chai]
|
||||
firstLineMatch: ^#!/usr/bin/env node
|
||||
foldingStartMarker: ^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$
|
||||
foldingStopMarker: ^\s*\}
|
||||
keyEquivalent: ^~J
|
||||
name: ChaiScript
|
||||
patterns:
|
||||
- {comment: chaiscript shebang, match: ^#, name: comment.line.chai}
|
||||
- {match: '\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b', name: constant.numeric.chai}
|
||||
- begin: ''''
|
||||
beginCaptures:
|
||||
'0': {name: punctuation.definition.string.begin.chai}
|
||||
end: ''''
|
||||
endCaptures:
|
||||
'0': {name: punctuation.definition.string.end.chai}
|
||||
name: string.quoted.single.chai
|
||||
patterns:
|
||||
- {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai}
|
||||
- begin: '"'
|
||||
beginCaptures:
|
||||
'0': {name: punctuation.definition.string.begin.chai}
|
||||
end: '"'
|
||||
endCaptures:
|
||||
'0': {name: punctuation.definition.string.end.chai}
|
||||
name: string.quoted.double.chai
|
||||
patterns:
|
||||
- {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai}
|
||||
- begin: /\*\*(?!/)
|
||||
captures:
|
||||
'0': {name: punctuation.definition.comment.chai}
|
||||
end: \*/
|
||||
name: comment.block.documentation.chai
|
||||
- begin: /\*
|
||||
captures:
|
||||
'0': {name: punctuation.definition.comment.chai}
|
||||
end: \*/
|
||||
name: comment.block.chai
|
||||
- captures:
|
||||
'1': {name: punctuation.definition.comment.chai}
|
||||
match: (//).*$\n?
|
||||
name: comment.line.double-slash.chai
|
||||
- captures:
|
||||
'0': {name: punctuation.definition.comment.html.chai}
|
||||
'2': {name: punctuation.definition.comment.html.chai}
|
||||
match: (<!--|-->)
|
||||
name: comment.block.html.chai
|
||||
- {match: \b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b,
|
||||
name: storage.type.chai}
|
||||
- {match: \b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b,
|
||||
name: keyword.control.chai}
|
||||
- {match: \b(delete|in|instanceof|new|typeof|with)\b, name: keyword.operator.chai}
|
||||
- {match: \btrue\b, name: constant.language.boolean.true.chai}
|
||||
- {match: \bfalse\b, name: constant.language.boolean.false.chai}
|
||||
- {match: \bnull\b, name: constant.language.null.chai}
|
||||
- {match: \b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b,
|
||||
name: support.class.chai}
|
||||
- {match: '\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()',
|
||||
name: support.function.chai}
|
||||
- {match: '\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()',
|
||||
name: support.function.dom.chai}
|
||||
- {match: '(?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b',
|
||||
name: support.constant.chai}
|
||||
- {match: '(?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b',
|
||||
name: support.constant.dom.chai}
|
||||
- {match: \b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b,
|
||||
name: support.constant.dom.chai}
|
||||
- {match: '\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b',
|
||||
name: support.function.event-handler.chai}
|
||||
- {match: '!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|void)\b',
|
||||
name: keyword.operator.chai}
|
||||
- {match: \b(Infinity|NaN|undefined)\b, name: constant.language.chai}
|
||||
- begin: (?<=[=(:]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?])
|
||||
beginCaptures:
|
||||
'1': {name: punctuation.definition.string.begin.chai}
|
||||
end: (/)[igm]*
|
||||
endCaptures:
|
||||
'1': {name: punctuation.definition.string.end.chai}
|
||||
name: string.regexp.chai
|
||||
patterns:
|
||||
- {match: \\., name: constant.character.escape.chai}
|
||||
- {match: \;, name: punctuation.terminator.statement.chai}
|
||||
- {match: ',[ |\t]*', name: meta.delimiter.object.comma.chai}
|
||||
- {match: \., name: meta.delimiter.method.period.chai}
|
||||
- {match: '\{|\}', name: meta.brace.curly.chai}
|
||||
- {match: \(|\), name: meta.brace.round.chai}
|
||||
- {match: '\[|\]', name: meta.brace.square.chai}
|
||||
scopeName: source.chai
|
||||
uuid: 93E017CC-6F27-11D9-90EB-000D93589AF6
|
||||
|
||||
...
|
||||
@@ -1,333 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>ChaiScript Syntax: version 2.0</string>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>chai</string>
|
||||
</array>
|
||||
<key>firstLineMatch</key>
|
||||
<string>^#!/usr/bin/env node</string>
|
||||
<key>foldingStartMarker</key>
|
||||
<string>^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$</string>
|
||||
<key>foldingStopMarker</key>
|
||||
<string>^\s*\}</string>
|
||||
<key>keyEquivalent</key>
|
||||
<string>^~J</string>
|
||||
<key>name</key>
|
||||
<string>ChaiScript</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>chaiscript shebang</string>
|
||||
<key>match</key>
|
||||
<string>^#</string>
|
||||
<key>name</key>
|
||||
<string>comment.line.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>'</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>'</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.single.chai</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.chai</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.chai</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.chai</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>/\*\*(?!/)</string>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>\*/</string>
|
||||
<key>name</key>
|
||||
<string>comment.block.documentation.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>/\*</string>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>\*/</string>
|
||||
<key>name</key>
|
||||
<string>comment.block.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(//).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>comment.line.double-slash.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.html.chai</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.html.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(<!--|-->)</string>
|
||||
<key>name</key>
|
||||
<string>comment.block.html.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b</string>
|
||||
<key>name</key>
|
||||
<string>storage.type.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.control.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(delete|in|instanceof|new|typeof|with)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\btrue\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.boolean.true.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\bfalse\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.boolean.false.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\bnull\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.null.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b</string>
|
||||
<key>name</key>
|
||||
<string>support.class.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()</string>
|
||||
<key>name</key>
|
||||
<string>support.function.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()</string>
|
||||
<key>name</key>
|
||||
<string>support.function.dom.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b</string>
|
||||
<key>name</key>
|
||||
<string>support.constant.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b</string>
|
||||
<key>name</key>
|
||||
<string>support.constant.dom.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b</string>
|
||||
<key>name</key>
|
||||
<string>support.constant.dom.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b</string>
|
||||
<key>name</key>
|
||||
<string>support.function.event-handler.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|void)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(Infinity|NaN|undefined)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(?<=[=(:]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?])</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>(/)[igm]*</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.chai</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.regexp.chai</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\.</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.chai</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\;</string>
|
||||
<key>name</key>
|
||||
<string>punctuation.terminator.statement.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>,[ |\t]*</string>
|
||||
<key>name</key>
|
||||
<string>meta.delimiter.object.comma.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\.</string>
|
||||
<key>name</key>
|
||||
<string>meta.delimiter.method.period.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\{|\}</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.curly.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\(|\)</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.round.chai</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\[|\]</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.square.chai</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>source.chai</string>
|
||||
<key>uuid</key>
|
||||
<string>93E017CC-6F27-11D9-90EB-000D93589AF6</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_HPP_
|
||||
@@ -170,7 +170,7 @@
|
||||
///
|
||||
/// ~~~~~~~~~{.cpp}
|
||||
/// chai.add_global_const(const_var(i), "i");
|
||||
/// chai("def somefun() { print(i); }; somefun();");
|
||||
/// chai("def somefun() { print(i); }; sumfun();");
|
||||
/// ~~~~~~~~~
|
||||
///
|
||||
/// @subsubsection adding_functions Adding Functions
|
||||
@@ -663,19 +663,6 @@
|
||||
///
|
||||
/// @sa @ref LangObjectSystemRef
|
||||
///
|
||||
///
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordauto auto
|
||||
///
|
||||
/// Defines a variable
|
||||
///
|
||||
/// ~~~~~~~~
|
||||
/// Variable ::= "auto" identifier
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// Synonym for @ref keywordvar
|
||||
///
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordbreak break
|
||||
@@ -695,13 +682,13 @@
|
||||
/// Begins a function or method definition
|
||||
///
|
||||
/// ~~~~~~~~
|
||||
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [arg ("," arg)*] ")" [":" guard] block
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// annotation: meta-annotation on function, currently used as documentation. Optional.
|
||||
/// identifier: name of function. Required.
|
||||
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
||||
/// args: comma-delimited list of parameter names. Optional.
|
||||
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
||||
/// { }: scoped block as function body. Required.
|
||||
///
|
||||
@@ -778,13 +765,12 @@
|
||||
/// @section keywordtry try
|
||||
/// ~~~~~~~~
|
||||
/// Try Block ::= "try" block
|
||||
/// ("catch" ["(" [type] variable ")"] [":" guards] block)+
|
||||
/// ("catch" ["(" variable ")"] [":" guards] block)+
|
||||
/// ["finally" block]
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// @sa ChaiScript_Language::throw
|
||||
///
|
||||
///
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordwhile while
|
||||
@@ -796,19 +782,6 @@
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// This loop can be broken using the @ref keywordbreak command.
|
||||
///
|
||||
///
|
||||
/// -----------------------------------------------------------------------
|
||||
///
|
||||
/// @section keywordvar var
|
||||
///
|
||||
/// Defines a variable
|
||||
///
|
||||
/// ~~~~~~~~
|
||||
/// Variable ::= "var" identifier
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// Synonym for @ref keywordauto
|
||||
|
||||
|
||||
/// @namespace chaiscript
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||
@@ -10,27 +10,14 @@
|
||||
#ifdef _MSC_VER
|
||||
#define CHAISCRIPT_MSVC _MSC_VER
|
||||
#define CHAISCRIPT_HAS_DECLSPEC
|
||||
#if _MSC_VER <= 1800
|
||||
#define CHAISCRIPT_MSVC_12
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CHAISCRIPT_MSVC_12
|
||||
#define CHAISCRIPT_HAS_MAGIC_STATICS
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#if defined( _LIBCPP_VERSION )
|
||||
#define CHAISCRIPT_LIBCPP
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define CHAISCRIPT_WINDOWS
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
||||
/// Currently only g++>=4.8 supports this natively
|
||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
/// Currently only g++>=4.8supports this natively
|
||||
/// \todo Make this support other compilers when possible
|
||||
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
||||
#endif
|
||||
@@ -56,23 +43,11 @@
|
||||
#define CHAISCRIPT_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace chaiscript {
|
||||
static const int version_major = 5;
|
||||
static const int version_minor = 7;
|
||||
static const int version_minor = 4;
|
||||
static const int version_patch = 0;
|
||||
|
||||
template<typename B, typename D, typename ...Arg>
|
||||
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
||||
{
|
||||
#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED
|
||||
return std::make_shared<D>(std::forward<Arg>(arg)...);
|
||||
#else
|
||||
return std::shared_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
#include "dispatchkit/boxed_value.hpp"
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <future>
|
||||
#endif
|
||||
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file generates the standard library that normal ChaiScript usage requires.
|
||||
@@ -45,11 +40,6 @@ namespace chaiscript
|
||||
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
lib->add(standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future"));
|
||||
lib->add(chaiscript::fun<std::future<Boxed_Value> (const std::function<chaiscript::Boxed_Value ()> &)>([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
|
||||
#endif
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||
#define CHAISCRIPT_THREADING_HPP_
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
@@ -17,8 +16,6 @@
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
#endif
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
|
||||
/// \file
|
||||
///
|
||||
/// This file contains code necessary for thread support in ChaiScript.
|
||||
@@ -85,27 +82,16 @@ namespace chaiscript
|
||||
t().erase(m_key);
|
||||
}
|
||||
|
||||
inline const T *operator->() const
|
||||
inline T *operator->() const
|
||||
{
|
||||
return &(t()[m_key]);
|
||||
}
|
||||
|
||||
inline const T &operator*() const
|
||||
inline T &operator*() const
|
||||
{
|
||||
return t()[m_key];
|
||||
}
|
||||
|
||||
inline T *operator->()
|
||||
{
|
||||
return &(t()[m_key]);
|
||||
}
|
||||
|
||||
inline T &operator*()
|
||||
{
|
||||
return t()[m_key];
|
||||
}
|
||||
|
||||
|
||||
void *m_key;
|
||||
|
||||
private:
|
||||
@@ -131,22 +117,12 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
inline const T *operator->() const
|
||||
inline T *operator->() const
|
||||
{
|
||||
return get_tls().get();
|
||||
}
|
||||
|
||||
inline const T &operator*() const
|
||||
{
|
||||
return *get_tls();
|
||||
}
|
||||
|
||||
inline T *operator->()
|
||||
{
|
||||
return get_tls().get();
|
||||
}
|
||||
|
||||
inline T &operator*()
|
||||
inline T &operator*() const
|
||||
{
|
||||
return *get_tls();
|
||||
}
|
||||
@@ -161,7 +137,7 @@ namespace chaiscript
|
||||
|
||||
if (itr != m_instances.end()) { return itr->second; }
|
||||
|
||||
std::shared_ptr<T> new_instance(std::make_shared<T>());
|
||||
std::shared_ptr<T> new_instance(new T());
|
||||
|
||||
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ namespace chaiscript {
|
||||
{
|
||||
}
|
||||
|
||||
bad_any_cast(const bad_any_cast &) = default;
|
||||
|
||||
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
@@ -46,31 +44,20 @@ namespace chaiscript {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
Data(const std::type_info &t_type)
|
||||
: m_type(t_type)
|
||||
{
|
||||
}
|
||||
|
||||
Data &operator=(const Data &) = delete;
|
||||
|
||||
virtual ~Data() {}
|
||||
|
||||
virtual void *data() = 0;
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<Data> clone() const = 0;
|
||||
const std::type_info &m_type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
explicit Data_Impl(T t_type)
|
||||
: Data(typeid(T)),
|
||||
m_data(std::move(t_type))
|
||||
: m_data(std::move(t_type))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -92,34 +79,54 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
std::unique_ptr<Data> m_data;
|
||||
mutable std::array<uint8_t, 15> m_smallSize;
|
||||
bool m_isSmall = false;
|
||||
const std::type_info *m_type = &typeid(void);
|
||||
|
||||
public:
|
||||
// construct/copy/destruct
|
||||
Any() = default;
|
||||
|
||||
Any(const Any &t_any)
|
||||
{
|
||||
if (!t_any.empty())
|
||||
{
|
||||
m_data = t_any.m_data->clone();
|
||||
} else {
|
||||
m_data.reset();
|
||||
}
|
||||
: m_data(t_any.m_data?t_any.m_data->clone():nullptr),
|
||||
m_smallSize(t_any.m_smallSize),
|
||||
m_isSmall(t_any.m_isSmall),
|
||||
m_type(t_any.m_type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
#if _MSC_VER != 1800
|
||||
Any(Any &&) = default;
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
#endif
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
|
||||
typename = typename std::enable_if< std::is_trivial<typename std::decay<ValueType>::type>::value>::type,
|
||||
typename = typename std::enable_if<sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize)) >::type>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value))))
|
||||
: m_isSmall(true), m_type(&typeid(typename std::decay<ValueType>::type))
|
||||
{
|
||||
m_smallSize.fill(0);
|
||||
*(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) = t_value;
|
||||
// std::cout << "Setting type: " << typeid(typename std::decay<ValueType>::type).name() << " " << t_value << " actual val: " << *(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) << " cast: " << cast<typename std::decay<ValueType>::type>() << "\n";
|
||||
}
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
|
||||
typename = typename std::enable_if<
|
||||
!std::is_trivial<typename std::decay<ValueType>::type>::value
|
||||
|| !(sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize))) >::type>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value)))),
|
||||
m_isSmall(false),
|
||||
m_type(&typeid(typename std::decay<ValueType>::type))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Any & operator=(const Any &t_any)
|
||||
{
|
||||
Any copy(t_any);
|
||||
@@ -130,14 +137,20 @@ namespace chaiscript {
|
||||
template<typename ToType>
|
||||
ToType &cast() const
|
||||
{
|
||||
if (m_data && typeid(ToType) == m_data->type())
|
||||
if (m_isSmall && typeid(ToType) == *m_type)
|
||||
{
|
||||
return *static_cast<ToType *>(static_cast<void *>(m_smallSize.data()));
|
||||
} else if (!m_isSmall && m_data && typeid(ToType) == *m_type) {
|
||||
return *static_cast<ToType *>(m_data->data());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return *m_type;
|
||||
}
|
||||
|
||||
~Any()
|
||||
{
|
||||
@@ -146,25 +159,31 @@ namespace chaiscript {
|
||||
// modifiers
|
||||
Any & swap(Any &t_other)
|
||||
{
|
||||
std::swap(t_other.m_smallSize, m_smallSize);
|
||||
std::swap(t_other.m_isSmall, m_isSmall);
|
||||
std::swap(t_other.m_data, m_data);
|
||||
std::swap(t_other.m_type, m_type);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// queries
|
||||
bool empty() const
|
||||
{
|
||||
return !bool(m_data);
|
||||
return !bool(m_data) && !m_isSmall;
|
||||
}
|
||||
|
||||
const std::type_info & type() const
|
||||
void *data() const
|
||||
{
|
||||
if (m_data)
|
||||
if (m_isSmall)
|
||||
{
|
||||
return m_data->type();
|
||||
return static_cast<void *>(m_smallSize.data());
|
||||
} else if (m_data) {
|
||||
return m_data->data();
|
||||
} else {
|
||||
return typeid(void);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
@@ -29,14 +28,14 @@ namespace chaiscript
|
||||
class bad_boxed_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
|
||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,8 +44,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const bad_boxed_cast &) = default;
|
||||
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||
@@ -14,56 +14,56 @@ namespace chaiscript
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
T* get_pointer(T *t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
struct Placeholder
|
||||
{
|
||||
static std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)> placeholder() {
|
||||
return std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)>(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10);
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T* get_pointer(const std::reference_wrapper<T> &t)
|
||||
template<int count, int maxcount, typename Sig>
|
||||
struct Bind_First
|
||||
{
|
||||
return &t.get();
|
||||
}
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
{
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(f, innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
|
||||
}
|
||||
};
|
||||
|
||||
template<int maxcount, typename Sig>
|
||||
struct Bind_First<0, maxcount, Sig>
|
||||
{
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
{
|
||||
return std::bind(f, innerparams...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O o)
|
||||
{
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
});
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
@@ -10,20 +10,21 @@
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
@@ -51,50 +52,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
|
||||
ModulePtr array(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
typedef typename std::remove_extent<T>::type ReturnType;
|
||||
const auto extent = std::extent<T>::value;
|
||||
m->add(user_type<T>(), type);
|
||||
m->add(fun<ReturnType& (T &, size_t)>(
|
||||
[extent](T& t, size_t index)->ReturnType &{
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
} else {
|
||||
return t[index];
|
||||
}
|
||||
}
|
||||
), "[]"
|
||||
);
|
||||
|
||||
m->add(fun<const ReturnType& (const T &, size_t)>(
|
||||
[extent](const T &t, size_t index)->const ReturnType &{
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
} else {
|
||||
return t[index];
|
||||
}
|
||||
}
|
||||
), "[]"
|
||||
);
|
||||
|
||||
m->add(fun<size_t (const T &)>(
|
||||
[extent](const T &) {
|
||||
return extent;
|
||||
}), "size");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Adds a copy constructor for the given type to the given Model
|
||||
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
||||
/// \param[in,out] m The Module to add the copy constructor to
|
||||
/// \tparam T The type to add a copy constructor for
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
template<typename T>
|
||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(constructor<T (const T &)>(), type);
|
||||
return m;
|
||||
@@ -105,7 +69,7 @@ namespace chaiscript
|
||||
/// \param[in,out] m module to add comparison operators to
|
||||
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
|
||||
template<typename T>
|
||||
ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
operators::equal<T>(m);
|
||||
operators::greater_than<T>(m);
|
||||
@@ -126,7 +90,7 @@ namespace chaiscript
|
||||
/// \sa copy_constructor
|
||||
/// \sa constructor
|
||||
template<typename T>
|
||||
ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(constructor<T ()>(), type);
|
||||
copy_constructor<T>(type, m);
|
||||
@@ -138,7 +102,7 @@ namespace chaiscript
|
||||
/// \param[in] type The name of the type
|
||||
/// \param[in,out] m The Module to add the constructor to
|
||||
template<typename T>
|
||||
ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::construct_pod<T>), type);
|
||||
return m;
|
||||
@@ -169,17 +133,13 @@ namespace chaiscript
|
||||
/// Add all common functions for a POD type. All operators, and
|
||||
/// common conversions
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<T>(), name);
|
||||
m->add(constructor<T()>(), name);
|
||||
m->add(constructor<T ()>(), name);
|
||||
construct_pod<T>(name, m);
|
||||
|
||||
auto to_s = fun(&to_string<T>);
|
||||
|
||||
if (!m->has_function(to_s, "to_string")) {
|
||||
m->add(to_s, "to_string");
|
||||
}
|
||||
m->add(fun(&to_string<T>), "to_string");
|
||||
m->add(fun(&parse_string<T>), "to_" + name);
|
||||
return m;
|
||||
}
|
||||
@@ -196,7 +156,9 @@ namespace chaiscript
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
/**
|
||||
* Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
*/
|
||||
template<typename Type>
|
||||
std::shared_ptr<typename std::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
|
||||
@@ -206,9 +168,11 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/// Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
/// object pointed to, instead maintains the shared_ptr concept.
|
||||
/// Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
/**
|
||||
* Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
* object pointed to, instead maintains the shared_ptr concept.
|
||||
* Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
*/
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
|
||||
{
|
||||
@@ -222,12 +186,16 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// Class consisting of only static functions. All default bootstrapping occurs
|
||||
/// from this class.
|
||||
/**
|
||||
* Class consisting of only static functions. All default bootstrapping occurs
|
||||
* from this class.
|
||||
*/
|
||||
class Bootstrap
|
||||
{
|
||||
private:
|
||||
/// Function allowing for assignment of an unknown type to any other value
|
||||
/**
|
||||
* Function allowing for assignment of an unknown type to any other value
|
||||
*/
|
||||
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
|
||||
{
|
||||
if (lhs.is_undef())
|
||||
@@ -240,17 +208,19 @@ namespace chaiscript
|
||||
|
||||
static void print(const std::string &s)
|
||||
{
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
std::cout << s;
|
||||
}
|
||||
|
||||
static void println(const std::string &s)
|
||||
{
|
||||
puts(s.c_str());
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/// Add all arithmetic operators for PODs
|
||||
static void opers_arithmetic_pod(ModulePtr m = std::make_shared<Module>())
|
||||
/**
|
||||
* Add all arithmetic operators for PODs
|
||||
*/
|
||||
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&Boxed_Number::equals), "==");
|
||||
m->add(fun(&Boxed_Number::less_than), "<");
|
||||
@@ -289,8 +259,11 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
/// Create a bound function object. The first param is the function to bind
|
||||
/// the remaining parameters are the args to bind into the result
|
||||
/**
|
||||
* Create a bound function object. The first param is the function to bind
|
||||
* the remaining parameters are the args to bind into the
|
||||
* result
|
||||
*/
|
||||
static Boxed_Value bind_function(const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
@@ -300,7 +273,7 @@ namespace chaiscript
|
||||
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
|
||||
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
|
||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
}
|
||||
|
||||
@@ -308,15 +281,29 @@ namespace chaiscript
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return pf && pf->get_guard();
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_guard()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf && pf->get_guard())
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return pf->get_guard();
|
||||
if (pf->get_guard())
|
||||
{
|
||||
return pf->get_guard();
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a guard");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a guard");
|
||||
}
|
||||
@@ -331,7 +318,9 @@ namespace chaiscript
|
||||
return e.what();
|
||||
}
|
||||
|
||||
/// Boolean specialization of internal to_string function
|
||||
/**
|
||||
* Boolean specialization of internal to_string function
|
||||
*/
|
||||
static std::string bool_to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
@@ -361,16 +350,33 @@ namespace chaiscript
|
||||
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return pf && pf->get_parse_tree();
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf && pf->get_parse_tree())
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return pf->get_parse_tree();
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
return pf->get_parse_tree();
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Function does not have a parse tree");
|
||||
}
|
||||
@@ -379,9 +385,7 @@ namespace chaiscript
|
||||
template<typename Function>
|
||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return [f](const dispatch::Proxy_Function_Base *b) {
|
||||
return do_return_boxed_value_vector(f, b);
|
||||
};
|
||||
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
|
||||
}
|
||||
|
||||
|
||||
@@ -389,14 +393,13 @@ namespace chaiscript
|
||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||
/// \param[in,out] m Module to add bootstrapped functions to
|
||||
/// \returns passed in ModulePtr, or newly created one if default argument is used
|
||||
static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
|
||||
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<void>(), "void");
|
||||
m->add(user_type<bool>(), "bool");
|
||||
m->add(user_type<Boxed_Value>(), "Object");
|
||||
m->add(user_type<Boxed_Number>(), "Number");
|
||||
m->add(user_type<Proxy_Function>(), "Function");
|
||||
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
||||
m->add(user_type<std::exception>(), "exception");
|
||||
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||
@@ -410,24 +413,16 @@ namespace chaiscript
|
||||
|
||||
m->add(user_type<std::runtime_error>(), "runtime_error");
|
||||
m->add(chaiscript::base_class<std::exception, std::runtime_error>());
|
||||
|
||||
|
||||
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
|
||||
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||
|
||||
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
||||
|
||||
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::method_missing)), "method_missing");
|
||||
|
||||
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_attr), "get_attr");
|
||||
|
||||
m->eval("def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
|
||||
|
||||
@@ -465,7 +460,7 @@ namespace chaiscript
|
||||
operators::assign<bool>(m);
|
||||
operators::equal<bool>(m);
|
||||
|
||||
m->add(fun<std::string (const std::string &t_ss)>([](const std::string &s) -> std::string { return s; }), "to_string");
|
||||
m->add(fun(&to_string<const std::string &>), "to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "to_string");
|
||||
m->add(fun(&unknown_assign), "=");
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
@@ -497,18 +492,11 @@ namespace chaiscript
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m->add(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Dynamic_Proxy_Function>(&bind_function), "bind");
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(&bind_function)), "bind");
|
||||
|
||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
|
||||
m->add(fun<void (dispatch::Assignable_Proxy_Function &, const std::shared_ptr<const dispatch::Proxy_Function_Base> &)>(
|
||||
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
||||
t_lhs.assign(t_rhs);
|
||||
}
|
||||
), "="
|
||||
);
|
||||
|
||||
m->add(fun(&Boxed_Value::type_match), "type_match");
|
||||
|
||||
@@ -516,11 +504,7 @@ namespace chaiscript
|
||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
||||
|
||||
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
||||
|
||||
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||
|
||||
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
/// \file
|
||||
@@ -14,8 +14,10 @@
|
||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
@@ -177,7 +179,7 @@ namespace chaiscript
|
||||
|
||||
/// Add Bidir_Range support for the given ContainerType
|
||||
template<typename Bidir_Type>
|
||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<Bidir_Type>(), type + "_Range");
|
||||
|
||||
@@ -226,11 +228,12 @@ namespace chaiscript
|
||||
|
||||
std::advance(itr, pos);
|
||||
container.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
|
||||
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
|
||||
@@ -241,10 +244,10 @@ namespace chaiscript
|
||||
/// Add random_access_container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
// cppcheck-suppress syntaxError
|
||||
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
|
||||
typedef typename ContainerType::const_reference(ContainerType::*constindexoper)(size_t) const;
|
||||
|
||||
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||
//to throw an exception in an out of bounds condition.
|
||||
@@ -252,10 +255,8 @@ namespace chaiscript
|
||||
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
|
||||
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||
m->add(
|
||||
fun<typename ContainerType::const_reference (const ContainerType *, int)>(
|
||||
[](const ContainerType *c, int index) -> typename ContainerType::const_reference {
|
||||
return c->at(index);
|
||||
}), "[]");
|
||||
fun(std::function<typename ContainerType::const_reference (const ContainerType *, int)>
|
||||
(std::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -264,9 +265,9 @@ namespace chaiscript
|
||||
/// Add assignable concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
copy_constructor<ContainerType>(type, m);
|
||||
basic_constructors<ContainerType>(type, m);
|
||||
operators::assign<ContainerType>(m);
|
||||
return m;
|
||||
}
|
||||
@@ -275,11 +276,11 @@ namespace chaiscript
|
||||
/// Add container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Container.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun<size_t (const ContainerType *)>([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m->add(fun<bool (const ContainerType *)>([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m->add(fun<void (ContainerType *)>([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
m->add(fun( std::function<size_t (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
|
||||
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
|
||||
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -287,7 +288,7 @@ namespace chaiscript
|
||||
/// Add default constructable concept to the given Type
|
||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
template<typename Type>
|
||||
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(constructor<Type ()>(), type);
|
||||
return m;
|
||||
@@ -299,17 +300,17 @@ namespace chaiscript
|
||||
/// Add sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::insert_at<ContainerType>),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref_at";
|
||||
} else {
|
||||
return "insert_at";
|
||||
}
|
||||
}());
|
||||
std::string insert_name;
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||
{
|
||||
insert_name = "insert_ref_at";
|
||||
} else {
|
||||
insert_name = "insert_at";
|
||||
}
|
||||
|
||||
m->add(fun(&detail::insert_at<ContainerType>), insert_name);
|
||||
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||
|
||||
return m;
|
||||
@@ -319,23 +320,22 @@ namespace chaiscript
|
||||
/// Add back insertion sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
|
||||
std::string push_back_name;
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||
{
|
||||
push_back_name = "push_back_ref";
|
||||
} else {
|
||||
push_back_name = "push_back";
|
||||
}
|
||||
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
return "push_back_ref";
|
||||
} else {
|
||||
return "push_back";
|
||||
}
|
||||
}());
|
||||
|
||||
m->add(fun(static_cast<push_back>(&ContainerType::push_back)), push_back_name);
|
||||
m->add(fun(&ContainerType::pop_back), "pop_back");
|
||||
return m;
|
||||
}
|
||||
@@ -345,26 +345,26 @@ namespace chaiscript
|
||||
/// Front insertion sequence
|
||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
||||
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*pop_ptr)();
|
||||
typedef typename ContainerType::reference (ContainerType::*frontptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*constfrontptr)() const;
|
||||
typedef void (ContainerType::*pushptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*popptr)();
|
||||
|
||||
m->add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<constfrontptr>(&ContainerType::front)), "front");
|
||||
|
||||
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
return "push_front_ref";
|
||||
} else {
|
||||
return "push_front";
|
||||
}
|
||||
}());
|
||||
std::string push_front_name;
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||
{
|
||||
push_front_name = "push_front_ref";
|
||||
} else {
|
||||
push_front_name = "push_front";
|
||||
}
|
||||
|
||||
m->add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
|
||||
m->add(fun(static_cast<pushptr>(&ContainerType::push_front)), push_front_name);
|
||||
m->add(fun(static_cast<popptr>(&ContainerType::pop_front)), "pop_front");
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace chaiscript
|
||||
/// bootstrap a given PairType
|
||||
/// http://www.sgi.com/tech/stl/pair.html
|
||||
template<typename PairType>
|
||||
ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<PairType>(), type);
|
||||
|
||||
@@ -395,7 +395,7 @@ namespace chaiscript
|
||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||
|
||||
template<typename ContainerType>
|
||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||
|
||||
@@ -406,7 +406,7 @@ namespace chaiscript
|
||||
/// Add unique associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(detail::count<ContainerType>), "count");
|
||||
|
||||
@@ -416,16 +416,15 @@ namespace chaiscript
|
||||
|
||||
m->add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
m->add(fun(&detail::insert_ref<ContainerType>),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref";
|
||||
} else {
|
||||
return "insert";
|
||||
}
|
||||
}());
|
||||
|
||||
std::string insert_name;
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value))
|
||||
{
|
||||
insert_name = "insert_ref";
|
||||
} else {
|
||||
insert_name = "insert";
|
||||
}
|
||||
|
||||
m->add(fun(&detail::insert_ref<ContainerType>), insert_name);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -433,16 +432,15 @@ namespace chaiscript
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename MapType>
|
||||
ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<MapType>(), type);
|
||||
|
||||
typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
|
||||
typedef typename MapType::mapped_type &(MapType::*elemaccess)(const typename MapType::key_type &);
|
||||
|
||||
m->add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||
m->add(fun(static_cast<elemaccess>(&MapType::operator[])), "[]");
|
||||
|
||||
container_type<MapType>(type, m);
|
||||
default_constructible_type<MapType>(type, m);
|
||||
assignable_type<MapType>(type, m);
|
||||
unique_associative_container_type<MapType>(type, m);
|
||||
pair_associative_container_type<MapType>(type, m);
|
||||
@@ -455,7 +453,7 @@ namespace chaiscript
|
||||
/// hopefully working List type
|
||||
/// http://www.sgi.com/tech/stl/List.html
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<ListType>(), type);
|
||||
|
||||
@@ -474,7 +472,7 @@ namespace chaiscript
|
||||
/// Create a vector type with associated concepts
|
||||
/// http://www.sgi.com/tech/stl/Vector.html
|
||||
template<typename VectorType>
|
||||
ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<VectorType>(), type);
|
||||
|
||||
@@ -495,26 +493,24 @@ namespace chaiscript
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
m->eval(R"(
|
||||
def Vector::`==`(rhs) : type_match(rhs, this) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
} else {
|
||||
auto r1 = range(this);
|
||||
auto r2 = range(rhs);
|
||||
while (!r1.empty())
|
||||
{
|
||||
if (!eq(r1.front(), r2.front()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
r1.pop_front();
|
||||
r2.pop_front();
|
||||
}
|
||||
true;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
m->eval("def Vector::`==`(rhs) : type_match(rhs, this) { \
|
||||
if ( rhs.size() != this.size() ) { \
|
||||
return false; \
|
||||
} else { \
|
||||
auto r1 = range(this); \
|
||||
auto r2 = range(rhs); \
|
||||
while (!r1.empty()) \
|
||||
{ \
|
||||
if (!eq(r1.front(), r2.front())) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
r1.pop_front(); \
|
||||
r2.pop_front(); \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
}");
|
||||
}
|
||||
|
||||
return m;
|
||||
@@ -523,7 +519,7 @@ namespace chaiscript
|
||||
/// Add a String container
|
||||
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||
template<typename String>
|
||||
ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<String>(), type);
|
||||
operators::addition<String>(m);
|
||||
@@ -537,15 +533,14 @@ namespace chaiscript
|
||||
input_range_type<String>(type, m);
|
||||
|
||||
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||
m->add(fun(&String::push_back),
|
||||
[]()->std::string{
|
||||
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
||||
return "push_back_ref";
|
||||
} else {
|
||||
return "push_back";
|
||||
}
|
||||
}());
|
||||
|
||||
std::string push_back_name;
|
||||
if (typeid(typename String::value_type) == typeid(Boxed_Value))
|
||||
{
|
||||
push_back_name = "push_back_ref";
|
||||
} else {
|
||||
push_back_name = "push_back";
|
||||
}
|
||||
m->add(fun(&String::push_back), push_back_name);
|
||||
|
||||
typedef std::function<size_t (const String *, const String &, size_t)> find_func;
|
||||
|
||||
@@ -567,22 +562,6 @@ namespace chaiscript
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename FutureType>
|
||||
ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m->add(user_type<FutureType>(), type);
|
||||
|
||||
m->add(fun<bool (const FutureType &)>([](const FutureType &t) { return t.valid(); }), "valid");
|
||||
m->add(fun(&FutureType::get), "get");
|
||||
m->add(fun(&FutureType::wait), "wait");
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace detail {
|
||||
namespace exception {
|
||||
class bad_any_cast;
|
||||
@@ -69,49 +72,48 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions = nullptr)
|
||||
{
|
||||
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !t_conversions->convertable_type<Type>())) {
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
//Thank you MSVC, yes we know that a constant value is being used in the if
|
||||
// statment in THIS VERSION of the template instantiation
|
||||
//Thank you MSVC, yes we know that a constant value is being used in the if
|
||||
// statment in THIS VERSION of the template instantiation
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
||||
{
|
||||
try {
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
|
||||
} catch (...) {
|
||||
if (std::is_polymorphic<typename detail::Bare_Type<Type>::type>::value && t_conversions)
|
||||
{
|
||||
try {
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
|
||||
// try going the other way - down the inheritance graph
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << std::endl;
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
|
||||
} catch (...) {
|
||||
try {
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << std::endl;
|
||||
// try going the other way - down the inheritance graph
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_down_cast<Type>(bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it's not polymorphic, just throw the error, don't waste the time on the
|
||||
// attempted dynamic_cast
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
} else {
|
||||
// If it's not polymorphic, just throw the error, don't waste the time on the
|
||||
// attempted dynamic_cast
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -16,7 +17,7 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -33,14 +34,13 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
auto p = throw_if_null(ob.get_const_ptr());
|
||||
return std::cref(*static_cast<const Result *>(p));
|
||||
return *(static_cast<const Result *>(throw_if_null(ob.get_const_ptr())));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
@@ -63,13 +63,23 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
if (ob.is_ref())
|
||||
{
|
||||
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
|
||||
} else {
|
||||
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return (ob.get().cast<std::shared_ptr<Result> >()).get();
|
||||
} else {
|
||||
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -79,7 +89,7 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -91,14 +101,13 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@@ -111,11 +120,11 @@ namespace chaiscript
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
|
||||
{
|
||||
typedef std::shared_ptr<Result> Result_Type;
|
||||
typedef typename std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
@@ -123,11 +132,11 @@ namespace chaiscript
|
||||
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
|
||||
{
|
||||
typedef std::shared_ptr<const Result> Result_Type;
|
||||
typedef typename std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@@ -169,7 +178,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef const Boxed_Value & Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
@@ -181,7 +190,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_Value& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return const_cast<Boxed_Value &>(ob);
|
||||
}
|
||||
@@ -237,7 +246,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||
@@ -19,22 +19,9 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
struct arithmetic_error : std::runtime_error
|
||||
{
|
||||
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
|
||||
arithmetic_error(const arithmetic_error &) = default;
|
||||
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
@@ -46,37 +33,16 @@ namespace chaiscript
|
||||
#pragma warning(disable : 4244 4018 4389 4146 4365)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
class Boxed_Number
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
|
||||
if (t == 0) {
|
||||
throw chaiscript::exception::arithmetic_error("divide by zero");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void check_divide_by_zero(T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
struct boolean
|
||||
{
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
|
||||
{
|
||||
@@ -95,7 +61,7 @@ namespace chaiscript
|
||||
case Operators::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -123,14 +89,13 @@ namespace chaiscript
|
||||
t += u;
|
||||
break;
|
||||
case Operators::assign_quotient:
|
||||
check_divide_by_zero(u);
|
||||
t /= u;
|
||||
break;
|
||||
case Operators::assign_difference:
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
return t_lhs;
|
||||
@@ -157,14 +122,13 @@ namespace chaiscript
|
||||
t >>= u;
|
||||
break;
|
||||
case Operators::assign_remainder:
|
||||
check_divide_by_zero(u);
|
||||
t %= u;
|
||||
break;
|
||||
case Operators::assign_bitwise_xor:
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return t_lhs;
|
||||
}
|
||||
@@ -182,7 +146,6 @@ namespace chaiscript
|
||||
case Operators::shift_right:
|
||||
return const_var(t >> u);
|
||||
case Operators::remainder:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t % u);
|
||||
case Operators::bitwise_and:
|
||||
return const_var(t & u);
|
||||
@@ -193,7 +156,7 @@ namespace chaiscript
|
||||
case Operators::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -208,7 +171,6 @@ namespace chaiscript
|
||||
case Operators::sum:
|
||||
return const_var(t + u);
|
||||
case Operators::quotient:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t / u);
|
||||
case Operators::product:
|
||||
return const_var(t * u);
|
||||
@@ -219,7 +181,7 @@ namespace chaiscript
|
||||
case Operators::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -232,9 +194,9 @@ namespace chaiscript
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
{
|
||||
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
|
||||
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const()) {
|
||||
return binary_int::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
return const_binary_int::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
@@ -254,7 +216,7 @@ namespace chaiscript
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
{
|
||||
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
|
||||
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -365,6 +327,7 @@ namespace chaiscript
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
Boxed_Number()
|
||||
: bv(Boxed_Value(0))
|
||||
@@ -377,13 +340,6 @@ namespace chaiscript
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
Boxed_Number(const Boxed_Number &) = default;
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Boxed_Number(Boxed_Number &&) = default;
|
||||
Boxed_Number& operator=(Boxed_Number &&) = default;
|
||||
#endif
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
: bv(Boxed_Value(t))
|
||||
{
|
||||
@@ -591,7 +547,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress operatorEq
|
||||
Boxed_Number operator=(const Boxed_Value &v)
|
||||
{
|
||||
validate_boxed_number(v);
|
||||
@@ -599,7 +554,6 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
// cppcheck-suppress operatorEq
|
||||
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::assign, this->bv, t_rhs.bv);
|
||||
@@ -872,35 +826,37 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_Number>
|
||||
{
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
};
|
||||
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
#define CHAISCRIPT_BOXED_VALUE_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "any.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
@@ -36,10 +37,9 @@ namespace chaiscript
|
||||
Data(const Type_Info &ti,
|
||||
chaiscript::detail::Any to,
|
||||
bool tr,
|
||||
const void *t_void_ptr,
|
||||
bool t_return_value)
|
||||
const void *t_void_ptr)
|
||||
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
m_is_ref(tr), m_return_value(t_return_value)
|
||||
m_is_ref(tr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,11 +50,10 @@ namespace chaiscript
|
||||
m_is_ref = rhs.m_is_ref;
|
||||
m_data_ptr = rhs.m_data_ptr;
|
||||
m_const_data_ptr = rhs.m_const_data_ptr;
|
||||
m_return_value = rhs.m_return_value;
|
||||
|
||||
if (rhs.m_attrs)
|
||||
{
|
||||
m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*rhs.m_attrs));
|
||||
m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*rhs.m_attrs));
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -67,108 +66,128 @@ namespace chaiscript
|
||||
Data &operator=(Data &&rhs) = default;
|
||||
#endif
|
||||
|
||||
|
||||
Type_Info m_type_info;
|
||||
chaiscript::detail::Any m_obj;
|
||||
void *m_data_ptr;
|
||||
const void *m_const_data_ptr;
|
||||
std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>> m_attrs;
|
||||
bool m_is_ref;
|
||||
bool m_return_value;
|
||||
std::unique_ptr<std::map<std::string, Boxed_Value>> m_attrs;
|
||||
};
|
||||
|
||||
struct Object_Data
|
||||
{
|
||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool, bool)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<void>::get(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
nullptr,
|
||||
t_return_value)
|
||||
nullptr)
|
||||
;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool, bool)
|
||||
{
|
||||
return get(*obj, t_return_value);
|
||||
return get(*obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool, bool)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(obj),
|
||||
false,
|
||||
obj.get(),
|
||||
t_return_value
|
||||
obj.get()
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool, bool)
|
||||
{
|
||||
auto ptr = obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
false,
|
||||
ptr,
|
||||
t_return_value
|
||||
ptr
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(T *t, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(T *t)
|
||||
{
|
||||
return get(std::ref(*t), t_return_value);
|
||||
return get(std::ref(*t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
|
||||
{
|
||||
return get(std::cref(*t), t_return_value);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool, bool)
|
||||
{
|
||||
auto p = &obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
true,
|
||||
p,
|
||||
t_return_value
|
||||
p
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(T t, bool t_return_value)
|
||||
static std::shared_ptr<Data> get(T t, bool t_value_type, bool t_make_const)
|
||||
{
|
||||
auto p = std::make_shared<T>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr,
|
||||
t_return_value
|
||||
);
|
||||
typedef typename std::add_const<T>::type const_type;
|
||||
if (t_make_const)
|
||||
{
|
||||
if (t_value_type)
|
||||
{
|
||||
chaiscript::detail::Any a(std::move(t));
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<const_type>::get(),
|
||||
std::move(a),
|
||||
false,
|
||||
nullptr
|
||||
);
|
||||
} else {
|
||||
auto p = std::make_shared<const_type>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<const_type>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (t_value_type)
|
||||
{
|
||||
chaiscript::detail::Any a(std::move(t));
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
std::move(a),
|
||||
false,
|
||||
nullptr
|
||||
);
|
||||
} else {
|
||||
auto p = std::make_shared<T>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<Data> get()
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
Type_Info(),
|
||||
Type_Info(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
nullptr,
|
||||
false
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -178,9 +197,10 @@ namespace chaiscript
|
||||
/// Basic Boxed_Value constructor
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
|
||||
explicit Boxed_Value(T &&t, bool t_return_value = false)
|
||||
: m_data(Object_Data::get(std::forward<T>(t), t_return_value))
|
||||
explicit Boxed_Value(T &&t, bool t_make_const=false, bool t_value_type = std::is_trivial<typename std::decay<T>::type>::value)
|
||||
: m_data(Object_Data::get(std::forward<T>(t), t_make_const, t_value_type))
|
||||
{
|
||||
//std::cout << "typeid: " << typeid(T).name() << " is trivial " << std::is_trivial<typename std::decay<T>::type>::value << "\n";
|
||||
}
|
||||
|
||||
/// Unknown-type constructor
|
||||
@@ -246,16 +266,6 @@ namespace chaiscript
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
|
||||
bool is_return_value() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_return_value;
|
||||
}
|
||||
|
||||
void reset_return_value() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
m_data->m_return_value = false;
|
||||
}
|
||||
|
||||
bool is_pointer() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return !is_ref();
|
||||
@@ -263,36 +273,39 @@ namespace chaiscript
|
||||
|
||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
if (m_data->m_data_ptr)
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
} else {
|
||||
return m_data->m_obj.data();
|
||||
}
|
||||
}
|
||||
|
||||
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
if (m_data->m_const_data_ptr)
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
} else {
|
||||
return m_data->m_obj.data();
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value get_attr(const std::string &t_name)
|
||||
{
|
||||
if (!m_data->m_attrs)
|
||||
{
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>());
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>());
|
||||
}
|
||||
|
||||
auto &attr = (*m_data->m_attrs)[t_name];
|
||||
if (attr) {
|
||||
return Boxed_Value(attr, Internal_Construction());
|
||||
} else {
|
||||
Boxed_Value bv; //default construct a new one
|
||||
attr = bv.m_data;
|
||||
return bv;
|
||||
}
|
||||
return (*m_data->m_attrs)[t_name];
|
||||
}
|
||||
|
||||
Boxed_Value ©_attrs(const Boxed_Value &t_obj)
|
||||
{
|
||||
if (t_obj.m_data->m_attrs)
|
||||
{
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, std::shared_ptr<Data>>>(new std::map<std::string, std::shared_ptr<Data>>(*t_obj.m_data->m_attrs));
|
||||
m_data->m_attrs = std::unique_ptr<std::map<std::string, Boxed_Value>>(new std::map<std::string, Boxed_Value>(*t_obj.m_data->m_attrs));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -305,13 +318,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
// necessary to avoid hitting the templated && constructor of Boxed_Value
|
||||
struct Internal_Construction{};
|
||||
|
||||
Boxed_Value(const std::shared_ptr<Data> &t_data, Internal_Construction)
|
||||
: m_data(t_data) {
|
||||
}
|
||||
|
||||
std::shared_ptr<Data> m_data;
|
||||
};
|
||||
|
||||
@@ -343,7 +349,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t), true);
|
||||
}
|
||||
|
||||
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
@@ -409,18 +415,7 @@ namespace chaiscript
|
||||
return detail::const_var_impl(t);
|
||||
}
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
|
||||
inline Boxed_Value const_var(bool b) {
|
||||
static auto t = detail::const_var_impl(true);
|
||||
static auto f = detail::const_var_impl(false);
|
||||
|
||||
if (b) {
|
||||
return t;
|
||||
} else {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
|
||||
#define CHAISCRIPT_DISPATCHKIT_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -25,7 +27,7 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
@@ -60,8 +62,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
reserved_word_error(const reserved_word_error &) = default;
|
||||
|
||||
virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::string word() const
|
||||
@@ -82,8 +82,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
illegal_name_error(const illegal_name_error &) = default;
|
||||
|
||||
virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::string name() const
|
||||
@@ -105,8 +103,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
name_conflict_error(const name_conflict_error &) = default;
|
||||
|
||||
virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::string name() const
|
||||
@@ -129,7 +125,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
global_non_const(const global_non_const &) = default;
|
||||
virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
@@ -146,7 +141,7 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(Type_Conversion d)
|
||||
Module &add(Dynamic_Cast_Conversion d)
|
||||
{
|
||||
m_conversions.push_back(std::move(d));
|
||||
return *this;
|
||||
@@ -162,7 +157,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!t_bv.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
// throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
m_globals.emplace_back(std::move(t_bv), std::move(t_name));
|
||||
@@ -171,9 +166,9 @@ namespace chaiscript
|
||||
|
||||
|
||||
//Add a bit of ChaiScript to eval during module implementation
|
||||
Module &eval(const std::string &str)
|
||||
Module &eval(std::string str)
|
||||
{
|
||||
m_evals.push_back(str);
|
||||
m_evals.push_back(std::move(str));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -197,20 +192,12 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bool has_function(const Proxy_Function &new_f, const std::string &name)
|
||||
{
|
||||
return std::any_of(m_funcs.begin(), m_funcs.end(), [&](const std::pair<Proxy_Function, std::string> &existing_f) {
|
||||
return existing_f.second == name && *(existing_f.first) == *(new_f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||
std::vector<std::pair<Boxed_Value, std::string> > m_globals;
|
||||
std::vector<std::string> m_evals;
|
||||
std::vector<Type_Conversion> m_conversions;
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
static void apply(InItr begin, const InItr end, T &t)
|
||||
@@ -270,7 +257,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
||||
m_funcs(std::move(t_funcs))
|
||||
{
|
||||
}
|
||||
@@ -278,8 +265,8 @@ namespace chaiscript
|
||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
try {
|
||||
const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
return m_funcs == dispatch_fun.m_funcs;
|
||||
const Dispatch_Function &dispatchfun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
return m_funcs == dispatchfun.m_funcs;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
}
|
||||
@@ -293,15 +280,15 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static int calculate_arity(const std::vector<Proxy_Function> &t_funcs)
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (t_funcs.empty()) {
|
||||
if (m_funcs.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto arity = t_funcs.front()->get_arity();
|
||||
const int arity = m_funcs.front()->get_arity();
|
||||
|
||||
for (const auto &func : t_funcs)
|
||||
for (const auto &func : m_funcs)
|
||||
{
|
||||
if (arity != func->get_arity())
|
||||
{
|
||||
@@ -313,10 +300,17 @@ namespace chaiscript
|
||||
return arity;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
|
||||
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
||||
for (const auto &func : m_funcs)
|
||||
{
|
||||
if (func->call_match(vals, t_conversions))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
@@ -325,9 +319,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dispatch::dispatch(m_funcs, params, t_conversions);
|
||||
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -335,8 +329,10 @@ namespace chaiscript
|
||||
|
||||
static std::vector<Type_Info> build_type_infos(const std::vector<Proxy_Function> &t_funcs)
|
||||
{
|
||||
auto begin = t_funcs.cbegin();
|
||||
const auto &end = t_funcs.cend();
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
auto begin = t_funcs.begin();
|
||||
const function_vec::const_iterator end = t_funcs.end();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
@@ -384,8 +380,10 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Main class for the dispatchkit. Handles management
|
||||
/// of the object stack, functions and registered types.
|
||||
/**
|
||||
* Main class for the dispatchkit. Handles management
|
||||
* of the object stack, functions and registered types.
|
||||
*/
|
||||
class Dispatch_Engine
|
||||
{
|
||||
public:
|
||||
@@ -402,8 +400,6 @@ namespace chaiscript
|
||||
std::set<std::string> m_reserved_words;
|
||||
|
||||
State &operator=(const State &) = default;
|
||||
State() = default;
|
||||
State(const State &) = default;
|
||||
};
|
||||
|
||||
Dispatch_Engine()
|
||||
@@ -424,7 +420,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Add a new conversion for upcasting to a base class
|
||||
void add(const Type_Conversion &d)
|
||||
void add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_conversions.add_conversion(d);
|
||||
}
|
||||
@@ -441,12 +437,12 @@ namespace chaiscript
|
||||
void add(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
auto &stack = get_stack_data();
|
||||
StackData &stack = get_stack_data();
|
||||
|
||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
|
||||
{
|
||||
auto itr = stack_elem->find(name);
|
||||
if (itr != stack_elem->end())
|
||||
const auto itr = stack[i].find(name);
|
||||
if (itr != stack[i].end())
|
||||
{
|
||||
itr->second = std::move(obj);
|
||||
return;
|
||||
@@ -458,13 +454,17 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Adds a named object to the current scope
|
||||
/// \warning This version does not check the validity of the name
|
||||
/// it is meant for internal use only
|
||||
void add_object(const std::string &name, const Boxed_Value &obj)
|
||||
void add_object(const std::string &name, const Boxed_Value &obj) const
|
||||
{
|
||||
if (!get_stack_data().back().insert(std::make_pair(name, obj)).second)
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
|
||||
const Scope &scope = stack.back();
|
||||
if (scope.find(name) != scope.end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
stack.back().insert(std::make_pair(name, std::move(obj)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ namespace chaiscript
|
||||
validate_object_name(name);
|
||||
if (!obj.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
// throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
@@ -487,23 +487,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a new global (non-const) shared object, between all the threads
|
||||
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
const auto itr = m_state.m_global_objects.find(name);
|
||||
if (itr == m_state.m_global_objects.end())
|
||||
{
|
||||
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||
return obj;
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds a new global (non-const) shared object, between all the threads
|
||||
void add_global(const Boxed_Value &obj, const std::string &name)
|
||||
@@ -525,13 +508,11 @@ namespace chaiscript
|
||||
void new_scope()
|
||||
{
|
||||
get_stack_data().emplace_back();
|
||||
m_stack_holder->call_params.emplace_back();
|
||||
}
|
||||
|
||||
/// Pops the current scope from the stack
|
||||
void pop_scope()
|
||||
{
|
||||
m_stack_holder->call_params.pop_back();
|
||||
StackData &stack = get_stack_data();
|
||||
if (stack.size() > 1)
|
||||
{
|
||||
@@ -565,13 +546,13 @@ namespace chaiscript
|
||||
return m_place_holder;
|
||||
}
|
||||
|
||||
auto &stack = get_stack_data();
|
||||
StackData &stack = get_stack_data();
|
||||
|
||||
// Is it in the stack?
|
||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
|
||||
{
|
||||
const auto stackitr = stack_elem->find(name);
|
||||
if (stackitr != stack_elem->end())
|
||||
const auto stackitr = stack[i].find(name);
|
||||
if (stackitr != stack[i].end())
|
||||
{
|
||||
return stackitr->second;
|
||||
}
|
||||
@@ -603,7 +584,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Returns the type info for a named type
|
||||
Type_Info get_type(const std::string &name, bool t_throw = true) const
|
||||
Type_Info get_type(const std::string &name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@@ -614,11 +595,7 @@ namespace chaiscript
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
if (t_throw) {
|
||||
throw std::range_error("Type Not Known");
|
||||
} else {
|
||||
return Type_Info();
|
||||
}
|
||||
throw std::range_error("Type Not Known");
|
||||
}
|
||||
|
||||
/// Returns the registered name of a known type_info object
|
||||
@@ -668,7 +645,6 @@ namespace chaiscript
|
||||
/// \throws std::range_error if it does not
|
||||
Boxed_Value get_function_object(const std::string &t_name) const
|
||||
{
|
||||
// std::cout << "Getting function object: " << t_name << '\n';
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto &funs = get_function_objects_int();
|
||||
@@ -696,7 +672,7 @@ namespace chaiscript
|
||||
/// the current scope.
|
||||
std::map<std::string, Boxed_Value> get_parent_locals() const
|
||||
{
|
||||
auto &stack = get_stack_data();
|
||||
StackData &stack = get_stack_data();
|
||||
if (stack.size() > 1)
|
||||
{
|
||||
return stack[1];
|
||||
@@ -708,8 +684,8 @@ namespace chaiscript
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
auto &stack = get_stack_data();
|
||||
auto &scope = stack.front();
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
return scope;
|
||||
}
|
||||
|
||||
@@ -720,8 +696,8 @@ namespace chaiscript
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
auto &stack = get_stack_data();
|
||||
auto &scope = stack.front();
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
scope = t_locals;
|
||||
}
|
||||
|
||||
@@ -732,10 +708,10 @@ namespace chaiscript
|
||||
///
|
||||
std::map<std::string, Boxed_Value> get_scripting_objects() const
|
||||
{
|
||||
const Stack_Holder &s = *m_stack_holder;
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
|
||||
// We don't want the current context, but one up if it exists
|
||||
const StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]);
|
||||
StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]);
|
||||
|
||||
std::map<std::string, Boxed_Value> retval;
|
||||
|
||||
@@ -803,125 +779,16 @@ namespace chaiscript
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
const Type_Conversions &conversions() const
|
||||
const Dynamic_Cast_Conversions &conversions() const
|
||||
{
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
|
||||
bool t_has_params) const
|
||||
{
|
||||
if (!t_has_params || t_params.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto &fun : t_funs) {
|
||||
if (fun->is_attribute_function()) {
|
||||
if (fun->compare_first_type(t_params[0], m_conversions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// MSVC is unable to recognize that "rethrow_exception" causes the function to return
|
||||
// so we must disable it here.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4715)
|
||||
#endif
|
||||
Boxed_Value call_member(const std::string &t_name, const std::vector<Boxed_Value> ¶ms, bool t_has_params) const
|
||||
{
|
||||
const auto funs = get_function(t_name);
|
||||
|
||||
const auto do_attribute_call =
|
||||
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value
|
||||
{
|
||||
std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
|
||||
std::vector<Boxed_Value> remaining_params{l_params.begin() + l_num_params, l_params.end()};
|
||||
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
|
||||
if (!remaining_params.empty() || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
|
||||
return (*boxed_cast<const dispatch::Proxy_Function_Base *>(bv))(remaining_params, l_conversions);
|
||||
} else {
|
||||
return bv;
|
||||
}
|
||||
};
|
||||
|
||||
if (is_attribute_call(funs, params, t_has_params)) {
|
||||
return do_attribute_call(1, params, funs, m_conversions);
|
||||
} else {
|
||||
std::exception_ptr except;
|
||||
|
||||
if (!funs.empty()) {
|
||||
try {
|
||||
return dispatch::dispatch(funs, params, m_conversions);
|
||||
} catch(chaiscript::exception::dispatch_error&) {
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here we know that either there was no method with that name,
|
||||
// or there was no matching method
|
||||
|
||||
const auto functions = [&]()->std::vector<Proxy_Function> {
|
||||
std::vector<Proxy_Function> fs;
|
||||
|
||||
for (const auto &f : get_function("method_missing"))
|
||||
{
|
||||
if(f->compare_first_type(params[0], m_conversions)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
}
|
||||
|
||||
return fs;
|
||||
}();
|
||||
|
||||
|
||||
|
||||
const bool is_no_param = [&]()->bool{
|
||||
for (const auto &f : functions) {
|
||||
if (f->get_arity() != 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
|
||||
if (!functions.empty()) {
|
||||
if (is_no_param) {
|
||||
std::vector<Boxed_Value> tmp_params(params);
|
||||
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
||||
return do_attribute_call(2, tmp_params, functions, m_conversions);
|
||||
} else {
|
||||
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
|
||||
}
|
||||
}
|
||||
|
||||
// If we get all the way down here we know there was no "method_missing"
|
||||
// method at all.
|
||||
if (except) {
|
||||
std::rethrow_exception(except);
|
||||
} else {
|
||||
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.begin(), funs.end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
Boxed_Value bv = dispatch::dispatch(get_function(t_name), params, m_conversions);
|
||||
// the result of a clone is never to be marked as a return_value
|
||||
if (t_name == "clone") {
|
||||
bv.reset_return_value();
|
||||
}
|
||||
return bv;
|
||||
std::vector<Proxy_Function> functions = get_function(t_name);
|
||||
|
||||
return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name) const
|
||||
@@ -942,7 +809,7 @@ namespace chaiscript
|
||||
/// Dump object info to stdout
|
||||
void dump_object(const Boxed_Value &o) const
|
||||
{
|
||||
std::cout << (o.is_const()?"const ":"") << type_name(o) << '\n';
|
||||
std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl;
|
||||
}
|
||||
|
||||
/// Dump type info to stdout
|
||||
@@ -976,14 +843,14 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << ") \n";
|
||||
std::cout << ") " << std::endl;
|
||||
}
|
||||
|
||||
/// Returns true if a call can be made that consists of the first parameter
|
||||
/// (the function) with the remaining parameters as its arguments.
|
||||
Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.empty())
|
||||
if (params.size() < 1)
|
||||
{
|
||||
throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
@@ -996,7 +863,7 @@ namespace chaiscript
|
||||
/// Dump all system info to stdout
|
||||
void dump_system() const
|
||||
{
|
||||
std::cout << "Registered Types: \n";
|
||||
std::cout << "Registered Types: " << std::endl;
|
||||
std::vector<std::pair<std::string, Type_Info> > types = get_types();
|
||||
for (std::vector<std::pair<std::string, Type_Info> >::const_iterator itr = types.begin();
|
||||
itr != types.end();
|
||||
@@ -1004,20 +871,20 @@ namespace chaiscript
|
||||
{
|
||||
std::cout << itr->first << ": ";
|
||||
std::cout << itr->second.bare_name();
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
std::vector<std::pair<std::string, Proxy_Function > > funcs = get_functions();
|
||||
|
||||
std::cout << "Functions: \n";
|
||||
std::cout << "Functions: " << std::endl;
|
||||
for (std::vector<std::pair<std::string, Proxy_Function > >::const_iterator itr = funcs.begin();
|
||||
itr != funcs.end();
|
||||
++itr)
|
||||
{
|
||||
dump_function(*itr);
|
||||
}
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/// return true if the Boxed_Value matches the registered type by name
|
||||
@@ -1061,39 +928,15 @@ namespace chaiscript
|
||||
m_state = t_state;
|
||||
}
|
||||
|
||||
void save_function_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
s.call_params.back().insert(s.call_params.back().begin(), std::move(t_params));
|
||||
}
|
||||
|
||||
void save_function_params(std::vector<Boxed_Value> &&t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
|
||||
for (auto &¶m : t_params)
|
||||
{
|
||||
s.call_params.back().insert(s.call_params.back().begin(), std::move(param));
|
||||
}
|
||||
}
|
||||
|
||||
void save_function_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
s.call_params.back().insert(s.call_params.back().begin(), t_params.begin(), t_params.end());
|
||||
s.call_params.insert(s.call_params.begin(), t_params.begin(), t_params.end());
|
||||
}
|
||||
|
||||
void new_function_call()
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
if (s.call_depth == 0)
|
||||
{
|
||||
m_conversions.enable_conversion_saves(true);
|
||||
}
|
||||
|
||||
++s.call_depth;
|
||||
|
||||
save_function_params(m_conversions.take_saves());
|
||||
++m_stack_holder->call_depth;
|
||||
}
|
||||
|
||||
void pop_function_call()
|
||||
@@ -1105,20 +948,16 @@ namespace chaiscript
|
||||
|
||||
if (s.call_depth == 0)
|
||||
{
|
||||
s.call_params.back().clear();
|
||||
m_conversions.enable_conversion_saves(false);
|
||||
/// \todo Critical: this needs to be smarter, memory can expand quickly
|
||||
/// in tight loops involving function calls
|
||||
s.call_params.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// Returns the current stack
|
||||
/// make const/non const versions
|
||||
const StackData &get_stack_data() const
|
||||
{
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
StackData &get_stack_data()
|
||||
StackData &get_stack_data() const
|
||||
{
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
@@ -1145,15 +984,28 @@ namespace chaiscript
|
||||
|
||||
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
|
||||
{
|
||||
const std::vector<Type_Info> &lhsparamtypes = lhs->get_param_types();
|
||||
const std::vector<Type_Info> &rhsparamtypes = rhs->get_param_types();
|
||||
|
||||
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
const size_t lhssize = lhsparamtypes.size();
|
||||
const size_t rhssize = rhsparamtypes.size();
|
||||
|
||||
const Type_Info boxed_type = user_type<Boxed_Value>();
|
||||
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
|
||||
if (dynamic_lhs && dynamic_rhs)
|
||||
{
|
||||
if (dynamic_lhs->get_guard())
|
||||
{
|
||||
return dynamic_rhs->get_guard() ? false : true;
|
||||
if (dynamic_rhs->get_guard())
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1169,14 +1021,6 @@ namespace chaiscript
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto &lhsparamtypes = lhs->get_param_types();
|
||||
const auto &rhsparamtypes = rhs->get_param_types();
|
||||
|
||||
const auto lhssize = lhsparamtypes.size();
|
||||
const auto rhssize = rhsparamtypes.size();
|
||||
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_type = user_type<Boxed_Value>();
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
|
||||
{
|
||||
@@ -1297,16 +1141,15 @@ namespace chaiscript
|
||||
: call_depth(0)
|
||||
{
|
||||
stacks.emplace_back(1);
|
||||
call_params.emplace_back();
|
||||
}
|
||||
|
||||
std::deque<StackData> stacks;
|
||||
|
||||
std::deque<std::list<Boxed_Value>> call_params;
|
||||
std::list<Boxed_Value> call_params;
|
||||
int call_depth;
|
||||
};
|
||||
|
||||
Type_Conversions m_conversions;
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
|
||||
|
||||
294
include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
Normal file
294
include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
Normal file
@@ -0,0 +1,294 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0;
|
||||
|
||||
const Type_Info &base() const
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
const Type_Info &derived() const
|
||||
{
|
||||
return m_derived;
|
||||
}
|
||||
|
||||
protected:
|
||||
Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived)
|
||||
: m_base(t_base), m_derived(t_derived)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Conversion() {}
|
||||
|
||||
private:
|
||||
Type_Info m_base;
|
||||
Type_Info m_derived;
|
||||
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
if (t_from.get_type_info().bare_equal(user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
std::shared_ptr<const To> data
|
||||
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<To> data
|
||||
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = dynamic_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
|
||||
To &data = dynamic_cast<To &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Dynamic_Cast_Conversions
|
||||
{
|
||||
public:
|
||||
Dynamic_Cast_Conversions()
|
||||
{
|
||||
}
|
||||
|
||||
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
|
||||
: m_conversions(t_other.get_conversions())
|
||||
{
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Dynamic_Conversion> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
m_conversions.insert(conversion);
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
bool dynamic_cast_converts() const
|
||||
{
|
||||
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
|
||||
}
|
||||
|
||||
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
return has_conversion(base, derived) || has_conversion(derived, base);
|
||||
}
|
||||
|
||||
template<typename Base>
|
||||
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
|
||||
{
|
||||
try {
|
||||
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const
|
||||
{
|
||||
try {
|
||||
return get_conversion(base.get_type_info(), user_type<Derived>())->convert_down(base);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
return find(base, derived) != m_conversions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr =
|
||||
find(base, derived);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
|
||||
const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
for (auto itr = m_conversions.begin();
|
||||
itr != m_conversions.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
|
||||
return m_conversions.end();
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> > m_conversions;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||
|
||||
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
///
|
||||
/// Create a new base class registration for applying to a module or to the ChaiScript engine
|
||||
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
|
||||
/// if you have a type that is introduced in a loadable module and is used by multiple modules
|
||||
/// (through a tertiary dll that is shared between the modules, static linking the new type
|
||||
/// into both loadable modules would not be portable), you need to register the base type
|
||||
/// relationship in all modules that use the newly added type in a polymorphic way.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// class Base
|
||||
/// {};
|
||||
/// class Derived : public Base
|
||||
/// {};
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<Base, Derived>());
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Dynamic_Cast_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
|
||||
return std::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<Base, Derived>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,20 +1,29 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
@@ -32,42 +41,16 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Dynamic_Object() : m_type_name("")
|
||||
{
|
||||
}
|
||||
|
||||
std::string get_type_name() const
|
||||
{
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
const Boxed_Value &get_attr(const std::string &t_attr_name) const
|
||||
{
|
||||
auto a = m_attrs.find(t_attr_name);
|
||||
|
||||
if (a != m_attrs.end()) {
|
||||
return a->second;
|
||||
} else {
|
||||
throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value &get_attr(const std::string &t_attr_name)
|
||||
Boxed_Value get_attr(const std::string &t_attr_name)
|
||||
{
|
||||
return m_attrs[t_attr_name];
|
||||
}
|
||||
|
||||
Boxed_Value &method_missing(const std::string &t_method_name)
|
||||
{
|
||||
return get_attr(t_method_name);
|
||||
}
|
||||
|
||||
const Boxed_Value &method_missing(const std::string &t_method_name) const
|
||||
{
|
||||
return get_attr(t_method_name);
|
||||
}
|
||||
|
||||
|
||||
std::map<std::string, Boxed_Value> get_attrs() const
|
||||
{
|
||||
return m_attrs;
|
||||
@@ -79,6 +62,234 @@ namespace chaiscript
|
||||
std::map<std::string, Boxed_Value> m_attrs;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* A Proxy_Function implementation designed for calling a function
|
||||
* that is automatically guarded based on the first param based on the
|
||||
* param's type name
|
||||
*/
|
||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(t_func->get_param_types()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
Dynamic_Object_Function(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
const Type_Info &t_ti)
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
|
||||
if (df)
|
||||
{
|
||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
return m_func->call_match(vals, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->get_arity();
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
return (*m_func)(params, t_conversions);
|
||||
} else {
|
||||
throw exception::guard_error();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> build_param_types(
|
||||
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
|
||||
{
|
||||
std::vector<Type_Info> types(t_inner_types);
|
||||
|
||||
assert(types.size() > 1);
|
||||
assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
||||
types[1] = t_objectti;
|
||||
return types;
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ti)
|
||||
{
|
||||
return bv.get_type_info().bare_equal(*ti);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A Proxy_Function implementation designed for creating a new
|
||||
* Dynamic_Object
|
||||
* that is automatically guarded based on the first param based on the
|
||||
* param's type name
|
||||
*/
|
||||
class Dynamic_Object_Constructor : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Constructor(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
||||
{
|
||||
auto begin = tl.begin();
|
||||
auto end = tl.end();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
++begin;
|
||||
}
|
||||
|
||||
return std::vector<Type_Info>(begin, end);
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Constructor() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
if (dc)
|
||||
{
|
||||
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals;
|
||||
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
|
||||
return m_func->call_match(new_vals, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
// "this" is not considered part of the arity
|
||||
return m_func->get_arity() - 1;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_params;
|
||||
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
||||
new_params.push_back(bv);
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
|
||||
(*m_func)(new_params, t_conversions);
|
||||
|
||||
return bv;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// A Proxy_Function implementation designed for calling a function
|
||||
/// that is automatically guarded based on the first param based on the
|
||||
/// param's type name
|
||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
bool t_is_attribute = false)
|
||||
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
|
||||
m_is_attribute(t_is_attribute)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
Dynamic_Object_Function(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
const Type_Info &t_ti,
|
||||
bool t_is_attribute = false)
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>()),
|
||||
m_is_attribute(t_is_attribute)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
{
|
||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
return m_func->call_match(vals, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
return (*m_func)(params, t_conversions);
|
||||
} else {
|
||||
throw exception::guard_error();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> build_param_types(
|
||||
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
|
||||
{
|
||||
std::vector<Type_Info> types(t_inner_types);
|
||||
|
||||
assert(types.size() > 1);
|
||||
//assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
||||
types[1] = t_objectti;
|
||||
return types;
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ti)
|
||||
{
|
||||
return bv.get_type_info().bare_equal(*ti);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::unique_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
bool m_is_attribute;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A Proxy_Function implementation designed for creating a new
|
||||
* Dynamic_Object
|
||||
* that is automatically guarded based on the first param based on the
|
||||
* param's type name
|
||||
*/
|
||||
class Dynamic_Object_Constructor : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Constructor(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
||||
{
|
||||
auto begin = tl.begin();
|
||||
auto end = tl.end();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
++begin;
|
||||
}
|
||||
|
||||
return std::vector<Type_Info>(begin, end);
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Constructor() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
|
||||
return m_func->call_match(new_vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
auto bv = var(Dynamic_Object(m_type_name));
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
|
||||
(*m_func)(new_params, t_conversions);
|
||||
|
||||
return bv;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -17,7 +18,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
@@ -27,56 +28,66 @@ namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
/// Build a function caller that knows how to dispatch on a set of functions
|
||||
/// example:
|
||||
/// std::function<void (int)> f =
|
||||
/// build_function_caller(dispatchkit.get_function("print"));
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] funcs the set of functions to dispatch on.
|
||||
/**
|
||||
* Build a function caller that knows how to dispatch on a set of functions
|
||||
* example:
|
||||
* std::function<void (int)> f =
|
||||
* build_function_caller(dispatchkit.get_function("print"));
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] funcs the set of functions to dispatch on.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
FunctionType *p=nullptr;
|
||||
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||
}
|
||||
|
||||
/// Build a function caller for a particular Proxy_Function object
|
||||
/// useful in the case that a function is being pass out from scripting back
|
||||
/// into code
|
||||
/// example:
|
||||
/// void my_function(Proxy_Function f)
|
||||
/// {
|
||||
/// std::function<void (int)> local_f =
|
||||
/// build_function_caller(f);
|
||||
/// }
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] func A function to execute.
|
||||
/**
|
||||
* Build a function caller for a particular Proxy_Function object
|
||||
* useful in the case that a function is being pass out from scripting back
|
||||
* into code
|
||||
* example:
|
||||
* void my_function(Proxy_Function f)
|
||||
* {
|
||||
* std::function<void (int)> local_f =
|
||||
* build_function_caller(f);
|
||||
* }
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] func A function to execute.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
||||
functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
funcs.push_back(func);
|
||||
return functor<FunctionType>(funcs, t_conversions);
|
||||
}
|
||||
|
||||
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
/// and creating a typesafe C++ function caller from it.
|
||||
/**
|
||||
* Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
* and creating a typesafe C++ function caller from it.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
|
||||
functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
/// Cast helper to handle automatic casting to const std::function &
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function &
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -87,13 +98,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast helper to handle automatic casting to std::function
|
||||
/**
|
||||
* Cast helper to handle automatic casting to std::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -104,13 +117,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast helper to handle automatic casting to const std::function
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -16,7 +17,7 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -25,13 +26,15 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// Internal helper class for handling the return
|
||||
/// value of a build_function_caller
|
||||
/**
|
||||
* Internal helper class for handling the return
|
||||
* value of a build_function_caller
|
||||
*/
|
||||
template<typename Ret, bool is_arithmetic>
|
||||
struct Function_Caller_Ret
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
||||
}
|
||||
@@ -44,7 +47,7 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<Ret, true>
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
|
||||
}
|
||||
@@ -58,7 +61,7 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<void, false>
|
||||
{
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||
}
|
||||
@@ -70,7 +73,7 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Dynamic_Cast_Conversions &t_conversions)
|
||||
: m_funcs(std::move(t_funcs)),
|
||||
m_conversions(t_conversions)
|
||||
{
|
||||
@@ -87,13 +90,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
Type_Conversions m_conversions;
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
@@ -109,7 +112,7 @@ namespace chaiscript
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_Conversions()));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Dynamic_Cast_Conversions()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||
@@ -9,11 +9,13 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Number;
|
||||
@@ -23,9 +25,6 @@ namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
template<class T> class Proxy_Function_Impl;
|
||||
template<class T> class Assignable_Proxy_Function_Impl;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
@@ -34,110 +33,9 @@ namespace chaiscript
|
||||
template<typename Ret>
|
||||
struct Handle_Return
|
||||
{
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<std::is_pod<typename std::decay<T>::type>::value>::type>
|
||||
static Boxed_Value handle(T r)
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::move(r), true);
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<!std::is_pod<typename std::decay<T>::type>::value>::type>
|
||||
static Boxed_Value handle(T &&r)
|
||||
{
|
||||
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::function<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<dispatch::Proxy_Function_Base>(
|
||||
new dispatch::Proxy_Function_Impl<Ret>(f)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::function<Ret>>
|
||||
{
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<dispatch::Proxy_Function_Base>(
|
||||
new Proxy_Function_Impl<Ret>(f)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<Proxy_Function_Base>(
|
||||
new Assignable_Proxy_Function_Impl<Ret>(
|
||||
std::ref(*f),
|
||||
f
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<Proxy_Function_Base>(
|
||||
new Assignable_Proxy_Function_Impl<Ret>(
|
||||
std::ref(*f),
|
||||
f
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<Proxy_Function_Base>(
|
||||
new Assignable_Proxy_Function_Impl<Ret>(
|
||||
std::ref(*f),
|
||||
f
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::function<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<Proxy_Function_Base>(
|
||||
new Assignable_Proxy_Function_Impl<Ret>(
|
||||
std::ref(f),
|
||||
std::shared_ptr<std::function<Ret>>()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
std::shared_ptr<dispatch::Proxy_Function_Base>(
|
||||
new dispatch::Proxy_Function_Impl<Ret>(f)
|
||||
)
|
||||
);
|
||||
return const_var(r);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -146,16 +44,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
return Boxed_Value(p);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -164,7 +53,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r, true);
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -173,7 +62,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r, true);
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -182,7 +71,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r, true);
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -191,7 +80,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r), true);
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
@@ -229,231 +229,231 @@ namespace chaiscript
|
||||
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_xor(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_difference(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_left_shift(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_product(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_quotient(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_remainder(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_right_shift(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_sum(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_decrement(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_increment(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr equal(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than_equal(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than_equal(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr logical_compliment(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr not_equal(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr addition(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_plus(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr subtraction(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_minus(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_and(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_compliment(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_xor(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_or(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr division(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr left_shift(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr multiplication(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr remainder(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr right_shift(ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
|
||||
return m;
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
@@ -30,7 +28,7 @@ namespace chaiscript
|
||||
Proxy_Function build_constructor_(Class (*)(Params...))
|
||||
{
|
||||
typedef std::shared_ptr<Class> (sig)(Params...);
|
||||
return Proxy_Function(static_cast<Proxy_Function_Impl_Base *>(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>)))));
|
||||
return Proxy_Function(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_HPP_
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@@ -19,13 +20,13 @@
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "proxy_functions_detail.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
struct arity_error;
|
||||
@@ -41,98 +42,6 @@ namespace chaiscript
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions *t_conversions);
|
||||
|
||||
class Param_Types
|
||||
{
|
||||
public:
|
||||
Param_Types()
|
||||
: m_has_types(false),
|
||||
m_doti(user_type<Dynamic_Object>())
|
||||
{}
|
||||
|
||||
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
|
||||
: m_types(std::move(t_types)),
|
||||
m_has_types(false),
|
||||
m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
update_has_types();
|
||||
}
|
||||
|
||||
void push_front(std::string t_name, Type_Info t_ti)
|
||||
{
|
||||
m_types.emplace(m_types.begin(), std::move(t_name), std::move(t_ti));
|
||||
update_has_types();
|
||||
}
|
||||
|
||||
bool operator==(const Param_Types &t_rhs) const
|
||||
{
|
||||
return m_types == t_rhs.m_types;
|
||||
}
|
||||
|
||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (!m_has_types) return true;
|
||||
if (vals.size() != m_types.size()) return false;
|
||||
|
||||
for (size_t i = 0; i < vals.size(); ++i)
|
||||
{
|
||||
const auto &name = m_types[i].first;
|
||||
if (!name.empty()) {
|
||||
const auto &bv = vals[i];
|
||||
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const auto &ti = m_types[i].second;
|
||||
if (!ti.is_undef())
|
||||
{
|
||||
if (!bv.get_type_info().bare_equal(ti)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, Type_Info>> &types() const
|
||||
{
|
||||
return m_types;
|
||||
}
|
||||
|
||||
private:
|
||||
void update_has_types()
|
||||
{
|
||||
for (const auto &type : m_types)
|
||||
{
|
||||
if (!type.first.empty())
|
||||
{
|
||||
m_has_types = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_has_types = false;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, Type_Info>> m_types;
|
||||
bool m_has_types;
|
||||
Type_Info m_doti;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Pure virtual base class for all Proxy_Function implementations
|
||||
* Proxy_Functions are a type erasure of type safe C++
|
||||
@@ -146,9 +55,10 @@ namespace chaiscript
|
||||
public:
|
||||
virtual ~Proxy_Function_Base() {}
|
||||
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
return do_call(params, t_conversions);
|
||||
Boxed_Value bv = do_call(params, t_conversions);
|
||||
return bv;
|
||||
}
|
||||
|
||||
/// Returns a vector containing all of the types of the parameters the function returns/takes
|
||||
@@ -158,9 +68,7 @@ namespace chaiscript
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
|
||||
virtual bool is_attribute_function() const { return false; }
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
|
||||
bool has_arithmetic_param() const
|
||||
{
|
||||
@@ -174,17 +82,17 @@ namespace chaiscript
|
||||
|
||||
//! Return true if the function is a possible match
|
||||
//! to the passed in values
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (m_arity < 0)
|
||||
int arity = get_arity();
|
||||
|
||||
if (arity < 0)
|
||||
{
|
||||
return true;
|
||||
} else if (static_cast<size_t>(m_arity) == vals.size()) {
|
||||
if (m_arity == 0)
|
||||
} else if (size_t(arity) == vals.size()) {
|
||||
if (arity == 0)
|
||||
{
|
||||
return true;
|
||||
} else if (m_arity > 1 && m_types.size() > 1) {
|
||||
return compare_first_type(vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
|
||||
} else {
|
||||
return compare_first_type(vals[0], t_conversions);
|
||||
}
|
||||
@@ -194,14 +102,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \returns the number of arguments the function takes or -1 if it is variadic
|
||||
int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
virtual int get_arity() const = 0;
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
@@ -209,7 +114,7 @@ namespace chaiscript
|
||||
&& (ti.bare_equal(user_type<Boxed_Number>())
|
||||
|| ti.bare_equal(bv.get_type_info())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| t_conversions.converts(ti, bv.get_type_info())
|
||||
|| t_conversions.dynamic_cast_converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -219,17 +124,11 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
return compare_type_to_param(m_types[1], bv, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
|
||||
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types)
|
||||
: m_types(std::move(t_types)), m_has_arithmetic_param(false)
|
||||
{
|
||||
for (size_t i = 1; i < m_types.size(); ++i)
|
||||
{
|
||||
@@ -242,6 +141,19 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
const std::vector<Type_Info> &types = get_param_types();
|
||||
|
||||
if (types.size() < 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const Type_Info &ti = types[1];
|
||||
return compare_type_to_param(ti, bv, t_conversions);
|
||||
|
||||
}
|
||||
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
|
||||
{
|
||||
@@ -249,7 +161,7 @@ namespace chaiscript
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
const size_t size = bvs.size();
|
||||
size_t size = bvs.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (!(tis[i+1].bare_equal(bvs[i].get_type_info()) && tis[i+1].is_const() >= bvs[i].get_type_info().is_const() ))
|
||||
@@ -262,8 +174,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
std::vector<Type_Info> m_types;
|
||||
int m_arity;
|
||||
bool m_has_arithmetic_param;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -284,8 +196,6 @@ namespace chaiscript
|
||||
: std::runtime_error("Guard evaluation failed")
|
||||
{ }
|
||||
|
||||
guard_error(const guard_error &) = default;
|
||||
|
||||
virtual ~guard_error() CHAISCRIPT_NOEXCEPT
|
||||
{ }
|
||||
};
|
||||
@@ -304,13 +214,10 @@ namespace chaiscript
|
||||
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> t_f,
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
||||
m_param_types(std::move(t_param_types)),
|
||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description)),
|
||||
m_f(std::move(t_f))
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity)),
|
||||
m_f(std::move(t_f)), m_arity(t_arity), m_description(std::move(t_description)), m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -323,16 +230,19 @@ namespace chaiscript
|
||||
return this == &rhs
|
||||
|| (prhs
|
||||
&& this->m_arity == prhs->m_arity
|
||||
&& !this->m_guard && !prhs->m_guard
|
||||
&& this->m_param_types == prhs->m_param_types);
|
||||
&& !this->m_guard && !prhs->m_guard);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
|
||||
return (m_arity < 0 || vals.size() == size_t(m_arity))
|
||||
&& test_guard(vals, t_conversions);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
Proxy_Function get_guard() const
|
||||
{
|
||||
@@ -350,11 +260,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
||||
{
|
||||
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
|
||||
|
||||
if (test_guard(params, t_conversions))
|
||||
{
|
||||
return m_f(params);
|
||||
} else {
|
||||
@@ -367,7 +278,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (m_guard)
|
||||
{
|
||||
@@ -383,49 +294,52 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
|
||||
static std::vector<Type_Info> build_param_type_list(int arity)
|
||||
{
|
||||
std::vector<Type_Info> types;
|
||||
|
||||
// For the return type
|
||||
types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get());
|
||||
|
||||
for (const auto &t : t_types.types())
|
||||
if (arity > 0)
|
||||
{
|
||||
if (t.second.is_undef()) {
|
||||
for (int i = 0; i < arity; ++i)
|
||||
{
|
||||
types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get());
|
||||
} else {
|
||||
types.push_back(t.second);
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
Param_Types m_param_types;
|
||||
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||
int m_arity;
|
||||
std::string m_description;
|
||||
Proxy_Function m_guard;
|
||||
AST_NodePtr m_parsenode;
|
||||
std::string m_description;
|
||||
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||
};
|
||||
|
||||
/// An object used by Bound_Function to represent "_" parameters
|
||||
/// of a binding. This allows for unbound parameters during bind.
|
||||
/**
|
||||
* An object used by Bound_Function to represent "_" parameters
|
||||
* of a binding. This allows for unbound parameters during bind.
|
||||
*/
|
||||
struct Placeholder_Object
|
||||
{
|
||||
};
|
||||
|
||||
/// An implementation of Proxy_Function that takes a Proxy_Function
|
||||
/// and substitutes bound parameters into the parameter list
|
||||
/// at runtime, when call() is executed.
|
||||
/// it is used for bind(function, param1, _, param2) style calls
|
||||
/**
|
||||
* An implementation of Proxy_Function that takes a Proxy_Function
|
||||
* and substitutes bound parameters into the parameter list
|
||||
* at runtime, when call() is executed.
|
||||
* it is used for bind(function, param1, _, param2) style calls
|
||||
*/
|
||||
class Bound_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Bound_Function(const Const_Proxy_Function &t_f,
|
||||
const std::vector<Boxed_Value> &t_args)
|
||||
: Proxy_Function_Base(build_param_type_info(t_f, t_args), (t_f->get_arity()<0?-1:static_cast<int>(build_param_type_info(t_f, t_args).size())-1)),
|
||||
m_f(t_f), m_args(t_args)
|
||||
: Proxy_Function_Base(build_param_type_info(t_f, t_args)),
|
||||
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
|
||||
{
|
||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||
}
|
||||
@@ -437,14 +351,16 @@ namespace chaiscript
|
||||
|
||||
virtual ~Bound_Function() {}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||
}
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return std::vector<Const_Proxy_Function>{m_f};
|
||||
std::vector<Const_Proxy_Function> fs;
|
||||
fs.push_back(m_f);
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
@@ -479,6 +395,11 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "Bound: " + m_f->annotation();
|
||||
@@ -495,17 +416,9 @@ namespace chaiscript
|
||||
std::vector<Type_Info> types = t_f->get_param_types();
|
||||
assert(types.size() == t_args.size() + 1);
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6011)
|
||||
#endif
|
||||
// this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14
|
||||
std::vector<Type_Info> retval{types[0]};
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < types.size() - 1; ++i)
|
||||
std::vector<Type_Info> retval;
|
||||
retval.push_back(types[0]);
|
||||
for (size_t i = 0; i < types.size()-1; ++i)
|
||||
{
|
||||
if (t_args[i].get_type_info() == chaiscript::detail::Get_Type_Info<Placeholder_Object>::get())
|
||||
{
|
||||
@@ -516,7 +429,7 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
@@ -524,34 +437,47 @@ namespace chaiscript
|
||||
private:
|
||||
Const_Proxy_Function m_f;
|
||||
std::vector<Boxed_Value> m_args;
|
||||
int m_arity;
|
||||
};
|
||||
|
||||
class Proxy_Function_Impl_Base : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
||||
Proxy_Function_Impl_Base(std::vector<Type_Info> t_types)
|
||||
: Proxy_Function_Base(std::move(t_types))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Impl_Base() {}
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return static_cast<int>(m_types.size()) - 1;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions));
|
||||
if (int(vals.size()) != get_arity())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
};
|
||||
|
||||
/// The standard typesafe function call implementation of Proxy_Function
|
||||
/// It takes a std::function<> object and performs runtime
|
||||
/// type checking of Boxed_Value parameters, in a type safe manner
|
||||
/**
|
||||
* The standard typesafe function call implementation of Proxy_Function
|
||||
* It takes a std::function<> object and performs runtime
|
||||
* type checking of Boxed_Value parameters, in a type safe manner
|
||||
*/
|
||||
template<typename Func>
|
||||
class Proxy_Function_Impl : public Proxy_Function_Impl_Base
|
||||
{
|
||||
@@ -564,7 +490,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||
}
|
||||
@@ -580,93 +506,31 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::function<Func> m_f;
|
||||
Func *m_dummy_func;
|
||||
};
|
||||
|
||||
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Impl_Base(t_types)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Assignable_Proxy_Function() {}
|
||||
|
||||
|
||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
template<typename Func>
|
||||
class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function
|
||||
{
|
||||
public:
|
||||
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
|
||||
: Assignable_Proxy_Function(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
||||
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr)), m_dummy_func(nullptr)
|
||||
{
|
||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||
|
||||
}
|
||||
|
||||
virtual ~Assignable_Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
|
||||
}
|
||||
|
||||
std::function<Func> internal_function() const
|
||||
{
|
||||
return m_f.get();
|
||||
}
|
||||
|
||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) CHAISCRIPT_OVERRIDE {
|
||||
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f.get(), params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::reference_wrapper<std::function<Func>> m_f;
|
||||
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
|
||||
Func *m_dummy_func;
|
||||
};
|
||||
/// Attribute getter Proxy_Function implementation
|
||||
/**
|
||||
* Attribute getter Proxy_Function implementation
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
class Attribute_Access : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types(), 1),
|
||||
m_attr(t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Attribute_Access<T, Class> * aa
|
||||
@@ -679,7 +543,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@@ -695,7 +565,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
@@ -703,14 +573,14 @@ namespace chaiscript
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
||||
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
}
|
||||
} else {
|
||||
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -739,7 +609,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
dispatch_error(const dispatch_error &) = default;
|
||||
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::vector<Boxed_Value> parameters;
|
||||
@@ -753,7 +622,7 @@ namespace chaiscript
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
if (t_func->get_arity() != static_cast<int>(plist.size()))
|
||||
{
|
||||
@@ -781,7 +650,7 @@ namespace chaiscript
|
||||
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
|
||||
@@ -795,18 +664,8 @@ namespace chaiscript
|
||||
{
|
||||
matching_func = begin;
|
||||
} else {
|
||||
// handle const members vs non-const member, which is not really ambiguous
|
||||
const auto &mat_fun_param_types = (*matching_func)->get_param_types();
|
||||
const auto &next_fun_param_types = (*begin)->get_param_types();
|
||||
|
||||
if (plist[0].is_const() && !mat_fun_param_types[1].is_const() && next_fun_param_types[1].is_const()) {
|
||||
matching_func = begin; // keep the new one, the const/non-const matchup is correct
|
||||
} else if (!plist[0].is_const() && !mat_fun_param_types[1].is_const() && next_fun_param_types[1].is_const()) {
|
||||
// keep the old one, it has a better const/non-const matchup
|
||||
} else {
|
||||
// ambiguous function call
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
// More than one function matches, not attempting
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,42 +712,17 @@ namespace chaiscript
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
//std::cout << "starting dispatch: " << funcs.size() << '\n';
|
||||
std::multimap<size_t, const Proxy_Function_Base *> ordered_funcs;
|
||||
|
||||
for (const auto &func : funcs)
|
||||
{
|
||||
size_t numdiffs = 0;
|
||||
const auto arity = func->get_arity();
|
||||
|
||||
if (arity == -1)
|
||||
{
|
||||
numdiffs = plist.size();
|
||||
} else if (arity == static_cast<int>(plist.size())) {
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
{
|
||||
if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info()))
|
||||
{
|
||||
++numdiffs;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
ordered_funcs.insert(std::make_pair(numdiffs, func.get()));
|
||||
}
|
||||
|
||||
for (const auto &func : ordered_funcs )
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
if (func.first == 0 || func.second->filter(plist, t_conversions))
|
||||
if ((*begin)->filter(plist, t_conversions))
|
||||
{
|
||||
return (*(func.second))(plist, t_conversions);
|
||||
return (*(*begin))(plist, t_conversions);
|
||||
}
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
//parameter failed to cast, try again
|
||||
@@ -898,9 +732,22 @@ namespace chaiscript
|
||||
//guard failed to allow the function to execute,
|
||||
//try again
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
|
||||
return detail::dispatch_with_conversions(funcs.cbegin(), funcs.cend(), plist, t_conversions);
|
||||
return detail::dispatch_with_conversions(orig, end, plist, t_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
@@ -18,7 +20,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
@@ -40,8 +42,6 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
arity_error(const arity_error &) = default;
|
||||
|
||||
virtual ~arity_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
int got;
|
||||
@@ -72,7 +72,7 @@ namespace chaiscript
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Try_Cast<Param, Rest...>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, size_t generation, const Type_Conversions &t_conversions)
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, int generation, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
boxed_cast<Param>(params[generation], &t_conversions);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
|
||||
@@ -83,7 +83,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions &)
|
||||
static void do_try(const std::vector<Boxed_Value> &, int, const Dynamic_Cast_Conversions &)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -96,7 +96,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
||||
@@ -113,7 +113,7 @@ namespace chaiscript
|
||||
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
}
|
||||
@@ -128,7 +128,7 @@ namespace chaiscript
|
||||
#endif
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> &, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
Ret call_func(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
{
|
||||
@@ -171,7 +171,7 @@ namespace chaiscript
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
|
||||
}
|
||||
@@ -181,7 +181,7 @@ namespace chaiscript
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
call_func(fun, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "bind_first.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -39,29 +40,40 @@ namespace chaiscript
|
||||
template<typename Ret, typename Class, typename ... Args>
|
||||
std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
|
||||
/// std::function for member function pointers seems to be broken in MSVC
|
||||
return std::function<Ret(Class &, Args...)>(std::mem_fn(func));
|
||||
#else
|
||||
return std::function<Ret(Class &, Args...)>(func);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Args>
|
||||
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
|
||||
{
|
||||
#if defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_LIBCPP)
|
||||
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
|
||||
/// std::function for member function pointers seems to be broken in MSVC
|
||||
return std::function<Ret (const Class &, Args...)>([func](const Class &o, Args... args)->Ret {
|
||||
return (o.*func)(std::forward<Args>(args)...);
|
||||
});
|
||||
#else
|
||||
return std::function<Ret(const Class &, Args...)>(func);
|
||||
#endif
|
||||
return std::function<Ret (const Class &, Args...)>(std::mem_fn(func));
|
||||
}
|
||||
|
||||
template<bool Object>
|
||||
struct Fun_Helper
|
||||
{
|
||||
template<typename T>
|
||||
static Proxy_Function go(T t)
|
||||
{
|
||||
/// \todo is it possible to reduce the number of templates generated here?
|
||||
return Proxy_Function(
|
||||
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Fun_Helper<true>
|
||||
{
|
||||
template<typename T, typename Class>
|
||||
static Proxy_Function go(T Class::* m)
|
||||
{
|
||||
return Proxy_Function(new Attribute_Access<T, Class>(m));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,31 +98,9 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T>
|
||||
Proxy_Function fun(const T &t)
|
||||
Proxy_Function fun(T t)
|
||||
{
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(t)) >::Signature>>(dispatch::detail::to_function(t)));
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*func)(Param...) const)
|
||||
{
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>>(dispatch::detail::to_function(func)));
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*func)(Param...))
|
||||
{
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>>(dispatch::detail::to_function(func)));
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
|
||||
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
|
||||
{
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<T, Class>>(m));
|
||||
return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +118,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Proxy_Function fun(const std::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<T>>(f));
|
||||
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
|
||||
@@ -151,9 +141,9 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T, typename Q>
|
||||
Proxy_Function fun(T &&t, const Q &q)
|
||||
Proxy_Function fun(T t, const Q &q)
|
||||
{
|
||||
return fun(detail::bind_first(std::forward<T>(t), q));
|
||||
return fun(detail::bind_first(t, q));
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it
|
||||
@@ -177,11 +167,11 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T, typename Q, typename R>
|
||||
Proxy_Function fun(T &&t, Q &&q, R &&r)
|
||||
Proxy_Function fun(T t, const Q &q, const R &r)
|
||||
{
|
||||
return fun(detail::bind_first(detail::bind_first(std::forward<T>(t), std::forward<Q>(q)), std::forward<R>(r)));
|
||||
return fun(detail::bind_first(detail::bind_first(t, q), r));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,464 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
|
||||
class bad_boxed_type_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
|
||||
|
||||
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &from) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0;
|
||||
|
||||
const Type_Info &to() const
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
const Type_Info &from() const
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
|
||||
virtual ~Type_Conversion_Base() {}
|
||||
|
||||
protected:
|
||||
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
|
||||
: m_to(t_to), m_from(t_from)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Type_Info m_to;
|
||||
Type_Info m_from;
|
||||
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<const To>{
|
||||
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
} else {
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
} else {
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<To>{
|
||||
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
} else {
|
||||
#ifdef CHAISCRIPT_LIBCPP
|
||||
/// \todo fix this someday after libc++ is fixed.
|
||||
if (std::string(typeid(To).name()).find("Assignable_Proxy_Function") != std::string::npos) {
|
||||
auto from = detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr);
|
||||
if (std::string(typeid(*from).name()).find("Assignable_Proxy_Function_Impl") != std::string::npos) {
|
||||
return std::static_pointer_cast<To>(from);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = dynamic_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
|
||||
To &data = dynamic_cast<To &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
class Type_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
||||
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
|
||||
m_func(std::move(t_func))
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
/// \todo better handling of errors from the conversion function
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
private:
|
||||
Callable m_func;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class Type_Conversions
|
||||
{
|
||||
public:
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||
{
|
||||
return *t_lhs != *t_rhs && t_lhs->before(*t_rhs);
|
||||
}
|
||||
};
|
||||
|
||||
Type_Conversions()
|
||||
: m_mutex(),
|
||||
m_conversions(),
|
||||
m_convertableTypes(),
|
||||
m_num_types(0),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Conversions(const Type_Conversions &t_other)
|
||||
: m_mutex(),
|
||||
m_conversions(t_other.get_conversions()),
|
||||
m_convertableTypes(),
|
||||
m_num_types(m_conversions.size()),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
||||
{
|
||||
auto &cache = *m_thread_cache;
|
||||
if (cache.size() != m_num_types)
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
cache = m_convertableTypes;
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
/// \todo error if a conversion already exists
|
||||
m_conversions.insert(conversion);
|
||||
m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()});
|
||||
m_num_types = m_convertableTypes.size();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool convertable_type() const
|
||||
{
|
||||
return thread_cache().count(user_type<T>().bare_type_info()) != 0;
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
bool converts() const
|
||||
{
|
||||
return converts(user_type<To>(), user_type<From>());
|
||||
}
|
||||
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
const auto &types = thread_cache();
|
||||
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0)
|
||||
{
|
||||
return has_conversion(to, from) || has_conversion(from, to);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
void enable_conversion_saves(bool t_val)
|
||||
{
|
||||
m_conversion_saves->enabled = t_val;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> take_saves()
|
||||
{
|
||||
std::vector<Boxed_Value> ret;
|
||||
std::swap(ret, m_conversion_saves->saves);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool has_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
return find(to, from) != m_conversions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::Type_Conversion_Base> get_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr = find(to, from);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
return std::find_if(m_conversions.begin(), m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
return conversion->to().bare_equal(to) && conversion->from().bare_equal(from);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> get_conversions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
|
||||
struct Conversion_Saves
|
||||
{
|
||||
Conversion_Saves()
|
||||
: enabled(false)
|
||||
{}
|
||||
|
||||
bool enabled;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||
std::set<const std::type_info *, Less_Than> m_convertableTypes;
|
||||
std::atomic_size_t m_num_types;
|
||||
mutable chaiscript::detail::threading::Thread_Storage<std::set<const std::type_info *, Less_Than>> m_thread_cache;
|
||||
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||
|
||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
///
|
||||
/// Create a new to class registration for applying to a module or to the ChaiScript engine
|
||||
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
|
||||
/// if you have a type that is introduced in a loadable module and is used by multiple modules
|
||||
/// (through a tertiary dll that is shared between the modules, static linking the new type
|
||||
/// into both loadable modules would not be portable), you need to register the type
|
||||
/// relationship in all modules that use the newly added type in a polymorphic way.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// class Base
|
||||
/// {};
|
||||
/// class Derived : public Base
|
||||
/// {};
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::to_class<Base, Derived>());
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Type_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Dynamic_Conversion_Impl<Base, Derived>>();
|
||||
}
|
||||
|
||||
template<typename Callable>
|
||||
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to,
|
||||
const Callable &t_func)
|
||||
{
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
|
||||
}
|
||||
|
||||
template<typename From, typename To, typename Callable>
|
||||
Type_Conversion type_conversion(const Callable &t_function)
|
||||
{
|
||||
auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
return chaiscript::Boxed_Value(t_function(detail::Cast_Helper<const From &>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
Type_Conversion type_conversion()
|
||||
{
|
||||
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
return chaiscript::Boxed_Value(To(detail::Cast_Helper<From>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,16 +1,17 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||
#define CHAISCRIPT_TYPE_INFO_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -30,8 +31,8 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bareti),
|
||||
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
|
||||
m_is_undef(false)
|
||||
@@ -110,11 +111,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
|
||||
{
|
||||
return m_bare_type_info;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
@@ -128,7 +124,9 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Helper used to create a Type_Info object
|
||||
/**
|
||||
* Helper used to create a Type_Info object
|
||||
*/
|
||||
template<typename T>
|
||||
struct Get_Type_Info
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
@@ -26,7 +26,6 @@ struct AST_Node;
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
/// Signature of module entry point that all binary loadable modules must implement.
|
||||
typedef ModulePtr (*Create_Module_Func)();
|
||||
|
||||
@@ -38,7 +37,7 @@ namespace chaiscript
|
||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class
|
||||
};
|
||||
};
|
||||
|
||||
@@ -51,7 +50,7 @@ namespace chaiscript
|
||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
@@ -68,31 +67,6 @@ namespace chaiscript
|
||||
File_Position() : line(0), column(0) { }
|
||||
};
|
||||
|
||||
struct Parse_Location {
|
||||
Parse_Location(std::string t_fname="", const int t_start_line=0, const int t_start_col=0,
|
||||
const int t_end_line=0, const int t_end_col=0)
|
||||
: start(t_start_line, t_start_col),
|
||||
end(t_end_line, t_end_col),
|
||||
filename(std::make_shared<std::string>(std::move(t_fname)))
|
||||
{
|
||||
}
|
||||
|
||||
Parse_Location(std::shared_ptr<std::string> t_fname, const int t_start_line=0, const int t_start_col=0,
|
||||
const int t_end_line=0, const int t_end_col=0)
|
||||
: start(t_start_line, t_start_col),
|
||||
end(t_end_line, t_end_col),
|
||||
filename(std::move(t_fname))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
File_Position start;
|
||||
File_Position end;
|
||||
std::shared_ptr<std::string> filename;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<const AST_Node> AST_NodePtr_Const;
|
||||
@@ -103,9 +77,10 @@ namespace chaiscript
|
||||
{
|
||||
|
||||
/// Errors generated during parsing or evaluation
|
||||
struct eval_error : std::runtime_error {
|
||||
struct eval_error : public std::runtime_error {
|
||||
std::string reason;
|
||||
File_Position start_position;
|
||||
File_Position end_position;
|
||||
std::string filename;
|
||||
std::string detail;
|
||||
std::vector<AST_NodePtr_Const> call_stack;
|
||||
@@ -115,7 +90,7 @@ namespace chaiscript
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why,
|
||||
@@ -129,7 +104,7 @@ namespace chaiscript
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
|
||||
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||
reason(t_why), start_position(t_where), filename(t_fname)
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
|
||||
@@ -137,27 +112,25 @@ namespace chaiscript
|
||||
reason(t_why)
|
||||
{}
|
||||
|
||||
eval_error(const eval_error &) = default;
|
||||
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << what();
|
||||
if (call_stack.size() > 0) {
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
||||
ss << '\n' << detail << '\n';
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")" << std::endl;
|
||||
ss << std::endl << detail << std::endl;
|
||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||
for (size_t j = 1; j < call_stack.size(); ++j) {
|
||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
|
||||
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
ss << '\n';
|
||||
ss << std::endl;
|
||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << '\n';
|
||||
ss << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -178,16 +151,16 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static const std::string &fname(const T& t)
|
||||
static std::string fname(const T& t)
|
||||
{
|
||||
return t->filename();
|
||||
return *t->filename;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string startpos(const T& t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << t->start().line << ", " << t->start().column;
|
||||
oss << t->start.line << ", " << t->start.column;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -254,7 +227,8 @@ namespace chaiscript
|
||||
|
||||
if (f)
|
||||
{
|
||||
auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
|
||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||
if (dynfunguard)
|
||||
{
|
||||
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||
@@ -277,7 +251,7 @@ namespace chaiscript
|
||||
static std::string format_location(const T &t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
|
||||
oss << "(" << *t->filename << " " << t->start.line << ", " << t->start.column << ")";
|
||||
|
||||
return oss.str();
|
||||
|
||||
@@ -290,13 +264,13 @@ namespace chaiscript
|
||||
std::stringstream ss;
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:\n";
|
||||
ss << " " << t_functions.size() << " overloads available:" << std::endl;
|
||||
|
||||
for (const auto & t_function : t_functions)
|
||||
{
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -416,12 +390,11 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Errors generated when loading a file
|
||||
struct file_not_found_error : std::runtime_error {
|
||||
struct file_not_found_error : public std::runtime_error {
|
||||
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
{ }
|
||||
|
||||
file_not_found_error(const file_not_found_error &) = default;
|
||||
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
|
||||
@@ -431,24 +404,13 @@ namespace chaiscript
|
||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
||||
public:
|
||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
||||
std::shared_ptr<const std::string> filename;
|
||||
File_Position start, end;
|
||||
std::vector<AST_NodePtr> children;
|
||||
AST_NodePtr annotation;
|
||||
|
||||
const std::string &filename() const {
|
||||
return *location.filename;
|
||||
}
|
||||
|
||||
const File_Position &start() const {
|
||||
return location.start;
|
||||
}
|
||||
|
||||
const File_Position &end() const {
|
||||
return location.end;
|
||||
}
|
||||
|
||||
virtual std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
@@ -468,7 +430,7 @@ namespace chaiscript
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
||||
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
|
||||
|
||||
for (size_t j = 0; j < this->children.size(); ++j) {
|
||||
oss << this->children[j]->to_string(t_prepend + " ");
|
||||
@@ -486,32 +448,25 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv) {
|
||||
try {
|
||||
return boxed_cast<bool>(t_bv);
|
||||
}
|
||||
catch (const exception::bad_boxed_cast &) {
|
||||
throw exception::eval_error("Condition not boolean");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
|
||||
{
|
||||
std::replace(children.begin(), children.end(), t_child, t_new_child);
|
||||
}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
||||
protected:
|
||||
AST_Node(std::string t_ast_node_text, int t_id, Parse_Location t_loc,
|
||||
std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
|
||||
identifier(t_id), text(std::move(t_ast_node_text)),
|
||||
location(std::move(t_loc)),
|
||||
children(std::move(t_children))
|
||||
AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname,
|
||||
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
|
||||
text(std::move(t_ast_node_text)), identifier(t_id), filename(t_fname),
|
||||
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
|
||||
{
|
||||
}
|
||||
|
||||
AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
|
||||
text(std::move(t_ast_node_text)), identifier(t_id), filename(t_fname) {}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const
|
||||
{
|
||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
||||
@@ -519,8 +474,8 @@ namespace chaiscript
|
||||
|
||||
private:
|
||||
// Copy and assignment explicitly unimplemented
|
||||
AST_Node(const AST_Node &) = delete;
|
||||
AST_Node& operator=(const AST_Node &) = delete;
|
||||
AST_Node(const AST_Node &);
|
||||
AST_Node& operator=(const AST_Node &);
|
||||
};
|
||||
|
||||
|
||||
@@ -528,11 +483,12 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Special type for returned values
|
||||
struct Return_Value {
|
||||
Boxed_Value retval;
|
||||
|
||||
Return_Value(Boxed_Value t_return_value) : retval(std::move(t_return_value)) { }
|
||||
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
|
||||
};
|
||||
|
||||
|
||||
@@ -593,11 +549,6 @@ namespace chaiscript
|
||||
m_de.save_function_params(t_params);
|
||||
}
|
||||
|
||||
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
m_de.save_function_params(std::move(t_params));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||
#define CHAISCRIPT_ENGINE_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
@@ -16,6 +18,7 @@
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
@@ -23,7 +26,7 @@
|
||||
#include "../dispatchkit/boxed_cast_helper.hpp"
|
||||
#include "../dispatchkit/boxed_value.hpp"
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "../dispatchkit/type_conversions.hpp"
|
||||
#include "../dispatchkit/dynamic_cast_conversion.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
@@ -58,8 +61,9 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
|
||||
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -147,8 +151,8 @@ namespace chaiscript
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
template<typename T>
|
||||
#ifdef _UNICODE
|
||||
template<typename T>
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_wstring(t_str);
|
||||
@@ -163,11 +167,11 @@ namespace chaiscript
|
||||
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
typedef LPTSTR StringType;
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
#ifdef _UNICODE
|
||||
typedef LPWSTR StringType;
|
||||
std::wstring retval = L"Unknown Error";
|
||||
#else
|
||||
typedef LPSTR StringType;
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = nullptr;
|
||||
@@ -179,7 +183,7 @@ namespace chaiscript
|
||||
NULL,
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||
(StringType)&lpMsgBuf,
|
||||
0, NULL ) != 0 && lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
@@ -261,8 +265,8 @@ namespace chaiscript
|
||||
std::map<std::string, detail::Loadable_Module_Ptr> m_loaded_modules;
|
||||
std::set<std::string> m_active_loaded_modules;
|
||||
|
||||
std::vector<std::string> m_module_paths;
|
||||
std::vector<std::string> m_use_paths;
|
||||
std::vector<std::string> m_modulepaths;
|
||||
std::vector<std::string> m_usepaths;
|
||||
|
||||
chaiscript::detail::Dispatch_Engine m_engine;
|
||||
|
||||
@@ -273,7 +277,7 @@ namespace chaiscript
|
||||
parser::ChaiScript_Parser parser;
|
||||
if (parser.parse(t_input, t_filename)) {
|
||||
//parser.show_match_stack();
|
||||
return parser.optimized_ast()->eval(m_engine);
|
||||
return parser.ast()->eval(m_engine);
|
||||
} else {
|
||||
return Boxed_Value();
|
||||
}
|
||||
@@ -294,25 +298,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the given file and looks in the 'use' paths
|
||||
const Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||
for (const auto &path : m_use_paths)
|
||||
{
|
||||
try {
|
||||
const auto appendedpath = path + t_filename;
|
||||
return do_eval(load_file(appendedpath), appendedpath, true);
|
||||
} catch (const exception::file_not_found_error &) {
|
||||
// failed to load, try the next path
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
throw Boxed_Value(t_ee);
|
||||
}
|
||||
}
|
||||
|
||||
// failed to load by any name
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Evaluates the given string, used during eval() inside of a script
|
||||
@@ -346,9 +331,6 @@ namespace chaiscript
|
||||
m_engine.add_reserved_word("true");
|
||||
m_engine.add_reserved_word("false");
|
||||
m_engine.add_reserved_word("class");
|
||||
m_engine.add_reserved_word("attr");
|
||||
m_engine.add_reserved_word("var");
|
||||
m_engine.add_reserved_word("GLOBAL");
|
||||
m_engine.add_reserved_word("_");
|
||||
|
||||
if (t_lib)
|
||||
@@ -363,29 +345,14 @@ namespace chaiscript
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
|
||||
m_engine.add(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Dynamic_Proxy_Function>(
|
||||
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(
|
||||
[this](const std::vector<Boxed_Value> &t_params) {
|
||||
return m_engine.call_exists(t_params);
|
||||
}), "call_exists");
|
||||
|
||||
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
//
|
||||
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base &, const std::vector<Boxed_Value> &)>(
|
||||
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
|
||||
return t_fun(t_params, this->m_engine.conversions());
|
||||
}), "call");
|
||||
})), "call_exists");
|
||||
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type");
|
||||
m_engine.add(fun<chaiscript::Type_Info (const std::string &)>([this](const std::string &t_type_name){ return this->m_engine.get_type(t_type_name, true); }), "type");
|
||||
|
||||
m_engine.add(fun<void(const Type_Info &, const Type_Info &, const std::function<Boxed_Value(const Boxed_Value &)> &)>(
|
||||
[=](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
|
||||
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
|
||||
}
|
||||
), "add_type_conversion");
|
||||
|
||||
|
||||
typedef std::string (ChaiScript::*load_mod_1)(const std::string&);
|
||||
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
|
||||
@@ -394,14 +361,13 @@ namespace chaiscript
|
||||
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
|
||||
|
||||
m_engine.add(fun(&ChaiScript::use, this), "use");
|
||||
m_engine.add(fun(&ChaiScript::internal_eval_file, this), "eval_file");
|
||||
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
|
||||
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
|
||||
|
||||
m_engine.add(fun(&ChaiScript::version_major), "version_major");
|
||||
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
|
||||
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
|
||||
m_engine.add(fun(&ChaiScript::version), "version");
|
||||
m_engine.add(fun(&ChaiScript::version_major, this), "version_major");
|
||||
m_engine.add(fun(&ChaiScript::version_minor, this), "version_minor");
|
||||
m_engine.add(fun(&ChaiScript::version_patch, this), "version_patch");
|
||||
m_engine.add(fun(&ChaiScript::version, this), "version");
|
||||
|
||||
m_engine.add(fun(&ChaiScript::add_global_const, this), "add_global_const");
|
||||
m_engine.add(fun(&ChaiScript::add_global, this), "add_global");
|
||||
@@ -441,16 +407,16 @@ namespace chaiscript
|
||||
ChaiScript(const ModulePtr &t_lib,
|
||||
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
||||
: m_modulepaths(std::move(t_modulepaths)), m_usepaths(std::move(t_usepaths))
|
||||
{
|
||||
if (m_module_paths.empty())
|
||||
if (m_modulepaths.empty())
|
||||
{
|
||||
m_module_paths.push_back("");
|
||||
m_modulepaths.push_back("");
|
||||
}
|
||||
|
||||
if (m_use_paths.empty())
|
||||
if (m_usepaths.empty())
|
||||
{
|
||||
m_use_paths.push_back("");
|
||||
m_usepaths.push_back("");
|
||||
}
|
||||
|
||||
build_eval_system(t_lib);
|
||||
@@ -465,16 +431,16 @@ namespace chaiscript
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
||||
: m_modulepaths(std::move(t_modulepaths)), m_usepaths(std::move(t_usepaths))
|
||||
{
|
||||
if (m_module_paths.empty())
|
||||
if (m_modulepaths.empty())
|
||||
{
|
||||
m_module_paths.push_back("");
|
||||
m_modulepaths.push_back("");
|
||||
}
|
||||
|
||||
if (m_use_paths.empty())
|
||||
if (m_usepaths.empty())
|
||||
{
|
||||
m_use_paths.push_back("");
|
||||
m_usepaths.push_back("");
|
||||
}
|
||||
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
@@ -483,7 +449,7 @@ namespace chaiscript
|
||||
|
||||
union cast_union
|
||||
{
|
||||
Boxed_Value (ChaiScript::*in_ptr)(const std::string&);
|
||||
void (ChaiScript::*in_ptr)(const std::string&);
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
@@ -491,7 +457,7 @@ namespace chaiscript
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
cast_union u;
|
||||
u.in_ptr = &ChaiScript::use;
|
||||
if ( dladdr(static_cast<void*>(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
|
||||
if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
|
||||
std::string dllpath(rInfo.dli_fname);
|
||||
const size_t lastslash = dllpath.rfind('/');
|
||||
if (lastslash != std::string::npos)
|
||||
@@ -507,7 +473,7 @@ namespace chaiscript
|
||||
dllpath = std::string(&buf.front(), pathlen);
|
||||
}
|
||||
|
||||
m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
|
||||
m_modulepaths.insert(m_modulepaths.begin(), dllpath+"/");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -518,22 +484,22 @@ namespace chaiscript
|
||||
build_eval_system(ModulePtr());
|
||||
}
|
||||
|
||||
static int version_major()
|
||||
int version_major() const
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
|
||||
static int version_minor()
|
||||
int version_minor() const
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
|
||||
static int version_patch()
|
||||
int version_patch() const
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
|
||||
static std::string version()
|
||||
std::string version() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << version_major() << "." << version_minor() << "." << version_patch();
|
||||
@@ -557,9 +523,9 @@ namespace chaiscript
|
||||
/// requested file.
|
||||
///
|
||||
/// \param[in] t_filename Filename to load and evaluate
|
||||
Boxed_Value use(const std::string &t_filename)
|
||||
void use(const std::string &t_filename)
|
||||
{
|
||||
for (const auto &path : m_use_paths)
|
||||
for (const auto &path : m_usepaths)
|
||||
{
|
||||
try {
|
||||
const auto appendedpath = path + t_filename;
|
||||
@@ -567,17 +533,15 @@ namespace chaiscript
|
||||
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);
|
||||
|
||||
Boxed_Value retval;
|
||||
|
||||
if (m_used_files.count(appendedpath) == 0)
|
||||
{
|
||||
l2.unlock();
|
||||
retval = eval_file(appendedpath);
|
||||
eval_file(appendedpath);
|
||||
l2.lock();
|
||||
m_used_files.insert(appendedpath);
|
||||
}
|
||||
}
|
||||
|
||||
return retval; // return, we loaded it, or it was already loaded
|
||||
return; // return, we loaded it, or it was already loaded
|
||||
} catch (const exception::file_not_found_error &) {
|
||||
// failed to load, try the next path
|
||||
}
|
||||
@@ -610,8 +574,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
||||
/// \warning State object does not contain the user defined type conversions of the engine. They
|
||||
/// are left out due to performance considerations involved in tracking the state
|
||||
/// \sa ChaiScript::get_state
|
||||
/// \sa ChaiScript::set_state
|
||||
struct State
|
||||
@@ -634,7 +596,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chaiscript::ChaiScript::State s = chai.get_state(); // represents bootstrapped initial state
|
||||
/// \endcode
|
||||
State get_state() const
|
||||
State get_state()
|
||||
{
|
||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||
@@ -717,7 +679,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||
/// \endcode
|
||||
ChaiScript &add(const Type_Conversion &d)
|
||||
ChaiScript &add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_engine.add(d);
|
||||
return *this;
|
||||
@@ -737,7 +699,7 @@ namespace chaiscript
|
||||
/// \param[in] t_module_name Name of the module to load
|
||||
///
|
||||
/// The module is searched for in the registered module path folders (chaiscript::ChaiScript::ChaiScript)
|
||||
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|".bundle"|"").
|
||||
/// and with standard prefixes and postfixes: ("lib"|"")\<t_module_name\>(".dll"|".so"|"").
|
||||
///
|
||||
/// Once the file is located, the system looks for the symbol "create_chaiscript_module_\<t_module_name\>".
|
||||
/// If no file can be found matching the search criteria and containing the appropriate entry point
|
||||
@@ -756,9 +718,9 @@ namespace chaiscript
|
||||
|
||||
std::vector<std::string> prefixes{"lib", "cyg", ""};
|
||||
|
||||
std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
|
||||
std::vector<std::string> postfixes{".dll", ".so", ""};
|
||||
|
||||
for (auto & elem : m_module_paths)
|
||||
for (auto & elem : m_modulepaths)
|
||||
{
|
||||
for (auto & prefix : prefixes)
|
||||
{
|
||||
@@ -766,11 +728,11 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
const auto name = elem + prefix + t_module_name + postfix;
|
||||
// std::cerr << "trying location: " << name << '\n';
|
||||
// std::cerr << "trying location: " << name << std::endl;
|
||||
load_module(version_stripped_name, name);
|
||||
return name;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
// std::cerr << "error: " << e.what() << '\n';
|
||||
// std::cerr << "error: " << e.what() << std::endl;
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -38,24 +38,7 @@ def eq(l, r) {
|
||||
|
||||
def new(x) {
|
||||
eval(type_name(x))();
|
||||
}
|
||||
|
||||
def clone(double x) {
|
||||
double(x).copy_var_attrs(x)
|
||||
}
|
||||
|
||||
def clone(string x) {
|
||||
string(x).copy_var_attrs(x)
|
||||
}
|
||||
|
||||
def clone(vector x) {
|
||||
vector(x).copy_var_attrs(x)
|
||||
}
|
||||
|
||||
|
||||
def clone(int x) {
|
||||
int(x).copy_var_attrs(x)
|
||||
}
|
||||
}
|
||||
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
|
||||
{
|
||||
@@ -472,37 +455,37 @@ def zip(x, y) {
|
||||
|
||||
|
||||
# Returns the position of the second value string in the first value string
|
||||
def string::find(string substr) {
|
||||
def string::find(substr) : is_type(substr, "string") {
|
||||
find(this, substr, size_t(0));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of last match of the second value string in the first value string
|
||||
def string::rfind(string substr) {
|
||||
def string::rfind(substr) : is_type(substr, "string") {
|
||||
rfind(this, substr, size_t(-1));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the first match of elements in the second value string in the first value string
|
||||
def string::find_first_of(string list) {
|
||||
def string::find_first_of(list) : is_type(list, "string") {
|
||||
find_first_of(this, list, size_t(0));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the last match of elements in the second value string in the first value string
|
||||
def string::find_last_of(string list) {
|
||||
def string::find_last_of(list) : is_type(list, "string") {
|
||||
find_last_of(this, list, size_t(-1));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the first non-matching element in the second value string in the first value string
|
||||
def string::find_first_not_of(string list) {
|
||||
def string::find_first_not_of(list) : is_type(list, "string") {
|
||||
find_first_not_of(this, list, size_t(0));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the last non-matching element in the second value string in the first value string
|
||||
def string::find_last_not_of(string list) {
|
||||
def string::find_last_not_of(list) : is_type(list, "string") {
|
||||
find_last_not_of(this, list, size_t(-1));
|
||||
}
|
||||
|
||||
@@ -522,7 +505,7 @@ def string::trim() {
|
||||
}
|
||||
|
||||
|
||||
def find(container, value, Function compare_func) : call_exists(range, container) {
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
|
||||
auto range := range(container);
|
||||
while (!range.empty()) {
|
||||
if (compare_func(range.front(), value)) {
|
||||
|
||||
@@ -309,7 +309,7 @@ class Range
|
||||
|
||||
/// \brief Moves the front pointer forward one
|
||||
///
|
||||
/// \post front() returns the element at front() + 1;
|
||||
/// \post front() returne the element at front() + 1;
|
||||
void pop_front();
|
||||
|
||||
};
|
||||
@@ -340,7 +340,7 @@ class Const_Range
|
||||
|
||||
/// \brief Moves the front pointer forward one
|
||||
///
|
||||
/// \post front() returns the element at front() + 1;
|
||||
/// \post front() returne the element at front() + 1;
|
||||
void pop_front();
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
@@ -38,8 +38,8 @@ namespace chaiscript
|
||||
/// { {fun(&test::function), "function"},
|
||||
/// {fun(&test::function2), "function2"},
|
||||
/// {fun(&test::function3), "function3"},
|
||||
/// {fun(static_cast<std::string(test::*)(double)>(&test::function_overload)), "function_overload" },
|
||||
/// {fun(static_cast<std::string(test::*)(int)>(&test::function_overload)), "function_overload" },
|
||||
/// {fun(static_cast<std::string(test::*)(double)>(&test::functionoverload)), "functionoverload" },
|
||||
/// {fun(static_cast<std::string(test::*)(int)>(&test::functionoverload)), "functionoverload" },
|
||||
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
|
||||
/// }
|
||||
/// );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2015 Jason Turner
|
||||
Copyright 2009-2014 Jason Turner
|
||||
Copyright 2009-2012 Jonathan Turner.
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
@@ -8,7 +8,7 @@ ChaiScript
|
||||
http://www.chaiscript.com
|
||||
|
||||
(c) 2009-2012 Jonathan Turner
|
||||
(c) 2009-2015 Jason Turner
|
||||
(c) 2009-2014 Jason Turner
|
||||
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
@@ -16,8 +16,6 @@ Release under the BSD license, see "license.txt" for details.
|
||||
Introduction
|
||||
============
|
||||
|
||||
[](https://gitter.im/ChaiScript/ChaiScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
ChaiScript is one of the only embedded scripting language designed from the
|
||||
ground up to directly target C++ and take advantage of modern C++ development
|
||||
techniques, working with the developer like he expects it to work. Being a
|
||||
@@ -35,10 +33,9 @@ Requirements
|
||||
============
|
||||
|
||||
ChaiScript requires a C++11 compiler to build with support for variadic
|
||||
templates. It has been tested with gcc 4.6 and clang 3.1 (with libcxx). MacOS
|
||||
templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx). MacOS
|
||||
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
|
||||
clang 4.0. MSVC 2013 or newer is supports also. For more information see the build
|
||||
[dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html).
|
||||
clang 4.0.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
@@ -1,68 +1,6 @@
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.7.0
|
||||
|
||||
### Changes since 5.6.0
|
||||
|
||||
* Significant code cleanups and reduction
|
||||
* Smaller builds
|
||||
* Faster compiles
|
||||
* Less runtime memory usage
|
||||
* ~2x faster runtimes
|
||||
* biicode support
|
||||
* method_missing feature added #164 @arBmind
|
||||
* Generic objects with dynamic properties support
|
||||
* Add ability to call functions contained in properties
|
||||
* Add lambda captures
|
||||
* Create [cheatsheet.md](cheatsheet.md) for all-in-one reference of features
|
||||
* Fix support for libc++
|
||||
* Eliminate clone of return value stored locally
|
||||
* Eliminate 'return' statements when last line of function
|
||||
* Reduce number of runtime exceptions occuring
|
||||
* Reduce copies / moves of return values.
|
||||
* make `use` statement return value of last statement in file
|
||||
* Add ability to access fixed array sizes
|
||||
* Add support for scientific notation floating point literals #174 @totalgee
|
||||
|
||||
|
||||
### Changes since 5.5.1
|
||||
* Throw exception on integer divide by 0
|
||||
* Add optional type specification to function declarations
|
||||
|
||||
```
|
||||
def func(int i, j, double k) {
|
||||
// i must be an int.
|
||||
// j can be anything
|
||||
// k must be a double
|
||||
// normal conversion rules still apply
|
||||
}
|
||||
```
|
||||
* Many minor fixes for compiler warnings
|
||||
* Add support for `std::future` and `std::async`
|
||||
```
|
||||
var f := async(someFunction);
|
||||
var f2 := async(someFunction2);
|
||||
|
||||
// someFunction and someFunction2 are running in parallel now
|
||||
f.get();
|
||||
f2.get();
|
||||
```
|
||||
* Fully support r-value returns, supporting move-only objects and reducing object copies
|
||||
|
||||
|
||||
### Changes since 5.5.0
|
||||
* 30% performance increase
|
||||
* Fix handling of object stack, resulting in greatly reduced memory usage
|
||||
* Code cleanups
|
||||
|
||||
### Changes since 5.4.0
|
||||
* 2x performance increase
|
||||
* Significant code cleanups
|
||||
* Throw exception if user attempts to call function on null object
|
||||
* Allow user defined type conversions
|
||||
* Fix object lifetime for nested function calls made at the global scope
|
||||
* Fix returning of boolean values from function calls
|
||||
|
||||
Current Version: 5.4.0
|
||||
|
||||
### Changes since 5.3.1
|
||||
* Decreased compile time and build size
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
|
||||
void log(const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << '\n';
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
|
||||
}
|
||||
|
||||
void log(const std::string &module, const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
@@ -28,12 +28,12 @@ void bound_log(const std::string &msg)
|
||||
|
||||
void hello_world(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
std::cout << "Hello World\n";
|
||||
std::cout << "Hello World" << std::endl;
|
||||
}
|
||||
|
||||
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
std::cout << "Hello Constructor\n";
|
||||
std::cout << "Hello Constructor" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,21 +62,20 @@ struct System
|
||||
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
|
||||
{
|
||||
std::cout << *p << '\n';
|
||||
std::cout << *p << std::endl;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char * /*argv*/[]) {
|
||||
using namespace chaiscript;
|
||||
|
||||
ChaiScript chai;
|
||||
|
||||
|
||||
//Create a new system object and share it with the chaiscript engine
|
||||
System system;
|
||||
chai.add(var(&system), "system");
|
||||
|
||||
//Add a bound callback method
|
||||
chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound");
|
||||
chai.add(fun(&System::add_callback, system), "add_callback_bound");
|
||||
|
||||
//Register the two methods of the System structure.
|
||||
chai.add(fun(&System::add_callback), "add_callback");
|
||||
@@ -123,7 +122,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//the templated version of eval:
|
||||
int i = chai.eval<int>("5+5");
|
||||
|
||||
std::cout << "5+5: " << i << '\n';
|
||||
std::cout << "5+5: " << i << std::endl;
|
||||
|
||||
//Add a new variable
|
||||
chai("var scripti = 15");
|
||||
@@ -131,9 +130,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//We can even get a handle to the variables in the system
|
||||
int &scripti = chai.eval<int &>("scripti");
|
||||
|
||||
std::cout << "scripti: " << scripti << '\n';
|
||||
std::cout << "scripti: " << scripti << std::endl;
|
||||
scripti *= 2;
|
||||
std::cout << "scripti (updated): " << scripti << '\n';
|
||||
std::cout << "scripti (updated): " << scripti << std::endl;
|
||||
chai("print(\"Scripti from chai: \" + to_string(scripti))");
|
||||
|
||||
//To do: Add examples of handling Boxed_Values directly when needed
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
puts(helloWorld("Bob12345"))
|
||||
}
|
||||
|
||||
@@ -1,405 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
|
||||
char *mystrdup(const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc(len + 1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len + 1, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d, s, len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
std::string retval;
|
||||
std::cout << p;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char*){}
|
||||
void using_history(){}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
std::vector<std::string>(*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = t_path;
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
return{ exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\" };
|
||||
}
|
||||
#else
|
||||
|
||||
std::string exepath;
|
||||
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
Dl_info rInfo;
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
if (!dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
exepath = std::string(rInfo.dli_fname);
|
||||
}
|
||||
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void help(int n) {
|
||||
if (n >= 0) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
|
||||
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
|
||||
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "usage : chai [option]+" << std::endl;
|
||||
std::cout << "option:" << std::endl;
|
||||
std::cout << " -h | --help" << std::endl;
|
||||
std::cout << " -i | --interactive" << std::endl;
|
||||
std::cout << " -c | --command cmd" << std::endl;
|
||||
std::cout << " -v | --version" << std::endl;
|
||||
std::cout << " - --stdin" << std::endl;
|
||||
std::cout << " filepath" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string helloWorld(const std::string &t_name)
|
||||
{
|
||||
return "Hello " + t_name + "!";
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
throw std::runtime_error("no exception throw");
|
||||
}
|
||||
|
||||
std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if (!std::cin.eof()) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if (input_raw) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos + 1, std::string::npos);
|
||||
}
|
||||
|
||||
retval = val;
|
||||
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if (retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// We have to wrap exit with our own because Clang has a hard time with
|
||||
// function pointers to functions with special attributes (system exit being marked NORETURN)
|
||||
void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript& chai)
|
||||
{
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
std::string input = get_next_command();
|
||||
try {
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.push_back("");
|
||||
if (usepath)
|
||||
{
|
||||
usepaths.push_back(usepath);
|
||||
}
|
||||
|
||||
std::vector<std::string> modulepaths;
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
|
||||
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths);
|
||||
|
||||
chai.add(chaiscript::fun(&myexit), "exit");
|
||||
chai.add(chaiscript::fun(&myexit), "quit");
|
||||
chai.add(chaiscript::fun(&help), "help");
|
||||
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
|
||||
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
|
||||
|
||||
chai.add(chaiscript::fun(&helloWorld), "helloWorld");
|
||||
|
||||
clock_t begin = clock();
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
std::string str = helloWorld("Bob12345");
|
||||
fwrite(str.c_str(), 1, str.size(), stdout);
|
||||
}
|
||||
|
||||
clock_t end = clock();
|
||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
|
||||
//begin = clock();
|
||||
|
||||
////for (int i = 0; i < 1000; i++)
|
||||
////{
|
||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
||||
////}
|
||||
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
|
||||
|
||||
//end = clock();
|
||||
//elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
//printf("**MyProgram::time= %lf\n", elapsed_secs);
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (i == 0 && argc > 1) {
|
||||
++i;
|
||||
}
|
||||
|
||||
std::string arg(i ? argv[i] : "--interactive");
|
||||
|
||||
enum {
|
||||
eInteractive
|
||||
, eCommand
|
||||
, eFile
|
||||
} mode = eCommand;
|
||||
|
||||
if (arg == "-c" || arg == "--command") {
|
||||
if ((i + 1) >= argc) {
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
arg = argv[++i];
|
||||
}
|
||||
}
|
||||
else if (arg == "-" || arg == "--stdin") {
|
||||
arg = "";
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
arg += line + '\n';
|
||||
}
|
||||
}
|
||||
else if (arg == "-v" || arg == "--version") {
|
||||
arg = "version()";
|
||||
}
|
||||
else if (arg == "-h" || arg == "--help") {
|
||||
arg = "help(-1)";
|
||||
}
|
||||
else if (arg == "-i" || arg == "--interactive") {
|
||||
mode = eInteractive;
|
||||
}
|
||||
else if (arg.find('-') == 0) {
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
mode = eFile;
|
||||
}
|
||||
|
||||
chaiscript::Boxed_Value val;
|
||||
try {
|
||||
switch (mode) {
|
||||
case eInteractive: interactive(chai); break;
|
||||
case eCommand: val = chai.eval(arg); break;
|
||||
case eFile: {
|
||||
begin = clock();
|
||||
|
||||
val = chai.eval_file(arg);
|
||||
|
||||
end = clock();
|
||||
double elapsed_secs1 = double(end - begin) / CLOCKS_PER_SEC;
|
||||
printf("**C++::time= %.10f\n", elapsed_secs);
|
||||
printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ class BaseClass
|
||||
{
|
||||
}
|
||||
|
||||
BaseClass(const BaseClass &) = default;
|
||||
|
||||
virtual ~BaseClass() {}
|
||||
virtual ~BaseClass() = default;
|
||||
|
||||
virtual std::string doSomething(float, double) const = 0;
|
||||
|
||||
@@ -44,14 +42,14 @@ class ChaiScriptDerived : public BaseClass
|
||||
tie(t_funcs.at(1), m_validateValueImpl);
|
||||
}
|
||||
|
||||
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
|
||||
std::string doSomething(float f, double d) const override
|
||||
{
|
||||
assert(m_doSomethingImpl);
|
||||
return m_doSomethingImpl(*this, f, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
|
||||
bool validateValue(const std::string &t_val) override
|
||||
{
|
||||
assert(m_validateValueImpl);
|
||||
return m_validateValueImpl(*this, t_val);
|
||||
|
||||
@@ -54,7 +54,7 @@ class test
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << '\n';
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
77
src/main.cpp
77
src/main.cpp
@@ -1,17 +1,14 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
@@ -21,10 +18,10 @@
|
||||
|
||||
char *mystrdup (const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
char *d = static_cast<char*>(malloc (len+1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len+1, s); // Copy the characters
|
||||
strcpy_s(d, len, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d,s,len); // Copy the characters
|
||||
#endif
|
||||
@@ -139,22 +136,26 @@ std::vector<std::string> default_search_paths()
|
||||
|
||||
void help(int n) {
|
||||
if ( n >= 0 ) {
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
|
||||
std::cout << "Additionally, you can inspect the runtime system using:\n";
|
||||
std::cout << " dump_system() - outputs all functions registered to the system\n";
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol\n";
|
||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
|
||||
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
|
||||
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
|
||||
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
|
||||
} else {
|
||||
std::cout << "usage : chai [option]+\n";
|
||||
std::cout << "option:" << '\n';
|
||||
std::cout << " -h | --help" << '\n';
|
||||
std::cout << " -i | --interactive" << '\n';
|
||||
std::cout << " -c | --command cmd" << '\n';
|
||||
std::cout << " -v | --version" << '\n';
|
||||
std::cout << " - --stdin" << '\n';
|
||||
std::cout << " filepath" << '\n';
|
||||
std::cout << "usage : chai [option]+" << std::endl;
|
||||
std::cout << "option:" << std::endl;
|
||||
std::cout << " -h | --help" << std::endl;
|
||||
std::cout << " -i | --interactive" << std::endl;
|
||||
std::cout << " -c | --command cmd" << std::endl;
|
||||
std::cout << " -v | --version" << std::endl;
|
||||
std::cout << " - --stdin" << std::endl;
|
||||
std::cout << " filepath" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void version(int){
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
@@ -230,7 +231,7 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
@@ -238,24 +239,17 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")";
|
||||
std::cout << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
||||
}
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double now()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto now = high_resolution_clock::now();
|
||||
return duration_cast<duration<double>>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
@@ -293,10 +287,9 @@ int main(int argc, char *argv[])
|
||||
chai.add(chaiscript::fun(&myexit), "exit");
|
||||
chai.add(chaiscript::fun(&myexit), "quit");
|
||||
chai.add(chaiscript::fun(&help), "help");
|
||||
chai.add(chaiscript::fun(&version), "version");
|
||||
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
|
||||
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
|
||||
chai.add(chaiscript::fun(&now), "now");
|
||||
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if ( i == 0 && argc > 1 ) {
|
||||
@@ -312,7 +305,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if ( arg == "-c" || arg == "--command" ) {
|
||||
if ( (i+1) >= argc ) {
|
||||
std::cout << "insufficient input following " << arg << '\n';
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
arg = argv[++i];
|
||||
@@ -324,13 +317,13 @@ int main(int argc, char *argv[])
|
||||
arg += line + '\n' ;
|
||||
}
|
||||
} else if ( arg == "-v" || arg == "--version" ) {
|
||||
arg = "version()" ;
|
||||
arg = "version(0)" ;
|
||||
} else if ( arg == "-h" || arg == "--help" ) {
|
||||
arg = "help(-1)";
|
||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
||||
mode = eInteractive ;
|
||||
} else if ( arg.find('-') == 0 ) {
|
||||
std::cout << "unrecognised argument " << arg << '\n';
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
mode = eFile;
|
||||
@@ -339,23 +332,19 @@ int main(int argc, char *argv[])
|
||||
chaiscript::Boxed_Value val ;
|
||||
try {
|
||||
switch ( mode ) {
|
||||
case eInteractive:
|
||||
interactive(chai);
|
||||
break;
|
||||
case eCommand:
|
||||
val = chai.eval(arg);
|
||||
break;
|
||||
case eFile:
|
||||
val = chai.eval_file(arg);
|
||||
case eInteractive : interactive(chai); break;
|
||||
case eCommand : val = chai.eval(arg); break;
|
||||
case eFile : val = chai.eval_file(arg); break;
|
||||
default : std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << '\n';
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2015, Jason Turner (jason@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
@@ -1,26 +1,13 @@
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4351)
|
||||
#endif
|
||||
// MSVC 12 warns that we are using new (correct) behavior
|
||||
TestBaseType() : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
|
||||
#ifdef CHAISCRIPT_MSVC_12
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
TestBaseType(const TestBaseType &) = default;
|
||||
TestBaseType() : val(10), const_val(15) { }
|
||||
TestBaseType(int) : val(10), const_val(15) {}
|
||||
TestBaseType(int *) : val(10), const_val(15) {}
|
||||
virtual ~TestBaseType() {}
|
||||
virtual int func() { return 0; }
|
||||
|
||||
@@ -31,35 +18,8 @@ class TestBaseType
|
||||
int val;
|
||||
const int const_val;
|
||||
|
||||
int mdarray[2][3][5];
|
||||
std::function<int (int)> func_member;
|
||||
|
||||
private:
|
||||
TestBaseType &operator=(const TestBaseType &) = delete;
|
||||
};
|
||||
|
||||
class Type2
|
||||
{
|
||||
public:
|
||||
Type2(TestBaseType t_bt)
|
||||
: m_bt(std::move(t_bt)),
|
||||
m_str("Hello World")
|
||||
{
|
||||
}
|
||||
|
||||
int get_val() const
|
||||
{
|
||||
return m_bt.val;
|
||||
}
|
||||
|
||||
const char *get_str() const
|
||||
{
|
||||
return m_str.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
TestBaseType m_bt;
|
||||
std::string m_str;
|
||||
TestBaseType &operator=(const TestBaseType &);
|
||||
};
|
||||
|
||||
enum TestEnum
|
||||
@@ -76,20 +36,16 @@ class TestDerivedType : public TestBaseType
|
||||
{
|
||||
public:
|
||||
virtual ~TestDerivedType() {}
|
||||
TestDerivedType(const TestDerivedType &) = default;
|
||||
TestDerivedType() = default;
|
||||
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
|
||||
int derived_only_func() { return 19; }
|
||||
|
||||
private:
|
||||
TestDerivedType &operator=(const TestDerivedType &) = delete;
|
||||
TestDerivedType &operator=(const TestDerivedType &);
|
||||
};
|
||||
|
||||
class TestMoreDerivedType : public TestDerivedType
|
||||
{
|
||||
public:
|
||||
TestMoreDerivedType(const TestMoreDerivedType &) = default;
|
||||
TestMoreDerivedType() = default;
|
||||
virtual ~TestMoreDerivedType() {}
|
||||
};
|
||||
|
||||
@@ -113,11 +69,9 @@ std::string hello_world()
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
static int global_i = 1;
|
||||
|
||||
int *get_new_int()
|
||||
{
|
||||
return &global_i;
|
||||
return new int(1);
|
||||
}
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
@@ -141,7 +95,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
|
||||
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
|
||||
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::user_type<Type2>(), "Type2");
|
||||
|
||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
@@ -172,19 +125,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
|
||||
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
|
||||
|
||||
#ifndef CHAISCRIPT_MSVC_12
|
||||
// we cannot support these in MSVC_12 because of a bug in the implementation of
|
||||
// std::reference_wrapper
|
||||
// Array types
|
||||
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
|
||||
m->add(chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5"));
|
||||
m->add(chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5"));
|
||||
m->add(chaiscript::bootstrap::array<int[5]>("IntArray_5"));
|
||||
// end array types
|
||||
#endif
|
||||
|
||||
// member that is a function
|
||||
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
|
||||
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
||||
|
||||
|
||||
@@ -195,12 +135,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&to_int), "to_int");
|
||||
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
|
||||
|
||||
m->add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { return Type2(t_bt); }));
|
||||
|
||||
m->add(chaiscript::fun(&Type2::get_val), "get_val");
|
||||
m->add(chaiscript::fun(&Type2::get_str), "get_str");
|
||||
m->add(chaiscript::type_conversion<const char *, std::string>());
|
||||
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
70
unittests/arithmetic_conversions_test.cpp
Normal file
70
unittests/arithmetic_conversions_test.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Tests to make sure that type conversions happen only when they should
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
void f1(int)
|
||||
{
|
||||
}
|
||||
|
||||
void f4(std::string)
|
||||
{
|
||||
}
|
||||
|
||||
void f2(int)
|
||||
{
|
||||
}
|
||||
|
||||
void f3(double)
|
||||
{
|
||||
}
|
||||
|
||||
void f_func_return(const std::function<unsigned int (unsigned long)> &f)
|
||||
{
|
||||
// test the ability to return an unsigned with auto conversion
|
||||
f(4);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&f1), "f1");
|
||||
chai.add(chaiscript::fun(&f2), "f2");
|
||||
chai.add(chaiscript::fun(&f3), "f2");
|
||||
chai.add(chaiscript::fun(&f1), "f3");
|
||||
chai.add(chaiscript::fun(&f4), "f3");
|
||||
|
||||
chai.add(chaiscript::fun(&f_func_return), "func_return");
|
||||
|
||||
// no overloads
|
||||
chai.eval("f1(0)");
|
||||
chai.eval("f1(0l)");
|
||||
chai.eval("f1(0ul)");
|
||||
chai.eval("f1(0ll)");
|
||||
chai.eval("f1(0ull)");
|
||||
chai.eval("f1(0.0)");
|
||||
chai.eval("f1(0.0f)");
|
||||
chai.eval("f1(0.0l)");
|
||||
|
||||
// expected overloads
|
||||
chai.eval("f2(1)");
|
||||
chai.eval("f2(1.0)");
|
||||
|
||||
// 1 non-arithmetic overload
|
||||
chai.eval("f2(1.0)");
|
||||
|
||||
// various options for returning with conversions from chaiscript
|
||||
chai.eval("func_return(fun(x) { return 5u; })");
|
||||
chai.eval("func_return(fun(x) { return 5; })");
|
||||
chai.eval("func_return(fun(x) { return 5.0f; })");
|
||||
|
||||
// this is the one call we expect to fail, ambiguous overloads
|
||||
try {
|
||||
chai.eval("f2(1.0l)");
|
||||
} catch (const std::exception &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// if the last one did not throw, we failed
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
load_module("test_module")
|
||||
|
||||
auto t0 = TestBaseType()
|
||||
|
||||
assert_true(t0.mdarray.size() == 2)
|
||||
assert_true(t0.mdarray[0].size() == 3)
|
||||
assert_true(t0.mdarray[0][0].size() == 5)
|
||||
|
||||
t0.mdarray[1][2][4] = 15;
|
||||
|
||||
assert_true(t0.mdarray[1][2][4] == 15)
|
||||
|
||||
@@ -15,16 +15,16 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
use(ret);
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
|
||||
if (expectedpass) {
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << std::endl;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << '\n';
|
||||
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << std::endl;
|
||||
return false;
|
||||
} catch (...) {
|
||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion.\n";
|
||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
|
||||
<< " To: "
|
||||
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not\n";
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not" << std::endl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -117,37 +117,37 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
ispod && true, ispod && true, ispod && true, true, true);
|
||||
|
||||
passed &= do_test<T>(const_var(i), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
passed &= do_test<T>(var(&i), true, true, true, true, true,
|
||||
true, true, true, false, false,
|
||||
false, false, false, false, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
ispod && true, ispod && true, ispod && true, true, true);
|
||||
|
||||
passed &= do_test<T>(const_var(&i), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, ispod && false, true);
|
||||
|
||||
passed &= do_test<T>(var(std::ref(i)), true, true, true, true, true,
|
||||
true, true, true, false, false,
|
||||
false, false, false, false, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
ispod && true, ispod && true, ispod && true, true, true);
|
||||
|
||||
passed &= do_test<T>(var(std::cref(i)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
/** Const Reference Variable tests */
|
||||
|
||||
@@ -158,33 +158,33 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
ispod && true, ispod && true, ispod && true, true, true);
|
||||
|
||||
// But a pointer or reference to it should be necessarily const
|
||||
passed &= do_test<T>(var(&ir), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
passed &= do_test<T>(var(std::ref(ir)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
// Make sure const of const works too
|
||||
passed &= do_test<T>(const_var(&ir), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
passed &= do_test<T>(const_var(std::ref(ir)), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
/** Const Reference Variable tests */
|
||||
|
||||
@@ -194,14 +194,14 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
// make sure const of const works
|
||||
passed &= do_test<T>(const_var(cip), true, true, false, true, false,
|
||||
true, false, true, false, false,
|
||||
false, false, false, false, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
/** shared_ptr tests **/
|
||||
|
||||
@@ -211,13 +211,13 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
true, true, true, true, true,
|
||||
ispod, ispod, ispod, true, true);
|
||||
ispod && true, ispod && true, ispod && true, true, true);
|
||||
|
||||
passed &= do_test<T>(const_var(ip), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
/** const shared_ptr tests **/
|
||||
std::shared_ptr<const T> ipc(new T(initial));
|
||||
@@ -226,14 +226,14 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
// const of this should be the same, making sure it compiles
|
||||
passed &= do_test<T>(const_var(ipc), true, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
|
||||
|
||||
/** Double ptr tests **/
|
||||
@@ -245,7 +245,7 @@ bool built_in_type_test(const T &initial, bool ispod)
|
||||
true, false, true, false, true,
|
||||
false, true, false, true, false,
|
||||
true, false, true, false, true,
|
||||
ispod, ispod, ispod, false, true);
|
||||
ispod && true, ispod && true, ispod && true, false, true);
|
||||
*/
|
||||
|
||||
return passed;
|
||||
@@ -264,26 +264,21 @@ bool pointer_test(const T& default_value, const T& new_value)
|
||||
|
||||
|
||||
if (p != (*result) ) {
|
||||
std::cerr << "Pointer passed in different than one returned\n";
|
||||
delete p;
|
||||
std::cerr << "Pointer passed in different than one returned" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*p != *(*result) ) {
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?\n";
|
||||
delete p;
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete p;
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
std::cerr << "Bad boxed cast performing ** to ** test\n";
|
||||
delete p;
|
||||
std::cerr << "Bad boxed cast performing ** to ** test" << std::endl;
|
||||
return false;
|
||||
} catch (...) {
|
||||
std::cerr << "Unknown exception performing ** to ** test\n";
|
||||
delete p;
|
||||
std::cerr << "Unknown exception performing ** to ** test" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
9427
unittests/catch.hpp
9427
unittests/catch.hpp
File diff suppressed because it is too large
Load Diff
@@ -1,725 +0,0 @@
|
||||
// All of these are necessary because of catch.hpp. It's OK, they'll be
|
||||
// caught in other cpp files if chaiscript causes them
|
||||
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190 4640 28251 4702 6330)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
// lambda_tests
|
||||
TEST_CASE("C++11 Lambdas Can Be Registered")
|
||||
{
|
||||
|
||||
// We cannot deduce the type of a lambda expression, you must either wrap it
|
||||
// in an std::function or provide the signature
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
// provide the signature
|
||||
chai.add(chaiscript::fun<std::string ()>([] { return "hello"; } ), "f1");
|
||||
|
||||
// wrap
|
||||
chai.add(chaiscript::fun(std::function<std::string ()>([] { return "world"; } )), "f2");
|
||||
|
||||
CHECK(chai.eval<std::string>("f1()") == "hello");
|
||||
CHECK(chai.eval<std::string>("f2()") == "world");
|
||||
}
|
||||
|
||||
|
||||
// dynamic_object tests
|
||||
TEST_CASE("Dynamic_Object attributes can be shared with C++")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai("attr bob::z; def bob::bob() { this.z = 10 }; auto x = bob()");
|
||||
|
||||
chaiscript::dispatch::Dynamic_Object &mydo = chai.eval<chaiscript::dispatch::Dynamic_Object &>("x");
|
||||
|
||||
CHECK(mydo.get_type_name() == "bob");
|
||||
|
||||
CHECK(chaiscript::boxed_cast<int>(mydo.get_attr("z")) == 10);
|
||||
|
||||
chai("x.z = 15");
|
||||
|
||||
CHECK(chaiscript::boxed_cast<int>(mydo.get_attr("z")) == 15);
|
||||
|
||||
int &z = chaiscript::boxed_cast<int&>(mydo.get_attr("z"));
|
||||
|
||||
CHECK(z == 15);
|
||||
|
||||
z = 20;
|
||||
|
||||
CHECK(z == 20);
|
||||
CHECK(chaiscript::boxed_cast<int>(chai("x.z")) == 20);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Function objects can be created from chaiscript functions")
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.eval("def func() { print(\"Hello World\"); } ");
|
||||
|
||||
std::function<void ()> f = chai.eval<std::function<void ()> >("func");
|
||||
f();
|
||||
|
||||
CHECK(chai.eval<std::function<std::string (int)> >("to_string")(6) == "6");
|
||||
CHECK(chai.eval<std::function<std::string (const chaiscript::Boxed_Value &)> >("to_string")(chaiscript::var(6)) == "6");
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("ChaiScript can be created and destroyed on heap")
|
||||
{
|
||||
chaiscript::ChaiScript *chai = new chaiscript::ChaiScript();
|
||||
delete chai;
|
||||
}
|
||||
|
||||
|
||||
///////// Arithmetic Conversions
|
||||
|
||||
// Tests to make sure that type conversions happen only when they should
|
||||
void arithmetic_conversions_f1(int)
|
||||
{
|
||||
}
|
||||
|
||||
void arithmetic_conversions_f4(std::string)
|
||||
{
|
||||
}
|
||||
|
||||
void arithmetic_conversions_f2(int)
|
||||
{
|
||||
}
|
||||
|
||||
void arithmetic_conversions_f3(double)
|
||||
{
|
||||
}
|
||||
|
||||
void arithmetic_conversions_f_func_return(const std::function<unsigned int (unsigned long)> &f)
|
||||
{
|
||||
// test the ability to return an unsigned with auto conversion
|
||||
f(4);
|
||||
}
|
||||
|
||||
TEST_CASE("Test automatic arithmetic conversions")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&arithmetic_conversions_f1), "f1");
|
||||
chai.add(chaiscript::fun(&arithmetic_conversions_f2), "f2");
|
||||
chai.add(chaiscript::fun(&arithmetic_conversions_f3), "f2");
|
||||
chai.add(chaiscript::fun(&arithmetic_conversions_f1), "f3");
|
||||
chai.add(chaiscript::fun(&arithmetic_conversions_f4), "f3");
|
||||
|
||||
chai.add(chaiscript::fun(&arithmetic_conversions_f_func_return), "func_return");
|
||||
|
||||
// no overloads
|
||||
chai.eval("f1(0)");
|
||||
chai.eval("f1(0l)");
|
||||
chai.eval("f1(0ul)");
|
||||
chai.eval("f1(0ll)");
|
||||
chai.eval("f1(0ull)");
|
||||
chai.eval("f1(0.0)");
|
||||
chai.eval("f1(0.0f)");
|
||||
chai.eval("f1(0.0l)");
|
||||
|
||||
// expected overloads
|
||||
chai.eval("f2(1)");
|
||||
chai.eval("f2(1.0)");
|
||||
|
||||
// 1 non-arithmetic overload
|
||||
chai.eval("f2(1.0)");
|
||||
|
||||
// various options for returning with conversions from chaiscript
|
||||
chai.eval("func_return(fun(x) { return 5u; })");
|
||||
chai.eval("func_return(fun(x) { return 5; })");
|
||||
chai.eval("func_return(fun(x) { return 5.0f; })");
|
||||
|
||||
CHECK_THROWS(chai.eval("f2(1.0l)"));
|
||||
}
|
||||
|
||||
|
||||
/////// Exception handling
|
||||
|
||||
|
||||
TEST_CASE("Generic exception handling with C++")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"));");
|
||||
REQUIRE(false);
|
||||
} catch (const chaiscript::Boxed_Value &bv) {
|
||||
const std::exception &e = chai.boxed_cast<const std::exception &>(bv);
|
||||
CHECK(e.what() == std::string("error"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Throw an int")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(1)", chaiscript::exception_specification<int>());
|
||||
REQUIRE(false);
|
||||
} catch (int e) {
|
||||
CHECK(e == 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Throw int or double")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(1.0)", chaiscript::exception_specification<int, double>());
|
||||
REQUIRE(false);
|
||||
} catch (const double e) {
|
||||
CHECK(e == 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Throw a runtime_error")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
REQUIRE(false);
|
||||
} catch (const double) {
|
||||
REQUIRE(false);
|
||||
} catch (int) {
|
||||
REQUIRE(false);
|
||||
} catch (float) {
|
||||
REQUIRE(false);
|
||||
} catch (const std::string &) {
|
||||
REQUIRE(false);
|
||||
} catch (const std::exception &) {
|
||||
REQUIRE(true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Throw unhandled type")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(\"error\")", chaiscript::exception_specification<int, double, float, const std::exception &>());
|
||||
REQUIRE(false);
|
||||
} catch (double) {
|
||||
REQUIRE(false);
|
||||
} catch (int) {
|
||||
REQUIRE(false);
|
||||
} catch (float) {
|
||||
REQUIRE(false);
|
||||
} catch (const std::exception &) {
|
||||
REQUIRE(false);
|
||||
} catch (const chaiscript::Boxed_Value &) {
|
||||
REQUIRE(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////// Tests to make sure no arity, dispatch or guard errors leak up past eval
|
||||
|
||||
|
||||
int expected_eval_errors_test_one(const int &)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TEST_CASE("No unexpected exceptions leak")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&expected_eval_errors_test_one), "test_fun");
|
||||
|
||||
chai.eval("def guard_fun(i) : i.get_type_info().is_type_arithmetic() {} ");
|
||||
|
||||
//// Dot notation
|
||||
|
||||
// non-existent function
|
||||
CHECK_THROWS_AS(chai.eval("\"test\".test_one()"), chaiscript::exception::eval_error);
|
||||
// wrong parameter type
|
||||
CHECK_THROWS_AS(chai.eval("\"test\".test_fun()"), chaiscript::exception::eval_error);
|
||||
|
||||
// wrong number of parameters
|
||||
CHECK_THROWS_AS(chai.eval("\"test\".test_fun(1)"), chaiscript::exception::eval_error);
|
||||
|
||||
// guard failure
|
||||
CHECK_THROWS_AS(chai.eval("\"test\".guard_fun()"), chaiscript::exception::eval_error);
|
||||
|
||||
|
||||
// regular notation
|
||||
|
||||
// non-existent function
|
||||
CHECK_THROWS_AS(chai.eval("test_one(\"test\")"), chaiscript::exception::eval_error);
|
||||
|
||||
// wrong parameter type
|
||||
CHECK_THROWS_AS(chai.eval("test_fun(\"test\")"), chaiscript::exception::eval_error);
|
||||
|
||||
// wrong number of parameters
|
||||
CHECK_THROWS_AS(chai.eval("test_fun(\"test\")"), chaiscript::exception::eval_error);
|
||||
|
||||
// guard failure
|
||||
CHECK_THROWS_AS(chai.eval("guard_fun(\"test\")"), chaiscript::exception::eval_error);
|
||||
|
||||
|
||||
// index operator
|
||||
CHECK_THROWS_AS(chai.eval("var a = [1,2,3]; a[\"bob\"];"), chaiscript::exception::eval_error);
|
||||
|
||||
// unary operator
|
||||
CHECK_THROWS_AS(chai.eval("++\"bob\""), chaiscript::exception::eval_error);
|
||||
|
||||
// binary operator
|
||||
CHECK_THROWS_AS(chai.eval("\"bob\" + 1"), chaiscript::exception::eval_error);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////// Tests to make sure that the order in which function dispatches occur is correct
|
||||
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
int function_ordering_test_one(const int &)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int function_ordering_test_two(int &)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
TEST_CASE("Function ordering")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.eval("def test_fun(x) { return 3; }");
|
||||
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
|
||||
// chai.eval("def test_fun(x) { return 5; }");
|
||||
chai.add(chaiscript::fun(&function_ordering_test_one), "test_fun");
|
||||
chai.add(chaiscript::fun(&function_ordering_test_two), "test_fun");
|
||||
|
||||
CHECK(chai.eval<int>("test_fun(1)") == 1);
|
||||
CHECK(chai.eval<int>("auto i = 1; test_fun(i)") == 2);
|
||||
CHECK(chai.eval<int>("test_fun(\"bob\")") == 3);
|
||||
CHECK(chai.eval<int>("test_fun(\"hi\")") == 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int functor_cast_test_call(const std::function<int (int)> &f, int val)
|
||||
{
|
||||
return f(val);
|
||||
}
|
||||
|
||||
TEST_CASE("Functor cast")
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&functor_cast_test_call), "test_call");
|
||||
|
||||
chai.eval("def func(i) { return i * 6; };");
|
||||
int d = chai.eval<int>("test_call(func, 3)");
|
||||
|
||||
CHECK(d == 3 * 6);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int set_state_test_myfun()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
TEST_CASE("Set and restore chai state")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
// save the initial state of globals and locals
|
||||
chaiscript::ChaiScript::State firststate = chai.get_state();
|
||||
std::map<std::string, chaiscript::Boxed_Value> locals = chai.get_locals();
|
||||
|
||||
// add some new globals and locals
|
||||
chai.add(chaiscript::var(1), "i");
|
||||
|
||||
chai.add(chaiscript::fun(&set_state_test_myfun), "myfun");
|
||||
|
||||
|
||||
CHECK(chai.eval<int>("myfun()") == 2);
|
||||
|
||||
CHECK(chai.eval<int>("i") == 1);
|
||||
|
||||
chai.set_state(firststate);
|
||||
|
||||
// set state should have reverted the state of the functions and dropped
|
||||
// the 'myfun'
|
||||
|
||||
CHECK_THROWS_AS(chai.eval<int>("myfun()"), chaiscript::exception::eval_error &);
|
||||
|
||||
// set state should not affect the local variables
|
||||
CHECK(chai.eval<int>("i") == 1);
|
||||
|
||||
// After resetting the locals we expect the 'i' to be gone
|
||||
chai.set_locals(locals);
|
||||
|
||||
CHECK_THROWS_AS(chai.eval<int>("i"), chaiscript::exception::eval_error &);
|
||||
}
|
||||
|
||||
|
||||
//// Short comparisons
|
||||
|
||||
class Short_Comparison_Test {
|
||||
public:
|
||||
Short_Comparison_Test() : value_(5) {}
|
||||
|
||||
short get_value() { return value_; }
|
||||
|
||||
short value_;
|
||||
};
|
||||
|
||||
TEST_CASE("Short comparison with int")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::user_type<Short_Comparison_Test>(), "Test");
|
||||
chai.add(chaiscript::constructor<Short_Comparison_Test()>(), "Test");
|
||||
|
||||
chai.add(chaiscript::fun(&Short_Comparison_Test::get_value), "get_value");
|
||||
|
||||
chai.eval("auto &t = Test();");
|
||||
|
||||
CHECK(chai.eval<bool>("t.get_value() == 5"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///// Test lookup of type names
|
||||
|
||||
|
||||
class Type_Name_MyClass
|
||||
{
|
||||
};
|
||||
|
||||
TEST_CASE("Test lookup of type names")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
auto type = chaiscript::user_type<Type_Name_MyClass>();
|
||||
chai.add(type, "MyClass");
|
||||
|
||||
CHECK(chai.get_type_name(type) == "MyClass");
|
||||
CHECK(chai.get_type_name<Type_Name_MyClass>() == "MyClass");
|
||||
}
|
||||
|
||||
|
||||
/////// make sure many chaiscript objects can exist simultaneously
|
||||
|
||||
|
||||
int simultaneous_chaiscript_do_something(int i)
|
||||
{
|
||||
return i + 2;
|
||||
}
|
||||
|
||||
int simultaneous_chaiscript_do_something_else(int i)
|
||||
{
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Simultaneous ChaiScript tests")
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&simultaneous_chaiscript_do_something), "do_something");
|
||||
chai.add(chaiscript::var(1), "i");
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
chaiscript::ChaiScript chai2;
|
||||
chai2.add(chaiscript::fun(&simultaneous_chaiscript_do_something_else), "do_something_else");
|
||||
|
||||
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_THROWS_AS(chai2.eval("do_something(1)"), chaiscript::exception::eval_error &);
|
||||
CHECK_THROWS_AS(chai2.eval("i"), chaiscript::exception::eval_error &);
|
||||
CHECK_NOTHROW(chai2.eval("do_something_else(1)"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////// test utility functions
|
||||
|
||||
class Utility_Test
|
||||
{
|
||||
public:
|
||||
void function() {}
|
||||
std::string function2() { return "Function2"; }
|
||||
void function3() {}
|
||||
std::string functionOverload(double) { return "double"; }
|
||||
std::string functionOverload(int) { return "int"; }
|
||||
};
|
||||
|
||||
TEST_CASE("Utility_Test utility class wrapper")
|
||||
{
|
||||
|
||||
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
/// \todo fix overload resolution for fun<>
|
||||
chaiscript::utility::add_class<Utility_Test>(*m,
|
||||
"Utility_Test",
|
||||
{ constructor<Utility_Test ()>(),
|
||||
constructor<Utility_Test (const Utility_Test &)>() },
|
||||
{ {fun(&Utility_Test::function), "function"},
|
||||
{fun(&Utility_Test::function2), "function2"},
|
||||
{fun(&Utility_Test::function3), "function3"},
|
||||
{fun(static_cast<std::string(Utility_Test::*)(double)>(&Utility_Test::functionOverload)), "functionOverload" },
|
||||
{fun(static_cast<std::string(Utility_Test::*)(int)>(&Utility_Test::functionOverload)), "functionOverload" },
|
||||
{fun(static_cast<Utility_Test & (Utility_Test::*)(const Utility_Test &)>(&Utility_Test::operator=)), "=" }
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(m);
|
||||
|
||||
CHECK(chai.eval<std::string>("auto t = Utility_Test(); t.function2(); ") == "Function2");
|
||||
CHECK(chai.eval<std::string>("auto t2 = Utility_Test(); t2.functionOverload(1); ") == "int");
|
||||
CHECK(chai.eval<std::string>("auto t3 = Utility_Test(); t3.functionOverload(1.1); ") == "double");
|
||||
chai.eval("t = Utility_Test();");
|
||||
|
||||
}
|
||||
|
||||
|
||||
////// Object copy count test
|
||||
|
||||
class Object_Copy_Count_Test
|
||||
{
|
||||
public:
|
||||
Object_Copy_Count_Test()
|
||||
{
|
||||
std::cout << "Object_Copy_Count_Test()\n";
|
||||
++constructcount();
|
||||
}
|
||||
|
||||
Object_Copy_Count_Test(const Object_Copy_Count_Test &)
|
||||
{
|
||||
std::cout << "Object_Copy_Count_Test(const Object_Copy_Count_Test &)\n";
|
||||
++copycount();
|
||||
}
|
||||
|
||||
Object_Copy_Count_Test(Object_Copy_Count_Test &&)
|
||||
{
|
||||
std::cout << "Object_Copy_Count_Test(Object_Copy_Count_Test &&)\n";
|
||||
++movecount();
|
||||
}
|
||||
|
||||
~Object_Copy_Count_Test()
|
||||
{
|
||||
std::cout << "~Object_Copy_Count_Test()\n";
|
||||
++destructcount();
|
||||
}
|
||||
|
||||
static int& constructcount()
|
||||
{
|
||||
static int c = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int& copycount()
|
||||
{
|
||||
static int c = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int& movecount()
|
||||
{
|
||||
static int c = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int& destructcount()
|
||||
{
|
||||
static int c = 0;
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
Object_Copy_Count_Test object_copy_count_create()
|
||||
{
|
||||
return Object_Copy_Count_Test();
|
||||
}
|
||||
|
||||
TEST_CASE("Object copy counts")
|
||||
{
|
||||
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||
|
||||
m->add(chaiscript::user_type<Object_Copy_Count_Test>(), "Object_Copy_Count_Test");
|
||||
m->add(chaiscript::constructor<Object_Copy_Count_Test()>(), "Object_Copy_Count_Test");
|
||||
m->add(chaiscript::constructor<Object_Copy_Count_Test(const Object_Copy_Count_Test &)>(), "Object_Copy_Count_Test");
|
||||
m->add(chaiscript::fun(&object_copy_count_create), "create");
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(m);
|
||||
|
||||
chai.eval(" { auto i = create(); } ");
|
||||
|
||||
CHECK(Object_Copy_Count_Test::copycount() == 0);
|
||||
CHECK(Object_Copy_Count_Test::constructcount() == 1);
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
CHECK(Object_Copy_Count_Test::destructcount() == 3);
|
||||
CHECK(Object_Copy_Count_Test::movecount() == 2);
|
||||
#else
|
||||
CHECK(Object_Copy_Count_Test::destructcount() == 2);
|
||||
CHECK(Object_Copy_Count_Test::movecount() == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
///////////////////// Object lifetime test 1
|
||||
|
||||
|
||||
class Object_Lifetime_Test
|
||||
{
|
||||
public:
|
||||
Object_Lifetime_Test()
|
||||
{
|
||||
++count();
|
||||
}
|
||||
|
||||
Object_Lifetime_Test(const Object_Lifetime_Test &)
|
||||
{
|
||||
++count();
|
||||
}
|
||||
|
||||
~Object_Lifetime_Test()
|
||||
{
|
||||
--count();
|
||||
}
|
||||
|
||||
static int& count()
|
||||
{
|
||||
static int c = 0;
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Object lifetime tests")
|
||||
{
|
||||
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||
|
||||
m->add(chaiscript::user_type<Object_Lifetime_Test>(), "Object_Lifetime_Test");
|
||||
m->add(chaiscript::constructor<Object_Lifetime_Test()>(), "Object_Lifetime_Test");
|
||||
m->add(chaiscript::constructor<Object_Lifetime_Test(const Object_Lifetime_Test &)>(), "Object_Lifetime_Test");
|
||||
m->add(chaiscript::fun(&Object_Lifetime_Test::count), "count");
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(m);
|
||||
|
||||
CHECK(chai.eval<int>("count()") == 0);
|
||||
CHECK(chai.eval<int>("auto i = 0; { auto t = Object_Lifetime_Test(); } return i;") == 0);
|
||||
CHECK(chai.eval<int>("i = 0; { auto t = Object_Lifetime_Test(); i = count(); } return i;") == 1);
|
||||
CHECK(chai.eval<int>("i = 0; { auto t = Object_Lifetime_Test(); { auto t2 = Object_Lifetime_Test(); i = count(); } } return i;") == 2);
|
||||
CHECK(chai.eval<int>("i = 0; { auto t = Object_Lifetime_Test(); { auto t2 = Object_Lifetime_Test(); } i = count(); } return i;") == 1);
|
||||
CHECK(chai.eval<int>("i = 0; { auto t = Object_Lifetime_Test(); { auto t2 = Object_Lifetime_Test(); } } i = count(); return i;") == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//// Object lifetime tests 2
|
||||
|
||||
template<typename T>
|
||||
struct Object_Lifetime_Vector2
|
||||
{
|
||||
Object_Lifetime_Vector2() : x(0), y(0) {}
|
||||
Object_Lifetime_Vector2(T px, T py) : x(px), y(py) {}
|
||||
Object_Lifetime_Vector2(const Object_Lifetime_Vector2& cp) : x(cp.x), y(cp.y) {}
|
||||
|
||||
Object_Lifetime_Vector2& operator+=(const Object_Lifetime_Vector2& vec_r)
|
||||
{
|
||||
x += vec_r.x;
|
||||
y += vec_r.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Object_Lifetime_Vector2 operator+(const Object_Lifetime_Vector2& vec_r)
|
||||
{
|
||||
return Object_Lifetime_Vector2(*this += vec_r);
|
||||
}
|
||||
|
||||
Object_Lifetime_Vector2 &operator=(const Object_Lifetime_Vector2& ver_r)
|
||||
{
|
||||
x = ver_r.x;
|
||||
y = ver_r.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
|
||||
Object_Lifetime_Vector2<float> Object_Lifetime_Vector2_GetValue()
|
||||
{
|
||||
return Object_Lifetime_Vector2<float>(10,15);
|
||||
}
|
||||
|
||||
TEST_CASE("Object lifetime test 2")
|
||||
{
|
||||
chaiscript::ChaiScript _script;
|
||||
|
||||
//Registering stuff
|
||||
_script.add(chaiscript::user_type<Object_Lifetime_Vector2<float>>(), "Object_Lifetime_Vector2f");
|
||||
_script.add(chaiscript::constructor<Object_Lifetime_Vector2<float> ()>(), "Object_Lifetime_Vector2f");
|
||||
_script.add(chaiscript::constructor<Object_Lifetime_Vector2<float> (float, float)>(), "Object_Lifetime_Vector2f");
|
||||
_script.add(chaiscript::constructor<Object_Lifetime_Vector2<float> (const Object_Lifetime_Vector2<float>&)>(), "Object_Lifetime_Vector2f");
|
||||
_script.add(chaiscript::fun(&Object_Lifetime_Vector2<float>::x), "x");
|
||||
_script.add(chaiscript::fun(&Object_Lifetime_Vector2<float>::y), "y");
|
||||
_script.add(chaiscript::fun(&Object_Lifetime_Vector2<float>::operator +), "+");
|
||||
_script.add(chaiscript::fun(&Object_Lifetime_Vector2<float>::operator +=), "+=");
|
||||
_script.add(chaiscript::fun(&Object_Lifetime_Vector2<float>::operator =), "=");
|
||||
_script.add(chaiscript::fun(&Object_Lifetime_Vector2_GetValue), "getValue");
|
||||
|
||||
_script.eval(R"(
|
||||
var test = 0.0
|
||||
var test2 = Object_Lifetime_Vector2f(10,10)
|
||||
|
||||
test = getValue().x
|
||||
print(test)
|
||||
print(test2.x)
|
||||
)");
|
||||
|
||||
CHECK(_script.eval<std::string>("to_string(test)") == "10");
|
||||
CHECK(_script.eval<std::string>("to_string(test2.x)") == "10");
|
||||
|
||||
}
|
||||
29
unittests/cpp_lambda_test.cpp
Normal file
29
unittests/cpp_lambda_test.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
// We cannot deduce the type of a lambda expression, you must either wrap it
|
||||
// in an std::function or provide the signature
|
||||
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
// provide the signature
|
||||
chai.add(chaiscript::fun<std::string ()>([] { return "hello"; } ), "f1");
|
||||
|
||||
// wrap
|
||||
chai.add(chaiscript::fun(std::function<std::string ()>([] { return "world"; } )), "f2");
|
||||
|
||||
if (chai.eval<std::string>("f1()") == "hello"
|
||||
&& chai.eval<std::string>("f2()") == "world")
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
try {
|
||||
3/0
|
||||
assert_true(false); // should never get here
|
||||
} catch (e) {
|
||||
assert_equal("Arithmetic error: divide by zero", e.what())
|
||||
}
|
||||
|
||||
assert_equal(3/0.0, Infinity)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
class MyClass {
|
||||
def MyClass()
|
||||
{
|
||||
}
|
||||
|
||||
def mult(double d) {
|
||||
this.y * d
|
||||
}
|
||||
};
|
||||
|
||||
var o = MyClass();
|
||||
o.f = fun(x,y) { x * y; }
|
||||
assert_true(o.f(3,4) == 12);
|
||||
|
||||
o.f2 = fun(x) { x * 3; }
|
||||
assert_true(o.f2(3) == 9);
|
||||
|
||||
o.y = 15;
|
||||
o.f3 = fun(x) { x * this.y; }
|
||||
assert_true(o.f3(4) == 60);
|
||||
|
||||
assert_true(o.mult(3.0) == 45.0);
|
||||
|
||||
|
||||
var o2 = Dynamic_Object();
|
||||
o2.a = 15
|
||||
assert_true(o2.a == 15)
|
||||
|
||||
assert_true(o2["a"] == 15)
|
||||
44
unittests/dynamic_object_test.cpp
Normal file
44
unittests/dynamic_object_test.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
void assert_equal(const LHS &lhs, const RHS &rhs)
|
||||
{
|
||||
if (lhs==rhs)
|
||||
{
|
||||
return;
|
||||
} else {
|
||||
std::cout << "Got: " << lhs << " expected " << rhs << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai("attr bob::z; def bob::bob() { this.z = 10 }; auto x = bob()");
|
||||
|
||||
chaiscript::dispatch::Dynamic_Object &mydo = chai.eval<chaiscript::dispatch::Dynamic_Object &>("x");
|
||||
|
||||
assert_equal(mydo.get_type_name(), "bob");
|
||||
|
||||
assert_equal(chaiscript::boxed_cast<int>(mydo.get_attr("z")), 10);
|
||||
|
||||
chai("x.z = 15");
|
||||
|
||||
assert_equal(chaiscript::boxed_cast<int>(mydo.get_attr("z")), 15);
|
||||
|
||||
int &z = chaiscript::boxed_cast<int&>(mydo.get_attr("z"));
|
||||
|
||||
assert_equal(z, 15);
|
||||
|
||||
z = 20;
|
||||
|
||||
assert_equal(z, 20);
|
||||
|
||||
assert_equal(chaiscript::boxed_cast<int>(chai("x.z")), 20);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
}
|
||||
@@ -1,3 +1 @@
|
||||
assert_equal(7, eval("3 + 4"))
|
||||
|
||||
|
||||
|
||||
122
unittests/eval_catch_exception_test.cpp
Normal file
122
unittests/eval_catch_exception_test.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
// Tests to make sure that the order in which function dispatches occur is correct
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
int test_generic()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"));");
|
||||
} catch (const chaiscript::Boxed_Value &bv) {
|
||||
const std::exception &e = chai.boxed_cast<const std::exception &>(bv);
|
||||
if (e.what() == std::string("error"))
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_generic failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int test_1()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(1)", chaiscript::exception_specification<int>());
|
||||
} catch (int e) {
|
||||
if (e == 1)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_1 failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int test_2()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(1.0)", chaiscript::exception_specification<int, double>());
|
||||
} catch (const double e) {
|
||||
if (e == 1.0)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_2 failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int test_5()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
} catch (const double) {
|
||||
std::cout << "test_5 failed with double" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (int) {
|
||||
std::cout << "test_5 failed with int" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (float) {
|
||||
std::cout << "test_5 failed with float" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::string &) {
|
||||
std::cout << "test_5 failed with string" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::exception &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::cout << "test_5 failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int test_unhandled()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
try {
|
||||
chai.eval("throw(\"error\")", chaiscript::exception_specification<int, double, float, const std::exception &>());
|
||||
} catch (double) {
|
||||
std::cout << "test_unhandled failed with double" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (int) {
|
||||
std::cout << "test_unhandled failed with int" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (float) {
|
||||
std::cout << "test_unhandled failed with float" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::exception &) {
|
||||
std::cout << "test_unhandled failed with std::exception" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const chaiscript::Boxed_Value &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::cout << "test_unhandled failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
if (test_generic() == EXIT_SUCCESS
|
||||
&& test_1() == EXIT_SUCCESS
|
||||
&& test_2() == EXIT_SUCCESS
|
||||
&& test_5() == EXIT_SUCCESS
|
||||
&& test_unhandled() == EXIT_SUCCESS)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
try {
|
||||
eval_file("use.inc")
|
||||
assert_true(true)
|
||||
print("used use.inc")
|
||||
} catch (e) {
|
||||
print("error: " + e.what())
|
||||
assert_true(false)
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
//we expect this second eval_file to fail because of a function redefinition
|
||||
eval_file("use.inc")
|
||||
assert_true(false)
|
||||
print("used use.inc x2")
|
||||
} catch (e) {
|
||||
assert_true(true)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
auto x = 1
|
||||
try {
|
||||
throw(x)
|
||||
x = 2
|
||||
}
|
||||
catch(int e) {
|
||||
x = e + 3
|
||||
}
|
||||
assert_equal(4, x);
|
||||
|
||||
x = 1
|
||||
try {
|
||||
throw(x)
|
||||
x = 2
|
||||
}
|
||||
catch(string e) {
|
||||
}
|
||||
catch(e) {
|
||||
x = e + 4
|
||||
}
|
||||
assert_equal(5, x);
|
||||
@@ -1,34 +0,0 @@
|
||||
auto results = [];
|
||||
|
||||
for (auto i = 2; i < 6; ++i) {
|
||||
try {
|
||||
throw(i)
|
||||
}
|
||||
catch(int e) : e < 2 {
|
||||
results.push_back("c1: " + e.to_string());
|
||||
}
|
||||
catch(int e) : e < 4 {
|
||||
results.push_back("c2: " + e.to_string());
|
||||
}
|
||||
catch(e) {
|
||||
results.push_back("c3: " + e.to_string());
|
||||
}
|
||||
catch {
|
||||
// Should never get called
|
||||
assert_equal(false, true)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
throw(3)
|
||||
}
|
||||
catch(int e) : e < 3
|
||||
{
|
||||
// Should never get called
|
||||
assert_equal(false, true);
|
||||
}
|
||||
catch {
|
||||
results.push_back("defaultcatch");
|
||||
}
|
||||
|
||||
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);
|
||||
111
unittests/expected_eval_errors_test.cpp
Normal file
111
unittests/expected_eval_errors_test.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Tests to make sure no arity, dispatch or guard errors leak up past eval
|
||||
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
int test_one(const int &)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&test_one), "test_fun");
|
||||
|
||||
chai.eval("def guard_fun(i) : i.get_type_info().is_type_arithmetic() {} ");
|
||||
|
||||
bool eval_error = true;
|
||||
|
||||
// Dot notation
|
||||
|
||||
try {
|
||||
// non-existent function
|
||||
chai.eval("\"test\".test_one()");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong parameter type
|
||||
chai.eval("\"test\".test_fun()");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong number of parameters
|
||||
chai.eval("\"test\".test_fun(1)");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// guard failure
|
||||
chai.eval("\"test\".guard_fun(1)");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// regular notation
|
||||
|
||||
try {
|
||||
// non-existent function
|
||||
chai.eval("test_one(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong parameter type
|
||||
chai.eval("test_fun(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// wrong number of parameters
|
||||
chai.eval("test_fun(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
// guard failure
|
||||
chai.eval("guard_fun(\"test\")");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
|
||||
// index operator
|
||||
try {
|
||||
chai.eval("var a = [1,2,3]; a[\"bob\"];");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
// unary operator
|
||||
try {
|
||||
chai.eval("++\"bob\"");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
// binary operator
|
||||
try {
|
||||
chai.eval("\"bob\" + 1");
|
||||
eval_error = false;
|
||||
} catch (const chaiscript::exception::eval_error &) {
|
||||
}
|
||||
|
||||
|
||||
if (eval_error)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,15 +5,3 @@ assert_equal(1.2, 1.2)
|
||||
assert_equal(true, .5 > 0)
|
||||
assert_equal(true, .5 < 1)
|
||||
assert_equal(0.5, .5)
|
||||
|
||||
// Scientific notation tests
|
||||
assert_true(to_string(-1.7e30f) == "-1.7e+30" || to_string(-1.7e30f) == "-1.7e+030")
|
||||
assert_equal(to_string(+17.9E04), "179000")
|
||||
assert_equal(to_string(-1.7e+300), "-1.7e+300")
|
||||
assert_equal(to_string(-1.7e-300), "-1.7e-300")
|
||||
assert_true(to_string(17.5e30l) == "1.75e+31" || to_string(17.5e30l) == "1.75e+031")
|
||||
assert_equal(to_string(1/3.14159e300L), "3.1831e-301")
|
||||
assert_true(to_string(1.0 / 12345) == "8.10045e-05" || to_string(1.0 / 12345) == "8.10045e-005")
|
||||
assert_true(to_string(3e8F) == "3e+08" || to_string(3e8F) == "3e+008" )
|
||||
assert_equal(to_string(-15E-8*3e8), "-45")
|
||||
assert_equal(to_string(-0.5e+3+20e-01), "-498")
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Test attributes/members that are functions
|
||||
|
||||
load_module("test_module")
|
||||
|
||||
class MyClass
|
||||
{
|
||||
var func_member;
|
||||
|
||||
def MyClass() {}
|
||||
|
||||
}
|
||||
|
||||
auto t0 = MyClass();
|
||||
|
||||
t0.func_member = fun(int i){ i * 3; };
|
||||
|
||||
assert_true(func_member(t0)(2) == 6)
|
||||
assert_true((func_member(t0))(2) == 6)
|
||||
assert_true(t0.func_member(2) == 6)
|
||||
|
||||
t0.func_member = fun() { 12; };
|
||||
|
||||
assert_true(t0.func_member() == 12);
|
||||
@@ -1,12 +0,0 @@
|
||||
// Test attributes/members that are functions
|
||||
|
||||
load_module("test_module")
|
||||
|
||||
auto t0 = TestBaseType()
|
||||
|
||||
t0.func_member = fun(int i){ i * 3; };
|
||||
|
||||
assert_true(func_member(t0)(2) == 6)
|
||||
assert_true((func_member(t0))(2) == 6)
|
||||
assert_true(t0.func_member(2) == 6)
|
||||
|
||||
38
unittests/function_ordering_test.cpp
Normal file
38
unittests/function_ordering_test.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Tests to make sure that the order in which function dispatches occur is correct
|
||||
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
int test_one(const int &)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_two(int &)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.eval("def test_fun(x) { return 3; }");
|
||||
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
|
||||
// chai.eval("def test_fun(x) { return 5; }");
|
||||
chai.add(chaiscript::fun(&test_one), "test_fun");
|
||||
chai.add(chaiscript::fun(&test_two), "test_fun");
|
||||
|
||||
int res1 = chai.eval<int>("test_fun(1)");
|
||||
int res2 = chai.eval<int>("auto i = 1; test_fun(i)");
|
||||
int res3 = chai.eval<int>("test_fun(\"bob\")");
|
||||
int res4 = chai.eval<int>("test_fun(\"hi\")");
|
||||
|
||||
if (res1 == 1
|
||||
&& res2 == 2
|
||||
&& res3 == 3
|
||||
&& res4 == 4 )
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
25
unittests/functor_cast_test.cpp
Normal file
25
unittests/functor_cast_test.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
double test_call(const std::function<double (int)> &f, int val)
|
||||
{
|
||||
return f(val);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&test_call), "test_call");
|
||||
|
||||
chai.eval("def func(i) { return i * 3.5; };");
|
||||
double d = chai.eval<double>("test_call(func, 3)");
|
||||
|
||||
if (d == 3 * 3.5)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
27
unittests/functor_creation_test.cpp
Normal file
27
unittests/functor_creation_test.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.eval("def func() { print(\"Hello World\"); } ");
|
||||
|
||||
std::function<void ()> f = chai.eval<std::function<void ()> >("func");
|
||||
f();
|
||||
|
||||
if (chai.eval<std::function<std::string (int)> >("to_string")(6) != "6")
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (chai.eval<std::function<std::string (const chaiscript::Boxed_Value &)> >("to_string")(chaiscript::var(6)) == "6")
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
var func = fun(){
|
||||
var ret = 0;
|
||||
for (var i = 0; i < 50000; ++i) {
|
||||
ret += i;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
var fut1 = async(func);
|
||||
var fut2 = async(func);
|
||||
|
||||
// simply executing without crashing is good enough for this test
|
||||
|
||||
print(" ${fut1.get()} ${fut2.get()} ")
|
||||
@@ -1,18 +0,0 @@
|
||||
// Test global
|
||||
|
||||
GLOBAL g = 3;
|
||||
assert_true(g == 3);
|
||||
|
||||
var v := g;
|
||||
assert_true(v == 3);
|
||||
|
||||
GLOBAL g = 2;
|
||||
assert_true(g == 2);
|
||||
assert_true(v == 2);
|
||||
|
||||
def f() {
|
||||
assert_true(g == 2);
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
10
unittests/heap_allocated_chaiscript_test.cpp
Normal file
10
unittests/heap_allocated_chaiscript_test.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript *chai = new chaiscript::ChaiScript();
|
||||
delete chai;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ bool test_literal(T val, const std::string &str)
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
T val2 = chai.eval<T>(str);
|
||||
std::cout << "Comparing : " << val << " " << val2 << '\n';
|
||||
std::cout << "Comparing : " << val << " " << val2 << std::endl;
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user