Compare commits
102 Commits
Release-3.
...
Release-4.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
deef33640c | ||
![]() |
58f3256389 | ||
![]() |
f1a4c4c427 | ||
![]() |
afd27a4b01 | ||
![]() |
4c65e45598 | ||
![]() |
923369a4f4 | ||
![]() |
964342bff3 | ||
![]() |
623c64299a | ||
![]() |
9832d1ce39 | ||
![]() |
ed7bdfb172 | ||
![]() |
204ab53afc | ||
![]() |
8f7226051e | ||
![]() |
46d1c50923 | ||
![]() |
9e3c2960aa | ||
![]() |
9fd4a1b9f5 | ||
![]() |
441cdf0935 | ||
![]() |
f0016d978a | ||
![]() |
1155720b14 | ||
![]() |
f5b7be3743 | ||
![]() |
d8f881239f | ||
![]() |
0a436398dd | ||
![]() |
9f309fcbe9 | ||
![]() |
4e33e969dc | ||
![]() |
08d9d9e28e | ||
![]() |
935276fccd | ||
![]() |
f8feaf6ea8 | ||
![]() |
dfcc415c31 | ||
![]() |
927235d871 | ||
![]() |
bf4f90a4ff | ||
![]() |
45f07f9924 | ||
![]() |
39d817469c | ||
![]() |
7a25625fdd | ||
![]() |
5e6a51ba63 | ||
![]() |
a8ea5f151d | ||
![]() |
5a76d98692 | ||
![]() |
3bccf4d977 | ||
![]() |
d2aba2ef56 | ||
![]() |
832df7f9e8 | ||
![]() |
6c53e08e9b | ||
![]() |
254d176266 | ||
![]() |
a5f29e93f5 | ||
![]() |
7f253bd6c1 | ||
![]() |
7cbd494123 | ||
![]() |
ed15cc1730 | ||
![]() |
db8863c736 | ||
![]() |
4233d21e5b | ||
![]() |
f65e095e4d | ||
![]() |
7ad58c7bcd | ||
![]() |
433905b33c | ||
![]() |
3a7eff1478 | ||
![]() |
ef46d1bf60 | ||
![]() |
654f7e6b01 | ||
![]() |
4aec12c68f | ||
![]() |
a818e7b185 | ||
![]() |
5aed00dd0b | ||
![]() |
349425fe8a | ||
![]() |
6c57729779 | ||
![]() |
56757973b6 | ||
![]() |
f1f4aeb4be | ||
![]() |
804de05a0a | ||
![]() |
0fd4b828f2 | ||
![]() |
ae02706c71 | ||
![]() |
c386af6813 | ||
![]() |
08c153abea | ||
![]() |
897ad7007f | ||
![]() |
13fb930676 | ||
![]() |
8af41b1d3c | ||
![]() |
025db4ce3a | ||
![]() |
78f02c375e | ||
![]() |
4e14a57016 | ||
![]() |
af1e02b0bb | ||
![]() |
4bcaa75fa4 | ||
![]() |
7deb2311f5 | ||
![]() |
730bad9728 | ||
![]() |
437f6a03a9 | ||
![]() |
94fefa0690 | ||
![]() |
91dc3604f5 | ||
![]() |
59dfc847ae | ||
![]() |
cdfefed385 | ||
![]() |
b0b1549503 | ||
![]() |
277b4eec9a | ||
![]() |
41b0c7768c | ||
![]() |
3b95931973 | ||
![]() |
13f98fa8ce | ||
![]() |
b0953fb466 | ||
![]() |
1186926f30 | ||
![]() |
70db5d67ff | ||
![]() |
d9727973c1 | ||
![]() |
0293762904 | ||
![]() |
95c6131ce7 | ||
![]() |
e326fe6f2d | ||
![]() |
2b64c90a0e | ||
![]() |
dd0d91c7e3 | ||
![]() |
a386142fa6 | ||
![]() |
cacc744411 | ||
![]() |
2d23578e0b | ||
![]() |
f8880066ea | ||
![]() |
a85423869f | ||
![]() |
469c02ad14 | ||
![]() |
a549e41558 | ||
![]() |
a82c892a4e | ||
![]() |
c839e4bc21 |
119
CMakeLists.txt
119
CMakeLists.txt
@@ -13,10 +13,10 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp")
|
|||||||
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
|
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
|
||||||
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
||||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.txt")
|
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR 3)
|
set(CPACK_PACKAGE_VERSION_MAJOR 4)
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR 1)
|
set(CPACK_PACKAGE_VERSION_MINOR 1)
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||||
@@ -39,62 +39,71 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
|||||||
include(CTest)
|
include(CTest)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
FIND_LIBRARY(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
|
||||||
MESSAGE(STATUS "Detecting readline support")
|
message(STATUS "Detecting readline support")
|
||||||
if (READLINE_LIBRARY)
|
if (READLINE_LIBRARY)
|
||||||
MESSAGE(STATUS "Found: ${READLINE_LIBRARY}")
|
message(STATUS "Found: ${READLINE_LIBRARY}")
|
||||||
SET (READLINE_LIB readline)
|
set (READLINE_LIB readline)
|
||||||
ADD_DEFINITIONS(/DREADLINE_AVAILABLE)
|
add_definitions(/DREADLINE_AVAILABLE)
|
||||||
else(READLINE_LIBRARY)
|
else(READLINE_LIBRARY)
|
||||||
MESSAGE(STATUS "Not Found")
|
message(STATUS "Not Found")
|
||||||
SET (READLINE_LIB )
|
set (READLINE_LIB )
|
||||||
SET (READLINE_FLAG )
|
set (READLINE_FLAG )
|
||||||
endif(READLINE_LIBRARY)
|
endif(READLINE_LIBRARY)
|
||||||
|
|
||||||
IF(MSVC)
|
if(MSVC)
|
||||||
ADD_DEFINITIONS(/W4)
|
add_definitions(/W4)
|
||||||
IF(CMAKE_CL_64)
|
if(CMAKE_CL_64)
|
||||||
ADD_DEFINITIONS(/bigobj)
|
add_definitions(/bigobj)
|
||||||
ENDIF()
|
endif()
|
||||||
ELSE()
|
else()
|
||||||
ADD_DEFINITIONS(-Wall -Wextra -Wshadow)
|
add_definitions(-Wall -Wextra -Wshadow -pedantic)
|
||||||
|
|
||||||
IF (APPLE)
|
if (APPLE)
|
||||||
# -Wno-missing-field-initializers is for boost on macos
|
# -Wno-missing-field-initializers is for boost on macos
|
||||||
ADD_DEFINITIONS(-Wno-missing-field-initializers -Wno-sign-compare)
|
add_definitions(-Wno-missing-field-initializers -Wno-sign-compare)
|
||||||
ENDIF()
|
endif()
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
|
||||||
SET(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
|
set(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
|
||||||
SET(Boost_USE_MULTITHREADED ON)
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
|
|
||||||
|
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.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||||
|
|
||||||
|
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||||
|
|
||||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||||
find_package(Boost 1.36.0 COMPONENTS thread)
|
find_package(Boost 1.36.0 COMPONENTS thread system)
|
||||||
|
|
||||||
if (Boost_FOUND)
|
if (Boost_FOUND)
|
||||||
link_directories( ${Boost_LIBRARY_DIRS} )
|
link_directories( ${Boost_LIBRARY_DIRS} )
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Can not find Boost")
|
message(FATAL_ERROR "Can not find Boost")
|
||||||
endif(Boost_FOUND)
|
endif(Boost_FOUND)
|
||||||
|
|
||||||
|
if (CMAKE_HOST_UNIX)
|
||||||
|
add_definitions(-pthread)
|
||||||
|
list(APPEND LIBS "pthread")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
ADD_DEFINITIONS(-DCHAISCRIPT_NO_THREADS)
|
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_HOST_UNIX)
|
if (CMAKE_HOST_UNIX)
|
||||||
SET(DYNAMIC_LOADER "dl")
|
list(APPEND LIBS "dl")
|
||||||
endif(CMAKE_HOST_UNIX)
|
endif(CMAKE_HOST_UNIX)
|
||||||
|
|
||||||
if (MSVC)
|
list(APPEND LIBS ${READLINE_LIB})
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
# Boost on MSVC does automatic linking
|
# Boost on MSVC does automatic linking
|
||||||
SET(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
|
list(APPEND LIBS ${Boost_LIBRARIES})
|
||||||
else()
|
|
||||||
SET(LIBS ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_COMPILER_2005)
|
if (CMAKE_COMPILER_2005)
|
||||||
@@ -104,7 +113,7 @@ endif()
|
|||||||
|
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
include_directories(${Boost_INCLUDE_DIR})
|
include_directories(${Boost_INCLUDE_DIR})
|
||||||
add_executable(chai src/main.cpp)
|
add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
||||||
target_link_libraries(chai ${LIBS})
|
target_link_libraries(chai ${LIBS})
|
||||||
|
|
||||||
if (BUILD_SAMPLES)
|
if (BUILD_SAMPLES)
|
||||||
@@ -128,7 +137,7 @@ file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CUR
|
|||||||
|
|
||||||
list(SORT UNIT_TESTS)
|
list(SORT UNIT_TESTS)
|
||||||
|
|
||||||
IF(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
|
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
|
||||||
|
|
||||||
foreach(filename ${UNIT_TESTS})
|
foreach(filename ${UNIT_TESTS})
|
||||||
@@ -136,13 +145,13 @@ IF(BUILD_TESTING)
|
|||||||
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
||||||
endforeach(filename)
|
endforeach(filename)
|
||||||
|
|
||||||
SET_PROPERTY(TEST ${UNIT_TESTS}
|
set_property(TEST ${UNIT_TESTS}
|
||||||
PROPERTY ENVIRONMENT
|
PROPERTY ENVIRONMENT
|
||||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||||
)
|
)
|
||||||
|
|
||||||
IF (NOT UNIT_TEST_LIGHT)
|
if (NOT UNIT_TEST_LIGHT)
|
||||||
add_executable(utility_test unittests/utility_test.cpp)
|
add_executable(utility_test unittests/utility_test.cpp)
|
||||||
target_link_libraries(utility_test ${LIBS})
|
target_link_libraries(utility_test ${LIBS})
|
||||||
add_test(NAME Utility_Test COMMAND utility_test)
|
add_test(NAME Utility_Test COMMAND utility_test)
|
||||||
@@ -179,6 +188,43 @@ IF(BUILD_TESTING)
|
|||||||
target_link_libraries(eval_catch_exception_test ${LIBS})
|
target_link_libraries(eval_catch_exception_test ${LIBS})
|
||||||
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
|
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(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(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)
|
||||||
|
|
||||||
|
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
|
||||||
|
target_link_libraries(integer_literal_test ${LIBS})
|
||||||
|
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
||||||
|
|
||||||
|
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||||
|
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
|
||||||
|
target_link_libraries(multithreaded_test ${LIBS})
|
||||||
|
add_test(NAME Multithreaded_Test COMMAND multithreaded_test)
|
||||||
|
set_property(TEST Multithreaded_Test
|
||||||
|
PROPERTY ENVIRONMENT
|
||||||
|
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||||
|
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||||
|
)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
|
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
|
||||||
unittests/multifile_test_module.cpp)
|
unittests/multifile_test_module.cpp)
|
||||||
target_link_libraries(multifile_test ${LIBS})
|
target_link_libraries(multifile_test ${LIBS})
|
||||||
@@ -188,8 +234,8 @@ IF(BUILD_TESTING)
|
|||||||
target_link_libraries(test_module ${LIBS})
|
target_link_libraries(test_module ${LIBS})
|
||||||
|
|
||||||
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||||
ENDIF()
|
endif()
|
||||||
ENDIF(BUILD_TESTING)
|
endif(BUILD_TESTING)
|
||||||
|
|
||||||
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
|
install(TARGETS chai ${MODULES} RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
|
||||||
install(DIRECTORY include/chaiscript DESTINATION include
|
install(DIRECTORY include/chaiscript DESTINATION include
|
||||||
@@ -209,7 +255,6 @@ install(DIRECTORY samples DESTINATION share/chaiscript
|
|||||||
PATTERN "*/.git*" EXCLUDE
|
PATTERN "*/.git*" EXCLUDE
|
||||||
PATTERN "*~" EXCLUDE)
|
PATTERN "*~" EXCLUDE)
|
||||||
|
|
||||||
|
|
||||||
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
|
configure_file(contrib/pkgconfig/chaiscript.pc.in lib/pkgconfig/chaiscript.pc @ONLY)
|
||||||
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
|
install(FILES "${chaiscript_BINARY_DIR}/lib/pkgconfig/chaiscript.pc"
|
||||||
DESTINATION lib/pkgconfig)
|
DESTINATION lib/pkgconfig)
|
||||||
|
@@ -48,7 +48,7 @@ $language_data = array (
|
|||||||
'ESCAPE_CHAR' => '\\',
|
'ESCAPE_CHAR' => '\\',
|
||||||
'KEYWORDS' => array(
|
'KEYWORDS' => array(
|
||||||
1 => array(
|
1 => array(
|
||||||
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally',
|
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally', 'case', 'switch', 'default',
|
||||||
),
|
),
|
||||||
2 => array(
|
2 => array(
|
||||||
'def', 'false', 'fun', 'true', 'var', 'attr',
|
'def', 'false', 'fun', 'true', 'var', 'attr',
|
||||||
|
@@ -7,6 +7,9 @@ if exists("b:current_syntax")
|
|||||||
finish
|
finish
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let s:cpo_save = &cpo
|
||||||
|
set cpo&vim
|
||||||
|
|
||||||
syn case match
|
syn case match
|
||||||
|
|
||||||
" syncing method
|
" syncing method
|
||||||
@@ -42,7 +45,7 @@ syn match chaiscriptNumber "\<0b[01]\+\>"
|
|||||||
" Various language features
|
" Various language features
|
||||||
syn keyword chaiscriptCond if else
|
syn keyword chaiscriptCond if else
|
||||||
syn keyword chaiscriptRepeat while for do
|
syn keyword chaiscriptRepeat while for do
|
||||||
syn keyword chaiscriptStatement break continue return
|
syn keyword chaiscriptStatement break continue return switch case default
|
||||||
syn keyword chaiscriptExceptions try catch throw
|
syn keyword chaiscriptExceptions try catch throw
|
||||||
|
|
||||||
"Keyword
|
"Keyword
|
||||||
@@ -91,4 +94,6 @@ hi def link chaiscriptEval Special
|
|||||||
|
|
||||||
let b:current_syntax = "chaiscript"
|
let b:current_syntax = "chaiscript"
|
||||||
|
|
||||||
|
let &cpo = s:cpo_save
|
||||||
|
unlet s:cpo_save
|
||||||
" vim: nowrap sw=2 sts=2 ts=8 noet
|
" vim: nowrap sw=2 sts=2 ts=8 noet
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -140,7 +140,10 @@
|
|||||||
///
|
///
|
||||||
/// \subsubsection addingobjects Adding Objects
|
/// \subsubsection addingobjects Adding Objects
|
||||||
///
|
///
|
||||||
/// Named objects can be created with the chaiscript::var function.
|
/// Named objects can be created with the chaiscript::var function. Note: adding a object
|
||||||
|
/// adds it to the current thread scope, not to a global scope. If you have multiple
|
||||||
|
/// threads that need to access the same variables you will need to add them
|
||||||
|
/// separately for each thread, from the thread itself.
|
||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
/// using namespace chaiscript;
|
/// using namespace chaiscript;
|
||||||
@@ -192,8 +195,8 @@
|
|||||||
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
|
/// Overloaded methods will need some help, to hint the compiler as to which overload you want:
|
||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod"));
|
/// chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod");
|
||||||
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod, "overloadedmethod"));
|
/// chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod), "overloadedmethod");
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
|
/// There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
bad_boxed_cast(const std::string &t_what) throw()
|
bad_boxed_cast(const std::string &t_what) throw()
|
||||||
: m_what(t_what)
|
: to(0), m_what(t_what)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -89,5 +89,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
#undef n
|
#undef n
|
||||||
#undef m
|
#undef m
|
||||||
|
#undef param
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "operators.hpp"
|
#include "operators.hpp"
|
||||||
#include "boxed_number.hpp"
|
#include "boxed_number.hpp"
|
||||||
#include <boost/function_types/result_type.hpp>
|
#include <boost/function_types/result_type.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
@@ -98,10 +99,11 @@ namespace chaiscript
|
|||||||
template<typename Input>
|
template<typename Input>
|
||||||
std::string to_string(Input i)
|
std::string to_string(Input i)
|
||||||
{
|
{
|
||||||
return boost::lexical_cast<std::string>(i);
|
std::stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal function for converting from a string to a value
|
* Internal function for converting from a string to a value
|
||||||
* uses ostream operator >> to perform the conversion
|
* uses ostream operator >> to perform the conversion
|
||||||
@@ -109,11 +111,17 @@ namespace chaiscript
|
|||||||
template<typename Input>
|
template<typename Input>
|
||||||
Input parse_string(const std::string &i)
|
Input parse_string(const std::string &i)
|
||||||
{
|
{
|
||||||
return boost::lexical_cast<Input>(i);
|
std::stringstream ss(i);
|
||||||
|
Input t;
|
||||||
|
ss >> t;
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all common functions for a POD type. All operators, and
|
* Add all common functions for a POD type. All operators, and
|
||||||
* common conversions
|
* common conversions
|
||||||
@@ -419,12 +427,10 @@ namespace chaiscript
|
|||||||
m->add(fun(&Type_Info::is_void), "is_type_void");
|
m->add(fun(&Type_Info::is_void), "is_type_void");
|
||||||
m->add(fun(&Type_Info::is_undef), "is_type_undef");
|
m->add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||||
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||||
|
m->add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
||||||
m->add(fun(&Type_Info::name), "cpp_name");
|
m->add(fun(&Type_Info::name), "cpp_name");
|
||||||
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||||
typedef bool (Type_Info::*typeinfocompare)(const Type_Info &) const;
|
|
||||||
m->add(fun(typeinfocompare(&Type_Info::operator==)), "==");
|
|
||||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
|
||||||
|
|
||||||
|
|
||||||
basic_constructors<bool>("bool", m);
|
basic_constructors<bool>("bool", m);
|
||||||
@@ -441,6 +447,7 @@ namespace chaiscript
|
|||||||
bootstrap_pod_type<long double>("long_double", m);
|
bootstrap_pod_type<long double>("long_double", m);
|
||||||
bootstrap_pod_type<float>("float", m);
|
bootstrap_pod_type<float>("float", m);
|
||||||
bootstrap_pod_type<int>("int", m);
|
bootstrap_pod_type<int>("int", m);
|
||||||
|
bootstrap_pod_type<long>("long", m);
|
||||||
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
||||||
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
||||||
bootstrap_pod_type<size_t>("size_t", m);
|
bootstrap_pod_type<size_t>("size_t", m);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -147,6 +147,104 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
template<typename T>
|
||||||
|
int return_int_impl(const boost::function<typename T::size_type (const T *)> &t_func, const T *t_obj)
|
||||||
|
{
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4267)
|
||||||
|
#endif
|
||||||
|
return t_func(t_obj);
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
boost::function<int (const T *)> return_int(size_t (T::*t_func)() const)
|
||||||
|
{
|
||||||
|
return boost::bind(&return_int_impl<T>, boost::function<size_t (const T *)>(boost::mem_fn(t_func)), _1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename P1>
|
||||||
|
int return_int_impl(const boost::function<typename T::size_type (const T *, P1)> &t_func, const T *t_obj, P1 p1)
|
||||||
|
{
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4267)
|
||||||
|
#endif
|
||||||
|
return t_func(t_obj, p1);
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename P1>
|
||||||
|
int return_int_impl_non_const(const boost::function<typename T::size_type (T *, P1)> &t_func, T *t_obj, P1 p1)
|
||||||
|
{
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4267)
|
||||||
|
#endif
|
||||||
|
return t_func(t_obj, p1);
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename P1>
|
||||||
|
boost::function<int (const T *, P1)> return_int(size_t (T::*t_func)(P1) const)
|
||||||
|
{
|
||||||
|
return boost::bind(&return_int_impl<T, P1>, boost::function<size_t (const T *, P1)>(boost::mem_fn(t_func)), _1, _2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename P1>
|
||||||
|
boost::function<int (T *, P1)> return_int(size_t (T::*t_func)(P1) )
|
||||||
|
{
|
||||||
|
return boost::bind(&return_int_impl_non_const<T, P1>, boost::function<size_t (T*, P1)>(boost::mem_fn(t_func)), _1, _2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename P1, typename P2>
|
||||||
|
int return_int_impl(const boost::function<typename T::size_type (const T *, P1, P2)> &t_func, const T *t_obj, P1 p1, P2 p2)
|
||||||
|
{
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4267)
|
||||||
|
#endif
|
||||||
|
return t_func(t_obj, p1, p2);
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename StringType, StringType (StringType::*Func)(typename StringType::size_type, typename StringType::size_type) const >
|
||||||
|
StringType substr_helper(const StringType &str, int begin, int end)
|
||||||
|
{
|
||||||
|
return (str.*Func)(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename P1, typename P2>
|
||||||
|
boost::function<int (const T *, P1, P2)> return_int(size_t (T::*t_func)(P1, P2) const)
|
||||||
|
{
|
||||||
|
return boost::bind(&return_int_impl<T, P1, P2>, boost::function<size_t (const T *, P1, P2)>(boost::mem_fn(t_func)), _1, _2, _3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void insert(T &t_target, const T &t_other)
|
||||||
|
{
|
||||||
|
t_target.insert(t_other.begin(), t_other.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
||||||
|
{
|
||||||
|
t_target.insert(t_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add Bidir_Range support for the given ContainerType
|
* Add Bidir_Range support for the given ContainerType
|
||||||
*/
|
*/
|
||||||
@@ -255,7 +353,9 @@ namespace chaiscript
|
|||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
m->add(fun(boost::function<int (const ContainerType *)>(boost::mem_fn(&ContainerType::size))), "size");
|
boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
|
||||||
|
m->add(fun(f), "size");
|
||||||
|
// m->add(fun(boost::function<int (const ContainerType *)>(boost::mem_fn(&ContainerType::size))), "size");
|
||||||
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
|
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
|
||||||
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
|
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
|
||||||
|
|
||||||
@@ -390,8 +490,25 @@ namespace chaiscript
|
|||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(boost::mem_fn(&ContainerType::count))), "count");
|
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(&ContainerType::count))), "count");
|
||||||
|
|
||||||
|
|
||||||
|
typedef size_t (ContainerType::*erase)(const typename ContainerType::key_type &);
|
||||||
|
erase eraseptr(&ContainerType::erase);
|
||||||
|
|
||||||
|
m->add(fun(boost::function<int (ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(eraseptr))), "erase");
|
||||||
|
|
||||||
|
m->add(fun(&detail::insert<ContainerType>), "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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,15 +629,20 @@ namespace chaiscript
|
|||||||
m->add(fun(&String::push_back), push_back_name);
|
m->add(fun(&String::push_back), push_back_name);
|
||||||
|
|
||||||
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
|
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
|
||||||
|
|
||||||
typedef boost::function<int (const String *, const String &, int)> find_func;
|
typedef boost::function<int (const String *, const String &, int)> find_func;
|
||||||
|
|
||||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find)))), "find");
|
typedef String (String::*substr_ptr)(typename String::size_type, typename String::size_type) const;
|
||||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
typedef boost::function<String (const String *, int, int)> substr_func;
|
||||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
|
||||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_last_of)))), "find_last_of");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find)))), "find");
|
||||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
||||||
m->add(fun(find_func(boost::mem_fn(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
||||||
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_of)))), "find_last_of");
|
||||||
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
|
||||||
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
|
||||||
|
|
||||||
|
|
||||||
|
m->add(fun(&detail::substr_helper<String, static_cast<substr_ptr>(&String::substr)>), "substr");
|
||||||
|
|
||||||
m->add(fun(&String::c_str), "c_str");
|
m->add(fun(&String::c_str), "c_str");
|
||||||
m->add(fun(&String::data), "data");
|
m->add(fun(&String::data), "data");
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef __boxed_cast_hpp__
|
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||||
#define __boxed_cast_hpp__
|
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||||
|
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -14,13 +14,21 @@
|
|||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4244 4018 4389 4146)
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||||
class Boxed_Number
|
class Boxed_Number
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct boolean
|
struct boolean
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
#endif
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
|
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
|
||||||
{
|
{
|
||||||
@@ -41,7 +49,6 @@ namespace chaiscript
|
|||||||
default:
|
default:
|
||||||
throw boost::bad_any_cast();
|
throw boost::bad_any_cast();
|
||||||
}
|
}
|
||||||
throw boost::bad_any_cast();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,7 +144,6 @@ namespace chaiscript
|
|||||||
default:
|
default:
|
||||||
throw boost::bad_any_cast();
|
throw boost::bad_any_cast();
|
||||||
}
|
}
|
||||||
throw boost::bad_any_cast();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -163,7 +169,6 @@ namespace chaiscript
|
|||||||
default:
|
default:
|
||||||
throw boost::bad_any_cast();
|
throw boost::bad_any_cast();
|
||||||
}
|
}
|
||||||
throw boost::bad_any_cast();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -276,7 +281,7 @@ namespace chaiscript
|
|||||||
} else if (inp_ == typeid(boost::int8_t)) {
|
} else if (inp_ == typeid(boost::int8_t)) {
|
||||||
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
|
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
|
||||||
} else if (inp_ == typeid(boost::int16_t)) {
|
} else if (inp_ == typeid(boost::int16_t)) {
|
||||||
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
|
return oper_rhs<boost::int16_t, false>(t_oper, t_lhs, t_rhs);
|
||||||
} else if (inp_ == typeid(boost::int32_t)) {
|
} else if (inp_ == typeid(boost::int32_t)) {
|
||||||
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
|
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
|
||||||
} else if (inp_ == typeid(boost::int64_t)) {
|
} else if (inp_ == typeid(boost::int64_t)) {
|
||||||
@@ -294,24 +299,120 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
Target get_as_aux() const
|
||||||
|
{
|
||||||
|
return static_cast<Target>(*static_cast<const Source *>(bv.get_const_ptr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Source>
|
||||||
|
std::string to_string_aux(const Boxed_Value &v) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << *static_cast<const Source *>(v.get_const_ptr());
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Boxed_Number()
|
||||||
|
: bv(Boxed_Value(0))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Boxed_Number(const Boxed_Value &v)
|
Boxed_Number(const Boxed_Value &v)
|
||||||
: bv(v)
|
: bv(v)
|
||||||
{
|
{
|
||||||
const Type_Info &inp_ = v.get_type_info();
|
validate_boxed_number(v);
|
||||||
if (inp_ == typeid(bool))
|
|
||||||
{
|
|
||||||
throw boost::bad_any_cast();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inp_.is_arithmetic())
|
template<typename T> explicit Boxed_Number(T t)
|
||||||
|
: bv(Boxed_Value(t))
|
||||||
{
|
{
|
||||||
|
validate_boxed_number(bv);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Target> Target get_as() const
|
||||||
|
{
|
||||||
|
const Type_Info &inp_ = bv.get_type_info();
|
||||||
|
|
||||||
|
if (inp_ == typeid(int)) {
|
||||||
|
return get_as_aux<Target, int>();
|
||||||
|
} else if (inp_ == typeid(double)) {
|
||||||
|
return get_as_aux<Target, double>();
|
||||||
|
} else if (inp_ == typeid(float)) {
|
||||||
|
return get_as_aux<Target, float>();
|
||||||
|
} else if (inp_ == typeid(long double)) {
|
||||||
|
return get_as_aux<Target, long double>();
|
||||||
|
} else if (inp_ == typeid(char)) {
|
||||||
|
return get_as_aux<Target, char>();
|
||||||
|
} else if (inp_ == typeid(unsigned int)) {
|
||||||
|
return get_as_aux<Target, unsigned int>();
|
||||||
|
} else if (inp_ == typeid(long)) {
|
||||||
|
return get_as_aux<Target, long>();
|
||||||
|
} else if (inp_ == typeid(unsigned long)) {
|
||||||
|
return get_as_aux<Target, unsigned long>();
|
||||||
|
} else if (inp_ == typeid(boost::int8_t)) {
|
||||||
|
return get_as_aux<Target, boost::int8_t>();
|
||||||
|
} else if (inp_ == typeid(boost::int16_t)) {
|
||||||
|
return get_as_aux<Target, boost::int16_t>();
|
||||||
|
} else if (inp_ == typeid(boost::int32_t)) {
|
||||||
|
return get_as_aux<Target, boost::int32_t>();
|
||||||
|
} else if (inp_ == typeid(boost::int64_t)) {
|
||||||
|
return get_as_aux<Target, boost::int64_t>();
|
||||||
|
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||||
|
return get_as_aux<Target, boost::uint8_t>();
|
||||||
|
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||||
|
return get_as_aux<Target, boost::uint16_t>();
|
||||||
|
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||||
|
return get_as_aux<Target, boost::uint32_t>();
|
||||||
|
} else if (inp_ == typeid(boost::uint64_t)) {
|
||||||
|
return get_as_aux<Target, boost::uint64_t>();
|
||||||
|
} else {
|
||||||
throw boost::bad_any_cast();
|
throw boost::bad_any_cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string to_string() const
|
||||||
|
{
|
||||||
|
const Type_Info &inp_ = bv.get_type_info();
|
||||||
|
|
||||||
|
if (inp_ == typeid(int)) {
|
||||||
|
return to_string_aux<int>(bv);
|
||||||
|
} else if (inp_ == typeid(double)) {
|
||||||
|
return to_string_aux<double>(bv);
|
||||||
|
} else if (inp_ == typeid(float)) {
|
||||||
|
return to_string_aux<float>(bv);
|
||||||
|
} else if (inp_ == typeid(long double)) {
|
||||||
|
return to_string_aux<long double>(bv);
|
||||||
|
} else if (inp_ == typeid(char)) {
|
||||||
|
return to_string_aux<int>(Boxed_Value(get_as_aux<int, char>()));
|
||||||
|
} else if (inp_ == typeid(unsigned int)) {
|
||||||
|
return to_string_aux<unsigned int>(bv);
|
||||||
|
} else if (inp_ == typeid(long)) {
|
||||||
|
return to_string_aux<long>(bv);
|
||||||
|
} else if (inp_ == typeid(unsigned long)) {
|
||||||
|
return to_string_aux<unsigned long>(bv);
|
||||||
|
} else if (inp_ == typeid(boost::int8_t)) {
|
||||||
|
return to_string_aux<int>(Boxed_Value(get_as_aux<int, boost::int8_t>()));
|
||||||
|
} else if (inp_ == typeid(boost::int16_t)) {
|
||||||
|
return to_string_aux<boost::int16_t>(bv);
|
||||||
|
} else if (inp_ == typeid(boost::int32_t)) {
|
||||||
|
return to_string_aux<boost::int32_t>(bv);
|
||||||
|
} else if (inp_ == typeid(boost::int64_t)) {
|
||||||
|
return to_string_aux<boost::int64_t>(bv);
|
||||||
|
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||||
|
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, boost::uint8_t>()));
|
||||||
|
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||||
|
return to_string_aux<boost::uint16_t>(bv);
|
||||||
|
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||||
|
return to_string_aux<boost::uint32_t>(bv);
|
||||||
|
} else if (inp_ == typeid(boost::uint64_t)) {
|
||||||
|
return to_string_aux<boost::uint64_t>(bv);
|
||||||
|
} else {
|
||||||
|
throw boost::bad_any_cast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const Boxed_Number &t_rhs) const
|
bool operator==(const Boxed_Number &t_rhs) const
|
||||||
{
|
{
|
||||||
@@ -378,6 +479,27 @@ namespace chaiscript
|
|||||||
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
|
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void validate_boxed_number(const Boxed_Value &v)
|
||||||
|
{
|
||||||
|
const Type_Info &inp_ = v.get_type_info();
|
||||||
|
if (inp_ == typeid(bool))
|
||||||
|
{
|
||||||
|
throw boost::bad_any_cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inp_.is_arithmetic())
|
||||||
|
{
|
||||||
|
throw boost::bad_any_cast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Boxed_Number operator=(const Boxed_Value &v)
|
||||||
|
{
|
||||||
|
validate_boxed_number(v);
|
||||||
|
bv = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
||||||
{
|
{
|
||||||
return oper(Operators::assign, this->bv, t_rhs.bv);
|
return oper(Operators::assign, this->bv, t_rhs.bv);
|
||||||
@@ -681,6 +803,10 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/any.hpp>
|
#include <boost/any.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
@@ -71,19 +72,17 @@ namespace chaiscript
|
|||||||
void *m_data_ptr;
|
void *m_data_ptr;
|
||||||
const void *m_const_data_ptr;
|
const void *m_const_data_ptr;
|
||||||
bool m_is_ref;
|
bool m_is_ref;
|
||||||
std::vector<boost::shared_ptr<Data> > m_dependencies;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Object_Data
|
struct Object_Data
|
||||||
{
|
{
|
||||||
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data> (new Data(
|
return boost::make_shared<Data>(
|
||||||
detail::Get_Type_Info<void>::get(),
|
detail::Get_Type_Info<void>::get(),
|
||||||
boost::any(),
|
boost::any(),
|
||||||
false,
|
false,
|
||||||
0)
|
static_cast<void *>(0));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -95,12 +94,11 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data>(new Data(
|
return boost::make_shared<Data>(
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(obj),
|
boost::any(obj),
|
||||||
false,
|
false,
|
||||||
obj.get())
|
obj.get());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -112,34 +110,31 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data>(new Data(
|
return boost::make_shared<Data>(
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(obj),
|
boost::any(obj),
|
||||||
true,
|
true,
|
||||||
obj.get_pointer())
|
obj.get_pointer());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static boost::shared_ptr<Data> get(const T& t)
|
static boost::shared_ptr<Data> get(const T& t)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<T> p(new T(t));
|
boost::shared_ptr<T> p(new T(t));
|
||||||
return boost::shared_ptr<Data>(new Data(
|
return boost::make_shared<Data>(
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(p),
|
boost::any(p),
|
||||||
false,
|
false,
|
||||||
p.get())
|
p.get());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boost::shared_ptr<Data> get()
|
static boost::shared_ptr<Data> get()
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data> (new Data(
|
return boost::make_shared<Data>(
|
||||||
Type_Info(),
|
Type_Info(),
|
||||||
boost::any(),
|
boost::any(),
|
||||||
false,
|
false,
|
||||||
0)
|
static_cast<void *>(0));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -242,24 +237,6 @@ namespace chaiscript
|
|||||||
return !is_ref();
|
return !is_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_dependencies()
|
|
||||||
{
|
|
||||||
m_data->m_dependencies.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename InItr>
|
|
||||||
void add_dependencies(InItr begin, const InItr &end)
|
|
||||||
{
|
|
||||||
while (begin != end)
|
|
||||||
{
|
|
||||||
if (begin->m_data != m_data)
|
|
||||||
{
|
|
||||||
m_data->m_dependencies.push_back(begin->m_data);
|
|
||||||
}
|
|
||||||
++begin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *get_ptr() const
|
void *get_ptr() const
|
||||||
{
|
{
|
||||||
return m_data->m_data_ptr;
|
return m_data->m_data_ptr;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -12,12 +12,11 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/tuple/tuple.hpp>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
@@ -32,6 +31,71 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
namespace exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Exception thrown in the case that an object name is invalid because it is a reserved word
|
||||||
|
*/
|
||||||
|
class reserved_word_error : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
reserved_word_error(const std::string &t_word) throw()
|
||||||
|
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~reserved_word_error() throw() {}
|
||||||
|
|
||||||
|
std::string word() const
|
||||||
|
{
|
||||||
|
return m_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_word;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown in the case that an object name is invalid because it already exists in current context
|
||||||
|
*/
|
||||||
|
class name_conflict_error : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
name_conflict_error(const std::string &t_name) throw()
|
||||||
|
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~name_conflict_error() throw() {}
|
||||||
|
|
||||||
|
std::string name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown in the case that a non-const object was added as a shared object
|
||||||
|
*/
|
||||||
|
class global_non_const : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
global_non_const() throw()
|
||||||
|
: std::runtime_error("a global object must be const")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~global_non_const() throw() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Holds a collection of ChaiScript settings which can be applied to the ChaiScript runtime.
|
/// \brief Holds a collection of ChaiScript settings which can be applied to the ChaiScript runtime.
|
||||||
/// Used to implement loadable module support.
|
/// Used to implement loadable module support.
|
||||||
class Module
|
class Module
|
||||||
@@ -55,6 +119,17 @@ namespace chaiscript
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Module &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
|
{
|
||||||
|
if (!t_bv.is_const())
|
||||||
|
{
|
||||||
|
throw exception::global_non_const();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_globals.push_back(std::make_pair(t_bv, t_name));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Add a bit of chaiscript to eval during module implementation
|
//Add a bit of chaiscript to eval during module implementation
|
||||||
Module &eval(const std::string &str)
|
Module &eval(const std::string &str)
|
||||||
@@ -76,11 +151,13 @@ namespace chaiscript
|
|||||||
apply(m_funcs.begin(), m_funcs.end(), t_engine);
|
apply(m_funcs.begin(), m_funcs.end(), t_engine);
|
||||||
apply_eval(m_evals.begin(), m_evals.end(), t_eval);
|
apply_eval(m_evals.begin(), m_evals.end(), t_eval);
|
||||||
apply_single(m_conversions.begin(), m_conversions.end(), t_engine);
|
apply_single(m_conversions.begin(), m_conversions.end(), t_engine);
|
||||||
|
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
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<std::string> m_evals;
|
||||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||||
|
|
||||||
@@ -89,7 +166,22 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
t.add(begin->first, begin->second);
|
t.add(begin->first, begin->second);
|
||||||
|
} catch (const exception::name_conflict_error &) {
|
||||||
|
/// \todo Should we throw an error if there's a name conflict
|
||||||
|
/// while applying a module?
|
||||||
|
}
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename InItr>
|
||||||
|
void apply_globals(InItr begin, InItr end, T &t) const
|
||||||
|
{
|
||||||
|
while (begin != end)
|
||||||
|
{
|
||||||
|
t.add_global_const(begin->first, begin->second);
|
||||||
++begin;
|
++begin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,48 +358,6 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace exception
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Exception thrown in the case that a multi method dispatch fails
|
|
||||||
* because no matching function was found
|
|
||||||
* at runtime due to either an arity_error, a guard_error or a bad_boxed_cast
|
|
||||||
* exception
|
|
||||||
*/
|
|
||||||
class reserved_word_error : public std::runtime_error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
reserved_word_error(const std::string &t_word) throw()
|
|
||||||
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~reserved_word_error() throw() {}
|
|
||||||
|
|
||||||
std::string word() const
|
|
||||||
{
|
|
||||||
return m_word;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_word;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown in the case that a non-const object was added as a shared object
|
|
||||||
*/
|
|
||||||
class global_non_const : public std::runtime_error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
global_non_const() throw()
|
|
||||||
: std::runtime_error("a global object must be const")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~global_non_const() throw() {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@@ -326,6 +376,7 @@ namespace chaiscript
|
|||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
std::map<std::string, std::vector<Proxy_Function> > m_functions;
|
std::map<std::string, std::vector<Proxy_Function> > m_functions;
|
||||||
|
std::map<std::string, Proxy_Function> m_function_objects;
|
||||||
std::map<std::string, Boxed_Value> m_global_objects;
|
std::map<std::string, Boxed_Value> m_global_objects;
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
std::set<std::string> m_reserved_words;
|
std::set<std::string> m_reserved_words;
|
||||||
@@ -353,10 +404,10 @@ namespace chaiscript
|
|||||||
/**
|
/**
|
||||||
* Add a new named Proxy_Function to the system
|
* Add a new named Proxy_Function to the system
|
||||||
*/
|
*/
|
||||||
bool add(const Proxy_Function &f, const std::string &name)
|
void add(const Proxy_Function &f, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
validate_object_name(name);
|
||||||
return add_function(f, name);
|
add_function(f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -381,6 +432,7 @@ namespace chaiscript
|
|||||||
add_object(name, obj);
|
add_object(name, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a named object to the current scope
|
* Adds a named object to the current scope
|
||||||
*/
|
*/
|
||||||
@@ -388,7 +440,15 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
StackData &stack = get_stack_data();
|
StackData &stack = get_stack_data();
|
||||||
validate_object_name(name);
|
validate_object_name(name);
|
||||||
stack.back()[name] = obj;
|
|
||||||
|
Scope &scope = stack.back();
|
||||||
|
Scope::iterator itr = scope.find(name);
|
||||||
|
if (itr != stack.back().end())
|
||||||
|
{
|
||||||
|
throw exception::name_conflict_error(name);
|
||||||
|
} else {
|
||||||
|
stack.back().insert(std::make_pair(name, obj));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -404,7 +464,12 @@ namespace chaiscript
|
|||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||||
|
|
||||||
m_state.m_global_objects[name] = obj;
|
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||||
|
{
|
||||||
|
throw exception::name_conflict_error(name);
|
||||||
|
} else {
|
||||||
|
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -430,28 +495,24 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Swaps out the stack with a new stack
|
|
||||||
* \returns the old stack
|
|
||||||
* \param[in] s The new stack
|
|
||||||
*/
|
|
||||||
Stack set_stack(const Stack &s)
|
|
||||||
{
|
|
||||||
Stack old = m_stack_holder->stack;
|
|
||||||
m_stack_holder->stack = s;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack new_stack() const
|
/// Pushes a new stack on to the list of stacks
|
||||||
|
void new_stack()
|
||||||
{
|
{
|
||||||
Stack s(new Stack::element_type());
|
Stack s(new Stack::element_type());
|
||||||
s->push_back(Scope());
|
s->push_back(Scope());
|
||||||
return s;
|
m_stack_holder->stacks.push_back(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pop_stack()
|
||||||
|
{
|
||||||
|
m_stack_holder->stacks.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \returns the current stack
|
||||||
Stack get_stack() const
|
Stack get_stack() const
|
||||||
{
|
{
|
||||||
return m_stack_holder->stack;
|
return m_stack_holder->stacks.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -491,21 +552,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If all that failed, then check to see if it's a function
|
// If all that failed, then check to see if it's a function
|
||||||
std::vector<Proxy_Function> funcs = get_function(name);
|
return get_function_object(name);
|
||||||
|
|
||||||
if (funcs.empty())
|
|
||||||
{
|
|
||||||
throw std::range_error("Object not known: " + name);
|
|
||||||
} else {
|
|
||||||
if (funcs.size() == 1)
|
|
||||||
{
|
|
||||||
// Return the first item if there is only one,
|
|
||||||
// no reason to take the cast of the extra level of dispatch
|
|
||||||
return const_var(*funcs.begin());
|
|
||||||
} else {
|
|
||||||
return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -588,7 +635,24 @@ namespace chaiscript
|
|||||||
} else {
|
} else {
|
||||||
return std::vector<Proxy_Function>();
|
return std::vector<Proxy_Function>();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \returns a function object (Boxed_Value wrapper) if it exists
|
||||||
|
/// \throws std::range_error if it does not
|
||||||
|
Boxed_Value get_function_object(const std::string &t_name) const
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
|
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||||
|
|
||||||
|
std::map<std::string, Proxy_Function>::const_iterator itr = funs.find(t_name);
|
||||||
|
|
||||||
|
if (itr != funs.end())
|
||||||
|
{
|
||||||
|
return const_var(itr->second);
|
||||||
|
} else {
|
||||||
|
throw std::range_error("Object not found: " + t_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -602,6 +666,78 @@ namespace chaiscript
|
|||||||
return functions.find(name) != functions.end();
|
return functions.find(name) != functions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \returns All values in the local thread state, added through the add() function
|
||||||
|
std::map<std::string, Boxed_Value> get_locals() const
|
||||||
|
{
|
||||||
|
StackData &stack = get_stack_data();
|
||||||
|
Scope &scope = stack.front();
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Sets all of the locals for the current thread state.
|
||||||
|
///
|
||||||
|
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||||
|
///
|
||||||
|
/// 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)
|
||||||
|
{
|
||||||
|
StackData &stack = get_stack_data();
|
||||||
|
Scope &scope = stack.front();
|
||||||
|
scope = t_locals;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Get a map of all objects that can be seen from the current scope in a scripting context
|
||||||
|
///
|
||||||
|
std::map<std::string, Boxed_Value> get_scripting_objects() const
|
||||||
|
{
|
||||||
|
// We don't want the current context, but one up if it exists
|
||||||
|
StackData &stack = (m_stack_holder->stacks.size()==1)?(*(m_stack_holder->stacks.back())):(*m_stack_holder->stacks[m_stack_holder->stacks.size()-2]);
|
||||||
|
|
||||||
|
std::map<std::string, Boxed_Value> retval;
|
||||||
|
|
||||||
|
// note: map insert doesn't overwrite existing values, which is why this works
|
||||||
|
|
||||||
|
for (StackData::reverse_iterator itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||||
|
{
|
||||||
|
retval.insert(itr->begin(), itr->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the global values
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||||
|
|
||||||
|
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Get a map of all functions that can be seen from a scripting context
|
||||||
|
///
|
||||||
|
std::map<std::string, Boxed_Value> get_function_objects() const
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
|
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||||
|
|
||||||
|
std::map<std::string, Boxed_Value> objs;
|
||||||
|
|
||||||
|
for (std::map<std::string, Proxy_Function>::const_iterator itr = funs.begin();
|
||||||
|
itr != funs.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
objs.insert(std::make_pair(itr->first, const_var(itr->second)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return objs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a vector of all registered functions
|
* Get a vector of all registered functions
|
||||||
*/
|
*/
|
||||||
@@ -665,10 +801,9 @@ namespace chaiscript
|
|||||||
/**
|
/**
|
||||||
* Dump object info to stdout
|
* Dump object info to stdout
|
||||||
*/
|
*/
|
||||||
void dump_object(Boxed_Value o) const
|
void dump_object(const Boxed_Value &o) const
|
||||||
{
|
{
|
||||||
Type_Info ti = o.get_type_info();
|
std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl;
|
||||||
std::cout << (ti.is_const()?"const ":"") << get_type_name(ti) << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -760,7 +895,7 @@ namespace chaiscript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string type_name(Boxed_Value obj) const
|
std::string type_name(const Boxed_Value &obj) const
|
||||||
{
|
{
|
||||||
return get_type_name(obj.get_type_info());
|
return get_type_name(obj.get_type_info());
|
||||||
}
|
}
|
||||||
@@ -781,6 +916,29 @@ namespace chaiscript
|
|||||||
m_state = t_state;
|
m_state = t_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save_function_params(const std::vector<Boxed_Value> &t_params)
|
||||||
|
{
|
||||||
|
m_stack_holder->call_params.insert(m_stack_holder->call_params.begin(), t_params.begin(), t_params.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_function_call()
|
||||||
|
{
|
||||||
|
++m_stack_holder->call_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_function_call()
|
||||||
|
{
|
||||||
|
--m_stack_holder->call_depth;
|
||||||
|
|
||||||
|
assert(m_stack_holder->call_depth >= 0);
|
||||||
|
|
||||||
|
if (m_stack_holder->call_depth == 0)
|
||||||
|
{
|
||||||
|
/// \todo Critical: this needs to be smarter, memory can expand quickly
|
||||||
|
/// in tight loops involving function calls
|
||||||
|
m_stack_holder->call_params.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@@ -789,7 +947,17 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
StackData &get_stack_data() const
|
StackData &get_stack_data() const
|
||||||
{
|
{
|
||||||
return *(m_stack_holder->stack);
|
return *(m_stack_holder->stacks.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::map<std::string, Proxy_Function> &get_function_objects_int() const
|
||||||
|
{
|
||||||
|
return m_state.m_function_objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, Proxy_Function> &get_function_objects_int()
|
||||||
|
{
|
||||||
|
return m_state.m_function_objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
||||||
@@ -911,11 +1079,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation detail for adding a function. Returns
|
* Implementation detail for adding a function.
|
||||||
* true if the function was added, false if a function with the
|
* \throws exception::name_conflict_error if there's a function matching the given one being added
|
||||||
* same signature and name already exists.
|
|
||||||
*/
|
*/
|
||||||
bool add_function(const Proxy_Function &t_f, const std::string &t_name)
|
void add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||||
{
|
{
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
@@ -924,6 +1091,8 @@ namespace chaiscript
|
|||||||
std::map<std::string, std::vector<Proxy_Function> >::iterator itr
|
std::map<std::string, std::vector<Proxy_Function> >::iterator itr
|
||||||
= funcs.find(t_name);
|
= funcs.find(t_name);
|
||||||
|
|
||||||
|
std::map<std::string, Proxy_Function> &func_objs = get_function_objects_int();
|
||||||
|
|
||||||
if (itr != funcs.end())
|
if (itr != funcs.end())
|
||||||
{
|
{
|
||||||
std::vector<Proxy_Function> &vec = itr->second;
|
std::vector<Proxy_Function> &vec = itr->second;
|
||||||
@@ -933,19 +1102,21 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
if ((*t_f) == *(*itr2))
|
if ((*t_f) == *(*itr2))
|
||||||
{
|
{
|
||||||
return false;
|
throw exception::name_conflict_error(t_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec.push_back(t_f);
|
vec.push_back(t_f);
|
||||||
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
|
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
|
||||||
|
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||||
} else {
|
} else {
|
||||||
std::vector<Proxy_Function> vec;
|
std::vector<Proxy_Function> vec;
|
||||||
vec.push_back(t_f);
|
vec.push_back(t_f);
|
||||||
funcs.insert(std::make_pair(t_name, vec));
|
funcs.insert(std::make_pair(t_name, vec));
|
||||||
|
func_objs[t_name] = t_f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
@@ -954,12 +1125,17 @@ namespace chaiscript
|
|||||||
struct Stack_Holder
|
struct Stack_Holder
|
||||||
{
|
{
|
||||||
Stack_Holder()
|
Stack_Holder()
|
||||||
: stack(new StackData())
|
: call_depth(0)
|
||||||
{
|
{
|
||||||
stack->push_back(Scope());
|
Stack s(new StackData());
|
||||||
|
s->push_back(Scope());
|
||||||
|
stacks.push_back(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack stack;
|
std::deque<Stack> stacks;
|
||||||
|
|
||||||
|
std::list<Boxed_Value> call_params;
|
||||||
|
int call_depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -48,6 +48,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
|
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
|
||||||
|
|
||||||
const Type_Info &base()
|
const Type_Info &base()
|
||||||
{
|
{
|
||||||
return m_base;
|
return m_base;
|
||||||
@@ -63,6 +64,8 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~Dynamic_Conversion() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type_Info m_base;
|
Type_Info m_base;
|
||||||
Type_Info m_derived;
|
Type_Info m_derived;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -44,20 +44,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct Dynamic_Object_Attribute
|
|
||||||
{
|
|
||||||
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
|
|
||||||
Dynamic_Object &t_do)
|
|
||||||
{
|
|
||||||
if (t_do.get_type_name() != t_type_name)
|
|
||||||
{
|
|
||||||
throw exception::bad_boxed_cast("Dynamic object type mismatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
return t_do.get_attr(t_attr_name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Proxy_Function implementation designed for calling a function
|
* A Proxy_Function implementation designed for calling a function
|
||||||
* that is automatically guarded based on the first param based on the
|
* that is automatically guarded based on the first param based on the
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -114,6 +114,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef n
|
#undef n
|
||||||
|
#undef addparam
|
||||||
|
#undef curry
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -34,6 +34,15 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<Ret *>
|
||||||
|
{
|
||||||
|
static Boxed_Value handle(Ret *p)
|
||||||
|
{
|
||||||
|
return Boxed_Value(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Handle_Return<boost::shared_ptr<Ret> &>
|
struct Handle_Return<boost::shared_ptr<Ret> &>
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -25,7 +25,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||||
|
|
||||||
|
|
||||||
namespace dispatch
|
namespace dispatch
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +73,6 @@ namespace chaiscript
|
|||||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||||
{
|
{
|
||||||
Boxed_Value bv = do_call(params);
|
Boxed_Value bv = do_call(params);
|
||||||
bv.add_dependencies(params.begin(), params.end());
|
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +217,12 @@ namespace chaiscript
|
|||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &rhs) const
|
virtual bool operator==(const Proxy_Function_Base &rhs) const
|
||||||
{
|
{
|
||||||
return this == &rhs;
|
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||||
|
|
||||||
|
return this == &rhs
|
||||||
|
|| (prhs
|
||||||
|
&& this->m_arity == prhs->m_arity
|
||||||
|
&& !this->m_guard && !prhs->m_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
@@ -587,17 +590,16 @@ namespace chaiscript
|
|||||||
class dispatch_error : public std::runtime_error
|
class dispatch_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
dispatch_error() throw()
|
dispatch_error(const std::vector<Boxed_Value> &t_parameters,
|
||||||
: std::runtime_error("No matching function to dispatch to")
|
const std::vector<Const_Proxy_Function> &t_functions)
|
||||||
{
|
: std::runtime_error("Error with function dispatch"), parameters(t_parameters), functions(t_functions)
|
||||||
}
|
|
||||||
|
|
||||||
dispatch_error(bool is_const) throw()
|
|
||||||
: std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":""))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~dispatch_error() throw() {}
|
virtual ~dispatch_error() throw() {}
|
||||||
|
|
||||||
|
std::vector<Boxed_Value> parameters;
|
||||||
|
std::vector<Const_Proxy_Function> functions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,9 +612,10 @@ namespace chaiscript
|
|||||||
* function is found or throw dispatch_error if no matching function is found
|
* function is found or throw dispatch_error if no matching function is found
|
||||||
*/
|
*/
|
||||||
template<typename InItr>
|
template<typename InItr>
|
||||||
Boxed_Value dispatch(InItr begin, InItr end,
|
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||||
const std::vector<Boxed_Value> &plist)
|
const std::vector<Boxed_Value> &plist)
|
||||||
{
|
{
|
||||||
|
InItr orig(begin);
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -631,7 +634,7 @@ namespace chaiscript
|
|||||||
++begin;
|
++begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw exception::dispatch_error(plist.empty()?false:plist[0].is_const());
|
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -121,6 +120,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
#undef n
|
#undef n
|
||||||
|
#undef gettypeinfo
|
||||||
|
#undef casthelper
|
||||||
|
#undef trycast
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -39,39 +39,40 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
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_bareti)
|
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
|
||||||
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
: 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_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
|
||||||
m_type_info(t_ti), m_bare_type_info(t_bareti),
|
|
||||||
m_is_undef(false)
|
m_is_undef(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Info()
|
Type_Info()
|
||||||
: m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
: m_type_info(0), m_bare_type_info(0),
|
||||||
m_is_void(false), m_is_arithmetic(false), m_type_info(0), m_bare_type_info(0),
|
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||||
|
m_is_void(false), m_is_arithmetic(false),
|
||||||
m_is_undef(true)
|
m_is_undef(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Info(const Type_Info &ti)
|
Type_Info(const Type_Info &ti)
|
||||||
: m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
|
: m_type_info(ti.m_type_info),
|
||||||
|
m_bare_type_info(ti.m_bare_type_info),
|
||||||
|
m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
|
||||||
m_is_pointer(ti.m_is_pointer),
|
m_is_pointer(ti.m_is_pointer),
|
||||||
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
|
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
|
||||||
m_type_info(ti.m_type_info),
|
|
||||||
m_bare_type_info(ti.m_bare_type_info),
|
|
||||||
m_is_undef(ti.m_is_undef)
|
m_is_undef(ti.m_is_undef)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Info &operator=(const Type_Info &ti)
|
Type_Info &operator=(const Type_Info &ti)
|
||||||
{
|
{
|
||||||
|
m_type_info = ti.m_type_info;
|
||||||
|
m_bare_type_info = ti.m_bare_type_info;
|
||||||
m_is_const = ti.m_is_const;
|
m_is_const = ti.m_is_const;
|
||||||
m_is_reference = ti.m_is_reference;
|
m_is_reference = ti.m_is_reference;
|
||||||
m_is_pointer = ti.m_is_pointer;
|
m_is_pointer = ti.m_is_pointer;
|
||||||
m_is_void = ti.m_is_void;
|
m_is_void = ti.m_is_void;
|
||||||
m_is_arithmetic = ti.m_is_arithmetic;
|
m_is_arithmetic = ti.m_is_arithmetic;
|
||||||
m_type_info = ti.m_type_info;
|
|
||||||
m_bare_type_info = ti.m_bare_type_info;
|
|
||||||
m_is_undef = ti.m_is_undef;
|
m_is_undef = ti.m_is_undef;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -126,13 +127,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const std::type_info *m_type_info;
|
||||||
|
const std::type_info *m_bare_type_info;
|
||||||
bool m_is_const;
|
bool m_is_const;
|
||||||
bool m_is_reference;
|
bool m_is_reference;
|
||||||
bool m_is_pointer;
|
bool m_is_pointer;
|
||||||
bool m_is_void;
|
bool m_is_void;
|
||||||
bool m_is_arithmetic;
|
bool m_is_arithmetic;
|
||||||
const std::type_info *m_type_info;
|
|
||||||
const std::type_info *m_bare_type_info;
|
|
||||||
bool m_is_undef;
|
bool m_is_undef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ namespace chaiscript
|
|||||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
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, Map_Pair, Value_Range,
|
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||||
Logical_And, Logical_Or
|
Logical_And, Logical_Or, Switch, Case, Default, Ternary_Cond
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ namespace chaiscript
|
|||||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
"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", "Map_Pair", "Value_Range",
|
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||||
"Logical_And", "Logical_Or"};
|
"Logical_And", "Logical_Or", "Switch", "Case", "Default", "Ternary Condition"};
|
||||||
|
|
||||||
return ast_node_types[ast_node_type];
|
return ast_node_types[ast_node_type];
|
||||||
}
|
}
|
||||||
@@ -69,22 +69,312 @@ namespace chaiscript
|
|||||||
File_Position start_position;
|
File_Position start_position;
|
||||||
File_Position end_position;
|
File_Position end_position;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
std::string detail;
|
||||||
std::vector<AST_NodePtr> call_stack;
|
std::vector<AST_NodePtr> call_stack;
|
||||||
|
|
||||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) throw() :
|
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||||
std::runtime_error("Error: \"" + t_why + "\" " +
|
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
(t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") +
|
bool t_dot_notation,
|
||||||
+ "at (" + boost::lexical_cast<std::string>(t_where.line) + ", " +
|
const chaiscript::detail::Dispatch_Engine &t_ss) :
|
||||||
boost::lexical_cast<std::string>(t_where.column) + ")"),
|
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, 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,
|
||||||
|
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
|
bool t_dot_notation,
|
||||||
|
const chaiscript::detail::Dispatch_Engine &t_ss) :
|
||||||
|
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
|
||||||
|
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) :
|
||||||
|
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||||
reason(t_why), start_position(t_where), end_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) throw()
|
eval_error(const std::string &t_why) throw()
|
||||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||||
reason(t_why)
|
reason(t_why)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
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]) << ")" << 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 << std::endl;
|
||||||
|
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss << std::endl;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~eval_error() throw() {}
|
virtual ~eval_error() throw() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static int id(const T& t)
|
||||||
|
{
|
||||||
|
return t->identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string pretty(const T& t)
|
||||||
|
{
|
||||||
|
return t->pretty_print();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string fname(const T& t)
|
||||||
|
{
|
||||||
|
return *t->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string startpos(const T& t)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << t->start.line << ", " << t->start.column;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format_why(const std::string &t_why)
|
||||||
|
{
|
||||||
|
return "Error: \"" + t_why + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format_types(const Const_Proxy_Function &t_func,
|
||||||
|
bool t_dot_notation,
|
||||||
|
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||||
|
{
|
||||||
|
int arity = t_func->get_arity();
|
||||||
|
std::vector<Type_Info> types = t_func->get_param_types();
|
||||||
|
|
||||||
|
std::string retval;
|
||||||
|
if (arity == -1)
|
||||||
|
{
|
||||||
|
retval = "(...)";
|
||||||
|
if (t_dot_notation)
|
||||||
|
{
|
||||||
|
retval = "(Object)." + retval;
|
||||||
|
}
|
||||||
|
} else if (types.size() <= 1) {
|
||||||
|
retval = "()";
|
||||||
|
} else {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "(";
|
||||||
|
|
||||||
|
std::string paramstr;
|
||||||
|
|
||||||
|
for (size_t index = 1;
|
||||||
|
index != types.size();
|
||||||
|
++index)
|
||||||
|
{
|
||||||
|
paramstr += (types[index].is_const()?"const ":"");
|
||||||
|
paramstr += t_ss.get_type_name(types[index]);
|
||||||
|
|
||||||
|
if (index == 1 && t_dot_notation)
|
||||||
|
{
|
||||||
|
paramstr += ").(";
|
||||||
|
if (types.size() == 2)
|
||||||
|
{
|
||||||
|
paramstr += ", ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
paramstr += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << paramstr.substr(0, paramstr.size() - 2);
|
||||||
|
|
||||||
|
ss << ")";
|
||||||
|
retval = ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||||
|
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||||
|
|
||||||
|
if (dynfun)
|
||||||
|
{
|
||||||
|
Proxy_Function f = dynfun->get_guard();
|
||||||
|
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
|
||||||
|
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||||
|
if (dynfunguard)
|
||||||
|
{
|
||||||
|
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval += "\n Defined at " + format_location(dynfun->get_parse_tree());
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string format_guard(const T &t)
|
||||||
|
{
|
||||||
|
return t->pretty_print();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::string format_location(const T &t)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "(" << *t->filename << " " << t->start.line << ", " << t->start.column << ")";
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||||
|
bool t_dot_notation,
|
||||||
|
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
if (t_functions.size() == 1)
|
||||||
|
{
|
||||||
|
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
|
||||||
|
} else {
|
||||||
|
ss << " " << t_functions.size() << " overloads available:" << std::endl;
|
||||||
|
|
||||||
|
for (std::vector<chaiscript::Const_Proxy_Function>::const_iterator itr = t_functions.begin();
|
||||||
|
itr != t_functions.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
ss << " " << format_types((*itr), t_dot_notation, t_ss) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
||||||
|
bool t_dot_notation,
|
||||||
|
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "(";
|
||||||
|
|
||||||
|
if (!t_parameters.empty())
|
||||||
|
{
|
||||||
|
std::string paramstr;
|
||||||
|
|
||||||
|
for (std::vector<Boxed_Value>::const_iterator itr = t_parameters.begin();
|
||||||
|
itr != t_parameters.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
paramstr += (itr->is_const()?"const ":"");
|
||||||
|
paramstr += t_ss.type_name(*itr);
|
||||||
|
|
||||||
|
if (itr == t_parameters.begin() && t_dot_notation)
|
||||||
|
{
|
||||||
|
paramstr += ").(";
|
||||||
|
if (t_parameters.size() == 1)
|
||||||
|
{
|
||||||
|
paramstr += ", ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
paramstr += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << paramstr.substr(0, paramstr.size() - 2);
|
||||||
|
}
|
||||||
|
ss << ")";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format_filename(const std::string &t_fname)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
if (t_fname != "__EVAL__")
|
||||||
|
{
|
||||||
|
ss << "in '" << t_fname << "' ";
|
||||||
|
} else {
|
||||||
|
ss << "during evaluation ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format_location(const File_Position &t_where)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "at (" << t_where.line << ", " << t_where.column << ")";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||||
|
const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << format_why(t_why);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
ss << format_filename(t_fname);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
ss << format_location(t_where);
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format(const std::string &t_why,
|
||||||
|
const std::vector<Boxed_Value> &t_parameters,
|
||||||
|
bool t_dot_notation,
|
||||||
|
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << format_why(t_why);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << format_why(t_why);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
ss << format_filename(t_fname);
|
||||||
|
ss << " ";
|
||||||
|
|
||||||
|
ss << format_location(t_where);
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,6 +401,19 @@ namespace chaiscript
|
|||||||
std::vector<AST_NodePtr> children;
|
std::vector<AST_NodePtr> children;
|
||||||
AST_NodePtr annotation;
|
AST_NodePtr annotation;
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
oss << text;
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||||
|
oss << this->children[j]->pretty_print();
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the contents of an AST node, including its children, recursively
|
* Prints the contents of an AST node, including its children, recursively
|
||||||
*/
|
*/
|
||||||
@@ -213,6 +516,57 @@ namespace chaiscript
|
|||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine &m_de;
|
chaiscript::detail::Dispatch_Engine &m_de;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Creates a new functon call and pops it on destruction
|
||||||
|
struct Function_Push_Pop
|
||||||
|
{
|
||||||
|
Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||||
|
: m_de(t_de)
|
||||||
|
{
|
||||||
|
m_de.new_function_call();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Function_Push_Pop()
|
||||||
|
{
|
||||||
|
m_de.pop_function_call();
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_params(const std::vector<Boxed_Value> &t_params)
|
||||||
|
{
|
||||||
|
m_de.save_function_params(t_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// explicitly unimplemented copy and assignment
|
||||||
|
Function_Push_Pop(const Function_Push_Pop &);
|
||||||
|
Function_Push_Pop& operator=(const Function_Push_Pop &);
|
||||||
|
|
||||||
|
chaiscript::detail::Dispatch_Engine &m_de;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Creates a new scope then pops it on destruction
|
||||||
|
struct Stack_Push_Pop
|
||||||
|
{
|
||||||
|
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||||
|
: m_de(t_de)
|
||||||
|
{
|
||||||
|
m_de.new_stack();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Stack_Push_Pop()
|
||||||
|
{
|
||||||
|
m_de.pop_stack();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// explicitly unimplemented copy and assignment
|
||||||
|
Stack_Push_Pop(const Stack_Push_Pop &);
|
||||||
|
Stack_Push_Pop& operator=(const Stack_Push_Pop &);
|
||||||
|
|
||||||
|
chaiscript::detail::Dispatch_Engine &m_de;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <chaiscript/language/chaiscript_common.hpp>
|
#include "chaiscript_common.hpp"
|
||||||
|
|
||||||
#ifdef _POSIX_VERSION
|
#ifdef _POSIX_VERSION
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <chaiscript/language/chaiscript_prelude.hpp>
|
#include "chaiscript_prelude.hpp"
|
||||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
#include "chaiscript_parser.hpp"
|
||||||
#include "../dispatchkit/exception_specification.hpp"
|
#include "../dispatchkit/exception_specification.hpp"
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
@@ -76,7 +76,7 @@ namespace chaiscript
|
|||||||
struct DLSym
|
struct DLSym
|
||||||
{
|
{
|
||||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||||
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
|
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||||
{
|
{
|
||||||
if (!m_symbol)
|
if (!m_symbol)
|
||||||
{
|
{
|
||||||
@@ -84,6 +84,19 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static T cast_symbol(void *p)
|
||||||
|
{
|
||||||
|
union cast_union
|
||||||
|
{
|
||||||
|
T func_ptr;
|
||||||
|
void *in_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
cast_union c;
|
||||||
|
c.in_ptr = p;
|
||||||
|
return c.func_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
T m_symbol;
|
T m_symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -261,7 +274,11 @@ namespace chaiscript
|
|||||||
|
|
||||||
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
|
const Boxed_Value internal_eval_ast(const AST_NodePtr &t_ast)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
return t_ast->eval(m_engine);
|
return t_ast->eval(m_engine);
|
||||||
|
} catch (const exception::eval_error &t_ee) {
|
||||||
|
throw Boxed_Value(t_ee);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -269,36 +286,13 @@ namespace chaiscript
|
|||||||
* Evaluates the given string, used during eval() inside of a script
|
* Evaluates the given string, used during eval() inside of a script
|
||||||
*/
|
*/
|
||||||
const Boxed_Value internal_eval(const std::string &t_e) {
|
const Boxed_Value internal_eval(const std::string &t_e) {
|
||||||
return do_eval(t_e, "__EVAL__", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void use(const std::string &t_filename)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_usepaths.size(); ++i)
|
|
||||||
{
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
return do_eval(t_e, "__EVAL__", true);
|
||||||
|
} catch (const exception::eval_error &t_ee) {
|
||||||
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
throw Boxed_Value(t_ee);
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
|
||||||
|
|
||||||
if (m_used_files.count(appendedpath) == 0)
|
|
||||||
{
|
|
||||||
m_used_files.insert(appendedpath);
|
|
||||||
l2.unlock();
|
|
||||||
eval_file(appendedpath);
|
|
||||||
}
|
}
|
||||||
} catch (const exception::file_not_found_error &) {
|
|
||||||
if (i == m_usepaths.size() - 1)
|
|
||||||
{
|
|
||||||
throw exception::file_not_found_error(t_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed to load, try the next path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current evaluation m_engine
|
* Returns the current evaluation m_engine
|
||||||
@@ -312,6 +306,7 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
void build_eval_system() {
|
void build_eval_system() {
|
||||||
using namespace bootstrap;
|
using namespace bootstrap;
|
||||||
|
m_engine.add_reserved_word("auto");
|
||||||
m_engine.add_reserved_word("def");
|
m_engine.add_reserved_word("def");
|
||||||
m_engine.add_reserved_word("fun");
|
m_engine.add_reserved_word("fun");
|
||||||
m_engine.add_reserved_word("while");
|
m_engine.add_reserved_word("while");
|
||||||
@@ -336,6 +331,8 @@ namespace chaiscript
|
|||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
|
||||||
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, boost::ref(m_engine)), "get_functions");
|
||||||
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, boost::ref(m_engine)), "get_objects");
|
||||||
|
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
|
||||||
|
|
||||||
@@ -404,6 +401,40 @@ namespace chaiscript
|
|||||||
build_eval_system();
|
build_eval_system();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Loads and parses a file. If the file is already, it is not reloaded
|
||||||
|
/// The use paths specified at ChaiScript construction time are searched for the
|
||||||
|
/// requested file.
|
||||||
|
///
|
||||||
|
/// \param[in] t_filename Filename to load and evaluate
|
||||||
|
void use(const std::string &t_filename)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_usepaths.size(); ++i)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (m_used_files.count(appendedpath) == 0)
|
||||||
|
{
|
||||||
|
m_used_files.insert(appendedpath);
|
||||||
|
l2.unlock();
|
||||||
|
eval_file(appendedpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return; // return, we loaded it, or it was already loaded
|
||||||
|
} catch (const exception::file_not_found_error &) {
|
||||||
|
if (i == m_usepaths.size() - 1)
|
||||||
|
{
|
||||||
|
throw exception::file_not_found_error(t_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// failed to load, try the next path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Adds a constant object that is available in all contexts and to all threads
|
/// \brief Adds a constant object that is available in all contexts and to all threads
|
||||||
/// \param[in] t_bv Boxed_Value to add as a global
|
/// \param[in] t_bv Boxed_Value to add as a global
|
||||||
/// \param[in] t_name Name of the value to add
|
/// \param[in] t_name Name of the value to add
|
||||||
@@ -425,8 +456,12 @@ namespace chaiscript
|
|||||||
std::set<std::string> active_loaded_modules;
|
std::set<std::string> active_loaded_modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Returns a state object that represents the current state of the system
|
/// \brief Returns a state object that represents the current state of the global system
|
||||||
/// \return Current state of the system
|
///
|
||||||
|
/// The global system includes the reserved words, global const objects, functions and types.
|
||||||
|
/// local variables are thread specific and not included.
|
||||||
|
///
|
||||||
|
/// \return Current state of the global system
|
||||||
///
|
///
|
||||||
/// \b Example:
|
/// \b Example:
|
||||||
///
|
///
|
||||||
@@ -447,6 +482,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Sets the state of the system
|
/// \brief Sets the state of the system
|
||||||
|
///
|
||||||
|
/// The global system includes the reserved words, global objects, functions and types.
|
||||||
|
/// local variables are thread specific and not included.
|
||||||
|
///
|
||||||
/// \param[in] t_state New state to set
|
/// \param[in] t_state New state to set
|
||||||
///
|
///
|
||||||
/// \b Example:
|
/// \b Example:
|
||||||
@@ -466,7 +505,23 @@ namespace chaiscript
|
|||||||
m_engine.set_state(t_state.engine_state);
|
m_engine.set_state(t_state.engine_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Adds a type, function or object to ChaiScript
|
/// \returns All values in the local thread state, added through the add() function
|
||||||
|
std::map<std::string, Boxed_Value> get_locals() const
|
||||||
|
{
|
||||||
|
return m_engine.get_locals();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Sets all of the locals for the current thread state.
|
||||||
|
///
|
||||||
|
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||||
|
///
|
||||||
|
/// 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)
|
||||||
|
{
|
||||||
|
m_engine.set_locals(t_locals);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Adds a type, function or object to ChaiScript. Objects are added to the local thread state.
|
||||||
/// \param[in] t_t Item to add
|
/// \param[in] t_t Item to add
|
||||||
/// \param[in] t_name Name of item to add
|
/// \param[in] t_name Name of item to add
|
||||||
/// \returns Reference to current ChaiScript object
|
/// \returns Reference to current ChaiScript object
|
||||||
@@ -621,6 +676,8 @@ namespace chaiscript
|
|||||||
/// \tparam T Type to extract from the result value of the script execution
|
/// \tparam T Type to extract from the result value of the script execution
|
||||||
/// \param[in] t_input Script to execute
|
/// \param[in] t_input Script to execute
|
||||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||||
|
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
|
||||||
|
/// in special cases where you are loading a file internally instead of using eval_file
|
||||||
///
|
///
|
||||||
/// \return result of the script execution
|
/// \return result of the script execution
|
||||||
///
|
///
|
||||||
@@ -628,10 +685,10 @@ namespace chaiscript
|
|||||||
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||||
/// to the requested type.
|
/// to the requested type.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return boxed_cast<T>(do_eval(t_input));
|
return boxed_cast<T>(do_eval(t_input, t_filename));
|
||||||
} catch (Boxed_Value &bv) {
|
} catch (Boxed_Value &bv) {
|
||||||
if (t_handler) {
|
if (t_handler) {
|
||||||
t_handler->handle(bv);
|
t_handler->handle(bv);
|
||||||
@@ -644,14 +701,16 @@ namespace chaiscript
|
|||||||
///
|
///
|
||||||
/// \param[in] t_input Script to execute
|
/// \param[in] t_input Script to execute
|
||||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||||
|
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
|
||||||
|
/// in special cases where you are loading a file internally instead of using eval_file
|
||||||
///
|
///
|
||||||
/// \return result of the script execution
|
/// \return result of the script execution
|
||||||
///
|
///
|
||||||
/// \throw exception::eval_error In the case that evaluation fails.
|
/// \throw exception::eval_error In the case that evaluation fails.
|
||||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return do_eval(t_input);
|
return do_eval(t_input, t_filename);
|
||||||
} catch (Boxed_Value &bv) {
|
} catch (Boxed_Value &bv) {
|
||||||
if (t_handler) {
|
if (t_handler) {
|
||||||
t_handler->handle(bv);
|
t_handler->handle(bv);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -49,11 +49,27 @@ namespace chaiscript
|
|||||||
this->children[2]->eval(t_ss));
|
this->children[2]->eval(t_ss));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
if (children.size() == 3)
|
||||||
|
{
|
||||||
|
return "(" + this->children[0]->pretty_print() + " " + this->children[1]->text + " " + this->children[2]->pretty_print() + ")";
|
||||||
|
} else {
|
||||||
|
return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Boxed_Value do_oper(chaiscript::detail::Dispatch_Engine &t_ss,
|
Boxed_Value do_oper(chaiscript::detail::Dispatch_Engine &t_ss,
|
||||||
Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
|
std::vector<Boxed_Value> params(2);
|
||||||
|
params.push_back(t_lhs);
|
||||||
|
params.push_back(t_rhs);
|
||||||
|
fpp.save_params(params);
|
||||||
|
|
||||||
if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
|
if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
|
||||||
{
|
{
|
||||||
// If it's an arithmetic operation we want to short circuit dispatch
|
// If it's an arithmetic operation we want to short circuit dispatch
|
||||||
@@ -64,11 +80,12 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
return t_ss.call_function(t_oper_string, t_lhs, t_rhs);
|
return t_ss.call_function(t_oper_string, t_lhs, t_rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &){
|
catch(const exception::dispatch_error &e){
|
||||||
throw exception::eval_error("Can not find appropriate '" + t_oper_string + "'");
|
throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -86,6 +103,9 @@ namespace chaiscript
|
|||||||
Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
m_value(const_var(int(atoi(t_ast_node_text.c_str())))) { }
|
m_value(const_var(int(atoi(t_ast_node_text.c_str())))) { }
|
||||||
|
Int_AST_Node(const std::string &t_ast_node_text, const Boxed_Value &t_bv, int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
|
m_value(t_bv) { }
|
||||||
virtual ~Int_AST_Node() {}
|
virtual ~Int_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
|
||||||
return m_value;
|
return m_value;
|
||||||
@@ -101,6 +121,9 @@ namespace chaiscript
|
|||||||
Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
m_value(const_var(double(atof(t_ast_node_text.c_str())))) { }
|
m_value(const_var(double(atof(t_ast_node_text.c_str())))) { }
|
||||||
|
Float_AST_Node(const std::string &t_ast_node_text, const Boxed_Value &t_bv, int t_id = AST_Node_Type::Float, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
|
||||||
|
m_value(t_bv) { }
|
||||||
virtual ~Float_AST_Node() {}
|
virtual ~Float_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
|
||||||
return m_value;
|
return m_value;
|
||||||
@@ -174,6 +197,11 @@ namespace chaiscript
|
|||||||
Eol_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Eol, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Eol_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Eol, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
virtual ~Eol_AST_Node() {}
|
virtual ~Eol_AST_Node() {}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
return "\n";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Fun_Call_AST_Node : public AST_Node {
|
struct Fun_Call_AST_Node : public AST_Node {
|
||||||
@@ -182,6 +210,7 @@ namespace chaiscript
|
|||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
virtual ~Fun_Call_AST_Node() {}
|
virtual ~Fun_Call_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
||||||
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
dispatch::Param_List_Builder plb;
|
dispatch::Param_List_Builder plb;
|
||||||
|
|
||||||
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
||||||
@@ -190,36 +219,56 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack prev_stack = t_ss.get_stack();
|
fpp.save_params(plb.objects);
|
||||||
chaiscript::detail::Dispatch_Engine::Stack new_stack = t_ss.new_stack();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Boxed_Value fn = this->children[0]->eval(t_ss);
|
Boxed_Value fn = this->children[0]->eval(t_ss);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
t_ss.set_stack(new_stack);
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(plb);
|
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(plb);
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
t_ss.set_stack(prev_stack);
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, t_ss);
|
||||||
|
}
|
||||||
|
catch(const exception::bad_boxed_cast &){
|
||||||
|
try {
|
||||||
|
Const_Proxy_Function f = boxed_cast<const Const_Proxy_Function &>(fn);
|
||||||
|
// handle the case where there is only 1 function to try to call and dispatch fails on it
|
||||||
|
std::vector<Const_Proxy_Function> funcs;
|
||||||
|
funcs.push_back(f);
|
||||||
|
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", plb.objects, funcs, false, t_ss);
|
||||||
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
|
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const exception::arity_error &e){
|
||||||
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||||
|
}
|
||||||
|
catch(const exception::guard_error &e){
|
||||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||||
}
|
}
|
||||||
catch(detail::Return_Value &rv) {
|
catch(detail::Return_Value &rv) {
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
return rv.retval;
|
return rv.retval;
|
||||||
}
|
}
|
||||||
catch(...) {
|
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(exception::eval_error &) {
|
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||||
|
oss << this->children[j]->pretty_print();
|
||||||
|
|
||||||
|
if (j == 0)
|
||||||
|
{
|
||||||
|
oss << "(";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << ")";
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -238,18 +287,53 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Boxed_Value bv;
|
||||||
|
Const_Proxy_Function fn;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return (*boxed_cast<const Const_Proxy_Function &>(this->children[0]->eval(t_ss)))(plb);
|
bv = this->children[0]->eval(t_ss);
|
||||||
|
try {
|
||||||
|
fn = boxed_cast<const Const_Proxy_Function &>(bv);
|
||||||
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
|
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
|
||||||
|
}
|
||||||
|
return (*fn)(plb);
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, t_ss);
|
||||||
|
}
|
||||||
|
catch(const exception::bad_boxed_cast &){
|
||||||
|
// handle the case where there is only 1 function to try to call and dispatch fails on it
|
||||||
|
std::vector<Const_Proxy_Function> funcs;
|
||||||
|
funcs.push_back(fn);
|
||||||
|
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", plb.objects, funcs, false, t_ss);
|
||||||
|
}
|
||||||
|
catch(const exception::arity_error &e){
|
||||||
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||||
|
}
|
||||||
|
catch(const exception::guard_error &e){
|
||||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||||
}
|
}
|
||||||
catch(detail::Return_Value &rv) {
|
catch(detail::Return_Value &rv) {
|
||||||
return rv.retval;
|
return rv.retval;
|
||||||
}
|
}
|
||||||
catch(...) {
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||||
|
oss << this->children[j]->pretty_print();
|
||||||
|
|
||||||
|
if (j == 0)
|
||||||
|
{
|
||||||
|
oss << "(";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << ")";
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -259,6 +343,21 @@ namespace chaiscript
|
|||||||
Arg_List_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Arg_List, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Arg_List_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Arg_List, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
virtual ~Arg_List_AST_Node() {}
|
virtual ~Arg_List_AST_Node() {}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||||
|
if (j != 0)
|
||||||
|
{
|
||||||
|
oss << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << this->children[j]->pretty_print();
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Variable_AST_Node : public AST_Node {
|
struct Variable_AST_Node : public AST_Node {
|
||||||
@@ -296,18 +395,17 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
if (lhs.is_undef()) {
|
if (lhs.is_undef()) {
|
||||||
retval = t_ss.call_function("clone", retval);
|
retval = t_ss.call_function("clone", retval);
|
||||||
retval.clear_dependencies();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
retval = t_ss.call_function(this->children[1]->text, lhs, retval);
|
retval = t_ss.call_function(this->children[1]->text, lhs, retval);
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &){
|
catch(const exception::dispatch_error &e){
|
||||||
throw exception::eval_error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."));
|
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &){
|
catch(const exception::dispatch_error &e){
|
||||||
throw exception::eval_error("Can not clone right hand side of equation");
|
throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this->children[1]->text == ":=") {
|
else if (this->children[1]->text == ":=") {
|
||||||
@@ -320,8 +418,8 @@ namespace chaiscript
|
|||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
retval = t_ss.call_function(this->children[1]->text, lhs, retval);
|
retval = t_ss.call_function(this->children[1]->text, lhs, retval);
|
||||||
} catch(const exception::dispatch_error &){
|
} catch(const exception::dispatch_error &e){
|
||||||
throw exception::eval_error("Can not find appropriate '" + this->children[1]->text + "'");
|
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,10 +438,17 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
catch (const exception::reserved_word_error &) {
|
catch (const exception::reserved_word_error &) {
|
||||||
throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'");
|
throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'");
|
||||||
|
} catch (const exception::name_conflict_error &e) {
|
||||||
|
throw exception::eval_error("Variable redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
return t_ss.get_object(this->children[0]->text);
|
return t_ss.get_object(this->children[0]->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
return "var " + this->children[0]->text;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Comparison_AST_Node : public Binary_Operator_AST_Node {
|
struct Comparison_AST_Node : public Binary_Operator_AST_Node {
|
||||||
@@ -355,7 +460,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Addition_AST_Node : public Binary_Operator_AST_Node {
|
struct Addition_AST_Node : public Binary_Operator_AST_Node {
|
||||||
public:
|
public:
|
||||||
Addition_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Addition,
|
Addition_AST_Node(const std::string &t_ast_node_text = "+", int t_id = AST_Node_Type::Addition,
|
||||||
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(),
|
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(),
|
||||||
int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
@@ -367,7 +472,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Subtraction_AST_Node : public Binary_Operator_AST_Node {
|
struct Subtraction_AST_Node : public Binary_Operator_AST_Node {
|
||||||
public:
|
public:
|
||||||
Subtraction_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Subtraction,
|
Subtraction_AST_Node(const std::string &t_ast_node_text = "-", int t_id = AST_Node_Type::Subtraction,
|
||||||
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
||||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
@@ -379,7 +484,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Multiplication_AST_Node : public Binary_Operator_AST_Node {
|
struct Multiplication_AST_Node : public Binary_Operator_AST_Node {
|
||||||
public:
|
public:
|
||||||
Multiplication_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Multiplication,
|
Multiplication_AST_Node(const std::string &t_ast_node_text = "*", int t_id = AST_Node_Type::Multiplication,
|
||||||
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
||||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
@@ -391,7 +496,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Division_AST_Node : public Binary_Operator_AST_Node {
|
struct Division_AST_Node : public Binary_Operator_AST_Node {
|
||||||
public:
|
public:
|
||||||
Division_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Division,
|
Division_AST_Node(const std::string &t_ast_node_text = "/", int t_id = AST_Node_Type::Division,
|
||||||
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
||||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
@@ -403,7 +508,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Modulus_AST_Node : public Binary_Operator_AST_Node {
|
struct Modulus_AST_Node : public Binary_Operator_AST_Node {
|
||||||
public:
|
public:
|
||||||
Modulus_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Modulus,
|
Modulus_AST_Node(const std::string &t_ast_node_text = "%", int t_id = AST_Node_Type::Modulus,
|
||||||
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
|
||||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
@@ -419,22 +524,46 @@ namespace chaiscript
|
|||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
virtual ~Array_Call_AST_Node() {}
|
virtual ~Array_Call_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
||||||
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
Boxed_Value retval = this->children[0]->eval(t_ss);
|
Boxed_Value retval = this->children[0]->eval(t_ss);
|
||||||
|
std::vector<Boxed_Value> params;
|
||||||
|
params.push_back(retval);
|
||||||
|
|
||||||
for (size_t i = 1; i < this->children.size(); ++i) {
|
for (size_t i = 1; i < this->children.size(); ++i) {
|
||||||
try {
|
try {
|
||||||
retval = t_ss.call_function("[]", retval, this->children[i]->eval(t_ss));
|
Boxed_Value p1(this->children[i]->eval(t_ss));
|
||||||
|
|
||||||
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
|
params.push_back(p1);
|
||||||
|
fpp.save_params(params);
|
||||||
|
params.clear();
|
||||||
|
retval = t_ss.call_function("[]", retval, p1);
|
||||||
}
|
}
|
||||||
catch(std::out_of_range &) {
|
catch(std::out_of_range &) {
|
||||||
throw exception::eval_error("Out of bounds exception");
|
throw exception::eval_error("Out of bounds exception");
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &){
|
catch(const exception::dispatch_error &e){
|
||||||
throw exception::eval_error("Can not find appropriate array lookup '[]' ");
|
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, t_ss );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << this->children[0]->pretty_print();
|
||||||
|
|
||||||
|
for (size_t i = 1; i < this->children.size(); ++i)
|
||||||
|
{
|
||||||
|
oss << "[";
|
||||||
|
oss << this->children[i]->pretty_print();
|
||||||
|
oss << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Dot_Access_AST_Node : public AST_Node {
|
struct Dot_Access_AST_Node : public AST_Node {
|
||||||
@@ -447,6 +576,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (this->children.size() > 1) {
|
if (this->children.size() > 1) {
|
||||||
for (size_t i = 2; i < this->children.size(); i+=2) {
|
for (size_t i = 2; i < this->children.size(); i+=2) {
|
||||||
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
dispatch::Param_List_Builder plb;
|
dispatch::Param_List_Builder plb;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
|
|
||||||
@@ -456,6 +586,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fpp.save_params(plb.objects);
|
||||||
|
|
||||||
std::string fun_name;
|
std::string fun_name;
|
||||||
if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) {
|
if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) {
|
||||||
fun_name = this->children[i]->children[0]->text;
|
fun_name = this->children[i]->children[0]->text;
|
||||||
@@ -464,26 +596,22 @@ namespace chaiscript
|
|||||||
fun_name = this->children[i]->text;
|
fun_name = this->children[i]->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack prev_stack = t_ss.get_stack();
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack new_stack = t_ss.new_stack();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
t_ss.set_stack(new_stack);
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
retval = t_ss.call_function(fun_name, plb);
|
retval = t_ss.call_function(fun_name, plb);
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
t_ss.set_stack(prev_stack);
|
if (e.functions.empty())
|
||||||
throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name);
|
{
|
||||||
|
throw exception::eval_error("'" + fun_name + "' is not a function.");
|
||||||
|
} else {
|
||||||
|
throw exception::eval_error(std::string(e.what()) + " for function '" + fun_name + "'", e.parameters, e.functions, true, t_ss);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(detail::Return_Value &rv) {
|
catch(detail::Return_Value &rv) {
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
retval = rv.retval;
|
retval = rv.retval;
|
||||||
}
|
}
|
||||||
catch(...) {
|
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
if (this->children[i]->identifier == AST_Node_Type::Array_Call) {
|
if (this->children[i]->identifier == AST_Node_Type::Array_Call) {
|
||||||
for (size_t j = 1; j < this->children[i]->children.size(); ++j) {
|
for (size_t j = 1; j < this->children[i]->children.size(); ++j) {
|
||||||
try {
|
try {
|
||||||
@@ -492,8 +620,8 @@ namespace chaiscript
|
|||||||
catch(std::out_of_range &) {
|
catch(std::out_of_range &) {
|
||||||
throw exception::eval_error("Out of bounds exception");
|
throw exception::eval_error("Out of bounds exception");
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &){
|
catch(const exception::dispatch_error &e){
|
||||||
throw exception::eval_error("Can not find appropriate array lookup '[]' ");
|
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,6 +643,11 @@ namespace chaiscript
|
|||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
return "\"" + text + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Boxed_Value m_value;
|
Boxed_Value m_value;
|
||||||
|
|
||||||
@@ -530,6 +663,11 @@ namespace chaiscript
|
|||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
return "'" + text + "'";
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Boxed_Value m_value;
|
Boxed_Value m_value;
|
||||||
};
|
};
|
||||||
@@ -639,6 +777,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
catch (const exception::reserved_word_error &e) {
|
catch (const exception::reserved_word_error &e) {
|
||||||
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
|
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
|
||||||
|
} catch (const exception::name_conflict_error &e) {
|
||||||
|
throw exception::eval_error("Function redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
return Boxed_Value();
|
return Boxed_Value();
|
||||||
}
|
}
|
||||||
@@ -681,6 +821,29 @@ namespace chaiscript
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ternary_Cond_AST_Node : public AST_Node {
|
||||||
|
public:
|
||||||
|
Ternary_Cond_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
|
virtual ~Ternary_Cond_AST_Node() {}
|
||||||
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
||||||
|
bool cond;
|
||||||
|
try {
|
||||||
|
cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
|
||||||
|
}
|
||||||
|
catch (const exception::bad_boxed_cast &) {
|
||||||
|
throw exception::eval_error("If condition not boolean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cond) {
|
||||||
|
return this->children[1]->eval(t_ss);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return this->children[2]->eval(t_ss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct If_AST_Node : public AST_Node {
|
struct If_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
If_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
If_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
@@ -776,20 +939,97 @@ namespace chaiscript
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Switch_AST_Node : public AST_Node {
|
||||||
|
public:
|
||||||
|
Switch_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Switch, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
|
virtual ~Switch_AST_Node() {}
|
||||||
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
|
Boxed_Value match_value;
|
||||||
|
bool breaking = false;
|
||||||
|
size_t currentCase = 1;
|
||||||
|
bool hasMatched = false;
|
||||||
|
|
||||||
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
|
||||||
|
match_value = this->children[0]->eval(t_ss);
|
||||||
|
|
||||||
|
while (!breaking && (currentCase < this->children.size())) {
|
||||||
|
try {
|
||||||
|
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
|
||||||
|
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
|
||||||
|
try {
|
||||||
|
if (hasMatched || boxed_cast<bool>(t_ss.call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) {
|
||||||
|
this->children[currentCase]->eval(t_ss);
|
||||||
|
hasMatched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const exception::bad_boxed_cast &) {
|
||||||
|
throw exception::eval_error("Internal error: case guard evaluation not boolean");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->children[currentCase]->identifier == AST_Node_Type::Default) {
|
||||||
|
this->children[currentCase]->eval(t_ss);
|
||||||
|
breaking = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (detail::Break_Loop &) {
|
||||||
|
breaking = true;
|
||||||
|
}
|
||||||
|
++currentCase;
|
||||||
|
}
|
||||||
|
return Boxed_Value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Case_AST_Node : public AST_Node {
|
||||||
|
public:
|
||||||
|
Case_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Case, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
|
virtual ~Case_AST_Node() {}
|
||||||
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
|
||||||
|
this->children[1]->eval(t_ss);
|
||||||
|
|
||||||
|
return Boxed_Value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Default_AST_Node : public AST_Node {
|
||||||
|
public:
|
||||||
|
Default_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Default, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
|
virtual ~Default_AST_Node() {}
|
||||||
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
|
||||||
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
|
||||||
|
this->children[0]->eval(t_ss);
|
||||||
|
|
||||||
|
return Boxed_Value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Inline_Array_AST_Node : public AST_Node {
|
struct Inline_Array_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
Inline_Array_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Array, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
Inline_Array_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Array, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||||
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||||
virtual ~Inline_Array_AST_Node() {}
|
virtual ~Inline_Array_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
||||||
|
try {
|
||||||
std::vector<Boxed_Value> vec;
|
std::vector<Boxed_Value> vec;
|
||||||
if (this->children.size() > 0) {
|
if (this->children.size() > 0) {
|
||||||
for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
|
for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
|
||||||
vec.push_back(this->children[0]->children[i]->eval(t_ss));
|
Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->eval(t_ss));
|
||||||
|
vec.push_back(bv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return const_var(vec);
|
||||||
|
}
|
||||||
|
catch (const exception::dispatch_error &) {
|
||||||
|
throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for vector elements");
|
||||||
|
}
|
||||||
|
|
||||||
return const_var(vec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -803,13 +1043,14 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
std::map<std::string, Boxed_Value> retval;
|
std::map<std::string, Boxed_Value> retval;
|
||||||
for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
|
for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
|
||||||
|
Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss));
|
||||||
retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))]
|
retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))]
|
||||||
= t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss));
|
= bv;
|
||||||
}
|
}
|
||||||
return const_var(retval);
|
return const_var(retval);
|
||||||
}
|
}
|
||||||
catch (const exception::dispatch_error &) {
|
catch (const exception::dispatch_error &e) {
|
||||||
throw exception::eval_error("Can not find appropriate 'Map()'");
|
throw exception::eval_error("Can not find appropriate copy constructor or 'clone' while inserting into Map.", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,6 +1097,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
virtual ~Prefix_AST_Node() {}
|
virtual ~Prefix_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
||||||
|
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||||
Boxed_Value bv(this->children[1]->eval(t_ss));
|
Boxed_Value bv(this->children[1]->eval(t_ss));
|
||||||
|
|
||||||
Operators::Opers oper = Operators::to_operator(children[0]->text, true);
|
Operators::Opers oper = Operators::to_operator(children[0]->text, true);
|
||||||
@@ -864,10 +1106,14 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return Boxed_Number::do_oper(oper, bv);
|
return Boxed_Number::do_oper(oper, bv);
|
||||||
} else {
|
} else {
|
||||||
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
|
std::vector<Boxed_Value> params;
|
||||||
|
params.push_back(bv);
|
||||||
|
fpp.save_params(params);
|
||||||
return t_ss.call_function(this->children[0]->text, bv);
|
return t_ss.call_function(this->children[0]->text, bv);
|
||||||
}
|
}
|
||||||
} catch (const exception::dispatch_error &) {
|
} catch (const exception::dispatch_error &e) {
|
||||||
throw exception::eval_error("Error with prefix operator evaluation: " + children[0]->text);
|
throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,8 +1154,8 @@ namespace chaiscript
|
|||||||
this->children[0]->children[0]->children[0]->eval(t_ss),
|
this->children[0]->children[0]->children[0]->eval(t_ss),
|
||||||
this->children[0]->children[0]->children[1]->eval(t_ss));
|
this->children[0]->children[0]->children[1]->eval(t_ss));
|
||||||
}
|
}
|
||||||
catch (const exception::dispatch_error &) {
|
catch (const exception::dispatch_error &e) {
|
||||||
throw exception::eval_error("Unable to generate range vector");
|
throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, t_ss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -950,6 +1196,7 @@ namespace chaiscript
|
|||||||
end_point = this->children.size() - 1;
|
end_point = this->children.size() - 1;
|
||||||
}
|
}
|
||||||
for (unsigned int i = 1; i < end_point; ++i) {
|
for (unsigned int i = 1; i < end_point; ++i) {
|
||||||
|
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
|
||||||
AST_NodePtr catch_block = this->children[i];
|
AST_NodePtr catch_block = this->children[i];
|
||||||
|
|
||||||
if (catch_block->children.size() == 1) {
|
if (catch_block->children.size() == 1) {
|
||||||
@@ -992,6 +1239,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
catch (Boxed_Value &except) {
|
catch (Boxed_Value &except) {
|
||||||
for (size_t i = 1; i < this->children.size(); ++i) {
|
for (size_t i = 1; i < this->children.size(); ++i) {
|
||||||
|
chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss);
|
||||||
AST_NodePtr catch_block = this->children[i];
|
AST_NodePtr catch_block = this->children[i];
|
||||||
|
|
||||||
if (catch_block->children.size() == 1) {
|
if (catch_block->children.size() == 1) {
|
||||||
@@ -1006,7 +1254,7 @@ namespace chaiscript
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (catch_block->children.size() == 3) {
|
else if (catch_block->children.size() == 3) {
|
||||||
//Variable capture, no guards
|
//Variable capture, guards
|
||||||
t_ss.add_object(catch_block->children[0]->text, except);
|
t_ss.add_object(catch_block->children[0]->text, except);
|
||||||
|
|
||||||
bool guard;
|
bool guard;
|
||||||
@@ -1134,6 +1382,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
catch (const exception::reserved_word_error &e) {
|
catch (const exception::reserved_word_error &e) {
|
||||||
throw exception::eval_error("Reserved word used as method name '" + e.word() + "'");
|
throw exception::eval_error("Reserved word used as method name '" + e.word() + "'");
|
||||||
|
} catch (const exception::name_conflict_error &e) {
|
||||||
|
throw exception::eval_error("Method redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
return Boxed_Value();
|
return Boxed_Value();
|
||||||
}
|
}
|
||||||
@@ -1147,12 +1397,22 @@ namespace chaiscript
|
|||||||
virtual ~Attr_Decl_AST_Node() {}
|
virtual ~Attr_Decl_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
|
||||||
try {
|
try {
|
||||||
t_ss.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, this->children[0]->text,
|
|
||||||
this->children[1]->text, _1))), this->children[1]->text);
|
t_ss.add(Proxy_Function
|
||||||
|
(new dispatch::detail::Dynamic_Object_Function(
|
||||||
|
this->children[0]->text,
|
||||||
|
fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::Dynamic_Object::get_attr,
|
||||||
|
_1,
|
||||||
|
this->children[1]->text
|
||||||
|
)))
|
||||||
|
)
|
||||||
|
), this->children[1]->text);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (const exception::reserved_word_error &) {
|
catch (const exception::reserved_word_error &) {
|
||||||
throw exception::eval_error("Reserved word used as attribute '" + this->children[1]->text + "'");
|
throw exception::eval_error("Reserved word used as attribute '" + this->children[1]->text + "'");
|
||||||
|
} catch (const exception::name_conflict_error &e) {
|
||||||
|
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
return Boxed_Value();
|
return Boxed_Value();
|
||||||
}
|
}
|
||||||
@@ -1221,6 +1481,11 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
return "(" + AST_Node::pretty_print() + ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Logical_Or_AST_Node : public AST_Node {
|
struct Logical_Or_AST_Node : public AST_Node {
|
||||||
@@ -1248,6 +1513,11 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string pretty_print() const
|
||||||
|
{
|
||||||
|
return "(" + AST_Node::pretty_print() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -33,6 +33,8 @@ namespace chaiscript
|
|||||||
, bin_alphabet
|
, bin_alphabet
|
||||||
, id_alphabet
|
, id_alphabet
|
||||||
, white_alphabet
|
, white_alphabet
|
||||||
|
, int_suffix_alphabet
|
||||||
|
, float_suffix_alphabet
|
||||||
, max_alphabet
|
, max_alphabet
|
||||||
, lengthof_alphabet = 256
|
, lengthof_alphabet = 256
|
||||||
};
|
};
|
||||||
@@ -66,6 +68,11 @@ namespace chaiscript
|
|||||||
|
|
||||||
void setup_operators()
|
void setup_operators()
|
||||||
{
|
{
|
||||||
|
m_operators.push_back(AST_Node_Type::Ternary_Cond);
|
||||||
|
std::vector<std::string> ternary_cond;
|
||||||
|
ternary_cond.push_back("?");
|
||||||
|
m_operator_matches.push_back(ternary_cond);
|
||||||
|
|
||||||
m_operators.push_back(AST_Node_Type::Logical_Or);
|
m_operators.push_back(AST_Node_Type::Logical_Or);
|
||||||
std::vector<std::string> logical_or;
|
std::vector<std::string> logical_or;
|
||||||
logical_or.push_back("||");
|
logical_or.push_back("||");
|
||||||
@@ -131,6 +138,7 @@ namespace chaiscript
|
|||||||
m_alphabet[a][c]=false;
|
m_alphabet[a][c]=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_alphabet[detail::symbol_alphabet][static_cast<int>('?')]=true;
|
||||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('+')]=true;
|
m_alphabet[detail::symbol_alphabet][static_cast<int>('+')]=true;
|
||||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('-')]=true;
|
m_alphabet[detail::symbol_alphabet][static_cast<int>('-')]=true;
|
||||||
m_alphabet[detail::symbol_alphabet][static_cast<int>('*')]=true;
|
m_alphabet[detail::symbol_alphabet][static_cast<int>('*')]=true;
|
||||||
@@ -169,6 +177,17 @@ namespace chaiscript
|
|||||||
|
|
||||||
m_alphabet[detail::white_alphabet][static_cast<int>(' ')]=true;
|
m_alphabet[detail::white_alphabet][static_cast<int>(' ')]=true;
|
||||||
m_alphabet[detail::white_alphabet][static_cast<int>('\t')]=true;
|
m_alphabet[detail::white_alphabet][static_cast<int>('\t')]=true;
|
||||||
|
|
||||||
|
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('l')] = true;
|
||||||
|
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('L')] = true;
|
||||||
|
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('u')] = true;
|
||||||
|
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('U')] = true;
|
||||||
|
|
||||||
|
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('l')] = true;
|
||||||
|
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('L')] = true;
|
||||||
|
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('f')] = true;
|
||||||
|
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('F')] = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -322,7 +341,6 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
bool Float_() {
|
bool Float_() {
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
std::string::const_iterator start = m_input_pos;
|
|
||||||
|
|
||||||
if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) {
|
if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) {
|
||||||
while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) {
|
while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) {
|
||||||
@@ -338,6 +356,12 @@ namespace chaiscript
|
|||||||
++m_input_pos;
|
++m_input_pos;
|
||||||
++m_col;
|
++m_col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_suffix_alphabet))
|
||||||
|
{
|
||||||
|
++m_input_pos;
|
||||||
|
++m_col;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
--m_input_pos;
|
--m_input_pos;
|
||||||
@@ -366,6 +390,11 @@ namespace chaiscript
|
|||||||
++m_input_pos;
|
++m_input_pos;
|
||||||
++m_col;
|
++m_col;
|
||||||
}
|
}
|
||||||
|
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet))
|
||||||
|
{
|
||||||
|
++m_input_pos;
|
||||||
|
++m_col;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
--m_input_pos;
|
--m_input_pos;
|
||||||
@@ -381,6 +410,14 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntSuffix_() {
|
||||||
|
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet))
|
||||||
|
{
|
||||||
|
++m_input_pos;
|
||||||
|
++m_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a binary value from input, without skipping initial whitespace
|
* Reads a binary value from input, without skipping initial whitespace
|
||||||
*/
|
*/
|
||||||
@@ -414,6 +451,173 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Boxed_Value buildFloat(const std::string &t_val)
|
||||||
|
{
|
||||||
|
bool float_ = false;
|
||||||
|
bool long_ = false;
|
||||||
|
|
||||||
|
size_t i = t_val.size();
|
||||||
|
|
||||||
|
for (; i > 0; --i)
|
||||||
|
{
|
||||||
|
char val = t_val[i-1];
|
||||||
|
|
||||||
|
if (val == 'f' || val == 'F')
|
||||||
|
{
|
||||||
|
float_ = true;
|
||||||
|
} else if (val == 'l' || val == 'L') {
|
||||||
|
long_ = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(t_val.substr(0, i));
|
||||||
|
|
||||||
|
if (float_)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
ss >> f;
|
||||||
|
return Boxed_Value(const_var(f));
|
||||||
|
} else if (long_) {
|
||||||
|
long double f;
|
||||||
|
ss >> f;
|
||||||
|
return Boxed_Value(const_var(f));
|
||||||
|
} else {
|
||||||
|
double f;
|
||||||
|
ss >> f;
|
||||||
|
return Boxed_Value(const_var(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename IntType>
|
||||||
|
Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
|
||||||
|
{
|
||||||
|
bool unsigned_ = false;
|
||||||
|
bool long_ = false;
|
||||||
|
bool longlong_ = false;
|
||||||
|
|
||||||
|
size_t i = t_val.size();
|
||||||
|
|
||||||
|
for (; i > 0; --i)
|
||||||
|
{
|
||||||
|
char val = t_val[i-1];
|
||||||
|
|
||||||
|
if (val == 'u' || val == 'U')
|
||||||
|
{
|
||||||
|
unsigned_ = true;
|
||||||
|
} else if (val == 'l' || val == 'L') {
|
||||||
|
if (long_)
|
||||||
|
{
|
||||||
|
longlong_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
long_ = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(t_val.substr(0, i));
|
||||||
|
ss >> t_type;
|
||||||
|
|
||||||
|
std::stringstream testu(t_val.substr(0, i));
|
||||||
|
boost::uint64_t u;
|
||||||
|
testu >> t_type >> u;
|
||||||
|
|
||||||
|
bool unsignedrequired = false;
|
||||||
|
size_t size = sizeof(int) * 8;
|
||||||
|
|
||||||
|
if ((u >> (sizeof(int) * 8)) > 0)
|
||||||
|
{
|
||||||
|
//requires something bigger than int
|
||||||
|
long_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(sizeof(long) == sizeof(boost::uint64_t) || sizeof(long) * 2 == sizeof(boost::uint64_t));
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
//Thank you MSVC, yes we know that a constant value is being used in the if
|
||||||
|
// statment in this compiler / architecture
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4127)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( sizeof(long) < sizeof(boost::uint64_t) && (u >> ((sizeof(boost::uint64_t) - sizeof(long)) * 8)) > 0)
|
||||||
|
{
|
||||||
|
//requires something bigger than long
|
||||||
|
longlong_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (longlong_)
|
||||||
|
{
|
||||||
|
size = sizeof(boost::int64_t) * 8;
|
||||||
|
} else if (long_) {
|
||||||
|
size = sizeof(long) * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (u >> (size - 1)) > 0)
|
||||||
|
{
|
||||||
|
unsignedrequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unsignedrequired && !unsigned_)
|
||||||
|
{
|
||||||
|
if (t_type == &std::hex || t_type == &std::oct)
|
||||||
|
{
|
||||||
|
// with hex and octal we are happy to just make it unsigned
|
||||||
|
unsigned_ = true;
|
||||||
|
} else {
|
||||||
|
// with decimal we must bump it up to the next size
|
||||||
|
if (long_)
|
||||||
|
{
|
||||||
|
longlong_ = true;
|
||||||
|
} else if (!long_ && !longlong_) {
|
||||||
|
long_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unsigned_)
|
||||||
|
{
|
||||||
|
if (longlong_)
|
||||||
|
{
|
||||||
|
boost::uint64_t val;
|
||||||
|
ss >> val;
|
||||||
|
return Boxed_Value(const_var(val));
|
||||||
|
} else if (long_) {
|
||||||
|
unsigned long val;
|
||||||
|
ss >> val;
|
||||||
|
return Boxed_Value(const_var(val));
|
||||||
|
} else {
|
||||||
|
unsigned int val;
|
||||||
|
ss >> val;
|
||||||
|
return Boxed_Value(const_var(val));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (longlong_)
|
||||||
|
{
|
||||||
|
boost::int64_t val;
|
||||||
|
ss >> val;
|
||||||
|
return Boxed_Value(const_var(val));
|
||||||
|
} else if (long_) {
|
||||||
|
long val;
|
||||||
|
ss >> val;
|
||||||
|
return Boxed_Value(const_var(val));
|
||||||
|
} else {
|
||||||
|
int val;
|
||||||
|
ss >> val;
|
||||||
|
return Boxed_Value(const_var(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a number from the input, detecting if it's an integer or floating point
|
* Reads a number from the input, detecting if it's an integer or floating point
|
||||||
*/
|
*/
|
||||||
@@ -430,19 +634,14 @@ namespace chaiscript
|
|||||||
if (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_alphabet) ) {
|
if (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_alphabet) ) {
|
||||||
if (Hex_()) {
|
if (Hex_()) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
std::stringstream ss(match);
|
Boxed_Value i = buildInt(std::hex, match);
|
||||||
unsigned int temp_int;
|
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
ss >> std::hex >> temp_int;
|
|
||||||
|
|
||||||
std::ostringstream out_int;
|
|
||||||
out_int << static_cast<int>(temp_int);
|
|
||||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Binary_()) {
|
if (Binary_()) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
int temp_int = 0;
|
boost::int64_t temp_int = 0;
|
||||||
size_t pos = 0, end = match.length();
|
size_t pos = 0, end = match.length();
|
||||||
|
|
||||||
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
|
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
|
||||||
@@ -453,32 +652,36 @@ namespace chaiscript
|
|||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream out_int;
|
Boxed_Value i;
|
||||||
out_int << temp_int;
|
if (match.length() <= sizeof(int) * 8)
|
||||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
{
|
||||||
|
i = Boxed_Value(const_var(int(temp_int)));
|
||||||
|
} else {
|
||||||
|
i = Boxed_Value(const_var(temp_int));
|
||||||
|
}
|
||||||
|
|
||||||
|
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Float_()) {
|
if (Float_()) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Float_AST_Node(match, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col));
|
Boxed_Value f = buildFloat(match);
|
||||||
|
AST_NodePtr t(new eval::Float_AST_Node(match, f, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
IntSuffix_();
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
if ((match.size() > 0) && (match[0] == '0')) {
|
if ((match.size() > 0) && (match[0] == '0')) {
|
||||||
std::stringstream ss(match);
|
Boxed_Value i = buildInt(std::oct, match);
|
||||||
unsigned int temp_int;
|
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
ss >> std::oct >> temp_int;
|
|
||||||
|
|
||||||
std::ostringstream out_int;
|
|
||||||
out_int << int(temp_int);
|
|
||||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AST_NodePtr t(new eval::Int_AST_Node(match, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
Boxed_Value i = buildInt(std::dec, match);
|
||||||
|
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1416,6 +1619,90 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a case block from input
|
||||||
|
*/
|
||||||
|
bool Case() {
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
size_t prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
|
if (Keyword("case")) {
|
||||||
|
retval = true;
|
||||||
|
|
||||||
|
if (!Char('(')) {
|
||||||
|
throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Operator() && Char(')'))) {
|
||||||
|
throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Eol()) {}
|
||||||
|
|
||||||
|
if (!Block()) {
|
||||||
|
throw exception::eval_error("Incomplete 'case' block", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
build_match(AST_NodePtr(new eval::Case_AST_Node()), prev_stack_top);
|
||||||
|
}
|
||||||
|
else if (Keyword("default")) {
|
||||||
|
while (Eol()) {}
|
||||||
|
|
||||||
|
if (!Block()) {
|
||||||
|
throw exception::eval_error("Incomplete 'default' block", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
build_match(AST_NodePtr(new eval::Default_AST_Node()), prev_stack_top);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a switch statement from input
|
||||||
|
*/
|
||||||
|
bool Switch() {
|
||||||
|
size_t prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
|
if (Keyword("switch")) {
|
||||||
|
|
||||||
|
if (!Char('(')) {
|
||||||
|
throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Operator() && Char(')'))) {
|
||||||
|
throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Eol()) {}
|
||||||
|
|
||||||
|
if (Char('{')) {
|
||||||
|
while (Eol()) {}
|
||||||
|
|
||||||
|
while (Case()) {
|
||||||
|
while (Eol()) { } // eat
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Eol()) { } // eat
|
||||||
|
|
||||||
|
if (!Char('}')) {
|
||||||
|
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
build_match(AST_NodePtr(new eval::Switch_AST_Node()), prev_stack_top);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a curly-brace C-style block from input
|
* Reads a curly-brace C-style block from input
|
||||||
*/
|
*/
|
||||||
@@ -1478,7 +1765,6 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
bool Dot_Fun_Array() {
|
bool Dot_Fun_Array() {
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
std::string::const_iterator prev_pos = m_input_pos;
|
|
||||||
|
|
||||||
size_t prev_stack_top = m_match_stack.size();
|
size_t prev_stack_top = m_match_stack.size();
|
||||||
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
|
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
|
||||||
@@ -1584,7 +1870,7 @@ namespace chaiscript
|
|||||||
throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename);
|
throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename);
|
||||||
}
|
}
|
||||||
if (!Char(')')) {
|
if (!Char(')')) {
|
||||||
throw exception::eval_error("Missing closing parenthesis", File_Position(m_line, m_col), *m_filename);
|
throw exception::eval_error("Missing closing parenthesis ')'", File_Position(m_line, m_col), *m_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@@ -1602,7 +1888,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
Container_Arg_List();
|
Container_Arg_List();
|
||||||
if (!Char(']')) {
|
if (!Char(']')) {
|
||||||
throw exception::eval_error("Missing closing square bracket", File_Position(m_line, m_col), *m_filename);
|
throw exception::eval_error("Missing closing square bracket ']' in container initializer", File_Position(m_line, m_col), *m_filename);
|
||||||
}
|
}
|
||||||
if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) {
|
if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) {
|
||||||
if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) {
|
if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) {
|
||||||
@@ -1720,6 +2006,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
if (Operator_Helper(t_precedence)) {
|
if (Operator_Helper(t_precedence)) {
|
||||||
do {
|
do {
|
||||||
|
while (Eol()) {}
|
||||||
if (!Operator(t_precedence+1)) {
|
if (!Operator(t_precedence+1)) {
|
||||||
throw exception::eval_error("Incomplete "
|
throw exception::eval_error("Incomplete "
|
||||||
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
||||||
@@ -1730,6 +2017,23 @@ namespace chaiscript
|
|||||||
case(AST_Node_Type::Comparison) :
|
case(AST_Node_Type::Comparison) :
|
||||||
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
|
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
|
||||||
break;
|
break;
|
||||||
|
case(AST_Node_Type::Ternary_Cond) :
|
||||||
|
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||||
|
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||||
|
if (Symbol(":")) {
|
||||||
|
if (!Operator(t_precedence+1)) {
|
||||||
|
throw exception::eval_error("Incomplete "
|
||||||
|
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
||||||
|
File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
build_match(AST_NodePtr(new eval::Ternary_Cond_AST_Node()), prev_stack_top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw exception::eval_error("Incomplete "
|
||||||
|
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
|
||||||
|
File_Position(m_line, m_col), *m_filename);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case(AST_Node_Type::Addition) :
|
case(AST_Node_Type::Addition) :
|
||||||
oper = m_match_stack.at(m_match_stack.size()-2);
|
oper = m_match_stack.at(m_match_stack.size()-2);
|
||||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||||
@@ -1887,7 +2191,6 @@ namespace chaiscript
|
|||||||
bool saw_eol = true;
|
bool saw_eol = true;
|
||||||
|
|
||||||
while (has_more) {
|
while (has_more) {
|
||||||
has_more = false;
|
|
||||||
int prev_line = m_line;
|
int prev_line = m_line;
|
||||||
int prev_col = m_col;
|
int prev_col = m_col;
|
||||||
if (Def()) {
|
if (Def()) {
|
||||||
@@ -1930,6 +2233,14 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
saw_eol = true;
|
saw_eol = true;
|
||||||
}
|
}
|
||||||
|
else if (Switch()) {
|
||||||
|
if (!saw_eol) {
|
||||||
|
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||||
|
}
|
||||||
|
has_more = true;
|
||||||
|
retval = true;
|
||||||
|
saw_eol = true;
|
||||||
|
}
|
||||||
else if (Return()) {
|
else if (Return()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@@ -49,10 +49,20 @@
|
|||||||
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
|
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, _class_name_translator, _method_name_translator, _methods) \
|
||||||
|
{ \
|
||||||
|
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
|
||||||
|
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
|
||||||
|
}
|
||||||
|
|
||||||
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
|
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
|
||||||
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
|
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
|
||||||
chaiscript::utility::method_name_translator, _constructors, _methods)
|
chaiscript::utility::method_name_translator, _constructors, _methods)
|
||||||
|
|
||||||
|
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR(_module, _class_name, _methods) \
|
||||||
|
CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
|
||||||
|
chaiscript::utility::method_name_translator, _methods)
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/// \brief Classes and functions which provide general utility to the end user.
|
/// \brief Classes and functions which provide general utility to the end user.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2009-2011 Jason Turner and Jonathan Turner. All Rights Reserved.
|
Copyright 2009-2012 Jason Turner and Jonathan Turner. All Rights Reserved.
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
met:
|
met:
|
||||||
|
82
readme.md
Normal file
82
readme.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
ChaiScript
|
||||||
|
|
||||||
|
http://www.chaiscript.com
|
||||||
|
|
||||||
|
(c) 2009-2012 Jason Turner and Jonathan Turner
|
||||||
|
|
||||||
|
Release under the BSD license, see "license.txt" for details.
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
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
|
||||||
|
native C++ application, it has some advantages over existing embedded scripting
|
||||||
|
languages:
|
||||||
|
|
||||||
|
1) It uses a header-only approach, which makes it easy to integrate with
|
||||||
|
existing projects.
|
||||||
|
2) It maintains type safety between your C++ application and the user scripts.
|
||||||
|
3) It supports a variety of C++ techniques including callbacks, overloaded
|
||||||
|
functions, class methods, and stl containers.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
ChaiScript requires a recent version of Boost (http://www.boost.org) to build.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
* Add the ChaiScript include directory to your project's header search path
|
||||||
|
* Add `#include <chaiscript/chaiscript.hpp>` to your source file
|
||||||
|
* Instantiate the ChaiScript engine in your application. For example, create
|
||||||
|
a new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
|
||||||
|
|
||||||
|
Once instantiated, the engine is ready to start running ChaiScript source. You
|
||||||
|
have two main options for processing ChaiScript source: a line at a time using
|
||||||
|
`chai.eval(string)` and a file at a time using `chai.eval_file(fname)`
|
||||||
|
|
||||||
|
To make functions in your C++ code visible to scripts, they must be registered
|
||||||
|
with the scripting engine. To do so, call add:
|
||||||
|
|
||||||
|
chai.add(chaiscript::fun(&my_function), "my_function_name");
|
||||||
|
|
||||||
|
Once registered the function will be visible to scripts as "my_function_name"
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some
|
||||||
|
modifications to make it easier to use. For usage examples see the "samples"
|
||||||
|
directory, and for more in-depth look at the language, the unit tests in the
|
||||||
|
"unittests" directory cover the most ground.
|
||||||
|
|
||||||
|
For examples of how to register parts of your C++ application, see
|
||||||
|
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
|
||||||
|
possible way of working with the library. For further documentation generate
|
||||||
|
the doxygen documentation in the build folder or see the website
|
||||||
|
http://www.chaiscript.com.
|
||||||
|
|
||||||
|
|
||||||
|
The shortest complete example possible follows:
|
||||||
|
|
||||||
|
/// main.cpp
|
||||||
|
|
||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
|
double function(int i, double j)
|
||||||
|
{
|
||||||
|
return i * j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
chai.add(chaiscript::fun(&function), "function");
|
||||||
|
|
||||||
|
double d = chai.eval<double>("function(3, 4.75);");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
55
readme.txt
55
readme.txt
@@ -1,55 +0,0 @@
|
|||||||
ChaiScript
|
|
||||||
http://www.chaiscript.com
|
|
||||||
(c) 2009-2011 Jason Turner and Jonathan Turner
|
|
||||||
Release under the BSD license, see "license.txt" for details.
|
|
||||||
|
|
||||||
[Introduction]
|
|
||||||
|
|
||||||
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 native C++ application, it has some advantages over existing embedded scripting languages:
|
|
||||||
|
|
||||||
1) It uses a header-only approach, which makes it easy to integrate with existing projects.
|
|
||||||
2) It maintains type safety between your C++ application and the user scripts.
|
|
||||||
3) It supports a variety of C++ techniques including callbacks, overloaded functions, class methods, and stl containers.
|
|
||||||
|
|
||||||
[Requirements]
|
|
||||||
|
|
||||||
ChaiScript requires a recent version of Boost (http://www.boost.org) to build.
|
|
||||||
|
|
||||||
[Usage]
|
|
||||||
|
|
||||||
* Add the ChaiScript include directory to your project's header search path
|
|
||||||
* Add "#include <chaiscript/chaiscript.hpp> to your source file
|
|
||||||
* Instantiate the ChaiScript engine in your application. For example, create a new engine with the name 'chai' like so: "chaiscript::ChaiScript chai"
|
|
||||||
|
|
||||||
Once instantiated, the engine is ready to start running ChaiScript source. You have two main options for processing ChaiScript source: a line at a time using "chai.evaluate_string(string)" and a file at a time using "chai.evaluate_file(fname)"
|
|
||||||
|
|
||||||
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call add:
|
|
||||||
|
|
||||||
chai.add(chaiscript::fun(&my_function), "my_function_name");
|
|
||||||
|
|
||||||
Once registered the function will be visible to scripts as "my_function_name"
|
|
||||||
|
|
||||||
[Examples]
|
|
||||||
|
|
||||||
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some modifications to make it easier to use. For usage examples see the "samples" directory, and for more in-depth look at the language, the unit tests in the "unittests" directory cover the most ground.
|
|
||||||
|
|
||||||
For examples of how to register parts of your C++ application, see "example.cpp" in the "src" directory. Example.cpp is verbose and shows every possible way of working with the library. For further documentation generate the doxygen documentation in the build folder or see the website http://www.chaiscript.com.
|
|
||||||
|
|
||||||
The shortest complete example possible follows:
|
|
||||||
|
|
||||||
/// main.cpp
|
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
|
||||||
|
|
||||||
double function(int i, double j)
|
|
||||||
{
|
|
||||||
return i * j;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
chaiscript::ChaiScript chai;
|
|
||||||
chai.add(chaiscript::fun(&function), "function");
|
|
||||||
|
|
||||||
double d = chai.eval<double>("function(3, 4.75);");
|
|
||||||
}
|
|
@@ -1,3 +1,36 @@
|
|||||||
|
Changes since 4.0.0
|
||||||
|
* Fix sizing of numeric constants to match that of the C++ standard
|
||||||
|
* Add support for u,ll,l,f suffixes for numeric constants
|
||||||
|
* Siginificant improvement in error reporting
|
||||||
|
|
||||||
|
Changes since 3.1.0
|
||||||
|
* svenstaro: Unused variables and CMake consistency fixes
|
||||||
|
* Added support for returning pointers from functions (#13)
|
||||||
|
* Compile with -pedantic (#9)
|
||||||
|
* Fix issues with multiple ChaiScript object types having the same attribute name (#15)
|
||||||
|
* Prevent variable redeclaration in same scope (#22)
|
||||||
|
* mgee: Boxed_Number improvements (#27)
|
||||||
|
* Support switch statements (#34)
|
||||||
|
* Fix uint16 comparions (#26)
|
||||||
|
* Add ability to add const_var globals in Module objects (#14)
|
||||||
|
* Add support for ternary operators ?:
|
||||||
|
* Add headers to CMakeLists so they show up in IDEs
|
||||||
|
* Add ability to get vector of defined objects and vector of defined functions
|
||||||
|
* Fix memory leak in cyclical references
|
||||||
|
* Clean up static analysis issues discovered
|
||||||
|
* Fix vector construction to be consistent with map construction
|
||||||
|
* Increased unit tests to 161
|
||||||
|
* Performance enhancements
|
||||||
|
|
||||||
|
Changes since 3.0.0
|
||||||
|
* Numeric operations performance increased approximately 10x
|
||||||
|
* Looping operations performance increased up to 2x
|
||||||
|
* Engine start up time decreased
|
||||||
|
* Several parsing bugs related to index operators fixed
|
||||||
|
* Added full support for all C algebraic types: double, long double, float, int, long, char,
|
||||||
|
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
|
||||||
|
* Enhanced support for capturing of exceptions thrown from ChaiScript in C++
|
||||||
|
|
||||||
Changes since 2.3.3
|
Changes since 2.3.3
|
||||||
|
|
||||||
* Code simplifications
|
* Code simplifications
|
||||||
|
@@ -141,7 +141,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
//Creating a functor on the stack and using it immediatly
|
//Creating a functor on the stack and using it immediatly
|
||||||
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||||
|
|
||||||
log("Functor test output", boost::lexical_cast<std::string>(x));
|
std::stringstream ss;
|
||||||
|
ss << x;
|
||||||
|
log("Functor test output", ss.str());
|
||||||
|
|
||||||
chai.add(var(boost::shared_ptr<int>()), "nullvar");
|
chai.add(var(boost::shared_ptr<int>()), "nullvar");
|
||||||
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
|
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
|
||||||
@@ -165,7 +167,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
//Dynamic objects test
|
//Dynamic objects test
|
||||||
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
|
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
|
||||||
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
|
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
|
||||||
chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
|
// chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
|
||||||
|
|
||||||
chai.eval("var x = TestType()");
|
chai.eval("var x = TestType()");
|
||||||
// chai.eval("x.attr = \"hi\"");
|
// chai.eval("x.attr = \"hi\"");
|
||||||
|
27
src/main.cpp
27
src/main.cpp
@@ -80,7 +80,18 @@ std::string get_next_command() {
|
|||||||
char *input_raw = readline("eval> ");
|
char *input_raw = readline("eval> ");
|
||||||
if ( input_raw ) {
|
if ( input_raw ) {
|
||||||
add_history(input_raw);
|
add_history(input_raw);
|
||||||
retval = boost::trim_copy_if(std::string(input_raw),boost::is_any_of(" \t"));
|
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);
|
::free(input_raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,21 +226,11 @@ int main(int argc, char *argv[])
|
|||||||
case eInteractive : interactive(chai); break;
|
case eInteractive : interactive(chai); break;
|
||||||
case eCommand : val = chai.eval(arg); break;
|
case eCommand : val = chai.eval(arg); break;
|
||||||
case eFile : val = chai.eval_file(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) {
|
catch (const chaiscript::exception::eval_error &ee) {
|
||||||
std::cout << ee.what();
|
std::cout << ee.pretty_print();
|
||||||
if (ee.call_stack.size() > 0) {
|
|
||||||
std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
|
||||||
for (size_t j = 1; j < ee.call_stack.size(); ++j) {
|
|
||||||
if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
|
|
||||||
&& ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File)
|
|
||||||
{
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@@ -1,40 +0,0 @@
|
|||||||
// This file is distributed under the BSD License.
|
|
||||||
// See "license.txt" for details.
|
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
|
||||||
// http://www.chaiscript.com
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
void do_work(chaiscript::ChaiScript &c)
|
|
||||||
{
|
|
||||||
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
|
|
||||||
std::string name = "MyVar" + boost::lexical_cast<std::string>(rand());
|
|
||||||
c.add(chaiscript::var(5), name);
|
|
||||||
c("use(\"work.chai\"); do_chai_work(10000);");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
std::string input;
|
|
||||||
chaiscript::ChaiScript chai;
|
|
||||||
|
|
||||||
//chai.add_shared_object(chaiscript::Boxed_Value(10000), "num_iterations");
|
|
||||||
|
|
||||||
std::vector<boost::shared_ptr<boost::thread> > threads;
|
|
||||||
|
|
||||||
for (int i = 0; i < argc - 1; ++i)
|
|
||||||
{
|
|
||||||
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(do_work, boost::ref(chai)))));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < argc - 1; ++i)
|
|
||||||
{
|
|
||||||
threads[i]->join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -49,12 +49,12 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||||
|
|
||||||
|
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||||
|
|
||||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||||
|
|
||||||
CHAISCRIPT_CLASS( m,
|
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
|
||||||
chaiscript::exception::eval_error,
|
chaiscript::exception::eval_error,
|
||||||
,
|
|
||||||
((reason))
|
((reason))
|
||||||
((call_stack))
|
((call_stack))
|
||||||
);
|
);
|
||||||
@@ -67,9 +67,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
((column))
|
((column))
|
||||||
);
|
);
|
||||||
|
|
||||||
CHAISCRIPT_CLASS( m,
|
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
|
||||||
chaiscript::AST_Node,
|
chaiscript::AST_Node,
|
||||||
,
|
|
||||||
((text))
|
((text))
|
||||||
((identifier))
|
((identifier))
|
||||||
((filename))
|
((filename))
|
||||||
|
@@ -7,11 +7,22 @@ class TestBaseType
|
|||||||
public:
|
public:
|
||||||
TestBaseType() {}
|
TestBaseType() {}
|
||||||
TestBaseType(int) {}
|
TestBaseType(int) {}
|
||||||
|
TestBaseType(int *) {}
|
||||||
virtual ~TestBaseType() {}
|
virtual ~TestBaseType() {}
|
||||||
virtual int func() { return 0; }
|
virtual int func() { return 0; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TestEnum
|
||||||
|
{
|
||||||
|
TestValue1 = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
int to_int(TestEnum t)
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
class TestDerivedType : public TestBaseType
|
class TestDerivedType : public TestBaseType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -24,6 +35,11 @@ std::string hello_world()
|
|||||||
return "Hello World";
|
return "Hello World";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int *get_new_int()
|
||||||
|
{
|
||||||
|
return new int(1);
|
||||||
|
}
|
||||||
|
|
||||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||||
// but this is the best way to do it for cross platform compatibility
|
// but this is the best way to do it for cross platform compatibility
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
@@ -44,6 +60,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
|||||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||||
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
|
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
|
||||||
|
m->add(chaiscript::constructor<TestBaseType (int *)>(), "TestBaseType");
|
||||||
|
|
||||||
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
||||||
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
||||||
@@ -52,6 +69,15 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
|||||||
|
|
||||||
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
||||||
|
|
||||||
|
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
||||||
|
|
||||||
|
m->add_global_const(chaiscript::const_var(TestValue1), "TestValue1");
|
||||||
|
|
||||||
|
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
|
||||||
|
|
||||||
|
m->add(chaiscript::fun(&to_int), "to_int");
|
||||||
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
def do_chai_work(num_iters)
|
|
||||||
{
|
|
||||||
var i = 0;
|
|
||||||
for (var k = 0; k<num_iters * 10; ++k)
|
|
||||||
{
|
|
||||||
i += k;
|
|
||||||
}
|
|
||||||
|
|
||||||
print(i);
|
|
||||||
}
|
|
@@ -301,8 +301,8 @@ int main()
|
|||||||
passed &= built_in_type_test<int>(5, true);
|
passed &= built_in_type_test<int>(5, true);
|
||||||
passed &= built_in_type_test<double>(1.1, true);
|
passed &= built_in_type_test<double>(1.1, true);
|
||||||
passed &= built_in_type_test<char>('a', true);
|
passed &= built_in_type_test<char>('a', true);
|
||||||
passed &= built_in_type_test<uint8_t>('a', true);
|
passed &= built_in_type_test<boost::uint8_t>('a', true);
|
||||||
passed &= built_in_type_test<int64_t>('a', true);
|
passed &= built_in_type_test<boost::int64_t>('a', true);
|
||||||
passed &= built_in_type_test<bool>(false, false);
|
passed &= built_in_type_test<bool>(false, false);
|
||||||
passed &= built_in_type_test<std::string>("Hello World", false);
|
passed &= built_in_type_test<std::string>("Hello World", false);
|
||||||
|
|
||||||
|
20
unittests/c_linkage_test.cpp
Normal file
20
unittests/c_linkage_test.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
int dosomething(int i)
|
||||||
|
{
|
||||||
|
return i % 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
chai.add(chaiscript::fun(&dosomething), "dosomething");
|
||||||
|
|
||||||
|
return chai.eval<int>("dosomething(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
|
||||||
|
|
||||||
|
}
|
@@ -60,7 +60,7 @@ int test_5()
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||||
} catch (const double e) {
|
} catch (const double) {
|
||||||
std::cout << "test_5 failed with double" << std::endl;
|
std::cout << "test_5 failed with double" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} catch (int) {
|
} catch (int) {
|
||||||
@@ -72,7 +72,7 @@ int test_5()
|
|||||||
} catch (const std::string &) {
|
} catch (const std::string &) {
|
||||||
std::cout << "test_5 failed with string" << std::endl;
|
std::cout << "test_5 failed with string" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,10 +95,10 @@ int test_unhandled()
|
|||||||
} catch (float) {
|
} catch (float) {
|
||||||
std::cout << "test_unhandled failed with float" << std::endl;
|
std::cout << "test_unhandled failed with float" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &) {
|
||||||
std::cout << "test_unhandled failed with std::exception" << std::endl;
|
std::cout << "test_unhandled failed with std::exception" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} catch (const chaiscript::Boxed_Value &bv) {
|
} catch (const chaiscript::Boxed_Value &) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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-existant 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-existant 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -17,7 +17,7 @@ int main()
|
|||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
chai.eval("def test_fun(x) { return 3; }");
|
chai.eval("def test_fun(x) { return 3; }");
|
||||||
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
|
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
|
||||||
chai.eval("def test_fun(x) { return 5; }");
|
// chai.eval("def test_fun(x) { return 5; }");
|
||||||
chai.add(chaiscript::fun(&test_one), "test_fun");
|
chai.add(chaiscript::fun(&test_one), "test_fun");
|
||||||
chai.add(chaiscript::fun(&test_two), "test_fun");
|
chai.add(chaiscript::fun(&test_two), "test_fun");
|
||||||
|
|
||||||
|
2
unittests/function_redefinition.chai
Normal file
2
unittests/function_redefinition.chai
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
assert_throws("Function already defined", fun() { def foo(x) { x + 1 }; def foo(x) { x + 1 } } );
|
||||||
|
|
7
unittests/global_const_in_module.chai
Normal file
7
unittests/global_const_in_module.chai
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
load_module("test_module")
|
||||||
|
|
||||||
|
|
||||||
|
assert_equal(to_int(TestValue1), 1)
|
||||||
|
|
||||||
|
assert_equal(TestValue1.type_name(), "TestEnum")
|
||||||
|
|
4
unittests/hashbang.chai
Normal file
4
unittests/hashbang.chai
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env chai
|
||||||
|
|
||||||
|
//We just have to reach this point for success
|
||||||
|
assert_equal(true, true);
|
90
unittests/integer_literal_test.cpp
Normal file
90
unittests/integer_literal_test.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// Tests to make sure that the order in which function dispatches occur is correct
|
||||||
|
|
||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
|
#define TEST_LITERAL(v) test_literal(v, #v)
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool test_literal(T val, const std::string &str)
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
T val2 = chai.eval<T>(str);
|
||||||
|
std::cout << "Comparing : " << val << " " << val2 << std::endl;
|
||||||
|
return val == val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
if( TEST_LITERAL(0xF)
|
||||||
|
&& TEST_LITERAL(0xFF)
|
||||||
|
&& TEST_LITERAL(0xFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFFFFFFF)
|
||||||
|
&& TEST_LITERAL(0xFFFFFFFFFFFFFFFF)
|
||||||
|
|
||||||
|
|
||||||
|
&& TEST_LITERAL(01)
|
||||||
|
&& TEST_LITERAL(017)
|
||||||
|
&& TEST_LITERAL(0177)
|
||||||
|
&& TEST_LITERAL(01777)
|
||||||
|
&& TEST_LITERAL(017777)
|
||||||
|
&& TEST_LITERAL(0177777)
|
||||||
|
&& TEST_LITERAL(01777777)
|
||||||
|
&& TEST_LITERAL(017777777)
|
||||||
|
&& TEST_LITERAL(0177777777)
|
||||||
|
&& TEST_LITERAL(01777777777)
|
||||||
|
&& TEST_LITERAL(017777777777)
|
||||||
|
&& TEST_LITERAL(0177777777777)
|
||||||
|
&& TEST_LITERAL(01777777777777)
|
||||||
|
&& TEST_LITERAL(017777777777777)
|
||||||
|
&& TEST_LITERAL(0177777777777777)
|
||||||
|
&& TEST_LITERAL(01777777777777777)
|
||||||
|
&& TEST_LITERAL(017777777777777777)
|
||||||
|
&& TEST_LITERAL(0177777777777777777)
|
||||||
|
&& TEST_LITERAL(01777777777777777777)
|
||||||
|
&& TEST_LITERAL(017777777777777777777)
|
||||||
|
&& TEST_LITERAL(0177777777777777777777)
|
||||||
|
&& TEST_LITERAL(01777777777777777777777)
|
||||||
|
|
||||||
|
&& TEST_LITERAL(1)
|
||||||
|
&& TEST_LITERAL(17)
|
||||||
|
&& TEST_LITERAL(177)
|
||||||
|
&& TEST_LITERAL(1777)
|
||||||
|
&& TEST_LITERAL(17777)
|
||||||
|
&& TEST_LITERAL(177777)
|
||||||
|
&& TEST_LITERAL(1777777)
|
||||||
|
&& TEST_LITERAL(17777777)
|
||||||
|
&& TEST_LITERAL(177777777)
|
||||||
|
&& TEST_LITERAL(1777777777)
|
||||||
|
&& TEST_LITERAL(17777777777)
|
||||||
|
&& TEST_LITERAL(177777777777)
|
||||||
|
&& TEST_LITERAL(1777777777777)
|
||||||
|
&& TEST_LITERAL(17777777777777)
|
||||||
|
&& TEST_LITERAL(177777777777777)
|
||||||
|
&& TEST_LITERAL(1777777777777777)
|
||||||
|
&& TEST_LITERAL(17777777777777777)
|
||||||
|
&& TEST_LITERAL(177777777777777777)
|
||||||
|
&& TEST_LITERAL(1777777777777777777)
|
||||||
|
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1 +1,29 @@
|
|||||||
assert_equal([true, false, true], map([1,2,3], odd))
|
assert_equal([true, false, true], map([1,2,3], odd))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var m = ["a":1, "b":2];
|
||||||
|
|
||||||
|
assert_equal(1, m.count("a"))
|
||||||
|
assert_equal(0, m.count("c"))
|
||||||
|
assert_equal(1, m.erase("a"))
|
||||||
|
assert_equal(1, m.size())
|
||||||
|
assert_equal(0, m.erase("a"))
|
||||||
|
|
||||||
|
assert_equal(1, m.size());
|
||||||
|
|
||||||
|
var m2 = ["c":3, "b":4]
|
||||||
|
m.insert(m2);
|
||||||
|
|
||||||
|
assert_equal(3, m["c"])
|
||||||
|
// The inserted values do not overwrite the existing ones
|
||||||
|
assert_equal(2, m["b"])
|
||||||
|
assert_equal(2, m.size())
|
||||||
|
|
||||||
|
var v = "bob";
|
||||||
|
|
||||||
|
m.insert_ref(Map_Pair("d", v))
|
||||||
|
|
||||||
|
assert_equal("bob", m["d"])
|
||||||
|
v = "bob2"
|
||||||
|
assert_equal("bob2", m["d"])
|
||||||
|
@@ -1,3 +1,14 @@
|
|||||||
var x = ["bob":1, "fred":2]
|
var x = ["bob":1, "fred":2]
|
||||||
|
|
||||||
assert_equal(2, x.size());
|
assert_equal(2, x.size());
|
||||||
|
|
||||||
|
|
||||||
|
// Make sure vector elements are copied into place for consistency with
|
||||||
|
// map inplace construction
|
||||||
|
var i = 1;
|
||||||
|
var y = ["a":i];
|
||||||
|
|
||||||
|
assert_equal(1, y["a"]);
|
||||||
|
i = 3;
|
||||||
|
assert_equal(3, i);
|
||||||
|
assert_equal(1, y["a"]);
|
||||||
|
4
unittests/multiline_oper.chai
Normal file
4
unittests/multiline_oper.chai
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
var x = 3 +
|
||||||
|
4
|
||||||
|
|
||||||
|
assert_equal(x, 7);
|
101
unittests/multithreaded_test.cpp
Normal file
101
unittests/multithreaded_test.cpp
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
int expected_value(int num_iters)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (int k = 0; k<num_iters * 10; ++k)
|
||||||
|
{
|
||||||
|
i += k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_work(chaiscript::ChaiScript &c, int id)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "MyVar" << rand();
|
||||||
|
c.add(chaiscript::var(5), ss.str());
|
||||||
|
ss.str("");
|
||||||
|
ss << id;
|
||||||
|
c.use("multithreaded_work.inc");
|
||||||
|
c("do_chai_work(4000, " + ss.str() + ");");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Disable deprecation warning for getenv call.
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *usepath = getenv("CHAI_USE_PATH");
|
||||||
|
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<std::string> usepaths;
|
||||||
|
usepaths.push_back("");
|
||||||
|
if (usepath)
|
||||||
|
{
|
||||||
|
usepaths.push_back(usepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> modulepaths;
|
||||||
|
modulepaths.push_back("");
|
||||||
|
if (modulepath)
|
||||||
|
{
|
||||||
|
modulepaths.push_back(modulepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
chaiscript::ChaiScript chai(modulepaths,usepaths);
|
||||||
|
|
||||||
|
std::vector<boost::shared_ptr<boost::thread> > threads;
|
||||||
|
|
||||||
|
// Ensure at least two, but say only 7 on an 8 core processor
|
||||||
|
int num_threads = std::max<unsigned int>(boost::thread::hardware_concurrency() - 1, 2u);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_threads; ++i)
|
||||||
|
{
|
||||||
|
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(do_work, boost::ref(chai), i))));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_threads; ++i)
|
||||||
|
{
|
||||||
|
threads[i]->join();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < num_threads; ++i)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
if (chai.eval<int>("getvalue(" + ss.str() + ")") != expected_value(4000))
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chai.eval<int>("getid(" + ss.str() + ")") != i)
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
15
unittests/multithreaded_work.inc
Normal file
15
unittests/multithreaded_work.inc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
def do_chai_work(num_iters, id)
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
for (var k = 0; k<num_iters * 10; ++k)
|
||||||
|
{
|
||||||
|
if (k == 1000)
|
||||||
|
{
|
||||||
|
eval("def getid(id) : id == " + to_string(id) + " { return " + to_string(id) + "}");
|
||||||
|
}
|
||||||
|
i += k;
|
||||||
|
}
|
||||||
|
|
||||||
|
eval("def getvalue(id) : id == " + to_string(id) + " { return " + to_string(i) + "}");
|
||||||
|
|
||||||
|
}
|
11
unittests/number_suffixes.chai
Normal file
11
unittests/number_suffixes.chai
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
assert_equal(true, int_type.bare_equal(1.get_type_info()))
|
||||||
|
assert_equal(true, unsigned_int_type.bare_equal(1u.get_type_info()))
|
||||||
|
assert_equal(true, unsigned_long_type.bare_equal(1lu.get_type_info()))
|
||||||
|
assert_equal(true, long_type.bare_equal(1l.get_type_info()))
|
||||||
|
assert_equal(true, int64_t_type.bare_equal(1ll.get_type_info()))
|
||||||
|
assert_equal(true, uint64_t_type.bare_equal(1ull.get_type_info()))
|
||||||
|
|
||||||
|
assert_equal(true, double_type.bare_equal(1.6.get_type_info()))
|
||||||
|
assert_equal(true, float_type.bare_equal(1.6f.get_type_info()))
|
||||||
|
assert_equal(true, long_double_type.bare_equal(1.6l.get_type_info()))
|
||||||
|
|
9
unittests/object_attr_same_name.chai
Normal file
9
unittests/object_attr_same_name.chai
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
attr bob::z
|
||||||
|
def bob::bob() { this.z = 10 }
|
||||||
|
|
||||||
|
attr bob2::z
|
||||||
|
def bob2::bob2() { this.z = 12 }
|
||||||
|
|
||||||
|
var b = bob();
|
||||||
|
var b2 = bob2();
|
||||||
|
|
@@ -38,19 +38,19 @@ int main()
|
|||||||
|
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
chai.add(m);
|
chai.add(m);
|
||||||
chai.add(chaiscript::fun(&Test::count), "count");
|
// chai.add(chaiscript::fun(&Test::count), "count");
|
||||||
|
|
||||||
int count = chai.eval<int>("count()");
|
int count = chai.eval<int>("count()");
|
||||||
|
|
||||||
int count2 = chai.eval<int>("var i = 0; { var t = Test(); } return i;");
|
int count2 = chai.eval<int>("var i = 0; { var t = Test(); } return i;");
|
||||||
|
|
||||||
int count3 = chai.eval<int>("var i = 0; { var t = Test(); i = count(); } return i;");
|
int count3 = chai.eval<int>("i = 0; { var t = Test(); i = count(); } return i;");
|
||||||
|
|
||||||
int count4 = chai.eval<int>("var i = 0; { var t = Test(); { var t2 = Test(); i = count(); } } return i;");
|
int count4 = chai.eval<int>("i = 0; { var t = Test(); { var t2 = Test(); i = count(); } } return i;");
|
||||||
|
|
||||||
int count5 = chai.eval<int>("var i = 0; { var t = Test(); { var t2 = Test(); } i = count(); } return i;");
|
int count5 = chai.eval<int>("i = 0; { var t = Test(); { var t2 = Test(); } i = count(); } return i;");
|
||||||
|
|
||||||
int count6 = chai.eval<int>("var i = 0; { var t = Test(); { var t2 = Test(); } } i = count(); return i;");
|
int count6 = chai.eval<int>("i = 0; { var t = Test(); { var t2 = Test(); } } i = count(); return i;");
|
||||||
|
|
||||||
if (count == 0
|
if (count == 0
|
||||||
&& count2 == 0
|
&& count2 == 0
|
||||||
|
8
unittests/operator_scoping.chai
Normal file
8
unittests/operator_scoping.chai
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
load_module("reflection")
|
||||||
|
|
||||||
|
try {
|
||||||
|
eval("def `+`(x, y) \n { \n print(i); \n } \n \n var i = 10; \n \"1\" + 1;\n")
|
||||||
|
assert_false(true); // we should never get here
|
||||||
|
} catch (e) {
|
||||||
|
assert_equal("Error: \"Can not find object: i\" ", e.what());
|
||||||
|
}
|
19
unittests/pass_by_reference.chai
Normal file
19
unittests/pass_by_reference.chai
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
def f(x) { x+= 2; }
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
|
||||||
|
assert_equal(i, 1);
|
||||||
|
|
||||||
|
f(i);
|
||||||
|
|
||||||
|
assert_equal(i, 3);
|
||||||
|
|
||||||
|
def g(x) { x+= " World"; }
|
||||||
|
|
||||||
|
var s = "Hello";
|
||||||
|
|
||||||
|
assert_equal(s, "Hello");
|
||||||
|
|
||||||
|
g(s);
|
||||||
|
|
||||||
|
assert_equal(s, "Hello World");
|
8
unittests/pointer_passed_to_constructor.chai
Normal file
8
unittests/pointer_passed_to_constructor.chai
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
load_module("test_module")
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
var t0 = TestBaseType(i);
|
||||||
|
|
||||||
|
var t1 = TestBaseType(get_new_int())
|
||||||
|
|
||||||
|
|
61
unittests/set_state_test.cpp
Normal file
61
unittests/set_state_test.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
int myfun()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
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(&myfun), "myfun");
|
||||||
|
|
||||||
|
|
||||||
|
bool didcall = chai.eval<int>("myfun()") == 2;
|
||||||
|
|
||||||
|
bool hadi = chai.eval<int>("i") == 1;
|
||||||
|
|
||||||
|
chai.set_state(firststate);
|
||||||
|
|
||||||
|
// set state should have reverted the state of the functions and dropped
|
||||||
|
// the 'myfun'
|
||||||
|
bool didnotcall = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
chai.eval<int>("myfun()");
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
didnotcall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set state should not affect the local variables
|
||||||
|
bool stillhasid = chai.eval<int>("i") == 1;
|
||||||
|
|
||||||
|
// After resetting the locals we expect the 'i' to be gone
|
||||||
|
chai.set_locals(locals);
|
||||||
|
|
||||||
|
|
||||||
|
bool nolongerhasid = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
chai.eval<int>("i");
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
nolongerhasid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didcall && hadi && didnotcall && stillhasid && nolongerhasid)
|
||||||
|
{
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
29
unittests/short_comparison_test.cpp
Normal file
29
unittests/short_comparison_test.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <chaiscript/utility/utility.hpp>
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
Test() : value_(5) {}
|
||||||
|
|
||||||
|
short get_value() { return value_; }
|
||||||
|
|
||||||
|
short value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
chai.add(chaiscript::user_type<Test>(), "Test");
|
||||||
|
chai.add(chaiscript::constructor<Test()>(), "Test");
|
||||||
|
|
||||||
|
chai.add(chaiscript::fun(&Test::get_value), "get_value");
|
||||||
|
|
||||||
|
chai.eval("var t := Test();");
|
||||||
|
|
||||||
|
if (chai.eval<bool>("t.get_value() == 5"))
|
||||||
|
{
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
60
unittests/simultaneous_chaiscript_test.cpp
Normal file
60
unittests/simultaneous_chaiscript_test.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
|
int dosomething(int i)
|
||||||
|
{
|
||||||
|
return i + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dosomethingelse(int i)
|
||||||
|
{
|
||||||
|
return i * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
chai.add(chaiscript::fun(&dosomething), "dosomething");
|
||||||
|
chai.add(chaiscript::var(1), "i");
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai2;
|
||||||
|
chai2.add(chaiscript::fun(&dosomethingelse), "dosomethingelse");
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
|
||||||
|
if (chai.eval<int>("dosomething(" + ss.str() + ")") != i + 2)
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chai2.eval<int>("dosomethingelse(" + ss.str() + ")") != i * 2)
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
chai2.eval("dosomething(1)");
|
||||||
|
return EXIT_FAILURE; // should not get here
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
// nothing to do, expected case
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
chai2.eval("i");
|
||||||
|
return EXIT_FAILURE; // should not get here
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
// nothing to do, expected case
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
chai.eval("dosomethingelse(1)");
|
||||||
|
return EXIT_FAILURE; // should not get here
|
||||||
|
} catch (const chaiscript::exception::eval_error &) {
|
||||||
|
// nothing to do, expected case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
unittests/string_substr.chai
Normal file
1
unittests/string_substr.chai
Normal file
@@ -0,0 +1 @@
|
|||||||
|
assert_equal("3ab", "123abab".substr(2,3))
|
22
unittests/switch_break.chai
Normal file
22
unittests/switch_break.chai
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
var total = 0;
|
||||||
|
|
||||||
|
switch(2) {
|
||||||
|
case (1) {
|
||||||
|
total += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (2) {
|
||||||
|
total += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (3) {
|
||||||
|
total += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (4) {
|
||||||
|
total += 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(total, 2)
|
18
unittests/switch_default.chai
Normal file
18
unittests/switch_default.chai
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
var total = 0;
|
||||||
|
|
||||||
|
switch(2) {
|
||||||
|
case (1) {
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
case (3) {
|
||||||
|
total += 4;
|
||||||
|
}
|
||||||
|
case (4) {
|
||||||
|
total += 8;
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
total += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(total, 16)
|
4
unittests/switch_empty.chai
Normal file
4
unittests/switch_empty.chai
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
switch(true) { }
|
||||||
|
|
||||||
|
// We just have to get here without error for success
|
||||||
|
assert_equal(true, true);
|
18
unittests/switch_fallthru.chai
Normal file
18
unittests/switch_fallthru.chai
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
var total = 0;
|
||||||
|
|
||||||
|
switch(2) {
|
||||||
|
case (1) {
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
case (2) {
|
||||||
|
total += 2;
|
||||||
|
}
|
||||||
|
case (3) {
|
||||||
|
total += 4;
|
||||||
|
}
|
||||||
|
case (4) {
|
||||||
|
total += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(total, 14);
|
19
unittests/switch_fallthru_and_break.chai
Normal file
19
unittests/switch_fallthru_and_break.chai
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
var total = 0;
|
||||||
|
|
||||||
|
switch(2) {
|
||||||
|
case (1) {
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
case (2) {
|
||||||
|
total += 2;
|
||||||
|
}
|
||||||
|
case (3) {
|
||||||
|
total += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (4) {
|
||||||
|
total += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(total, 6)
|
18
unittests/system_introspection.chai
Normal file
18
unittests/system_introspection.chai
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
var funcs = get_functions();
|
||||||
|
|
||||||
|
assert_true(funcs.size() > 0);
|
||||||
|
assert_true(funcs["to_string"].get_type_info().bare_equal(Function_type));
|
||||||
|
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
var objs = get_objects();
|
||||||
|
|
||||||
|
assert_true(objs.size() > 0);
|
||||||
|
assert_true(objs["i"].get_type_info().bare_equal(int_type));
|
||||||
|
assert_true(objs.count("j") == 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
3
unittests/temporary_lifetime.chai
Normal file
3
unittests/temporary_lifetime.chai
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
for_each(range([1..10]), fun(x) {print(x);} );
|
||||||
|
|
||||||
|
assert_true(true);
|
2
unittests/ternary_condition.chai
Normal file
2
unittests/ternary_condition.chai
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
var x = 4;
|
||||||
|
assert_equal(x < 3 ? 4 < 1 : 5 > 3, true);
|
@@ -5,7 +5,7 @@ def assert_equal(x, y)
|
|||||||
// Passes
|
// Passes
|
||||||
} else {
|
} else {
|
||||||
// Fails
|
// Fails
|
||||||
print("assert_equal failure: got " + to_string(y) + " expected " + to_string(x));
|
print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ def assert_true(f)
|
|||||||
{
|
{
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
print("assert_false failure");
|
print("assert_true failure");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,8 +30,8 @@ int main()
|
|||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
chai.add(m);
|
chai.add(m);
|
||||||
if (chai.eval<std::string>("var t = Test(); t.function2(); ") == "Function2"
|
if (chai.eval<std::string>("var t = Test(); t.function2(); ") == "Function2"
|
||||||
&& chai.eval<std::string>("var t = Test(); t.functionOverload(1); ") == "int"
|
&& chai.eval<std::string>("var t2 = Test(); t2.functionOverload(1); ") == "int"
|
||||||
&& chai.eval<std::string>("var t = Test(); t.functionOverload(1.1); ") == "double")
|
&& chai.eval<std::string>("var t3 = Test(); t3.functionOverload(1.1); ") == "double")
|
||||||
{
|
{
|
||||||
chai.eval("t = Test();");
|
chai.eval("t = Test();");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
2
unittests/variable_redefinition.chai
Normal file
2
unittests/variable_redefinition.chai
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
assert_throws("Variable already defined", fun() { var y = 10; var y = 20; })
|
||||||
|
|
@@ -1,2 +1,14 @@
|
|||||||
var x = [1, 2, 3]
|
var x = [1, 2, 3]
|
||||||
assert_equal(3, x.size())
|
assert_equal(3, x.size())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Make sure vector elements are copied into place for consistency with
|
||||||
|
// map inplace construction
|
||||||
|
var i = 1;
|
||||||
|
var y = [i];
|
||||||
|
|
||||||
|
assert_equal(1, y[0]);
|
||||||
|
i = 3;
|
||||||
|
assert_equal(3, i);
|
||||||
|
assert_equal(1, y[0]);
|
||||||
|
Reference in New Issue
Block a user