Merge remote-tracking branch 'origin/release-4.x'

Conflicts:
	.travis.yml
	CMakeLists.txt
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/language/chaiscript_common.hpp
This commit is contained in:
Jason Turner
2014-03-29 07:30:14 -06:00
16 changed files with 220 additions and 87 deletions

View File

@@ -18,10 +18,14 @@ script:
- find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; - find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \;
- $GCOV -d -o gcov gcov/*.gcda - $GCOV -d -o gcov gcov/*.gcda
- coveralls -n -E ".*\.cpp" - coveralls -n -E ".*\.cpp"
after_script:
- contrib/codeanalysis/runcppcheck.sh
notifications: notifications:
email:
recipients: recipients:
- jason@emptycrate.com - jason@emptycrate.com
email:
on_success: always on_success: always
on_failure: always on_failure: always
env:
global:
secure: LCUAKUCRtFp2ak81nVLR+jx0C9+Drwx1OR4VzuvH+HNGWFdUZmAIV3R84euDqFC5cUhYYipaeMbiSOJUHE4MNlL58eQZryED6KSL7k7SgxOLpFSspMvuMjIYZLlBWpBneCR/EMDilu+zXEnASfVUMPuLmtY1GAyfSoZboqFProc=

View File

@@ -18,6 +18,18 @@ endif()
option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE) option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE)
option(BUILD_SAMPLES "Build Samples Folder" FALSE) option(BUILD_SAMPLES "Build Samples Folder" FALSE)
set(EXTRA_LINKER_FLAGS "")
if (CMAKE_COMPILER_IS_GNUCC)
option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE)
if (ENABLE_COVERAGE)
add_definitions(--coverage -O0)
SET(EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} "--coverage")
endif()
endif()
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}") list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn") list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn")
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.git") list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.git")
@@ -30,7 +42,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt"
set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 3) set(CPACK_PACKAGE_VERSION_MINOR 3)
set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_VERSION_PATCH 1)
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")

View File

@@ -0,0 +1,16 @@
#!/bin/bash
pushd ..
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.64/cppcheck-1.64.tar.bz2
tar -xvf cppcheck-1.64.tar.bz2
cd cppcheck-1.64
make -j2
popd
../cppcheck-1.64/cppcheck --enable=all --inconclusive -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
echo -n '{ "body": " ' > output.json
echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json
echo -n '"}' >> output.json
if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; else curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/issues/${TRAVIS_PULL_REQUEST}/comments; fi

View File

@@ -305,14 +305,6 @@ namespace chaiscript
throw bv; throw bv;
} }
static std::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(
std::shared_ptr<chaiscript::detail::Dispatch_Engine> e
= std::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
{
e->add(user_type<void>(), "void");
return e;
}
static std::string what(const std::exception &e) static std::string what(const std::exception &e)
{ {
return e.what(); return e.what();

View File

@@ -79,12 +79,19 @@ namespace chaiscript
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions) if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
{ {
try { try {
// std::cout << "trying an up conversion " << typeid(Type).name() << std::endl;
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // 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(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions); return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
} catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << std::endl;
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_down_cast<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) { } catch (const chaiscript::detail::exception::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));
} }
}
} else { } else {
// If it's not polymorphic, just throw the error, don't waste the time on the // If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast // attempted dynamic_cast

View File

@@ -307,7 +307,7 @@ namespace chaiscript
} }
template<typename Source> template<typename Source>
std::string to_string_aux(const Boxed_Value &v) const static std::string to_string_aux(const Boxed_Value &v)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << *static_cast<const Source *>(v.get_const_ptr()); oss << *static_cast<const Source *>(v.get_const_ptr());
@@ -520,7 +520,7 @@ namespace chaiscript
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv); return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
} }
void validate_boxed_number(const Boxed_Value &v) static void validate_boxed_number(const Boxed_Value &v)
{ {
const Type_Info &inp_ = v.get_type_info(); const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool)) if (inp_ == typeid(bool))

View File

@@ -48,12 +48,13 @@ namespace chaiscript
{ {
public: public:
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0; virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0;
const Type_Info &base() const Type_Info &base() const
{ {
return m_base; return m_base;
} }
const Type_Info &derived() const Type_Info &derived() const
{ {
return m_derived; return m_derived;
} }
@@ -72,26 +73,21 @@ namespace chaiscript
}; };
template<typename Base, typename Derived> template<typename From, typename To>
class Dynamic_Conversion_Impl : public Dynamic_Conversion class Dynamic_Caster
{ {
public: public:
Dynamic_Conversion_Impl() static Boxed_Value cast(const Boxed_Value &t_from)
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
{ {
} if (t_from.get_type_info().bare_equal(user_type<From>()))
virtual Boxed_Value convert(const Boxed_Value &t_derived) const
{ {
if (t_derived.get_type_info().bare_equal(user_type<Derived>())) if (t_from.is_pointer())
{
if (t_derived.is_pointer())
{ {
// Dynamic cast out the contained boxed value, which we know is the type we want // Dynamic cast out the contained boxed value, which we know is the type we want
if (t_derived.is_const()) if (t_from.is_const())
{ {
std::shared_ptr<const Base> data std::shared_ptr<const To> data
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived, nullptr)); = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
if (!data) if (!data)
{ {
throw std::bad_cast(); throw std::bad_cast();
@@ -99,8 +95,8 @@ namespace chaiscript
return Boxed_Value(data); return Boxed_Value(data);
} else { } else {
std::shared_ptr<Base> data std::shared_ptr<To> data
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived, nullptr)); = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
if (!data) if (!data)
{ {
@@ -111,22 +107,42 @@ namespace chaiscript
} }
} else { } else {
// 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_from.is_const())
{ {
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived, 0); const From &d = detail::Cast_Helper<const From &>::cast(t_from, 0);
const Base &data = dynamic_cast<const Base &>(d); const To &data = dynamic_cast<const To &>(d);
return Boxed_Value(std::cref(data)); return Boxed_Value(std::cref(data));
} else { } else {
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived, 0); From &d = detail::Cast_Helper<From &>::cast(t_from, 0);
Base &data = dynamic_cast<Base &>(d); To &data = dynamic_cast<To &>(d);
return Boxed_Value(std::ref(data)); return Boxed_Value(std::ref(data));
} }
} }
} else { } else {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion"); throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
} }
} }
}; };
template<typename Base, typename Derived>
class Dynamic_Conversion_Impl : public Dynamic_Conversion
{
public:
Dynamic_Conversion_Impl()
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
{
}
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const
{
return Dynamic_Caster<Base, Derived>::cast(t_base);
}
virtual Boxed_Value convert(const Boxed_Value &t_derived) const
{
return Dynamic_Caster<Derived, Base>::cast(t_derived);
}
};
} }
class Dynamic_Cast_Conversions class Dynamic_Cast_Conversions
@@ -155,7 +171,7 @@ namespace chaiscript
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
{ {
return has_conversion(base, derived); return has_conversion(base, derived) || has_conversion(derived, base);
} }
template<typename Base> template<typename Base>
@@ -170,6 +186,19 @@ namespace chaiscript
} }
} }
template<typename Derived>
Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const
{
try {
return get_conversion(base.get_type_info(), user_type<Derived>())->convert_down(base);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation");
}
}
bool has_conversion(const Type_Info &base, const Type_Info &derived) const 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); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
@@ -242,8 +271,6 @@ namespace chaiscript
/// chai.add(chaiscript::base_class<Base, Derived>()); /// chai.add(chaiscript::base_class<Base, Derived>());
/// \endcode /// \endcode
/// ///
/// \todo Move share static type registration code into a mechanism that allows it to be properly
/// shared by all modules
template<typename Base, typename Derived> template<typename Base, typename Derived>
Dynamic_Cast_Conversion base_class() Dynamic_Cast_Conversion base_class()
{ {

View File

@@ -30,7 +30,7 @@ namespace chaiscript
return m_attrs[t_attr_name]; return m_attrs[t_attr_name];
} }
std::map<std::string, Boxed_Value> get_attrs() std::map<std::string, Boxed_Value> get_attrs() const
{ {
return m_attrs; return m_attrs;
} }

View File

@@ -17,12 +17,11 @@ namespace chaiscript
{ {
namespace detail namespace detail
{ {
/** /**
* Internal helper class for handling the return * Internal helper class for handling the return
* value of a build_function_caller * value of a build_function_caller
*/ */
template<typename Ret> template<typename Ret, bool is_arithmetic>
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,
@@ -32,11 +31,25 @@ namespace chaiscript
} }
}; };
/**
* Specialization for arithmetic return types
*/
template<typename Ret>
struct Function_Caller_Ret<Ret, true>
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
}
};
/** /**
* Specialization for void return types * Specialization for void return types
*/ */
template<> template<>
struct Function_Caller_Ret<void> struct Function_Caller_Ret<void, false>
{ {
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> &params, const Dynamic_Cast_Conversions &t_conversions) const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
@@ -59,7 +72,7 @@ namespace chaiscript
Ret operator()(Param...param) Ret operator()(Param...param)
{ {
return Function_Caller_Ret<Ret>::call(m_funcs, { return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value>::call(m_funcs, {
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)... (std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
}, m_conversions }, m_conversions

View File

@@ -23,7 +23,7 @@ namespace chaiscript
class Boxed_Number; class Boxed_Number;
struct AST_Node; struct AST_Node;
typedef std::shared_ptr<struct AST_Node> AST_NodePtr; typedef std::shared_ptr<AST_Node> AST_NodePtr;
namespace dispatch namespace dispatch
{ {

View File

@@ -54,7 +54,7 @@ namespace chaiscript
}; };
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
typedef std::shared_ptr<struct AST_Node> AST_NodePtr; typedef std::shared_ptr<AST_Node> AST_NodePtr;
/// \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.
@@ -435,7 +435,7 @@ namespace chaiscript
return eval_internal(t_e); return eval_internal(t_e);
} catch (exception::eval_error &ee) { } catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this()); ee.call_stack.push_back(shared_from_this());
throw ee; throw;
} }
} }

