Compare commits
76 Commits
v4.0.0
...
Release-4.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8c70fff02b | ||
![]() |
af44da916a | ||
![]() |
04131d208b | ||
![]() |
9c35ede59a | ||
![]() |
71348b7967 | ||
![]() |
eb1a1c0275 | ||
![]() |
8724e0cb80 | ||
![]() |
b872a50acc | ||
![]() |
36466a4ac5 | ||
![]() |
bf83969723 | ||
![]() |
41f6ca18ea | ||
![]() |
a26d628e5c | ||
![]() |
d5fef3121a | ||
![]() |
16f09794cf | ||
![]() |
d44de49fb1 | ||
![]() |
101225aa68 | ||
![]() |
feb344e744 | ||
![]() |
12d842ca5a | ||
![]() |
e68599920a | ||
![]() |
1e1385bc52 | ||
![]() |
ae1221d46d | ||
![]() |
4fc51dfe05 | ||
![]() |
241ca75204 | ||
![]() |
2afc09dad4 | ||
![]() |
1858885010 | ||
![]() |
d068ce472c | ||
![]() |
380b94a8d2 | ||
![]() |
fd72b2951a | ||
![]() |
48f538438d | ||
![]() |
c9995480e6 | ||
![]() |
e298333ac6 | ||
![]() |
d225e09d5d | ||
![]() |
59df213e66 | ||
![]() |
0ea8931b21 | ||
![]() |
f24d376fa5 | ||
![]() |
7917ea02dc | ||
![]() |
deef33640c | ||
![]() |
58f3256389 | ||
![]() |
f1a4c4c427 | ||
![]() |
afd27a4b01 | ||
![]() |
4c65e45598 | ||
![]() |
923369a4f4 | ||
![]() |
964342bff3 | ||
![]() |
623c64299a | ||
![]() |
abcc6c9e3e | ||
![]() |
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 |
@@ -13,11 +13,11 @@ 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 4)
|
set(CPACK_PACKAGE_VERSION_MAJOR 4)
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
set(CPACK_PACKAGE_VERSION_MINOR 3)
|
||||||
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")
|
||||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||||
@@ -79,26 +79,31 @@ set (Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscri
|
|||||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
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 AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
set(DYNAMIC_LOADER "dl")
|
list(APPEND LIBS "dl")
|
||||||
endif(CMAKE_HOST_UNIX)
|
endif()
|
||||||
|
|
||||||
|
list(APPEND LIBS ${READLINE_LIB})
|
||||||
|
|
||||||
if (MSVC)
|
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)
|
||||||
@@ -187,6 +192,42 @@ if(BUILD_TESTING)
|
|||||||
target_link_libraries(short_comparison_test ${LIBS})
|
target_link_libraries(short_comparison_test ${LIBS})
|
||||||
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
|
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)
|
||||||
|
|
||||||
|
add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp)
|
||||||
|
target_link_libraries(arithmetic_conversions_test ${LIBS})
|
||||||
|
add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test)
|
||||||
|
|
||||||
|
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||||
|
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
|
||||||
|
target_link_libraries(multithreaded_test ${LIBS})
|
||||||
|
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)
|
||||||
@@ -201,6 +242,7 @@ if(BUILD_TESTING)
|
|||||||
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
|
||||||
PATTERN "*.hpp"
|
PATTERN "*.hpp"
|
||||||
PATTERN "*/.svn*" EXCLUDE
|
PATTERN "*/.svn*" EXCLUDE
|
||||||
|
10
contrib/codeanalysis/heterogenous_array_loop.chai
Normal file
10
contrib/codeanalysis/heterogenous_array_loop.chai
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
var my_array=["1", 4, 6.6l, 10ul, "1000", 100, 10.9f ];
|
||||||
|
|
||||||
|
for (var j = 0; j < 10000; ++j)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
to_string(my_array[i]);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HPP_
|
#ifndef CHAISCRIPT_HPP_
|
||||||
@@ -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;
|
||||||
|
@@ -1,14 +1,23 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||||
#define CHAISCRIPT_THREADING_HPP_
|
#define CHAISCRIPT_THREADING_HPP_
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wc++11-long-long"
|
||||||
|
#pragma clang diagnostic ignored "-Wshadow"
|
||||||
|
#endif
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||||
#endif
|
#endif
|
||||||
@@ -75,6 +84,8 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
unique_lock(T &) {}
|
unique_lock(T &) {}
|
||||||
|
void lock() {}
|
||||||
|
void unlock() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -82,6 +93,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
shared_lock(T &) {}
|
shared_lock(T &) {}
|
||||||
|
void lock() {}
|
||||||
void unlock() {}
|
void unlock() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
#ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
@@ -89,5 +89,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
#undef n
|
#undef n
|
||||||
#undef m
|
#undef m
|
||||||
|
#undef param
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -93,27 +94,34 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* to_string function for internal use. Uses ostream operator<<
|
* to_string function for internal use. Uses ostream operator<<
|
||||||
*/
|
*/
|
||||||
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
|
||||||
*/
|
*/
|
||||||
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
|
||||||
@@ -265,28 +273,17 @@ namespace chaiscript
|
|||||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a call can be made that consists of the first parameter
|
|
||||||
* (the function) with the remaining parameters as its arguments.
|
|
||||||
*/
|
|
||||||
static Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms)
|
|
||||||
{
|
|
||||||
if (params.size() < 1)
|
|
||||||
{
|
|
||||||
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
|
||||||
|
|
||||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool has_guard(const Const_Proxy_Function &t_pf)
|
static bool has_guard(const Const_Proxy_Function &t_pf)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||||
if (pf)
|
if (pf)
|
||||||
{
|
{
|
||||||
return pf->get_guard();
|
if (pf->get_guard()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -375,7 +372,6 @@ namespace chaiscript
|
|||||||
|
|
||||||
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||||
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
|
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
|
||||||
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
|
|
||||||
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
||||||
|
|
||||||
|
|
||||||
@@ -419,6 +415,7 @@ 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");
|
||||||
@@ -438,6 +435,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);
|
||||||
@@ -466,9 +464,6 @@ namespace chaiscript
|
|||||||
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||||
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||||
|
|
||||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
|
|
||||||
"call_exists");
|
|
||||||
|
|
||||||
m->add(fun(&type_match), "type_match");
|
m->add(fun(&type_match), "type_match");
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
@@ -1,16 +1,13 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
/**
|
/// \file
|
||||||
* \file
|
/// This file contains utility functions for registration of STL container
|
||||||
* This file contains utility functions for registration of STL container
|
/// classes. The methodology used is based on the SGI STL concepts.
|
||||||
* classes. The methodology used is based on the SGI STL concepts.
|
/// http://www.sgi.com/tech/stl/table_of_contents.html
|
||||||
* http://www.sgi.com/tech/stl/table_of_contents.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||||
@@ -25,11 +22,10 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
namespace standard_library
|
namespace standard_library
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Bidir_Range, based on the D concept of ranges.
|
/// Bidir_Range, based on the D concept of ranges.
|
||||||
* \todo Update the Range code to base its capabilities on
|
/// \todo Update the Range code to base its capabilities on
|
||||||
* the user_typetraits of the iterator passed in
|
/// the user_typetraits of the iterator passed in
|
||||||
*/
|
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
struct Bidir_Range
|
struct Bidir_Range
|
||||||
{
|
{
|
||||||
@@ -176,6 +172,19 @@ namespace chaiscript
|
|||||||
return t_func(t_obj, p1);
|
return t_func(t_obj, p1);
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
#pragma warning(pop)
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +194,13 @@ namespace chaiscript
|
|||||||
return boost::bind(&return_int_impl<T, P1>, boost::function<size_t (const T *, P1)>(boost::mem_fn(t_func)), _1, _2);
|
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>
|
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)
|
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)
|
||||||
{
|
{
|
||||||
@@ -198,16 +214,35 @@ namespace chaiscript
|
|||||||
#endif
|
#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>
|
template<typename T, typename P1, typename P2>
|
||||||
boost::function<int (const T *, P1, P2)> return_int(size_t (T::*t_func)(P1, P2) const)
|
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);
|
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>
|
||||||
* Add Bidir_Range support for the given ContainerType
|
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
|
||||||
template<typename Bidir_Type>
|
template<typename Bidir_Type>
|
||||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -226,9 +261,8 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Algorithm for inserting at a specific position into a container
|
/// Algorithm for inserting at a specific position into a container
|
||||||
*/
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void insert_at(Type &container, int pos, const typename Type::value_type &v)
|
void insert_at(Type &container, int pos, const typename Type::value_type &v)
|
||||||
{
|
{
|
||||||
@@ -244,9 +278,8 @@ namespace chaiscript
|
|||||||
container.insert(itr, v);
|
container.insert(itr, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Algorithm for erasing a specific position from a container
|
/// Algorithm for erasing a specific position from a container
|
||||||
*/
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void erase_at(Type &container, int pos)
|
void erase_at(Type &container, int pos)
|
||||||
{
|
{
|
||||||
@@ -272,10 +305,9 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add random_access_container concept to the given ContainerType
|
/// Add random_access_container concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -294,10 +326,9 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add assignable concept to the given ContainerType
|
/// Add assignable concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/Assignable.html
|
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -306,26 +337,22 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add container concept to the given ContainerType
|
/// Add container concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/Container.html
|
/// http://www.sgi.com/tech/stl/Container.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
|
boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
|
||||||
m->add(fun(f), "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");
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add default constructable concept to the given Type
|
/// Add default constructable concept to the given Type
|
||||||
* http://www.sgi.com/tech/stl/DefaultConstructible.html
|
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||||
*/
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -335,10 +362,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add sequence concept to the given ContainerType
|
/// Add sequence concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/Sequence.html
|
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -356,10 +382,9 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add back insertion sequence concept to the given ContainerType
|
/// Add back insertion sequence concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -382,10 +407,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*Front insertion sequence
|
/// Front insertion sequence
|
||||||
*http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -408,10 +432,9 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* bootstrap a given PairType
|
/// bootstrap a given PairType
|
||||||
* http://www.sgi.com/tech/stl/pair.html
|
/// http://www.sgi.com/tech/stl/pair.html
|
||||||
*/
|
|
||||||
template<typename PairType>
|
template<typename PairType>
|
||||||
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -431,10 +454,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add pair associative container concept to the given ContainerType
|
/// Add pair associative container concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -443,22 +466,37 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add unique associative container concept to the given ContainerType
|
/// Add unique associative container concept to the given ContainerType
|
||||||
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||||
*/
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = 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 &)>(detail::return_int(&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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a MapType container
|
/// Add a MapType container
|
||||||
* http://www.sgi.com/tech/stl/Map.html
|
/// http://www.sgi.com/tech/stl/Map.html
|
||||||
*/
|
|
||||||
template<typename MapType>
|
template<typename MapType>
|
||||||
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -477,10 +515,9 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* hopefully working List type
|
/// hopefully working List type
|
||||||
* http://www.sgi.com/tech/stl/List.html
|
/// http://www.sgi.com/tech/stl/List.html
|
||||||
*/
|
|
||||||
template<typename ListType>
|
template<typename ListType>
|
||||||
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -497,10 +534,9 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a vector type with associated concepts
|
/// Create a vector type with associated concepts
|
||||||
* http://www.sgi.com/tech/stl/Vector.html
|
/// http://www.sgi.com/tech/stl/Vector.html
|
||||||
*/
|
|
||||||
template<typename VectorType>
|
template<typename VectorType>
|
||||||
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -543,10 +579,34 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
namespace detail {
|
||||||
* Add a String container
|
template<typename String>
|
||||||
* http://www.sgi.com/tech/stl/basic_string.html
|
struct apple_string_workarounds
|
||||||
*/
|
{
|
||||||
|
/// The latest version of MacOS has a broken std::string implementation which will not allow
|
||||||
|
/// us to take pointers to the members. Code compiles, but does not link
|
||||||
|
/// \todo re-evaluate at some point
|
||||||
|
|
||||||
|
static size_t find(const String *s, const String &w, int pos) { return s->find(w, pos); }
|
||||||
|
static size_t rfind(const String *s, const String &w, size_t pos) { return s->rfind(w, pos); }
|
||||||
|
static size_t find_first_of(const String *s, const String &w, size_t pos) { return s->find_first_of(w, pos); }
|
||||||
|
static size_t find_last_of(const String *s, const String &w, size_t pos) { return s->find_last_of(w, pos); }
|
||||||
|
static size_t find_first_not_of(const String *s, const String &w, size_t pos) { return s->find_first_not_of(w, pos); }
|
||||||
|
static size_t find_last_not_of(const String *s, const String &w, size_t pos) { return s->find_last_not_of(w, pos); }
|
||||||
|
|
||||||
|
static void clear(String *s) { s->clear(); }
|
||||||
|
static bool empty(const String *s) { return s->empty(); }
|
||||||
|
static size_t size(const String *s) { return s->size(); }
|
||||||
|
|
||||||
|
static std::string substr(const String *s, size_t pos, size_t len) { return s->substr(pos,len); }
|
||||||
|
static const char *c_str(const String *s) { return s->c_str(); }
|
||||||
|
static const char *data(const String *s) { return s->data(); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Add a String container
|
||||||
|
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||||
template<typename String>
|
template<typename String>
|
||||||
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@@ -557,7 +617,7 @@ namespace chaiscript
|
|||||||
random_access_container_type<String>(type, m);
|
random_access_container_type<String>(type, m);
|
||||||
sequence_type<String>(type, m);
|
sequence_type<String>(type, m);
|
||||||
default_constructible_type<String>(type, m);
|
default_constructible_type<String>(type, m);
|
||||||
container_type<String>(type, m);
|
// container_type<String>(type, m);
|
||||||
assignable_type<String>(type, m);
|
assignable_type<String>(type, m);
|
||||||
input_range_type<String>(type, m);
|
input_range_type<String>(type, m);
|
||||||
|
|
||||||
@@ -571,18 +631,19 @@ 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 boost::function<int (const String *, const String &, int)> find_func;
|
m->add(fun(&detail::apple_string_workarounds<String>::find), "find");
|
||||||
|
m->add(fun(&detail::apple_string_workarounds<String>::rfind), "rfind");
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find)))), "find");
|
m->add(fun(&detail::apple_string_workarounds<String>::find_first_of), "find_first_of");
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
m->add(fun(&detail::apple_string_workarounds<String>::find_last_of), "find_last_of");
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
m->add(fun(&detail::apple_string_workarounds<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_of)))), "find_last_of");
|
m->add(fun(&detail::apple_string_workarounds<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_not_of)))), "find_first_not_of");
|
m->add(fun(&detail::apple_string_workarounds<String>::clear), "clear");
|
||||||
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::apple_string_workarounds<String>::size), "size");
|
||||||
|
m->add(fun(&detail::apple_string_workarounds<String>::empty), "empty");
|
||||||
m->add(fun(&String::c_str), "c_str");
|
m->add(fun(&detail::apple_string_workarounds<String>::substr), "substr");
|
||||||
m->add(fun(&String::data), "data");
|
m->add(fun(&detail::apple_string_workarounds<String>::c_str), "c_str");
|
||||||
|
m->add(fun(&detail::apple_string_workarounds<String>::data), "data");
|
||||||
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
@@ -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-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, 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"
|
||||||
@@ -68,10 +68,10 @@ namespace chaiscript
|
|||||||
/// assert(i == 5);
|
/// assert(i == 5);
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
|
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions = 0)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return detail::Cast_Helper<Type>::cast(bv);
|
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||||
} catch (const boost::bad_any_cast &) {
|
} catch (const boost::bad_any_cast &) {
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
@@ -81,12 +81,12 @@ namespace chaiscript
|
|||||||
#pragma warning(disable : 4127)
|
#pragma warning(disable : 4127)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
|
if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||||
// either way, we are not responsible if it doesn't work
|
// either way, we are not responsible if it doesn't work
|
||||||
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv));
|
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
|
||||||
} catch (const boost::bad_any_cast &) {
|
} catch (const boost::bad_any_cast &) {
|
||||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
#ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
class Dynamic_Cast_Conversions;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
// Cast_Helper_Inner helper classes
|
// Cast_Helper_Inner helper classes
|
||||||
@@ -29,7 +31,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
|
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
{
|
{
|
||||||
@@ -71,7 +73,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef const Result * Result_Type;
|
typedef const Result * Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
{
|
{
|
||||||
@@ -100,7 +102,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef Result * Result_Type;
|
typedef Result * Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
{
|
{
|
||||||
@@ -119,7 +121,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef typename boost::reference_wrapper<Result> Result_Type;
|
typedef typename boost::reference_wrapper<Result> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
{
|
{
|
||||||
@@ -138,7 +140,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef typename boost::shared_ptr<Result> Result_Type;
|
typedef typename boost::shared_ptr<Result> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
|
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
|
||||||
}
|
}
|
||||||
@@ -152,7 +154,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef typename boost::shared_ptr<const Result> Result_Type;
|
typedef typename boost::shared_ptr<const Result> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
if (!ob.get_type_info().is_const())
|
if (!ob.get_type_info().is_const())
|
||||||
{
|
{
|
||||||
@@ -200,7 +202,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef const Boxed_Value & Result_Type;
|
typedef const Boxed_Value & Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
return ob;
|
return ob;
|
||||||
}
|
}
|
||||||
@@ -261,9 +263,9 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
return Cast_Helper_Inner<T>::cast(ob);
|
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
#include "../language/chaiscript_algebraic.hpp"
|
#include "../language/chaiscript_algebraic.hpp"
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
@@ -298,7 +299,20 @@ namespace chaiscript
|
|||||||
throw boost::bad_any_cast();
|
throw boost::bad_any_cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
@@ -313,6 +327,133 @@ namespace chaiscript
|
|||||||
validate_boxed_number(v);
|
validate_boxed_number(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> explicit Boxed_Number(T t)
|
||||||
|
: bv(Boxed_Value(t))
|
||||||
|
{
|
||||||
|
validate_boxed_number(bv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Boxed_Number get_as(const Type_Info &inp_) const
|
||||||
|
{
|
||||||
|
if (inp_.bare_equal_type_info(typeid(int))) {
|
||||||
|
return Boxed_Number(get_as<int>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(double))) {
|
||||||
|
return Boxed_Number(get_as<double>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(float))) {
|
||||||
|
return Boxed_Number(get_as<float>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(long double))) {
|
||||||
|
return Boxed_Number(get_as<long double>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(char))) {
|
||||||
|
return Boxed_Number(get_as<char>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
|
||||||
|
return Boxed_Number(get_as<unsigned int>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(long))) {
|
||||||
|
return Boxed_Number(get_as<long>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
|
||||||
|
return Boxed_Number(get_as<unsigned long>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::int8_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::int8_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::int16_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::int16_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::int32_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::int32_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::int64_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::int64_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::uint8_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::uint8_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::uint16_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::uint16_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::uint32_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::uint32_t>());
|
||||||
|
} else if (inp_.bare_equal_type_info(typeid(boost::uint64_t))) {
|
||||||
|
return Boxed_Number(get_as<boost::uint64_t>());
|
||||||
|
} else {
|
||||||
|
throw boost::bad_any_cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
{
|
{
|
||||||
@@ -680,7 +821,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef Boxed_Number Result_Type;
|
typedef Boxed_Number Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||||
{
|
{
|
||||||
return Boxed_Number(ob);
|
return Boxed_Number(ob);
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
#ifndef CHAISCRIPT_BOXED_VALUE_HPP_
|
||||||
@@ -13,6 +13,19 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wshadow"
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <boost/any.hpp>
|
#include <boost/any.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
@@ -77,12 +90,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
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>
|
||||||
@@ -94,12 +106,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>
|
||||||
@@ -111,34 +122,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));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
|
#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
|
||||||
@@ -12,8 +12,6 @@
|
|||||||
#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>
|
||||||
@@ -55,9 +53,31 @@ namespace chaiscript
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_word;
|
std::string m_word;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown in the case that an object name is invalid because it contains illegal characters
|
||||||
|
*/
|
||||||
|
class illegal_name_error : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
illegal_name_error(const std::string &t_name) throw()
|
||||||
|
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~illegal_name_error() throw() {}
|
||||||
|
|
||||||
|
std::string name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown in the case that an object name is invalid because it already exists in current context
|
* Exception thrown in the case that an object name is invalid because it already exists in current context
|
||||||
*/
|
*/
|
||||||
@@ -224,9 +244,9 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
Dispatch_Function(const std::vector<Proxy_Function> &t_funcs)
|
Dispatch_Function(const std::vector<Proxy_Function> &t_funcs)
|
||||||
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
||||||
m_funcs(t_funcs)
|
m_funcs(t_funcs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const
|
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const
|
||||||
{
|
{
|
||||||
@@ -276,7 +296,7 @@ namespace chaiscript
|
|||||||
return -1; // unknown arity
|
return -1; // unknown arity
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
typedef std::vector<Proxy_Function> function_vec;
|
typedef std::vector<Proxy_Function> function_vec;
|
||||||
|
|
||||||
@@ -285,7 +305,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
if ((*begin)->call_match(vals))
|
if ((*begin)->call_match(vals, t_conversions))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -302,9 +322,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params);
|
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -391,16 +411,21 @@ namespace chaiscript
|
|||||||
|
|
||||||
~Dispatch_Engine()
|
~Dispatch_Engine()
|
||||||
{
|
{
|
||||||
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||||
|
template<typename Type>
|
||||||
|
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||||
|
{
|
||||||
|
return chaiscript::boxed_cast<Type>(bv, &m_conversions);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new conversion for upcasting to a base class
|
* Add a new conversion for upcasting to a base class
|
||||||
*/
|
*/
|
||||||
void add(const Dynamic_Cast_Conversion &d)
|
void add(const Dynamic_Cast_Conversion &d)
|
||||||
{
|
{
|
||||||
m_conversions.push_back(d);
|
m_conversions.add_conversion(d);
|
||||||
return detail::Dynamic_Conversions::get().add_conversion(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -474,6 +499,25 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new global (non-const) shared object, between all the threads
|
||||||
|
*/
|
||||||
|
void add_global(const Boxed_Value &obj, const std::string &name)
|
||||||
|
{
|
||||||
|
validate_object_name(name);
|
||||||
|
|
||||||
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new scope to the stack
|
* Adds a new scope to the stack
|
||||||
*/
|
*/
|
||||||
@@ -668,6 +712,27 @@ 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
|
/// Get a map of all objects that can be seen from the current scope in a scripting context
|
||||||
@@ -752,11 +817,16 @@ namespace chaiscript
|
|||||||
m_state.m_reserved_words.insert(name);
|
m_state.m_reserved_words.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Dynamic_Cast_Conversions &conversions() const
|
||||||
|
{
|
||||||
|
return m_conversions;
|
||||||
|
}
|
||||||
|
|
||||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||||
{
|
{
|
||||||
std::vector<Proxy_Function> functions = get_function(t_name);
|
std::vector<Proxy_Function> functions = get_function(t_name);
|
||||||
|
|
||||||
return dispatch::dispatch(functions.begin(), functions.end(), params);
|
return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Value call_function(const std::string &t_name) const
|
Boxed_Value call_function(const std::string &t_name) const
|
||||||
@@ -782,10 +852,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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -826,6 +895,22 @@ namespace chaiscript
|
|||||||
std::cout << ") " << std::endl;
|
std::cout << ") " << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a call can be made that consists of the first parameter
|
||||||
|
* (the function) with the remaining parameters as its arguments.
|
||||||
|
*/
|
||||||
|
Boxed_Value call_exists(const std::vector<Boxed_Value> ¶ms)
|
||||||
|
{
|
||||||
|
if (params.size() < 1)
|
||||||
|
{
|
||||||
|
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Const_Proxy_Function f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||||
|
|
||||||
|
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump all system info to stdout
|
* Dump all system info to stdout
|
||||||
*/
|
*/
|
||||||
@@ -877,7 +962,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());
|
||||||
}
|
}
|
||||||
@@ -1052,6 +1137,10 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
void validate_object_name(const std::string &name) const
|
void validate_object_name(const std::string &name) const
|
||||||
{
|
{
|
||||||
|
if (name.find("::") != std::string::npos) {
|
||||||
|
throw exception::illegal_name_error(name);
|
||||||
|
}
|
||||||
|
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
||||||
@@ -1091,6 +1180,14 @@ namespace chaiscript
|
|||||||
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));
|
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||||
|
} else if (t_f->has_arithmetic_param()) {
|
||||||
|
// if the function is the only function but it also contains
|
||||||
|
// arithmetic operators, we must wrap it in a dispatch function
|
||||||
|
// to allow for automatic arithmetic type conversions
|
||||||
|
std::vector<Proxy_Function> vec;
|
||||||
|
vec.push_back(t_f);
|
||||||
|
funcs.insert(std::make_pair(t_name, vec));
|
||||||
|
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);
|
||||||
@@ -1120,7 +1217,7 @@ namespace chaiscript
|
|||||||
int call_depth;
|
int call_depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
Dynamic_Cast_Conversions m_conversions;
|
||||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||||
@@ -47,7 +47,7 @@ namespace chaiscript
|
|||||||
class Dynamic_Conversion
|
class Dynamic_Conversion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Boxed_Value convert(const Boxed_Value &derived) = 0;
|
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
|
||||||
|
|
||||||
const Type_Info &base()
|
const Type_Info &base()
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Base, typename Derived>
|
template<typename Base, typename Derived>
|
||||||
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Conversion_Impl()
|
Dynamic_Conversion_Impl()
|
||||||
@@ -81,7 +81,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Boxed_Value convert(const Boxed_Value &t_derived)
|
virtual Boxed_Value convert(const Boxed_Value &t_derived) const
|
||||||
{
|
{
|
||||||
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
|
if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ namespace chaiscript
|
|||||||
if (t_derived.is_const())
|
if (t_derived.is_const())
|
||||||
{
|
{
|
||||||
boost::shared_ptr<const Base> data
|
boost::shared_ptr<const Base> data
|
||||||
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived));
|
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived, 0));
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
throw std::bad_cast();
|
throw std::bad_cast();
|
||||||
@@ -100,7 +100,7 @@ namespace chaiscript
|
|||||||
return Boxed_Value(data);
|
return Boxed_Value(data);
|
||||||
} else {
|
} else {
|
||||||
boost::shared_ptr<Base> data
|
boost::shared_ptr<Base> data
|
||||||
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived));
|
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived, 0));
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
@@ -113,11 +113,11 @@ namespace chaiscript
|
|||||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||||
if (t_derived.is_const())
|
if (t_derived.is_const())
|
||||||
{
|
{
|
||||||
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
|
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived, 0);
|
||||||
const Base &data = dynamic_cast<const Base &>(d);
|
const Base &data = dynamic_cast<const Base &>(d);
|
||||||
return Boxed_Value(boost::cref(data));
|
return Boxed_Value(boost::cref(data));
|
||||||
} else {
|
} else {
|
||||||
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
|
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived, 0);
|
||||||
Base &data = dynamic_cast<Base &>(d);
|
Base &data = dynamic_cast<Base &>(d);
|
||||||
return Boxed_Value(boost::ref(data));
|
return Boxed_Value(boost::ref(data));
|
||||||
}
|
}
|
||||||
@@ -127,101 +127,98 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Dynamic_Conversions
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static inline Dynamic_Conversions &get()
|
|
||||||
{
|
|
||||||
static Dynamic_Conversions obj;
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Base, typename Derived>
|
|
||||||
static boost::shared_ptr<Dynamic_Conversion> create()
|
|
||||||
{
|
|
||||||
boost::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
|
|
||||||
|
|
||||||
/// \todo this is a hack and a kludge. The idea is to make sure that
|
|
||||||
/// the conversion is registered both in the module's notion of the static conversion object
|
|
||||||
/// and in the global notion of the static conversion object
|
|
||||||
/// someday this will almost certainly have to change. Maybe it is time for ChaiScript
|
|
||||||
/// to become a library?
|
|
||||||
Dynamic_Conversions::get().add_conversion(conversion);
|
|
||||||
return conversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename InItr>
|
|
||||||
void cleanup(InItr begin, const InItr &end)
|
|
||||||
{
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
while (begin != end)
|
|
||||||
{
|
|
||||||
if (begin->unique())
|
|
||||||
{
|
|
||||||
m_conversions.erase(begin->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
++begin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
|
|
||||||
{
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
m_conversions.insert(conversion.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
|
|
||||||
{
|
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
return find(base, derived) != m_conversions.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
|
|
||||||
{
|
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
std::set<Dynamic_Conversion *>::const_iterator itr =
|
|
||||||
find(base, derived);
|
|
||||||
|
|
||||||
if (itr != m_conversions.end())
|
|
||||||
{
|
|
||||||
return *itr;
|
|
||||||
} else {
|
|
||||||
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Dynamic_Conversions() {}
|
|
||||||
|
|
||||||
std::set<Dynamic_Conversion *>::const_iterator find(
|
|
||||||
const Type_Info &base, const Type_Info &derived) const
|
|
||||||
{
|
|
||||||
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
|
|
||||||
itr != m_conversions.end();
|
|
||||||
++itr)
|
|
||||||
{
|
|
||||||
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
|
|
||||||
{
|
|
||||||
return itr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_conversions.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
|
||||||
std::set<Dynamic_Conversion *> m_conversions;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Dynamic_Cast_Conversions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Dynamic_Cast_Conversions()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
|
||||||
|
: m_conversions(t_other.get_conversions())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_conversion(const boost::shared_ptr<detail::Dynamic_Conversion> &conversion)
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
m_conversions.insert(conversion);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Base, typename Derived>
|
||||||
|
bool dynamic_cast_converts() const
|
||||||
|
{
|
||||||
|
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
|
||||||
|
{
|
||||||
|
return has_conversion(base, derived);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Base>
|
||||||
|
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
||||||
|
} catch (const std::out_of_range &) {
|
||||||
|
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||||
|
} catch (const std::bad_cast &) {
|
||||||
|
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
return find(base, derived) != m_conversions.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<detail::Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
|
std::set<boost::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr =
|
||||||
|
find(base, derived);
|
||||||
|
|
||||||
|
if (itr != m_conversions.end())
|
||||||
|
{
|
||||||
|
return *itr;
|
||||||
|
} else {
|
||||||
|
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<boost::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
|
||||||
|
const Type_Info &base, const Type_Info &derived) const
|
||||||
|
{
|
||||||
|
for (std::set<boost::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr = m_conversions.begin();
|
||||||
|
itr != m_conversions.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
|
||||||
|
{
|
||||||
|
return itr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_conversions.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<boost::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
|
return m_conversions;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
|
std::set<boost::shared_ptr<detail::Dynamic_Conversion> > m_conversions;
|
||||||
|
};
|
||||||
|
|
||||||
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||||
|
|
||||||
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
|
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
|
||||||
@@ -248,42 +245,17 @@ namespace chaiscript
|
|||||||
/// \todo Move share static type registration code into a mechanism that allows it to be properly
|
/// \todo Move share static type registration code into a mechanism that allows it to be properly
|
||||||
/// shared by all modules
|
/// shared by all modules
|
||||||
template<typename Base, typename Derived>
|
template<typename Base, typename Derived>
|
||||||
Dynamic_Cast_Conversion base_class()
|
Dynamic_Cast_Conversion base_class()
|
||||||
{
|
|
||||||
//Can only be used with related polymorphic types
|
|
||||||
//may be expanded some day to support conversions other than child -> parent
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_base_of<Base,Derived>::value));
|
|
||||||
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
|
|
||||||
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
|
|
||||||
|
|
||||||
return detail::Dynamic_Conversions::create<Base, Derived>();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<typename Base, typename Derived>
|
|
||||||
bool dynamic_cast_converts()
|
|
||||||
{
|
|
||||||
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
|
|
||||||
{
|
{
|
||||||
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
|
//Can only be used with related polymorphic types
|
||||||
|
//may be expanded some day to support conversions other than child -> parent
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_base_of<Base,Derived>::value));
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
|
||||||
|
|
||||||
|
return boost::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<Base, Derived>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Base>
|
|
||||||
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
|
||||||
} catch (const std::out_of_range &) {
|
|
||||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
|
||||||
} catch (const std::bad_cast &) {
|
|
||||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
@@ -57,11 +57,11 @@ namespace chaiscript
|
|||||||
const Proxy_Function &t_func,
|
const Proxy_Function &t_func,
|
||||||
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
|
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
|
||||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
|
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
|
||||||
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
|
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
|
||||||
{
|
{
|
||||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dynamic_Object_Function() {}
|
virtual ~Dynamic_Object_Function() {}
|
||||||
|
|
||||||
@@ -76,11 +76,11 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
|
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||||
{
|
{
|
||||||
return m_func->call_match(vals);
|
return m_func->call_match(vals, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -106,19 +106,19 @@ namespace chaiscript
|
|||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
if (dynamic_object_typename_match(params, m_type_name, m_ti))
|
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||||
{
|
{
|
||||||
return (*m_func)(params);
|
return (*m_func)(params, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
throw exception::guard_error();
|
throw exception::guard_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool compare_first_type(const Boxed_Value &bv) const
|
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return dynamic_object_typename_match(bv, m_type_name, m_ti);
|
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -139,13 +139,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||||
const boost::optional<Type_Info> &ti)
|
const boost::optional<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
static Type_Info doti = user_type<Dynamic_Object>();
|
static Type_Info doti = user_type<Dynamic_Object>();
|
||||||
if (bv.get_type_info().bare_equal(doti))
|
if (bv.get_type_info().bare_equal(doti))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
|
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||||
return name == "Dynamic_Object" || d.get_type_name() == name;
|
return name == "Dynamic_Object" || d.get_type_name() == name;
|
||||||
} catch (const std::bad_cast &) {
|
} catch (const std::bad_cast &) {
|
||||||
return false;
|
return false;
|
||||||
@@ -162,11 +162,11 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||||
const boost::optional<Type_Info> &ti)
|
const boost::optional<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
if (bvs.size() > 0)
|
if (bvs.size() > 0)
|
||||||
{
|
{
|
||||||
return dynamic_object_typename_match(bvs[0], name, ti);
|
return dynamic_object_typename_match(bvs[0], name, ti, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -192,11 +192,11 @@ namespace chaiscript
|
|||||||
const std::string &t_type_name,
|
const std::string &t_type_name,
|
||||||
const Proxy_Function &t_func)
|
const Proxy_Function &t_func)
|
||||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
|
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
|
||||||
m_type_name(t_type_name), m_func(t_func)
|
m_type_name(t_type_name), m_func(t_func)
|
||||||
{
|
{
|
||||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
||||||
{
|
{
|
||||||
@@ -224,13 +224,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> new_vals;
|
std::vector<Boxed_Value> new_vals;
|
||||||
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
||||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||||
|
|
||||||
return m_func->call_match(new_vals);
|
return m_func->call_match(new_vals, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -246,14 +246,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> new_params;
|
std::vector<Boxed_Value> new_params;
|
||||||
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
||||||
new_params.push_back(bv);
|
new_params.push_back(bv);
|
||||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||||
|
|
||||||
(*m_func)(new_params);
|
(*m_func)(new_params, t_conversions);
|
||||||
|
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
#ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
|
||||||
@@ -15,65 +15,77 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
struct Exception_Handler_Base
|
struct Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv) = 0;
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||||
|
|
||||||
|
virtual ~Exception_Handler_Base() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void throw_type(const Boxed_Value &bv)
|
void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
try { T t = boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
|
try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T1>
|
template<typename T1>
|
||||||
struct Exception_Handler_Impl1 : Exception_Handler_Base
|
struct Exception_Handler_Impl1 : Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv)
|
virtual ~Exception_Handler_Impl1() {}
|
||||||
|
|
||||||
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
throw_type<T1>(bv);
|
throw_type<T1>(bv, t_engine);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct Exception_Handler_Impl2 : Exception_Handler_Base
|
struct Exception_Handler_Impl2 : Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv)
|
virtual ~Exception_Handler_Impl2() {}
|
||||||
|
|
||||||
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
throw_type<T1>(bv);
|
throw_type<T1>(bv, t_engine);
|
||||||
throw_type<T2>(bv);
|
throw_type<T2>(bv, t_engine);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T1, typename T2, typename T3>
|
template<typename T1, typename T2, typename T3>
|
||||||
struct Exception_Handler_Impl3 : Exception_Handler_Base
|
struct Exception_Handler_Impl3 : Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv)
|
virtual ~Exception_Handler_Impl3() {}
|
||||||
|
|
||||||
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
throw_type<T1>(bv);
|
throw_type<T1>(bv, t_engine);
|
||||||
throw_type<T2>(bv);
|
throw_type<T2>(bv, t_engine);
|
||||||
throw_type<T3>(bv);
|
throw_type<T3>(bv, t_engine);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename T1, typename T2, typename T3, typename T4>
|
template<typename T1, typename T2, typename T3, typename T4>
|
||||||
struct Exception_Handler_Impl4 : Exception_Handler_Base
|
struct Exception_Handler_Impl4 : Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv)
|
virtual ~Exception_Handler_Impl4() {}
|
||||||
|
|
||||||
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
throw_type<T1>(bv);
|
throw_type<T1>(bv, t_engine);
|
||||||
throw_type<T2>(bv);
|
throw_type<T2>(bv, t_engine);
|
||||||
throw_type<T3>(bv);
|
throw_type<T3>(bv, t_engine);
|
||||||
throw_type<T4>(bv);
|
throw_type<T4>(bv, t_engine);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
template<typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||||
struct Exception_Handler_Impl5 : Exception_Handler_Base
|
struct Exception_Handler_Impl5 : Exception_Handler_Base
|
||||||
{
|
{
|
||||||
virtual void handle(const Boxed_Value &bv)
|
virtual ~Exception_Handler_Impl5() {}
|
||||||
|
|
||||||
|
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
|
||||||
{
|
{
|
||||||
throw_type<T1>(bv);
|
throw_type<T1>(bv, t_engine);
|
||||||
throw_type<T2>(bv);
|
throw_type<T2>(bv, t_engine);
|
||||||
throw_type<T3>(bv);
|
throw_type<T3>(bv, t_engine);
|
||||||
throw_type<T4>(bv);
|
throw_type<T4>(bv, t_engine);
|
||||||
throw_type<T5>(bv);
|
throw_type<T5>(bv, t_engine);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
@@ -32,10 +32,10 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(const std::vector<Const_Proxy_Function> &funcs)
|
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
FunctionType *p=0;
|
FunctionType *p=0;
|
||||||
return detail::build_function_caller_helper(p, funcs);
|
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,11 +53,11 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(Const_Proxy_Function func)
|
functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
std::vector<Const_Proxy_Function> funcs;
|
std::vector<Const_Proxy_Function> funcs;
|
||||||
funcs.push_back(func);
|
funcs.push_back(func);
|
||||||
return functor<FunctionType>(funcs);
|
return functor<FunctionType>(funcs, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,9 +66,9 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(const Boxed_Value &bv)
|
functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
|
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,13 +81,13 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef boost::function<Signature> Result_Type;
|
typedef boost::function<Signature> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
return dispatch::functor<Signature>(ob);
|
return dispatch::functor<Signature>(ob, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob);
|
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob, t_conversions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -100,13 +100,13 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef boost::function<Signature> Result_Type;
|
typedef boost::function<Signature> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
return dispatch::functor<Signature>(ob);
|
return dispatch::functor<Signature>(ob, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob);
|
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob, t_conversions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -119,13 +119,13 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef boost::function<Signature> Result_Type;
|
typedef boost::function<Signature> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
return dispatch::functor<Signature>(ob);
|
return dispatch::functor<Signature>(ob, t_conversions);
|
||||||
} else {
|
} else {
|
||||||
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
|
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob, t_conversions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
@@ -36,9 +36,9 @@ namespace chaiscript
|
|||||||
struct Function_Caller_Ret
|
struct Function_Caller_Ret
|
||||||
{
|
{
|
||||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params));
|
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ namespace chaiscript
|
|||||||
struct Function_Caller_Ret<void>
|
struct Function_Caller_Ret<void>
|
||||||
{
|
{
|
||||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
dispatch::dispatch(t_funcs, params);
|
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -76,14 +76,14 @@ namespace chaiscript
|
|||||||
* used internally for unwrapping a function call's types
|
* used internally for unwrapping a function call's types
|
||||||
*/
|
*/
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
|
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions &t_conversions
|
||||||
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> params;
|
std::vector<Boxed_Value> params;
|
||||||
|
|
||||||
BOOST_PP_REPEAT(n, addparam, ~)
|
BOOST_PP_REPEAT(n, addparam, ~);
|
||||||
|
|
||||||
return Function_Caller_Ret<Ret>::call(funcs, params);
|
return Function_Caller_Ret<Ret>::call(funcs, params, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,7 +91,8 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
||||||
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs)
|
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs,
|
||||||
|
const Dynamic_Cast_Conversions *t_conversions)
|
||||||
{
|
{
|
||||||
if (funcs.size() == 1)
|
if (funcs.size() == 1)
|
||||||
{
|
{
|
||||||
@@ -107,13 +108,15 @@ namespace chaiscript
|
|||||||
// we cannot make any other guesses or assumptions really, so continuing
|
// we cannot make any other guesses or assumptions really, so continuing
|
||||||
}
|
}
|
||||||
|
|
||||||
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
|
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs, (t_conversions?*t_conversions:Dynamic_Cast_Conversions())
|
||||||
BOOST_PP_ENUM_TRAILING(n, curry, ~));
|
BOOST_PP_ENUM_TRAILING(n, curry, ~));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef n
|
#undef n
|
||||||
|
#undef addparam
|
||||||
|
#undef curry
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
#ifndef CHAISCRIPT_HANDLE_RETURN_HPP_
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, 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
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -71,9 +70,9 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Proxy_Function_Base() {}
|
virtual ~Proxy_Function_Base() {}
|
||||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
Boxed_Value bv = do_call(params);
|
Boxed_Value bv = do_call(params, t_conversions);
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +83,12 @@ namespace chaiscript
|
|||||||
std::vector<Type_Info> get_param_types() const { return m_types; }
|
std::vector<Type_Info> get_param_types() const { return m_types; }
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||||
|
|
||||||
|
bool has_arithmetic_param() const
|
||||||
|
{
|
||||||
|
return m_has_arithmetic_param;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::vector<boost::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
virtual std::vector<boost::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
||||||
{
|
{
|
||||||
@@ -94,7 +98,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
//! Return true if the function is a possible match
|
//! Return true if the function is a possible match
|
||||||
//! to the passed in values
|
//! to the passed in values
|
||||||
bool filter(const std::vector<Boxed_Value> &vals) const
|
bool filter(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
int arity = get_arity();
|
int arity = get_arity();
|
||||||
|
|
||||||
@@ -106,7 +110,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return compare_first_type(vals[0]);
|
return compare_first_type(vals[0], t_conversions);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -118,30 +122,15 @@ namespace chaiscript
|
|||||||
|
|
||||||
virtual std::string annotation() const = 0;
|
virtual std::string annotation() const = 0;
|
||||||
|
|
||||||
protected:
|
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const = 0;
|
|
||||||
|
|
||||||
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
|
|
||||||
: m_types(t_types)
|
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool compare_first_type(const Boxed_Value &bv) const
|
|
||||||
{
|
|
||||||
const std::vector<Type_Info> &types = get_param_types();
|
|
||||||
|
|
||||||
if (types.size() < 2)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const Type_Info &ti = types[1];
|
|
||||||
if (ti.is_undef()
|
if (ti.is_undef()
|
||||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||||
|| (!bv.get_type_info().is_undef()
|
|| (!bv.get_type_info().is_undef()
|
||||||
&& (ti.bare_equal(user_type<Boxed_Number>())
|
&& (ti.bare_equal(user_type<Boxed_Number>())
|
||||||
|| ti.bare_equal(bv.get_type_info())
|
|| ti.bare_equal(bv.get_type_info())
|
||||||
|| chaiscript::detail::dynamic_cast_converts(ti, bv.get_type_info())
|
|
||||||
|| bv.get_type_info().bare_equal(user_type<boost::shared_ptr<const Proxy_Function_Base> >())
|
|| bv.get_type_info().bare_equal(user_type<boost::shared_ptr<const Proxy_Function_Base> >())
|
||||||
|
|| t_conversions.dynamic_cast_converts(ti, bv.get_type_info())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -151,8 +140,38 @@ namespace chaiscript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected:
|
||||||
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||||
|
|
||||||
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
|
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
|
||||||
|
: m_types(t_types), m_has_arithmetic_param(false)
|
||||||
|
{
|
||||||
|
for (size_t i = 1; i < m_types.size(); ++i)
|
||||||
|
{
|
||||||
|
if (m_types[i].is_arithmetic())
|
||||||
|
{
|
||||||
|
m_has_arithmetic_param = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
|
{
|
||||||
|
const std::vector<Type_Info> &types = get_param_types();
|
||||||
|
|
||||||
|
if (types.size() < 2)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type_Info &ti = types[1];
|
||||||
|
return compare_type_to_param(ti, bv, t_conversions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
|
||||||
{
|
{
|
||||||
if (tis.size() - 1 != bvs.size())
|
if (tis.size() - 1 != bvs.size())
|
||||||
{
|
{
|
||||||
@@ -171,6 +190,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Type_Info> m_types;
|
std::vector<Type_Info> m_types;
|
||||||
|
bool m_has_arithmetic_param;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,10 +247,10 @@ namespace chaiscript
|
|||||||
&& !this->m_guard && !prhs->m_guard);
|
&& !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 Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return (m_arity < 0 || vals.size() == size_t(m_arity))
|
return (m_arity < 0 || vals.size() == size_t(m_arity))
|
||||||
&& test_guard(vals);
|
&& test_guard(vals, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dynamic_Proxy_Function() {}
|
virtual ~Dynamic_Proxy_Function() {}
|
||||||
@@ -256,12 +277,12 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
if (m_arity < 0 || params.size() == size_t(m_arity))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (test_guard(params))
|
if (test_guard(params, t_conversions))
|
||||||
{
|
{
|
||||||
return m_f(params);
|
return m_f(params);
|
||||||
} else {
|
} else {
|
||||||
@@ -274,12 +295,12 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool test_guard(const std::vector<Boxed_Value> ¶ms) const
|
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
if (m_guard)
|
if (m_guard)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return boxed_cast<bool>((*m_guard)(params));
|
return boxed_cast<bool>((*m_guard)(params, t_conversions));
|
||||||
} catch (const exception::arity_error &) {
|
} catch (const exception::arity_error &) {
|
||||||
return false;
|
return false;
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
@@ -335,7 +356,7 @@ namespace chaiscript
|
|||||||
Bound_Function(const Const_Proxy_Function &t_f,
|
Bound_Function(const Const_Proxy_Function &t_f,
|
||||||
const std::vector<Boxed_Value> &t_args)
|
const std::vector<Boxed_Value> &t_args)
|
||||||
: Proxy_Function_Base(build_param_type_info(t_f, t_args)),
|
: Proxy_Function_Base(build_param_type_info(t_f, t_args)),
|
||||||
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
|
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
|
||||||
{
|
{
|
||||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||||
}
|
}
|
||||||
@@ -347,14 +368,9 @@ namespace chaiscript
|
|||||||
|
|
||||||
virtual ~Bound_Function() {}
|
virtual ~Bound_Function() {}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return m_f->call_match(build_param_list(vals));
|
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||||
}
|
|
||||||
|
|
||||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
|
||||||
{
|
|
||||||
return (*m_f)(build_param_list(params));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||||
@@ -431,9 +447,9 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return (*m_f)(build_param_list(params));
|
return (*m_f)(build_param_list(params), t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -454,8 +470,8 @@ namespace chaiscript
|
|||||||
Proxy_Function_Impl(const boost::function<Func> &f)
|
Proxy_Function_Impl(const boost::function<Func> &f)
|
||||||
: Proxy_Function_Base(detail::build_param_type_list(static_cast<Func *>(0))),
|
: Proxy_Function_Base(detail::build_param_type_list(static_cast<Func *>(0))),
|
||||||
m_f(f), m_dummy_func(0)
|
m_f(f), m_dummy_func(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Proxy_Function_Impl() {}
|
virtual ~Proxy_Function_Impl() {}
|
||||||
|
|
||||||
@@ -472,14 +488,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
if (int(vals.size()) != get_arity())
|
if (int(vals.size()) != get_arity())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals);
|
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const
|
virtual std::string annotation() const
|
||||||
@@ -493,9 +509,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return detail::Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
|
return detail::Do_Call<typename boost::function<Func>::result_type>::go(m_f, params, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -513,8 +529,8 @@ namespace chaiscript
|
|||||||
Attribute_Access(T Class::* t_attr)
|
Attribute_Access(T Class::* t_attr)
|
||||||
: Proxy_Function_Base(param_types()),
|
: Proxy_Function_Base(param_types()),
|
||||||
m_attr(t_attr)
|
m_attr(t_attr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Attribute_Access() {}
|
virtual ~Attribute_Access() {}
|
||||||
|
|
||||||
@@ -535,7 +551,7 @@ namespace chaiscript
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &) const
|
||||||
{
|
{
|
||||||
if (vals.size() != 1)
|
if (vals.size() != 1)
|
||||||
{
|
{
|
||||||
@@ -551,17 +567,17 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
if (params.size() == 1)
|
if (params.size() == 1)
|
||||||
{
|
{
|
||||||
const Boxed_Value &bv = params[0];
|
const Boxed_Value &bv = params[0];
|
||||||
if (bv.is_const())
|
if (bv.is_const())
|
||||||
{
|
{
|
||||||
const Class *o = boxed_cast<const Class *>(bv);
|
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
||||||
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||||
} else {
|
} else {
|
||||||
Class *o = boxed_cast<Class *>(bv);
|
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
||||||
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -591,22 +607,109 @@ 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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace dispatch
|
namespace dispatch
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename FuncType>
|
||||||
|
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||||
|
const Dynamic_Cast_Conversions &t_conversions)
|
||||||
|
{
|
||||||
|
if (t_func->get_arity() != static_cast<int>(plist.size()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||||
|
|
||||||
|
assert(plist.size() == types.size() - 1);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < plist.size(); ++i)
|
||||||
|
{
|
||||||
|
if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i], t_conversions)
|
||||||
|
|| (types[i+1].is_arithmetic() && plist[i].get_type_info().is_arithmetic()))
|
||||||
|
{
|
||||||
|
// types continue to match
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all types match
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InItr>
|
||||||
|
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||||
|
const Dynamic_Cast_Conversions &t_conversions)
|
||||||
|
{
|
||||||
|
InItr orig(begin);
|
||||||
|
|
||||||
|
InItr matching_func(end);
|
||||||
|
|
||||||
|
while (begin != end)
|
||||||
|
{
|
||||||
|
if (types_match_except_for_arithmetic(*begin, plist, t_conversions))
|
||||||
|
{
|
||||||
|
if (matching_func == end)
|
||||||
|
{
|
||||||
|
matching_func = begin;
|
||||||
|
} else {
|
||||||
|
// More than one function matches, not attempting
|
||||||
|
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matching_func == end)
|
||||||
|
{
|
||||||
|
// no appropriate function to attempt arithmetic type conversion on
|
||||||
|
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Boxed_Value> newplist;
|
||||||
|
const std::vector<Type_Info> &tis = (*matching_func)->get_param_types();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < plist.size(); ++i)
|
||||||
|
{
|
||||||
|
if (tis[i+1].is_arithmetic()
|
||||||
|
&& plist[i].get_type_info().is_arithmetic()) {
|
||||||
|
newplist.push_back(Boxed_Number(plist[i]).get_as(tis[i+1]).bv);
|
||||||
|
} else {
|
||||||
|
newplist.push_back(plist[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (*(*matching_func))(newplist, t_conversions);
|
||||||
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
|
//parameter failed to cast
|
||||||
|
} catch (const exception::arity_error &) {
|
||||||
|
//invalid num params
|
||||||
|
} catch (const exception::guard_error &) {
|
||||||
|
//guard failed to allow the function to execute
|
||||||
|
}
|
||||||
|
|
||||||
|
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||||
@@ -614,15 +717,16 @@ 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, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
|
InItr orig(begin);
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if ((*begin)->filter(plist))
|
if ((*begin)->filter(plist, t_conversions))
|
||||||
{
|
{
|
||||||
return (*(*begin))(plist);
|
return (*(*begin))(plist, t_conversions);
|
||||||
}
|
}
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
//parameter failed to cast, try again
|
//parameter failed to cast, try again
|
||||||
@@ -635,7 +739,7 @@ namespace chaiscript
|
|||||||
++begin;
|
++begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw exception::dispatch_error(plist.empty()?false:plist[0].is_const());
|
return detail::dispatch_with_conversions(orig, end, plist, t_conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -645,9 +749,9 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename Funcs>
|
template<typename Funcs>
|
||||||
Boxed_Value dispatch(const Funcs &funcs,
|
Boxed_Value dispatch(const Funcs &funcs,
|
||||||
const std::vector<Boxed_Value> &plist)
|
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
return dispatch::dispatch(funcs.begin(), funcs.end(), plist);
|
return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
#define gettypeinfo(z,n,text) ti.push_back(chaiscript::detail::Get_Type_Info<Param ## n>::get());
|
#define gettypeinfo(z,n,text) ti.push_back(chaiscript::detail::Get_Type_Info<Param ## n>::get());
|
||||||
#define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n])
|
#define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n], &t_conversions)
|
||||||
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
|
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n], &t_conversions);
|
||||||
|
|
||||||
#ifndef BOOST_PP_IS_ITERATING
|
#ifndef BOOST_PP_IS_ITERATING
|
||||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||||
@@ -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>
|
||||||
@@ -87,9 +86,23 @@ namespace chaiscript
|
|||||||
* if any unboxing fails the execution of the function fails and
|
* if any unboxing fails the execution of the function fails and
|
||||||
* the bad_boxed_cast is passed up to the caller.
|
* the bad_boxed_cast is passed up to the caller.
|
||||||
*/
|
*/
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions & BOOST_PP_IF(n, t_conversions, BOOST_PP_EMPTY))
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (params.size() != n)
|
if (params.size() != n)
|
||||||
{
|
{
|
||||||
@@ -99,16 +112,37 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||||
* Proxy_Function_Impl object. This function is primarly used to prevent
|
* Proxy_Function_Impl object. This function is primarly used to prevent
|
||||||
* registration of two functions with the exact same signatures
|
* registration of two functions with the exact same signatures
|
||||||
*/
|
*/
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
|
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
|
||||||
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, ))
|
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, BOOST_PP_EMPTY), const Dynamic_Cast_Conversions &t_conversions)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
(void)t_conversions;
|
||||||
BOOST_PP_REPEAT(n, trycast, ~);
|
BOOST_PP_REPEAT(n, trycast, ~);
|
||||||
} catch (const exception::bad_boxed_cast &) {
|
} catch (const exception::bad_boxed_cast &) {
|
||||||
return false;
|
return false;
|
||||||
@@ -116,11 +150,20 @@ namespace chaiscript
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef n
|
#undef n
|
||||||
|
#undef gettypeinfo
|
||||||
|
#undef casthelper
|
||||||
|
#undef trycast
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -137,9 +180,9 @@ namespace chaiscript
|
|||||||
struct Do_Call
|
struct Do_Call
|
||||||
{
|
{
|
||||||
template<typename Fun>
|
template<typename Fun>
|
||||||
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
return Handle_Return<Ret>::handle(call_func(fun, params));
|
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,9 +190,9 @@ namespace chaiscript
|
|||||||
struct Do_Call<void>
|
struct Do_Call<void>
|
||||||
{
|
{
|
||||||
template<typename Fun>
|
template<typename Fun>
|
||||||
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
call_func(fun, params);
|
call_func(fun, params, t_conversions);
|
||||||
return Handle_Return<void>::handle();
|
return Handle_Return<void>::handle();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
|
||||||
@@ -99,6 +99,12 @@ namespace chaiscript
|
|||||||
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bare_equal_type_info(const std::type_info &ti) const
|
||||||
|
{
|
||||||
|
return m_bare_type_info != 0
|
||||||
|
&& (*m_bare_type_info) == ti;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_const() const { return m_is_const; }
|
bool is_const() const { return m_is_const; }
|
||||||
bool is_reference() const { return m_is_reference; }
|
bool is_reference() const { return m_is_reference; }
|
||||||
bool is_void() const { return m_is_void; }
|
bool is_void() const { return m_is_void; }
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||||
@@ -21,23 +21,22 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||||
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, Continue, 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, Switch, Case, Default, Ternary_Cond
|
Logical_And, Logical_Or, Switch, Case, Default, Ternary_Cond, Noop
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Helper lookup to get the name of each node type
|
/// Helper lookup to get the name of each node type
|
||||||
*/
|
|
||||||
const char *ast_node_type_to_string(int ast_node_type) {
|
const char *ast_node_type_to_string(int ast_node_type) {
|
||||||
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||||
"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", "Continue", "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", "Switch", "Case", "Default", "Ternary Condition"};
|
"Logical_And", "Logical_Or", "Switch", "Case", "Default", "Ternary Condition", "Noop"};
|
||||||
|
|
||||||
return ast_node_types[ast_node_type];
|
return ast_node_types[ast_node_type];
|
||||||
}
|
}
|
||||||
@@ -61,35 +60,323 @@ namespace chaiscript
|
|||||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||||
namespace exception
|
namespace exception
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Errors generated during parsing or evaluation
|
/// Errors generated during parsing or evaluation
|
||||||
*/
|
|
||||||
struct eval_error : public std::runtime_error {
|
struct eval_error : public std::runtime_error {
|
||||||
std::string reason;
|
std::string reason;
|
||||||
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();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Errors generated when loading a file
|
/// Errors generated when loading a file
|
||||||
*/
|
|
||||||
struct file_not_found_error : public std::runtime_error {
|
struct file_not_found_error : public std::runtime_error {
|
||||||
file_not_found_error(const std::string &t_filename) throw()
|
file_not_found_error(const std::string &t_filename) throw()
|
||||||
: std::runtime_error("File Not Found: " + t_filename)
|
: std::runtime_error("File Not Found: " + t_filename)
|
||||||
@@ -111,9 +398,21 @@ namespace chaiscript
|
|||||||
std::vector<AST_NodePtr> children;
|
std::vector<AST_NodePtr> children;
|
||||||
AST_NodePtr annotation;
|
AST_NodePtr annotation;
|
||||||
|
|
||||||
/**
|
virtual std::string pretty_print() const
|
||||||
* Prints the contents of an AST node, including its children, recursively
|
{
|
||||||
*/
|
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
|
||||||
std::string to_string(std::string t_prepend = "") {
|
std::string to_string(std::string t_prepend = "") {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
|
||||||
@@ -175,22 +474,27 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Special type for returned values
|
/// Special type for returned values
|
||||||
*/
|
|
||||||
struct Return_Value {
|
struct Return_Value {
|
||||||
Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
|
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Special type indicating a call to 'break'
|
/// Special type indicating a call to 'break'
|
||||||
*/
|
|
||||||
struct Break_Loop {
|
struct Break_Loop {
|
||||||
Break_Loop() { }
|
Break_Loop() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Special type indicating a call to 'continue'
|
||||||
|
struct Continue_Loop {
|
||||||
|
Continue_Loop() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Creates a new scope then pops it on destruction
|
/// Creates a new scope then pops it on destruction
|
||||||
struct Scope_Push_Pop
|
struct Scope_Push_Pop
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_ENGINE_HPP_
|
#ifndef CHAISCRIPT_ENGINE_HPP_
|
||||||
@@ -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
|
||||||
@@ -251,9 +251,8 @@ namespace chaiscript
|
|||||||
chaiscript::detail::Dispatch_Engine m_engine;
|
chaiscript::detail::Dispatch_Engine m_engine;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates the given string in by parsing it and running the results through the evaluator
|
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||||
*/
|
|
||||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -282,9 +281,8 @@ 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) {
|
||||||
try {
|
try {
|
||||||
return do_eval(t_e, "__EVAL__", true);
|
return do_eval(t_e, "__EVAL__", true);
|
||||||
@@ -294,16 +292,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current evaluation m_engine
|
/// Returns the current evaluation m_engine
|
||||||
*/
|
|
||||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() {
|
chaiscript::detail::Dispatch_Engine &get_eval_engine() {
|
||||||
return m_engine;
|
return m_engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||||
*/
|
|
||||||
void build_eval_system() {
|
void build_eval_system() {
|
||||||
using namespace bootstrap;
|
using namespace bootstrap;
|
||||||
m_engine.add_reserved_word("auto");
|
m_engine.add_reserved_word("auto");
|
||||||
@@ -334,6 +330,13 @@ namespace chaiscript
|
|||||||
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_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_scripting_objects, boost::ref(m_engine)), "get_objects");
|
||||||
|
|
||||||
|
|
||||||
|
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&chaiscript::detail::Dispatch_Engine::call_exists, boost::ref(m_engine), _1))),
|
||||||
|
"call_exists");
|
||||||
|
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(boost::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), _1, _2, boost::ref(m_engine.conversions()))), "call");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
|
|
||||||
@@ -355,9 +358,8 @@ namespace chaiscript
|
|||||||
do_eval(chaiscript_prelude, "standard prelude");
|
do_eval(chaiscript_prelude, "standard prelude");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function for loading a file
|
/// Helper function for loading a file
|
||||||
*/
|
|
||||||
std::string load_file(const std::string &t_filename) {
|
std::string load_file(const std::string &t_filename) {
|
||||||
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
||||||
|
|
||||||
@@ -413,19 +415,20 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
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::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
|
|
||||||
if (m_used_files.count(appendedpath) == 0)
|
if (m_used_files.count(appendedpath) == 0)
|
||||||
{
|
{
|
||||||
m_used_files.insert(appendedpath);
|
|
||||||
l2.unlock();
|
l2.unlock();
|
||||||
eval_file(appendedpath);
|
eval_file(appendedpath);
|
||||||
}
|
l2.lock();
|
||||||
|
m_used_files.insert(appendedpath);
|
||||||
|
}
|
||||||
|
|
||||||
return; // return, we loaded it, or it was already loaded
|
return; // return, we loaded it, or it was already loaded
|
||||||
} catch (const exception::file_not_found_error &) {
|
} catch (const exception::file_not_found_error &) {
|
||||||
if (i == m_usepaths.size() - 1)
|
if (i == m_usepaths.size() - 1)
|
||||||
{
|
{
|
||||||
throw exception::file_not_found_error(t_filename);
|
throw exception::file_not_found_error(t_filename);
|
||||||
}
|
}
|
||||||
@@ -446,6 +449,17 @@ namespace chaiscript
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Adds a mutable 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_name Name of the value to add
|
||||||
|
/// \warning The user is responsible for making sure the object is thread-safe if necessary
|
||||||
|
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
||||||
|
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
|
{
|
||||||
|
m_engine.add_global(t_bv, t_name);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
/// \brief Represents the current state of the ChaiScript system. State and be saved and restored
|
||||||
/// \sa ChaiScript::get_state
|
/// \sa ChaiScript::get_state
|
||||||
/// \sa ChaiScript::set_state
|
/// \sa ChaiScript::set_state
|
||||||
@@ -456,8 +470,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:
|
||||||
///
|
///
|
||||||
@@ -478,6 +496,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:
|
||||||
@@ -497,7 +519,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
|
||||||
@@ -641,7 +679,7 @@ namespace chaiscript
|
|||||||
return do_eval(t_script);
|
return do_eval(t_script);
|
||||||
} catch (Boxed_Value &bv) {
|
} catch (Boxed_Value &bv) {
|
||||||
if (t_handler) {
|
if (t_handler) {
|
||||||
t_handler->handle(bv);
|
t_handler->handle(bv, m_engine);
|
||||||
}
|
}
|
||||||
throw bv;
|
throw bv;
|
||||||
}
|
}
|
||||||
@@ -652,6 +690,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
|
||||||
///
|
///
|
||||||
@@ -659,33 +699,43 @@ 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 m_engine.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, m_engine);
|
||||||
}
|
}
|
||||||
throw bv;
|
throw bv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||||
|
template<typename Type>
|
||||||
|
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||||
|
{
|
||||||
|
return m_engine.boxed_cast<Type>(bv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Evaluates a string.
|
/// \brief Evaluates a string.
|
||||||
///
|
///
|
||||||
/// \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, m_engine);
|
||||||
}
|
}
|
||||||
throw bv;
|
throw bv;
|
||||||
}
|
}
|
||||||
@@ -701,7 +751,7 @@ namespace chaiscript
|
|||||||
return do_eval(load_file(t_filename), t_filename);
|
return do_eval(load_file(t_filename), t_filename);
|
||||||
} catch (Boxed_Value &bv) {
|
} catch (Boxed_Value &bv) {
|
||||||
if (t_handler) {
|
if (t_handler) {
|
||||||
t_handler->handle(bv);
|
t_handler->handle(bv, m_engine);
|
||||||
}
|
}
|
||||||
throw bv;
|
throw bv;
|
||||||
}
|
}
|
||||||
@@ -718,10 +768,10 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||||
try {
|
try {
|
||||||
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
||||||
} catch (Boxed_Value &bv) {
|
} catch (Boxed_Value &bv) {
|
||||||
if (t_handler) {
|
if (t_handler) {
|
||||||
t_handler->handle(bv);
|
t_handler->handle(bv, m_engine);
|
||||||
}
|
}
|
||||||
throw bv;
|
throw bv;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PARSER_HPP_
|
#ifndef CHAISCRIPT_PARSER_HPP_
|
||||||
@@ -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
|
||||||
};
|
};
|
||||||
@@ -175,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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,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;
|
||||||
@@ -371,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;
|
||||||
@@ -386,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
|
||||||
*/
|
*/
|
||||||
@@ -419,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
|
||||||
*/
|
*/
|
||||||
@@ -435,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, 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))) {
|
||||||
@@ -458,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, 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, 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, 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, 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;
|
||||||
@@ -553,13 +751,13 @@ namespace chaiscript
|
|||||||
if (*start == '`') {
|
if (*start == '`') {
|
||||||
//Id Literal
|
//Id Literal
|
||||||
std::string match(start+1, m_input_pos-1);
|
std::string match(start+1, m_input_pos-1);
|
||||||
AST_NodePtr t(new eval::Id_AST_Node(match, AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Id_AST_Node(match, 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 {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Id_AST_Node(match, AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Id_AST_Node(match, 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;
|
||||||
}
|
}
|
||||||
@@ -592,7 +790,7 @@ namespace chaiscript
|
|||||||
} while (Symbol("#"));
|
} while (Symbol("#"));
|
||||||
|
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Annotation_AST_Node(match, AST_Node_Type::Annotation, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Annotation_AST_Node(match, 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;
|
||||||
}
|
}
|
||||||
@@ -667,13 +865,13 @@ namespace chaiscript
|
|||||||
if (is_interpolated) {
|
if (is_interpolated) {
|
||||||
//If we've seen previous interpolation, add on instead of making a new one
|
//If we've seen previous interpolation, add on instead of making a new one
|
||||||
|
|
||||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
|
|
||||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,17 +891,17 @@ namespace chaiscript
|
|||||||
|
|
||||||
size_t tostr_stack_top = m_match_stack.size();
|
size_t tostr_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
AST_NodePtr tostr(new eval::Id_AST_Node("to_string", AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr tostr(new eval::Id_AST_Node("to_string", m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(tostr);
|
m_match_stack.push_back(tostr);
|
||||||
|
|
||||||
size_t ev_stack_top = m_match_stack.size();
|
size_t ev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
AST_NodePtr ev(new eval::Id_AST_Node("eval", AST_Node_Type::Id, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr ev(new eval::Id_AST_Node("eval", m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(ev);
|
m_match_stack.push_back(ev);
|
||||||
|
|
||||||
size_t arg_stack_top = m_match_stack.size();
|
size_t arg_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
|
|
||||||
build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), arg_stack_top);
|
build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), arg_stack_top);
|
||||||
@@ -761,13 +959,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_interpolated) {
|
if (is_interpolated) {
|
||||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
|
|
||||||
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, 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;
|
||||||
@@ -859,7 +1057,7 @@ namespace chaiscript
|
|||||||
is_escaped = false;
|
is_escaped = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, AST_Node_Type::Single_Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, 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;
|
||||||
}
|
}
|
||||||
@@ -898,7 +1096,7 @@ namespace chaiscript
|
|||||||
int prev_line = m_line;
|
int prev_line = m_line;
|
||||||
if (Char_(t_c)) {
|
if (Char_(t_c)) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Char_AST_Node(match, AST_Node_Type::Char, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Char_AST_Node(match, 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;
|
||||||
}
|
}
|
||||||
@@ -950,7 +1148,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if ( t_capture && retval ) {
|
if ( t_capture && retval ) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Str_AST_Node(match, AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@@ -998,7 +1196,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if ( t_capture && retval ) {
|
if ( t_capture && retval ) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Str_AST_Node(match, AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||||
m_match_stack.push_back(t);
|
m_match_stack.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1038,7 +1236,7 @@ namespace chaiscript
|
|||||||
int prev_line = m_line;
|
int prev_line = m_line;
|
||||||
if (Eol_()) {
|
if (Eol_()) {
|
||||||
std::string match(start, m_input_pos);
|
std::string match(start, m_input_pos);
|
||||||
AST_NodePtr t(new eval::Eol_AST_Node(match, AST_Node_Type::Eol, m_filename, prev_line, prev_col, m_line, m_col));
|
AST_NodePtr t(new eval::Eol_AST_Node(match, 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;
|
||||||
}
|
}
|
||||||
@@ -1308,7 +1506,7 @@ namespace chaiscript
|
|||||||
if (Keyword("else", true)) {
|
if (Keyword("else", true)) {
|
||||||
if (Keyword("if")) {
|
if (Keyword("if")) {
|
||||||
AST_NodePtr back(m_match_stack.back());
|
AST_NodePtr back(m_match_stack.back());
|
||||||
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if", back->identifier));
|
m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if"));
|
||||||
m_match_stack.back()->start = back->start;
|
m_match_stack.back()->start = back->start;
|
||||||
m_match_stack.back()->end = back->end;
|
m_match_stack.back()->end = back->end;
|
||||||
m_match_stack.back()->children = back->children;
|
m_match_stack.back()->children = back->children;
|
||||||
@@ -1376,18 +1574,40 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the C-style for conditions from input
|
* Reads the C-style for conditions from input
|
||||||
*/
|
*/
|
||||||
bool For_Guards() {
|
bool For_Guards() {
|
||||||
Equation();
|
if (!(Equation() && Eol()))
|
||||||
|
{
|
||||||
|
if (!Eol())
|
||||||
|
{
|
||||||
|
throw exception::eval_error("'for' loop initial statment missing", File_Position(m_line, m_col), *m_filename);
|
||||||
|
} else {
|
||||||
|
AST_NodePtr t(new eval::Noop_AST_Node());
|
||||||
|
m_match_stack.push_back(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Char(';') && Operator() && Char(';') && Equation()) {
|
if (!(Equation() && Eol()))
|
||||||
return true;
|
{
|
||||||
|
if (!Eol())
|
||||||
|
{
|
||||||
|
throw exception::eval_error("'for' loop condition missing", File_Position(m_line, m_col), *m_filename);
|
||||||
|
} else {
|
||||||
|
AST_NodePtr t(new eval::Noop_AST_Node());
|
||||||
|
m_match_stack.push_back(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw exception::eval_error("Incomplete conditions in 'for' loop", File_Position(m_line, m_col), *m_filename);
|
if (!Equation())
|
||||||
|
{
|
||||||
|
AST_NodePtr t(new eval::Noop_AST_Node());
|
||||||
|
m_match_stack.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1483,10 +1703,10 @@ namespace chaiscript
|
|||||||
while (Eol()) {}
|
while (Eol()) {}
|
||||||
|
|
||||||
while (Case()) {
|
while (Case()) {
|
||||||
while (Eol());
|
while (Eol()) { } // eat
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol()) { } // eat
|
||||||
|
|
||||||
if (!Char('}')) {
|
if (!Char('}')) {
|
||||||
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
||||||
@@ -1562,6 +1782,23 @@ namespace chaiscript
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a continue statement from input
|
||||||
|
*/
|
||||||
|
bool Continue() {
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
size_t prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
|
if (Keyword("continue")) {
|
||||||
|
retval = true;
|
||||||
|
|
||||||
|
build_match(AST_NodePtr(new eval::Continue_AST_Node()), prev_stack_top);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a dot expression(member access), then proceeds to check if it's a function or array call
|
* Reads a dot expression(member access), then proceeds to check if it's a function or array call
|
||||||
*/
|
*/
|
||||||
@@ -1672,7 +1909,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;
|
||||||
@@ -1690,7 +1927,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) {
|
||||||
@@ -2059,6 +2296,14 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
saw_eol = false;
|
saw_eol = false;
|
||||||
}
|
}
|
||||||
|
else if (Continue()) {
|
||||||
|
if (!saw_eol) {
|
||||||
|
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||||
|
}
|
||||||
|
has_more = true;
|
||||||
|
retval = true;
|
||||||
|
saw_eol = false;
|
||||||
|
}
|
||||||
else if (Equation()) {
|
else if (Equation()) {
|
||||||
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,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
#ifndef CHAISCRIPT_PRELUDE_HPP_
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
Copyright 2009-2012 Jason Turner and Jonathan Turner. All Rights Reserved.
|
Copyright 2009-2014 Jason Turner
|
||||||
|
Copyright 2009-2012 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:
|
||||||
|
83
readme.md
Normal file
83
readme.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
ChaiScript
|
||||||
|
|
||||||
|
http://www.chaiscript.com
|
||||||
|
|
||||||
|
(c) 2009-2012 Jonathan Turner
|
||||||
|
(c) 2009-2014 Jason 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-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.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 @@
|
|||||||
|
Current Version: 4.3.0
|
||||||
|
|
||||||
|
Note: this is scheduled to be the last release that requires boost, new releases after this will require a C++11 compiler.
|
||||||
|
|
||||||
|
### Changes since 4.2.0
|
||||||
|
* Enhanced unit tests
|
||||||
|
* Add `continue` statement, fix various use cases for `for` loops
|
||||||
|
* Fix use of suffixed numbers in vector initialization
|
||||||
|
* Code cleanups
|
||||||
|
* Eliminate global data, which makes code more portable and thread safe
|
||||||
|
* Fix issue #79
|
||||||
|
* Merge pretty_print fixes from @mgee #82
|
||||||
|
* Compiler warning fixes for latest compiler releases
|
||||||
|
* Fix threading problems
|
||||||
|
* Fix linking error on MacOS Mavericks #88
|
||||||
|
* Allow non-const globals
|
||||||
|
* Make sure user cannot name a variable with `::` in it #91
|
||||||
|
* Fix various string / map / vector `size` and `count` calls for compilers which have weird overloads for them. #90 #93 #95
|
||||||
|
* Make module search path relative to the currently running executable
|
||||||
|
* Build and work with wstring windows builds
|
||||||
|
|
||||||
|
### Changes since 4.1.1
|
||||||
|
* Add support for automatic conversion of arithmetic types when possible
|
||||||
|
and when no ambiguous method dispatch exists.
|
||||||
|
|
||||||
|
### Changes since 4.1.0
|
||||||
|
* Fix missed gcc build error in 4.1.0
|
||||||
|
|
||||||
|
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
|
Changes since 3.1.0
|
||||||
* svenstaro: Unused variables and CMake consistency fixes
|
* svenstaro: Unused variables and CMake consistency fixes
|
||||||
* Added support for returning pointers from functions (#13)
|
* Added support for returning pointers from functions (#13)
|
||||||
@@ -17,7 +50,7 @@ Changes since 3.1.0
|
|||||||
* Increased unit tests to 161
|
* Increased unit tests to 161
|
||||||
* Performance enhancements
|
* Performance enhancements
|
||||||
|
|
||||||
Changes since 3.0.0
|
### Changes since 3.0.0
|
||||||
* Numeric operations performance increased approximately 10x
|
* Numeric operations performance increased approximately 10x
|
||||||
* Looping operations performance increased up to 2x
|
* Looping operations performance increased up to 2x
|
||||||
* Engine start up time decreased
|
* Engine start up time decreased
|
||||||
@@ -26,8 +59,7 @@ Changes since 3.0.0
|
|||||||
uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
|
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++
|
* 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
|
||||||
* Fully integrate documentation with source code in doxygen style comments
|
* Fully integrate documentation with source code in doxygen style comments
|
||||||
* Unit tests increased from 114 to 137
|
* Unit tests increased from 114 to 137
|
||||||
|
@@ -9,7 +9,18 @@
|
|||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
void log(const std::string &msg)
|
void log(const std::string &msg)
|
||||||
@@ -43,9 +54,9 @@ struct System
|
|||||||
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
||||||
|
|
||||||
void add_callback(const std::string &t_name,
|
void add_callback(const std::string &t_name,
|
||||||
const chaiscript::Proxy_Function &t_func)
|
const boost::function<std::string (const std::string &)> &t_func)
|
||||||
{
|
{
|
||||||
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func);
|
m_callbacks[t_name] = t_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -141,7 +152,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())");
|
||||||
|
@@ -5,7 +5,7 @@ def for_each(container, function)
|
|||||||
while (!range.empty())
|
while (!range.empty())
|
||||||
{
|
{
|
||||||
function(range.front());
|
function(range.front());
|
||||||
range.popFront();
|
range.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
112
src/main.cpp
112
src/main.cpp
@@ -1,7 +1,7 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -30,6 +30,86 @@ void add_history(const char*){}
|
|||||||
void using_history(){}
|
void using_history(){}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void *cast_module_symbol(std::string (*t_path)())
|
||||||
|
{
|
||||||
|
union cast_union
|
||||||
|
{
|
||||||
|
std::string (*in_ptr)();
|
||||||
|
void *out_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
cast_union c;
|
||||||
|
c.in_ptr = t_path;
|
||||||
|
return c.out_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string default_search_path()
|
||||||
|
{
|
||||||
|
#ifdef BOOST_WINDOWS // force no unicode
|
||||||
|
CHAR path[4096];
|
||||||
|
int size = GetModuleFileNameA(0, path, sizeof(path)-1);
|
||||||
|
|
||||||
|
std::string exepath(path, size);
|
||||||
|
|
||||||
|
size_t secondtolastslash = exepath.rfind('\\', exepath.rfind('\\') - 1);
|
||||||
|
if (secondtolastslash != std::string::npos)
|
||||||
|
{
|
||||||
|
return exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\";
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
std::string exepath;
|
||||||
|
|
||||||
|
std::vector<char> buf(2048);
|
||||||
|
ssize_t size = -1;
|
||||||
|
|
||||||
|
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||||
|
{
|
||||||
|
exepath = std::string(&buf.front(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exepath.empty())
|
||||||
|
{
|
||||||
|
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||||
|
{
|
||||||
|
exepath = std::string(&buf.front(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exepath.empty())
|
||||||
|
{
|
||||||
|
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||||
|
{
|
||||||
|
exepath = std::string(&buf.front(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exepath.empty())
|
||||||
|
{
|
||||||
|
Dl_info rInfo;
|
||||||
|
memset( &rInfo, 0, sizeof(rInfo) );
|
||||||
|
if ( !dladdr(cast_module_symbol(&default_search_path), &rInfo) || !rInfo.dli_fname ) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
exepath = std::string(rInfo.dli_fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secondtolastslash = exepath.rfind('/', exepath.rfind('/') - 1);
|
||||||
|
if (secondtolastslash != std::string::npos)
|
||||||
|
{
|
||||||
|
return exepath.substr(0, secondtolastslash) + "/lib/chaiscript/";
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void help(int n) {
|
void help(int n) {
|
||||||
if ( n >= 0 ) {
|
if ( n >= 0 ) {
|
||||||
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
|
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
|
||||||
@@ -80,7 +160,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,6 +247,8 @@ int main(int argc, char *argv[])
|
|||||||
usepaths.push_back(usepath);
|
usepaths.push_back(usepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string searchpath = default_search_path();
|
||||||
|
modulepaths.push_back(searchpath);
|
||||||
modulepaths.push_back("");
|
modulepaths.push_back("");
|
||||||
if (modulepath)
|
if (modulepath)
|
||||||
{
|
{
|
||||||
@@ -219,18 +312,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,3 +1,9 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <chaiscript/utility/utility.hpp>
|
#include <chaiscript/utility/utility.hpp>
|
||||||
@@ -18,7 +24,12 @@ bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
|||||||
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||||
if (pf)
|
if (pf)
|
||||||
{
|
{
|
||||||
return pf->get_parse_tree();
|
if (pf->get_parse_tree())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -42,6 +53,12 @@ chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
|
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflection()
|
||||||
{
|
{
|
||||||
chaiscript::ModulePtr m(new chaiscript::Module());
|
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||||
@@ -90,6 +107,11 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
|
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <chaiscript/chaiscript.hpp>
|
#include <chaiscript/chaiscript.hpp>
|
||||||
#include <list>
|
#include <list>
|
||||||
@@ -10,11 +15,19 @@
|
|||||||
#pragma warning(disable : 4190)
|
#pragma warning(disable : 4190)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
|
#endif
|
||||||
|
|
||||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||||
{
|
{
|
||||||
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@@ -5,12 +5,19 @@
|
|||||||
class TestBaseType
|
class TestBaseType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestBaseType() {}
|
TestBaseType() : val(10), const_val(15) { }
|
||||||
TestBaseType(int) {}
|
TestBaseType(int) : val(10), const_val(15) {}
|
||||||
TestBaseType(int *) {}
|
TestBaseType(int *) : val(10), const_val(15) {}
|
||||||
virtual ~TestBaseType() {}
|
virtual ~TestBaseType() {}
|
||||||
virtual int func() { return 0; }
|
virtual int func() { return 0; }
|
||||||
|
|
||||||
|
const TestBaseType &constMe() const { return *this; }
|
||||||
|
|
||||||
|
int val;
|
||||||
|
const int const_val;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TestBaseType &operator=(const TestBaseType &);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TestEnum
|
enum TestEnum
|
||||||
@@ -28,6 +35,9 @@ class TestDerivedType : public TestBaseType
|
|||||||
public:
|
public:
|
||||||
virtual ~TestDerivedType() {}
|
virtual ~TestDerivedType() {}
|
||||||
virtual int func() { return 1; }
|
virtual int func() { return 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TestDerivedType &operator=(const TestDerivedType &);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string hello_world()
|
std::string hello_world()
|
||||||
@@ -47,6 +57,10 @@ int *get_new_int()
|
|||||||
#pragma warning(disable : 4190)
|
#pragma warning(disable : 4190)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
|
#endif
|
||||||
|
|
||||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
|
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_module()
|
||||||
{
|
{
|
||||||
@@ -68,6 +82,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
|||||||
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
|
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
|
||||||
|
|
||||||
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
||||||
|
m->add(chaiscript::fun(&TestBaseType::val), "val");
|
||||||
|
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
|
||||||
|
|
||||||
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
m->add(chaiscript::fun(&get_new_int), "get_new_int");
|
||||||
|
|
||||||
@@ -76,12 +92,17 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
|||||||
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
|
m->add(chaiscript::user_type<TestEnum>(), "TestEnum");
|
||||||
|
|
||||||
m->add(chaiscript::fun(&to_int), "to_int");
|
m->add(chaiscript::fun(&to_int), "to_int");
|
||||||
|
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
|
||||||
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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);
|
|
||||||
}
|
|
58
unittests/arithmetic_conversions_test.cpp
Normal file
58
unittests/arithmetic_conversions_test.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Tests to make sure that type conversions happen only when they should
|
||||||
|
|
||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
|
||||||
|
void f1(int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void f4(std::string)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void f2(int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void f3(double)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
|
chai.add(chaiscript::fun(&f1), "f1");
|
||||||
|
chai.add(chaiscript::fun(&f2), "f2");
|
||||||
|
chai.add(chaiscript::fun(&f3), "f2");
|
||||||
|
chai.add(chaiscript::fun(&f1), "f3");
|
||||||
|
chai.add(chaiscript::fun(&f4), "f3");
|
||||||
|
|
||||||
|
// no overloads
|
||||||
|
chai.eval("f1(0)");
|
||||||
|
chai.eval("f1(0l)");
|
||||||
|
chai.eval("f1(0ul)");
|
||||||
|
chai.eval("f1(0ll)");
|
||||||
|
chai.eval("f1(0ull)");
|
||||||
|
chai.eval("f1(0.0)");
|
||||||
|
chai.eval("f1(0.0f)");
|
||||||
|
chai.eval("f1(0.0l)");
|
||||||
|
|
||||||
|
// expected overloads
|
||||||
|
chai.eval("f2(1)");
|
||||||
|
chai.eval("f2(1.0)");
|
||||||
|
|
||||||
|
// 1 non-arithmetic overload
|
||||||
|
chai.eval("f2(1.0)");
|
||||||
|
|
||||||
|
// this is the one call we expect to fail
|
||||||
|
try {
|
||||||
|
chai.eval("f2(1.0l)");
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the last one did not throw, we failed
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
11
unittests/break_for.chai
Normal file
11
unittests/break_for.chai
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var j = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
if (i == 5) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
j = i
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(4, j);
|
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;
|
||||||
|
|
||||||
|
}
|
16
unittests/continue_for.chai
Normal file
16
unittests/continue_for.chai
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
var j = 0;
|
||||||
|
var k = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
j = i
|
||||||
|
if (i > 5)
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
k = i
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(5, k);
|
||||||
|
assert_equal(9, j);
|
14
unittests/continue_while.chai
Normal file
14
unittests/continue_while.chai
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
var i = 0
|
||||||
|
var j = 0
|
||||||
|
|
||||||
|
while (i < 10) {
|
||||||
|
if (++i > 5)
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
j = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(10, i);
|
||||||
|
assert_equal(5, j);
|
@@ -9,7 +9,7 @@ int test_generic()
|
|||||||
try {
|
try {
|
||||||
chai.eval("throw(runtime_error(\"error\"));");
|
chai.eval("throw(runtime_error(\"error\"));");
|
||||||
} catch (const chaiscript::Boxed_Value &bv) {
|
} catch (const chaiscript::Boxed_Value &bv) {
|
||||||
const std::exception &e = chaiscript::boxed_cast<const std::exception &>(bv);
|
const std::exception &e = chai.boxed_cast<const std::exception &>(bv);
|
||||||
if (e.what() == std::string("error"))
|
if (e.what() == std::string("error"))
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -5,3 +5,57 @@ for (var i = 0; i < 5; ++i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert_equal([0,1,2,3,4], ret);
|
assert_equal([0,1,2,3,4], ret);
|
||||||
|
|
||||||
|
|
||||||
|
var j = 0;
|
||||||
|
|
||||||
|
for (;j<10; ++j)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(10, j);
|
||||||
|
|
||||||
|
|
||||||
|
var k = 0;
|
||||||
|
|
||||||
|
for (;k<10; )
|
||||||
|
{
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(10, k);
|
||||||
|
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var l = 0;
|
||||||
|
|
||||||
|
for (;;l = 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(0, l)
|
||||||
|
|
||||||
|
def isNotFive(x)
|
||||||
|
{
|
||||||
|
if (x != 5)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var m;
|
||||||
|
|
||||||
|
for (m = 0; isNotFive(m); m = m + 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal(5, m);
|
||||||
|
|
||||||
|
@@ -6,3 +6,12 @@ var t = TestDerivedType();
|
|||||||
assert_equal(t0.func(), 0);
|
assert_equal(t0.func(), 0);
|
||||||
assert_equal(t.func(), 1);
|
assert_equal(t.func(), 1);
|
||||||
|
|
||||||
|
assert_equal(10, t0.val);
|
||||||
|
assert_equal(15, t0.const_val);
|
||||||
|
|
||||||
|
assert_equal(10, t.val);
|
||||||
|
assert_equal(15, t.const_val);
|
||||||
|
|
||||||
|
t.val = 23;
|
||||||
|
assert_equal(23, t.val)
|
||||||
|
|
||||||
|
88
unittests/integer_literal_test.cpp
Normal file
88
unittests/integer_literal_test.cpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#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,2 +1,4 @@
|
|||||||
load_module("test_module")
|
load_module("test_module")
|
||||||
assert_equal("Hello World", hello_world());
|
assert_equal("Hello World", hello_world());
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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"])
|
||||||
|
5
unittests/map_count.chai
Normal file
5
unittests/map_count.chai
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
assert_equal(1, ["a":1].count("a"))
|
||||||
|
assert_equal(0, ["A":1].count("a"))
|
||||||
|
|
||||||
|
|
11
unittests/member_variable_access.chai
Normal file
11
unittests/member_variable_access.chai
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
load_module("test_module")
|
||||||
|
|
||||||
|
var t0 = TestBaseType()
|
||||||
|
t0.val = 13
|
||||||
|
|
||||||
|
assert_equal(15, t0.const_val)
|
||||||
|
assert_equal(13, t0.val)
|
||||||
|
assert_equal(15, t0.constMe().const_val)
|
||||||
|
assert_equal(13, t0.constMe().val)
|
||||||
|
|
||||||
|
|
96
unittests/multithreaded_test.cpp
Normal file
96
unittests/multithreaded_test.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#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)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
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() + ");");
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
std::cout << "exception: " << e.what() << " thread: " << id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
boost::thread_group 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.create_thread(boost::bind(&do_work, boost::ref(chai), i));
|
||||||
|
}
|
||||||
|
|
||||||
|
threads.join_all();
|
||||||
|
|
||||||
|
|
||||||
|
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()))
|
||||||
|
|
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;
|
||||||
|
}
|
||||||
|
}
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
unittests/string_size.chai
Normal file
2
unittests/string_size.chai
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
assert_equal(true, "".empty())
|
||||||
|
assert_equal(3, "123".size())
|
1
unittests/string_substr.chai
Normal file
1
unittests/string_substr.chai
Normal file
@@ -0,0 +1 @@
|
|||||||
|
assert_equal("3ab", "123abab".substr(2,3))
|
3
unittests/vector_of_suffixed_numbers.chai
Normal file
3
unittests/vector_of_suffixed_numbers.chai
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
var x = [1, 2u, 3.0l]
|
||||||
|
assert_equal(3.0l, x[2])
|
||||||
|
assert_equal(2u, x[1])
|
Reference in New Issue
Block a user