Add crashes and fixes found during fuzzy testing
* Let unhandled exceptions propogate to user * Report eval_error when break statement is not in loop * Fix handling of 0 length scripts closes #193 * Don't crash on arity mismatch - Specifically affects the case where no overloads exist for a given function * Fix error printing for `bind` calls * Handle unexpected continue statement * Check arity during bind * Don't allow arith conversion on variadic function * Correct `bind` parameter match count * Add in expected Boxed_Value exception cases * Check access to AST, don't allow `;` in func def * Don't attempt arithmetic unary & call * Don't crash on 0 param call to `bind` * Catch errors during member function dispatch * Properly handle type of const bool &
This commit is contained in:
@@ -14,13 +14,14 @@ env:
|
|||||||
before_install:
|
before_install:
|
||||||
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
|
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
|
||||||
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
|
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
|
||||||
|
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
|
||||||
- sudo pip install cpp-coveralls
|
- sudo pip install cpp-coveralls
|
||||||
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get install -qq g++-$GCC_VER
|
- sudo apt-get install -qq g++-$GCC_VER
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi
|
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi
|
||||||
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi
|
- if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi
|
||||||
- make test
|
- make test
|
||||||
- if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
|
- if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi
|
||||||
|
@@ -18,6 +18,7 @@ option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE)
|
|||||||
|
|
||||||
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
option(BUILD_MODULES "Build Extra Modules (stl)" TRUE)
|
||||||
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||||
|
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
|
||||||
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
||||||
|
|
||||||
mark_as_advanced(USE_STD_MAKE_SHARED)
|
mark_as_advanced(USE_STD_MAKE_SHARED)
|
||||||
@@ -269,9 +270,51 @@ if(BUILD_MODULES)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||||
|
|
||||||
list(SORT UNIT_TESTS)
|
list(SORT UNIT_TESTS)
|
||||||
|
|
||||||
|
|
||||||
|
if (RUN_FUZZY_TESTS)
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
file(GLOB FUZZY_CRASH_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/id*)
|
||||||
|
list(SORT FUZZY_CRASH_TESTS)
|
||||||
|
|
||||||
|
file(GLOB FUZZY_EXCEPTION_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/id*)
|
||||||
|
list(SORT FUZZY_EXCEPTION_TESTS)
|
||||||
|
|
||||||
|
|
||||||
|
foreach(filename ${FUZZY_CRASH_TESTS})
|
||||||
|
message(STATUS "Adding test ${filename}")
|
||||||
|
add_test(${filename} chai "-e" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_property(TEST ${FUZZY_CRASH_TESTS}
|
||||||
|
PROPERTY ENVIRONMENT
|
||||||
|
"CHAI_USE_PATH=${CMAKE_BINARY_DIR}/unittests/"
|
||||||
|
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(filename ${FUZZY_EXCEPTION_TESTS})
|
||||||
|
message(STATUS "Adding test ${filename}")
|
||||||
|
add_test(${filename} chai "--exception" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_property(TEST ${FUZZY_EXCEPTION_TESTS}
|
||||||
|
PROPERTY ENVIRONMENT
|
||||||
|
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||||
|
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||||
|
)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
|
|
||||||
# Add catch tests macro
|
# Add catch tests macro
|
||||||
|
@@ -304,13 +304,17 @@ namespace chaiscript
|
|||||||
/// the remaining parameters are the args to bind into the result
|
/// the remaining parameters are the args to bind into the result
|
||||||
static Boxed_Value bind_function(const std::vector<Boxed_Value> ¶ms)
|
static Boxed_Value bind_function(const std::vector<Boxed_Value> ¶ms)
|
||||||
{
|
{
|
||||||
if (params.size() < 2)
|
if (params.empty()) {
|
||||||
{
|
throw exception::arity_error(0, 1);
|
||||||
throw exception::arity_error(static_cast<int>(params.size()), 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||||
|
|
||||||
|
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1)
|
||||||
|
{
|
||||||
|
throw exception::arity_error(static_cast<int>(params.size()), f->get_arity());
|
||||||
|
}
|
||||||
|
|
||||||
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
|
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(std::move(f),
|
||||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "../chaiscript_defines.hpp"
|
#include "../chaiscript_defines.hpp"
|
||||||
#include "../chaiscript_threading.hpp"
|
#include "../chaiscript_threading.hpp"
|
||||||
|
#include "bad_boxed_cast.hpp"
|
||||||
#include "boxed_cast.hpp"
|
#include "boxed_cast.hpp"
|
||||||
#include "boxed_cast_helper.hpp"
|
#include "boxed_cast_helper.hpp"
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
@@ -873,7 +874,14 @@ namespace chaiscript
|
|||||||
std::vector<Boxed_Value> remaining_params{l_params.begin() + l_num_params, l_params.end()};
|
std::vector<Boxed_Value> remaining_params{l_params.begin() + l_num_params, l_params.end()};
|
||||||
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
|
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
|
||||||
if (!remaining_params.empty() || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
|
if (!remaining_params.empty() || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
|
||||||
return (*boxed_cast<const dispatch::Proxy_Function_Base *>(bv))(remaining_params, l_conversions);
|
auto func = boxed_cast<std::shared_ptr<const dispatch::Proxy_Function_Base>>(bv);
|
||||||
|
try {
|
||||||
|
return (*func)(remaining_params, l_conversions);
|
||||||
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
||||||
|
} catch (const chaiscript::exception::arity_error &) {
|
||||||
|
} catch (const chaiscript::exception::guard_error &) {
|
||||||
|
}
|
||||||
|
throw chaiscript::exception::dispatch_error(remaining_params, std::vector<Const_Proxy_Function>{func});
|
||||||
} else {
|
} else {
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
|
@@ -149,7 +149,11 @@ namespace chaiscript
|
|||||||
|
|
||||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||||
{
|
{
|
||||||
return do_call(params, t_conversions);
|
if (m_arity < 0 || size_t(m_arity) == params.size()) {
|
||||||
|
return do_call(params, t_conversions);
|
||||||
|
} else {
|
||||||
|
throw exception::arity_error(static_cast<int>(params.size()), m_arity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector containing all of the types of the parameters the function returns/takes
|
/// Returns a vector containing all of the types of the parameters the function returns/takes
|
||||||
@@ -420,17 +424,11 @@ namespace chaiscript
|
|||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||||
{
|
{
|
||||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
|
||||||
{
|
{
|
||||||
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
|
return m_f(params);
|
||||||
{
|
|
||||||
return m_f(params);
|
|
||||||
} else {
|
|
||||||
throw exception::guard_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw exception::arity_error(static_cast<int>(params.size()), m_arity);
|
throw exception::guard_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,19 +726,14 @@ namespace chaiscript
|
|||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||||
{
|
{
|
||||||
if (params.size() == 1)
|
const Boxed_Value &bv = params[0];
|
||||||
|
if (bv.is_const())
|
||||||
{
|
{
|
||||||
const Boxed_Value &bv = params[0];
|
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
||||||
if (bv.is_const())
|
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||||
{
|
|
||||||
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
|
|
||||||
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
|
||||||
} else {
|
|
||||||
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
|
||||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
Class *o = boxed_cast<Class *>(bv, &t_conversions);
|
||||||
|
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,6 +780,9 @@ namespace chaiscript
|
|||||||
const Type_Conversions &t_conversions)
|
const Type_Conversions &t_conversions)
|
||||||
{
|
{
|
||||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||||
|
|
||||||
|
if (t_func->get_arity() == -1) return false;
|
||||||
|
|
||||||
assert(plist.size() == types.size() - 1);
|
assert(plist.size() == types.size() - 1);
|
||||||
|
|
||||||
return std::mismatch(plist.begin(), plist.end(),
|
return std::mismatch(plist.begin(), plist.end(),
|
||||||
|
@@ -29,7 +29,7 @@ namespace chaiscript
|
|||||||
class Type_Info
|
class Type_Info
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||||
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||||
@@ -38,7 +38,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAISCRIPT_CONSTEXPR Type_Info()
|
CHAISCRIPT_CONSTEXPR Type_Info()
|
||||||
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
||||||
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||||
m_is_void(false), m_is_arithmetic(false),
|
m_is_void(false), m_is_arithmetic(false),
|
||||||
@@ -134,13 +134,13 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
static Type_Info get()
|
static Type_Info get()
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
(std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
|
(std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
|
||||||
&& !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
&& !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(T),
|
&typeid(T),
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(typename Bare_Type<T>::type));
|
||||||
}
|
}
|
||||||
@@ -151,11 +151,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
static Type_Info get()
|
static Type_Info get()
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(std::shared_ptr<T> ),
|
&typeid(std::shared_ptr<T> ),
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(typename Bare_Type<T>::type));
|
||||||
}
|
}
|
||||||
@@ -166,11 +166,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
static Type_Info get()
|
static Type_Info get()
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(const std::shared_ptr<T> &),
|
&typeid(const std::shared_ptr<T> &),
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(typename Bare_Type<T>::type));
|
||||||
}
|
}
|
||||||
@@ -181,11 +181,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
static Type_Info get()
|
static Type_Info get()
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(std::reference_wrapper<T> ),
|
&typeid(std::reference_wrapper<T> ),
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(typename Bare_Type<T>::type));
|
||||||
}
|
}
|
||||||
@@ -196,11 +196,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
static Type_Info get()
|
static Type_Info get()
|
||||||
{
|
{
|
||||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||||
std::is_void<T>::value,
|
std::is_void<T>::value,
|
||||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
|
||||||
&typeid(const std::reference_wrapper<T> &),
|
&typeid(const std::reference_wrapper<T> &),
|
||||||
&typeid(typename Bare_Type<T>::type));
|
&typeid(typename Bare_Type<T>::type));
|
||||||
}
|
}
|
||||||
|
@@ -276,10 +276,13 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string format_location(const T &t)
|
static std::string format_location(const T &t)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
if (t) {
|
||||||
oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
|
std::ostringstream oss;
|
||||||
|
oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
|
} else {
|
||||||
|
return "(internal)";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1117,11 +1117,22 @@ namespace chaiscript
|
|||||||
AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { }
|
AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { }
|
||||||
virtual ~File_AST_Node() {}
|
virtual ~File_AST_Node() {}
|
||||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||||
const auto num_children = children.size();
|
try {
|
||||||
for (size_t i = 0; i < num_children-1; ++i) {
|
const auto num_children = children.size();
|
||||||
children[i]->eval(t_ss);
|
|
||||||
|
if (num_children > 0) {
|
||||||
|
for (size_t i = 0; i < num_children-1; ++i) {
|
||||||
|
children[i]->eval(t_ss);
|
||||||
|
}
|
||||||
|
return children.back()->eval(t_ss);
|
||||||
|
} else {
|
||||||
|
return Boxed_Value();
|
||||||
|
}
|
||||||
|
} catch (const detail::Continue_Loop &) {
|
||||||
|
throw exception::eval_error("Unexpected `continue` statement outside of a loop");
|
||||||
|
} catch (const detail::Break_Loop &) {
|
||||||
|
throw exception::eval_error("Unexpected `break` statement outside of a loop");
|
||||||
}
|
}
|
||||||
return children.back()->eval(t_ss);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1158,7 +1169,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// short circuit arithmetic operations
|
// short circuit arithmetic operations
|
||||||
if (m_oper != Operators::invalid && bv.get_type_info().is_arithmetic())
|
if (m_oper != Operators::invalid && m_oper != Operators::bitwise_and && bv.get_type_info().is_arithmetic())
|
||||||
{
|
{
|
||||||
return Boxed_Number::do_oper(m_oper, bv);
|
return Boxed_Number::do_oper(m_oper, bv);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -194,6 +194,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
/// Returns the front-most AST node
|
/// Returns the front-most AST node
|
||||||
AST_NodePtr ast() const {
|
AST_NodePtr ast() const {
|
||||||
|
if (m_match_stack.empty()) throw exception::eval_error("Attempted to access AST of failed parse.");
|
||||||
return m_match_stack.front();
|
return m_match_stack.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +262,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
AST_NodePtr optimized_ast(bool t_optimize_blocks = false, bool t_optimize_returns = true) {
|
AST_NodePtr optimized_ast(bool t_optimize_blocks = false, bool t_optimize_returns = true) {
|
||||||
AST_NodePtr p = m_match_stack.front();
|
AST_NodePtr p = ast();
|
||||||
//Note, optimize_blocks is currently broken; it breaks stack management
|
//Note, optimize_blocks is currently broken; it breaks stack management
|
||||||
if (t_optimize_blocks) { optimize_blocks(p); }
|
if (t_optimize_blocks) { optimize_blocks(p); }
|
||||||
if (t_optimize_returns) { optimize_returns(p); }
|
if (t_optimize_returns) { optimize_returns(p); }
|
||||||
@@ -1208,37 +1209,32 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an end-of-line group from input, without skipping initial whitespace
|
/// Reads an end-of-line group from input, without skipping initial whitespace
|
||||||
bool Eol_() {
|
bool Eol_(const bool t_eos = false) {
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
if (has_more_input() && (Symbol_("\r\n") || Char_('\n'))) {
|
if (has_more_input() && (Symbol_("\r\n") || Char_('\n'))) {
|
||||||
retval = true;
|
retval = true;
|
||||||
++m_line;
|
++m_line;
|
||||||
m_col = 1;
|
m_col = 1;
|
||||||
} else if (has_more_input() && Char_(';')) {
|
} else if (has_more_input() && !t_eos && Char_(';')) {
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads (and potentially captures) an end-of-line group from input
|
/// Reads until the end of the current statement
|
||||||
bool Eol(const bool t_capture = false) {
|
bool Eos() {
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
if (!t_capture) {
|
return Eol_(true);
|
||||||
return Eol_();
|
}
|
||||||
} else {
|
|
||||||
const auto start = m_input_pos;
|
/// Reads (and potentially captures) an end-of-line group from input
|
||||||
const auto prev_col = m_col;
|
bool Eol() {
|
||||||
const auto prev_line = m_line;
|
SkipWS();
|
||||||
if (Eol_()) {
|
|
||||||
m_match_stack.push_back(make_node<eval::Eol_AST_Node>(std::string(start, m_input_pos), prev_line, prev_col));
|
return Eol_();
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a comma-separated list of values from input. Id's only, no types allowed
|
/// Reads a comma-separated list of values from input. Id's only, no types allowed
|
||||||
@@ -1441,7 +1437,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol()) {}
|
while (Eos()) {}
|
||||||
|
|
||||||
if (Char(':')) {
|
if (Char(':')) {
|
||||||
if (!Operator()) {
|
if (!Operator()) {
|
||||||
|
27
src/main.cpp
27
src/main.cpp
@@ -297,6 +297,8 @@ int main(int argc, char *argv[])
|
|||||||
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
|
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
|
||||||
chai.add(chaiscript::fun(&now), "now");
|
chai.add(chaiscript::fun(&now), "now");
|
||||||
|
|
||||||
|
bool eval_error_ok = false;
|
||||||
|
bool boxed_exception_ok = false;
|
||||||
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
if ( i == 0 && argc > 1 ) {
|
if ( i == 0 && argc > 1 ) {
|
||||||
@@ -327,6 +329,12 @@ int main(int argc, char *argv[])
|
|||||||
arg = "print(version())" ;
|
arg = "print(version())" ;
|
||||||
} else if ( arg == "-h" || arg == "--help" ) {
|
} else if ( arg == "-h" || arg == "--help" ) {
|
||||||
arg = "help(-1)";
|
arg = "help(-1)";
|
||||||
|
} else if ( arg == "-e" || arg == "--evalerrorok" ) {
|
||||||
|
eval_error_ok = true;
|
||||||
|
continue;
|
||||||
|
} else if ( arg == "--exception" ) {
|
||||||
|
boxed_exception_ok = true;
|
||||||
|
continue;
|
||||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
} else if ( arg == "-i" || arg == "--interactive" ) {
|
||||||
mode = eInteractive ;
|
mode = eInteractive ;
|
||||||
} else if ( arg.find('-') == 0 ) {
|
} else if ( arg.find('-') == 0 ) {
|
||||||
@@ -352,12 +360,23 @@ int main(int argc, char *argv[])
|
|||||||
catch (const chaiscript::exception::eval_error &ee) {
|
catch (const chaiscript::exception::eval_error &ee) {
|
||||||
std::cout << ee.pretty_print();
|
std::cout << ee.pretty_print();
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
return EXIT_FAILURE;
|
|
||||||
|
if (!eval_error_ok) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (const chaiscript::Boxed_Value &e) {
|
||||||
std::cout << e.what() << '\n';
|
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
|
||||||
return EXIT_FAILURE;
|
|
||||||
|
if (!boxed_exception_ok) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// catch (std::exception &e) {
|
||||||
|
// std::cout << e.what() << '\n';
|
||||||
|
// return EXIT_FAILURE;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
BIN
unittests/fuzzy_tests-2015-07-16.tar.bz2
Normal file
BIN
unittests/fuzzy_tests-2015-07-16.tar.bz2
Normal file
Binary file not shown.
@@ -5,33 +5,58 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
void test_type(const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void,
|
#ifdef CHAISCRIPT_MSVC
|
||||||
bool t_is_undef)
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4190 4640 28251 4702 6330)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wshadow"
|
||||||
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __llvm__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||||
|
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||||
|
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||||
|
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Type_Info objects generate expected results")
|
||||||
{
|
{
|
||||||
if (ti.is_const() == t_is_const
|
const auto test_type = [](const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void,
|
||||||
&& ti.is_pointer() == t_is_pointer
|
bool t_is_undef, bool t_is_arithmetic)
|
||||||
&& ti.is_reference() == t_is_reference
|
|
||||||
&& ti.is_void() == t_is_void
|
|
||||||
&& ti.is_undef() == t_is_undef)
|
|
||||||
{
|
{
|
||||||
return;
|
CHECK(ti.is_const() == t_is_const);
|
||||||
} else {
|
CHECK(ti.is_pointer() == t_is_pointer);
|
||||||
exit(EXIT_FAILURE);
|
CHECK(ti.is_reference() == t_is_reference);
|
||||||
}
|
CHECK(ti.is_void() == t_is_void);
|
||||||
}
|
CHECK(ti.is_undef() == t_is_undef);
|
||||||
|
CHECK(ti.is_arithmetic() == t_is_arithmetic);
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("void") { test_type(chaiscript::user_type<void>(), false, false, false, true, false, false); }
|
||||||
int main()
|
SECTION("const int") { test_type(chaiscript::user_type<const int>(), true, false, false, false, false, true); }
|
||||||
{
|
SECTION("const int &") { test_type(chaiscript::user_type<const int &>(), true, false, true, false, false, true); }
|
||||||
test_type(chaiscript::user_type<void>(), false, false, false, true, false);
|
SECTION("int") { test_type(chaiscript::user_type<int>(), false, false, false, false, false, true); }
|
||||||
test_type(chaiscript::user_type<const int>(), true, false, false, false, false);
|
SECTION("int *") { test_type(chaiscript::user_type<int *>(), false, true, false, false, false, false); }
|
||||||
test_type(chaiscript::user_type<const int &>(), true, false, true, false, false);
|
SECTION("const int *") { test_type(chaiscript::user_type<const int *>(), true, true, false, false, false, false); }
|
||||||
test_type(chaiscript::user_type<int>(), false, false, false, false, false);
|
SECTION("const bool &") { test_type(chaiscript::user_type<const bool &>(), true, false, true, false, false, false); }
|
||||||
test_type(chaiscript::user_type<int *>(), false, true, false, false, false);
|
SECTION("default") { test_type(chaiscript::Type_Info(), false, false, false, false, true, false); }
|
||||||
test_type(chaiscript::user_type<const int *>(), true, true, false, false, false);
|
|
||||||
test_type(chaiscript::Type_Info(), false, false, false, false, true);
|
|
||||||
|
|
||||||
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
|
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user