View File

@@ -742,7 +742,7 @@ namespace chaiscript
if (t_handler) { if (t_handler) {
t_handler->handle(bv, m_engine); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
@@ -768,7 +768,7 @@ namespace chaiscript
if (t_handler) { if (t_handler) {
t_handler->handle(bv, m_engine); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
@@ -798,7 +798,7 @@ namespace chaiscript
if (t_handler) { if (t_handler) {
t_handler->handle(bv, m_engine); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
@@ -814,7 +814,7 @@ namespace chaiscript
if (t_handler) { if (t_handler) {
t_handler->handle(bv, m_engine); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
@@ -834,7 +834,7 @@ namespace chaiscript
if (t_handler) { if (t_handler) {
t_handler->handle(bv, m_engine); t_handler->handle(bv, m_engine);
} }
throw bv; throw;
} }
} }
}; };

View File

@@ -56,7 +56,8 @@ namespace chaiscript
public: public:
ChaiScript_Parser() ChaiScript_Parser()
: m_multiline_comment_begin("/*"), : m_line(-1), m_col(-1),
m_multiline_comment_begin("/*"),
m_multiline_comment_end("*/"), m_multiline_comment_end("*/"),
m_singleline_comment("//") m_singleline_comment("//")
{ {
@@ -803,10 +804,9 @@ namespace chaiscript
*/ */
bool Quoted_String_() { bool Quoted_String_() {
bool retval = false; bool retval = false;
char prev_char = 0;
if (has_more_input() && (*m_input_pos == '\"')) { if (has_more_input() && (*m_input_pos == '\"')) {
retval = true; retval = true;
prev_char = *m_input_pos; char prev_char = *m_input_pos;
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
@@ -980,10 +980,9 @@ namespace chaiscript
*/ */
bool Single_Quoted_String_() { bool Single_Quoted_String_() {
bool retval = false; bool retval = false;
char prev_char = 0;
if (has_more_input() && (*m_input_pos == '\'')) { if (has_more_input() && (*m_input_pos == '\'')) {
retval = true; retval = true;
prev_char = *m_input_pos; char prev_char = *m_input_pos;
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
@@ -1356,7 +1355,6 @@ namespace chaiscript
bool Def() { bool Def() {
bool retval = false; bool retval = false;
bool is_annotated = false; bool is_annotated = false;
bool is_method = false;
AST_NodePtr annotation; AST_NodePtr annotation;
if (Annotation()) { if (Annotation()) {
@@ -1375,6 +1373,8 @@ namespace chaiscript
throw exception::eval_error("Missing function name in definition", File_Position(m_line, m_col), *m_filename); throw exception::eval_error("Missing function name in definition", File_Position(m_line, m_col), *m_filename);
} }
bool is_method = false;
if (Symbol("::", false)) { if (Symbol("::", false)) {
//We're now a method //We're now a method
is_method = true; is_method = true;

View File

@@ -11,6 +11,8 @@ class TestBaseType
virtual ~TestBaseType() {} virtual ~TestBaseType() {}
virtual int func() { return 0; } virtual int func() { return 0; }
int base_only_func() { return -9; }
const TestBaseType &constMe() const { return *this; } const TestBaseType &constMe() const { return *this; }
int val; int val;
@@ -35,11 +37,28 @@ class TestDerivedType : public TestBaseType
public: public:
virtual ~TestDerivedType() {} virtual ~TestDerivedType() {}
virtual int func() { return 1; } virtual int func() { return 1; }
int derived_only_func() { return 19; }
private: private:
TestDerivedType &operator=(const TestDerivedType &); TestDerivedType &operator=(const TestDerivedType &);
}; };
class TestMoreDerivedType : public TestDerivedType
{
public:
virtual ~TestMoreDerivedType() {}
};
std::shared_ptr<TestBaseType> derived_type_factory()
{
return std::shared_ptr<TestBaseType>(new TestDerivedType());
}
std::shared_ptr<TestBaseType> more_derived_type_factory()
{
return std::shared_ptr<TestBaseType>(new TestMoreDerivedType());
}
std::string hello_world() std::string hello_world()
{ {
return "Hello World"; return "Hello World";
@@ -70,6 +89,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType"); m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType"); m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType"); m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType"); // m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
@@ -79,11 +99,23 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType"); m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType"); m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
m->add(chaiscript::constructor<TestMoreDerivedType ()>(), "TestMoreDerivedType");
m->add(chaiscript::constructor<TestMoreDerivedType (const TestMoreDerivedType &)>(), "TestMoreDerivedType");
/// \todo automatic chaining of base classes?
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>()); m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
m->add(chaiscript::base_class<TestBaseType, TestMoreDerivedType>());
m->add(chaiscript::base_class<TestDerivedType, TestMoreDerivedType>());
m->add(chaiscript::fun(&TestDerivedType::derived_only_func), "derived_only_func");
m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory");
m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory");
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::val), "val");
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
m->add(chaiscript::fun(&get_new_int), "get_new_int"); m->add(chaiscript::fun(&get_new_int), "get_new_int");

View File

@@ -18,6 +18,11 @@ void f3(double)
{ {
} }
void f_func_return(const std::function<unsigned int (unsigned long)> &f)
{
// test the ability to return an unsigned with auto conversion
f(4);
}
int main() int main()
{ {
@@ -29,6 +34,8 @@ int main()
chai.add(chaiscript::fun(&f1), "f3"); chai.add(chaiscript::fun(&f1), "f3");
chai.add(chaiscript::fun(&f4), "f3"); chai.add(chaiscript::fun(&f4), "f3");
chai.add(chaiscript::fun(&f_func_return), "func_return");
// no overloads // no overloads
chai.eval("f1(0)"); chai.eval("f1(0)");
chai.eval("f1(0l)"); chai.eval("f1(0l)");
@@ -46,7 +53,12 @@ int main()
// 1 non-arithmetic overload // 1 non-arithmetic overload
chai.eval("f2(1.0)"); chai.eval("f2(1.0)");
// this is the one call we expect to fail // various options for returning with conversions from chaiscript
chai.eval("func_return(fun(x) { return 5u; })");
chai.eval("func_return(fun(x) { return 5; })");
chai.eval("func_return(fun(x) { return 5.0f; })");
// this is the one call we expect to fail, ambiguous overloads
try { try {
chai.eval("f2(1.0l)"); chai.eval("f2(1.0l)");
} catch (const std::exception &) { } catch (const std::exception &) {

View File

@@ -15,3 +15,21 @@ assert_equal(15, t.const_val);
t.val = 23; t.val = 23;
assert_equal(23, t.val) assert_equal(23, t.val)
// test_derived_factory returns a TestDerivedType contained
// in a shared_ptr<TestBaseType>. This is testing our ability
// to detect that and do the down casting for the user automatically
// at runtime
assert_equal(t.derived_only_func(), 19);
var d := derived_type_factory();
assert_equal(d.derived_only_func(), 19);
var t2 = TestMoreDerivedType();
assert_equal(t2.derived_only_func(), 19);
assert_equal(t2.base_only_func(), -9);
var md := more_derived_type_factory();
assert_equal(md.derived_only_func(), 19);
assert_equal(md.base_only_func(), -9);