Stub in of support for type conversions. Not yet fully implemented.

This commit is contained in:
Jason Turner 2010-07-17 21:49:27 +00:00
parent 3f9b5081c6
commit 35ac7342b6
4 changed files with 263 additions and 0 deletions

View File

@ -101,6 +101,11 @@ IF(BUILD_TESTING)
target_link_libraries(utility_test ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
add_test(NAME Utility_Test COMMAND utility_test)
add_executable(inheritance_test unittests/inheritance_test.cpp)
target_link_libraries(inheritance_test ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
add_test(NAME Inheritance_Test COMMAND inheritance_test)
ENDIF(BUILD_TESTING)
install(TARGETS chai stl_extra test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )

View File

@ -21,6 +21,7 @@
#include "boxed_value.hpp"
#include "type_info.hpp"
#include "type_conversion.hpp"
#include "proxy_functions.hpp"
#include "proxy_constructors.hpp"
#include "dynamic_object.hpp"
@ -43,6 +44,11 @@ namespace chaiscript
return *this;
}
Module &add(const Type_Conversion &tc)
{
m_conversions.push_back(tc);
return *this;
}
//Add a bit of chaiscript to eval during module implementation
Module &eval(const std::string &str)
@ -62,12 +68,14 @@ namespace chaiscript
{
apply(m_typeinfos.begin(), m_typeinfos.end(), t_engine);
apply(m_funcs.begin(), m_funcs.end(), t_engine);
apply_nameless(m_conversions.begin(), m_conversions.end(), t_engine);
apply_eval(m_evals.begin(), m_evals.end(), t_eval);
}
private:
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
std::vector<Type_Conversion> m_conversions;
std::vector<std::string> m_evals;
template<typename T, typename InItr>
@ -80,6 +88,16 @@ namespace chaiscript
}
}
template<typename T, typename InItr>
void apply_nameless(InItr begin, InItr end, T &t) const
{
while (begin != end)
{
t.add(*begin);
++begin;
}
}
template<typename T, typename InItr>
void apply_eval(InItr begin, InItr end, T &t) const
{
@ -202,6 +220,7 @@ namespace chaiscript
{
std::multimap<std::string, Proxy_Function> m_functions;
std::map<std::string, Boxed_Value> m_global_objects;
std::map<std::pair<Type_Info, Type_Info>, Type_Conversion> m_type_conversions;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
};
@ -230,6 +249,19 @@ namespace chaiscript
return add_function(f, name);
}
/**
* Add a new type converter to the system
*/
void add(const Type_Conversion &tc)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif
m_state.m_type_conversions.insert(std::make_pair(std::make_pair(tc.from(), tc.to()), tc));
}
/**
* Set the value of an object, by name. If the object
* is not available in the current scope it is created

View File

@ -0,0 +1,178 @@
#ifndef __CHAISCRIPT_DISPATCH_TYPE_CONVERSION_HPP__
#define __CHAISCRIPT_DISPATCH_TYPE_CONVERSION_HPP__
#include "boxed_value.hpp"
#include "type_info.hpp"
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/add_const.hpp>
namespace chaiscript
{
namespace detail
{
class Type_Conversion_Impl
{
public:
~Type_Conversion_Impl()
{ }
virtual Boxed_Value convert(const Boxed_Value &v) const = 0;
Type_Info from() const
{
return m_from;
}
Type_Info to() const
{
return m_to;
}
protected:
Type_Conversion_Impl(const Type_Info &t_from, const Type_Info &t_to)
: m_from(t_from), m_to(t_to)
{
}
private:
Type_Info m_from;
Type_Info m_to;
};
template<typename From, typename To>
class Dynamic_Cast_Conversion : public Type_Conversion_Impl
{
public:
typedef From From_Type;
typedef To To_Type;
Dynamic_Cast_Conversion()
: Type_Conversion_Impl(user_type<From_Type>(), user_type<To_Type>())
{ }
virtual ~Dynamic_Cast_Conversion()
{ }
virtual Boxed_Value convert(const Boxed_Value &v) const
{
if (v.is_pointer())
{
if (v.is_const())
{
return const_pointer_convert(v);
} else {
return pointer_convert(v);
}
} else {
if (v.is_const())
{
return const_reference_convert(v);
} else {
return reference_convert(v);
}
}
}
private:
Boxed_Value pointer_convert(const Boxed_Value &v) const
{
boost::shared_ptr<To_Type> to =
boost::dynamic_pointer_cast<To_Type>(boxed_cast<boost::shared_ptr<From_Type> >(v));
if (to) {
return Boxed_Value(to);
} else {
throw bad_boxed_cast(v.get_type_info(), typeid(To_Type));
}
}
Boxed_Value const_pointer_convert(const Boxed_Value &v) const
{
boost::shared_ptr<typename boost::add_const<To_Type>::type> to =
boost::dynamic_pointer_cast<typename boost::add_const<To_Type>::type>(boxed_cast<boost::shared_ptr<typename boost::add_const<From_Type>::type> >(v));
if (to) {
return Boxed_Value(to);
} else {
throw bad_boxed_cast(v.get_type_info(), typeid(To_Type));
}
}
Boxed_Value reference_convert(const Boxed_Value &v) const
{
To_Type *to =
dynamic_cast<To_Type *>(boxed_cast<From_Type *>(v));
if (to) {
return Boxed_Value(to);
} else {
throw bad_boxed_cast(v.get_type_info(), typeid(To_Type));
}
}
Boxed_Value const_reference_convert(const Boxed_Value &v) const
{
typename boost::add_const<To_Type>::type *to =
dynamic_cast<typename boost::add_const<To_Type>::type *>(boxed_cast<typename boost::add_const<From_Type>::type *>(v));
if (to) {
return Boxed_Value(to);
} else {
throw bad_boxed_cast(v.get_type_info(), typeid(To_Type));
}
}
};
}
class Type_Conversion
{
public:
Type_Conversion(const boost::shared_ptr<detail::Type_Conversion_Impl> t_impl)
: m_impl(t_impl)
{
}
Boxed_Value convert(const Boxed_Value &v) const
{
return m_impl->convert(v);
}
Type_Info from() const
{
return m_impl->from();
}
Type_Info to() const
{
return m_impl->to();
}
private:
boost::shared_ptr<detail::Type_Conversion_Impl> m_impl;
};
template<typename From, typename To>
Type_Conversion dynamic_cast_conversion()
{
typedef typename boost::remove_const<
typename boost::remove_pointer<
typename boost::remove_reference<From>::type>::type>::type Cleaned_From;
typedef typename boost::remove_const<
typename boost::remove_pointer<
typename boost::remove_reference<To>::type>::type>::type Cleaned_To;
return Type_Conversion(boost::shared_ptr<detail::Type_Conversion_Impl>(new detail::Dynamic_Cast_Conversion<Cleaned_From, Cleaned_To>()));
}
}
#endif

View File

@ -0,0 +1,48 @@
#include <chaiscript/utility/utility.hpp>
class Test
{
public:
std::string function() { return "Function"; }
};
class Test2 : public Test
{
public:
std::string function2() { return "Function2"; }
};
int main()
{
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
CHAISCRIPT_CLASS( m,
Test,
(Test ())
(Test (const Test &)),
((function))
);
CHAISCRIPT_CLASS( m,
Test2,
(Test2 ())
(Test2 (const Test2 &)),
((function2))
);
chaiscript::ChaiScript chai;
m->add(chaiscript::dynamic_cast_conversion<Test2, Test>());
chai.add(m);
if (chai.eval<std::string>("var t = Test2(); t.function(); ") == "Function"
&& chai.eval<std::string>("var t = Test2(); t.function2(); ") == "Function2")
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}