Compare commits
4 Commits
Release-4.
...
v4.2.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
59df213e66 | ||
![]() |
0ea8931b21 | ||
![]() |
f24d376fa5 | ||
![]() |
7917ea02dc |
@@ -17,7 +17,7 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
|||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
set(CPACK_PACKAGE_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 1)
|
set(CPACK_PACKAGE_VERSION_MINOR 2)
|
||||||
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")
|
||||||
@@ -212,6 +212,10 @@ if(BUILD_TESTING)
|
|||||||
target_link_libraries(integer_literal_test ${LIBS})
|
target_link_libraries(integer_literal_test ${LIBS})
|
||||||
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
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)
|
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||||
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
|
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
|
||||||
target_link_libraries(multithreaded_test ${LIBS})
|
target_link_libraries(multithreaded_test ${LIBS})
|
||||||
|
@@ -631,9 +631,6 @@ namespace chaiscript
|
|||||||
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
|
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
|
||||||
typedef boost::function<int (const String *, const String &, int)> find_func;
|
typedef boost::function<int (const String *, const String &, int)> find_func;
|
||||||
|
|
||||||
typedef String (String::*substr_ptr)(typename String::size_type, typename String::size_type) const;
|
|
||||||
typedef boost::function<String (const String *, int, int)> substr_func;
|
|
||||||
|
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find)))), "find");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find)))), "find");
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
||||||
@@ -641,8 +638,7 @@ namespace chaiscript
|
|||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
|
||||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
|
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
|
||||||
|
|
||||||
|
m->add(fun(&detail::substr_helper<String, &String::substr>), "substr");
|
||||||
m->add(fun(&detail::substr_helper<String, static_cast<substr_ptr>(&String::substr)>), "substr");
|
|
||||||
|
|
||||||
m->add(fun(&String::c_str), "c_str");
|
m->add(fun(&String::c_str), "c_str");
|
||||||
m->add(fun(&String::data), "data");
|
m->add(fun(&String::data), "data");
|
||||||
|
@@ -332,6 +332,46 @@ namespace chaiscript
|
|||||||
validate_boxed_number(bv);
|
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
|
template<typename Target> Target get_as() const
|
||||||
{
|
{
|
||||||
const Type_Info &inp_ = bv.get_type_info();
|
const Type_Info &inp_ = bv.get_type_info();
|
||||||
|
@@ -1109,6 +1109,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);
|
||||||
|
@@ -85,6 +85,11 @@ namespace chaiscript
|
|||||||
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 = 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
|
||||||
{
|
{
|
||||||
return std::vector<boost::shared_ptr<const Proxy_Function_Base> >();
|
return std::vector<boost::shared_ptr<const Proxy_Function_Base> >();
|
||||||
@@ -117,23 +122,8 @@ 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)
|
||||||
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()
|
||||||
@@ -150,6 +140,36 @@ namespace chaiscript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected:
|
||||||
|
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), m_has_arithmetic_param(false)
|
||||||
|
{
|
||||||
|
for (int 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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
|
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
|
||||||
{
|
{
|
||||||
@@ -170,6 +190,8 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Type_Info> m_types;
|
std::vector<Type_Info> m_types;
|
||||||
|
bool m_has_arithmetic_param;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,6 +627,92 @@ namespace chaiscript
|
|||||||
|
|
||||||
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)
|
||||||
|
{
|
||||||
|
if (t_func->get_arity() != plist.size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||||
|
|
||||||
|
assert(plist.size() == types.size() - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < plist.size(); ++i)
|
||||||
|
{
|
||||||
|
if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i])
|
||||||
|
|| (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)
|
||||||
|
{
|
||||||
|
InItr orig(begin);
|
||||||
|
|
||||||
|
InItr matching_func(end);
|
||||||
|
|
||||||
|
while (begin != end)
|
||||||
|
{
|
||||||
|
if (types_match_except_for_arithmetic(*begin, plist))
|
||||||
|
{
|
||||||
|
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 (int 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);
|
||||||
|
} 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
|
||||||
@@ -634,7 +742,7 @@ namespace chaiscript
|
|||||||
++begin;
|
++begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
return detail::dispatch_with_conversions(orig, end, plist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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,3 +1,10 @@
|
|||||||
|
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
|
Changes since 4.0.0
|
||||||
* Fix sizing of numeric constants to match that of the C++ standard
|
* Fix sizing of numeric constants to match that of the C++ standard
|
||||||
* Add support for u,ll,l,f suffixes for numeric constants
|
* Add support for u,ll,l,f suffixes for numeric constants
|
||||||
|
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;
|
||||||
|
}
|
Reference in New Issue
Block a user