eolian-cxx: Initial version of complex types / callbacks / events implementation.

This commit is contained in:
Savio Sena 2014-07-16 21:29:47 -03:00 committed by Felipe Magno de Almeida
parent 88f1293527
commit 78e396ac19
19 changed files with 943 additions and 134 deletions

View File

@ -16,6 +16,7 @@ bindings/eo_cxx/eo_inherit.hh \
bindings/eo_cxx/eo_ops.hh \
bindings/eo_cxx/eo_private.hh \
bindings/eo_cxx/eo_inherit_bindings.hh \
bindings/eo_cxx/Eo.hh
bindings/eo_cxx/Eo.hh \
bindings/eo_cxx/eo_cxx_interop.hh
endif

View File

@ -22,6 +22,7 @@ lib/eolian_cxx/grammar/eo_class_generator.hh \
lib/eolian_cxx/grammar/eo_header_generator.hh \
lib/eolian_cxx/grammar/inheritance_base_generator.hh \
lib/eolian_cxx/grammar/parameters_generator.hh \
lib/eolian_cxx/grammar/type_generator.hh \
lib/eolian_cxx/grammar/tab.hh
### Binary
@ -35,7 +36,8 @@ bin_eolian_cxx_eolian_cxx_SOURCES = \
bin/eolian_cxx/convert.hh \
bin/eolian_cxx/eolian_wrappers.hh \
bin/eolian_cxx/safe_strings.hh \
bin/eolian_cxx/type_lookup.hh \
bin/eolian_cxx/type_lookup.hh \
bin/eolian_cxx/type_lookup_table.cc \
bin/eolian_cxx/eolian_cxx.cc
bin_eolian_cxx_eolian_cxx_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
@ -82,11 +84,4 @@ tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
endif
EXTRA_DIST += \
tests/eolian_cxx/data/base.eo \
tests/eolian_cxx/data/class_simple.eo \
tests/eolian_cxx/data/scope.eo \
tests/eolian_cxx/data/ctor_dtor.eo \
tests/eolian_cxx/data/complex_type.eo
endif

View File

@ -116,7 +116,7 @@ convert_eolian_property_to_functions(Eolian_Class const& klass)
{
efl::eolian::eolian_type getter_param_type =
type_to_native(param.type);
getter_param_type/*.native*/ += "*"; // XXX implement complex types
getter_param_type.native += "*";
return efl::eolian::eo_parameter
{ { getter_param_type }, param.name };
});

View File

@ -180,8 +180,7 @@ function_type(Eolian_Function const& func)
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& func, Eolian_Function_Type func_type = method_t::value)
{
return type_lookup
(::eolian_function_return_type_get(&func, func_type));
return type_lookup(::eolian_function_return_type_get(&func, func_type));
}
inline efl::eolian::eolian_type_instance
@ -286,11 +285,17 @@ parameter_type(Eolian_Function_Parameter const& parameter,
efl::eolian::eolian_type_instance type
(type_lookup(::eolian_parameter_type_get(&parameter)));
assert(!type.empty());
// XXX implement complex types.
if (parameter_is_out(parameter))
type = { type_to_native(type) + "*" };
{
type = { efl::eolian::type_to_native(type) };
type.front().native += "*";
}
if (parameter_is_const(parameter, func_type))
type.insert(0, "const ");
{
type[0].native.insert(0, "const ");
if (!type[0].binding.empty())
type[0].binding.insert(0, "const ");
}
return type;
}
@ -311,7 +316,9 @@ event_create(Eolian_Class const& klass, const Eolian_Event *event_)
{
efl::eolian::eo_event event;
const char *name, *comment;
if(::eolian_class_event_information_get(event_, &name, NULL, &comment))
const Eolian_Type *type;
static_cast<void>(type); // XXX
if(::eolian_class_event_information_get(event_, &name, &type, &comment))
{
std::string name_ = safe_str(name);
std::transform(name_.begin(), name_.end(), name_.begin(),

View File

@ -12,6 +12,8 @@
#include <cstddef>
#include <Eolian.h>
#include <eolian_database.h>
#include <Eina.hh>
#include "eo_types.hh"
@ -19,18 +21,46 @@
namespace eolian_cxx {
inline std::string
type_lookup(const Eolian_Type *type)
typedef std::vector<efl::eolian::eolian_type> lookup_table_type;
extern const lookup_table_type type_lookup_table;
inline efl::eolian::eolian_type
type_from_eolian(Eolian_Type const& type)
{
if (type == NULL)
return "void";
// XXX add complex types implementation.
const char *tps = eolian_type_c_type_get(type);
std::string ret = safe_str(tps);
::eina_stringshare_del(tps);
return ret;
efl::eolian::eolian_type x;
x.native = normalize_spaces(safe_str(type.name));
x.is_own = type.is_own;
return x;
}
template <typename Iterator>
inline const efl::eolian::eolian_type&
type_find(Iterator first, Iterator last, efl::eolian::eolian_type const& type)
{
auto res = std::find_if
(first, last,
[&type] (efl::eolian::eolian_type const& x)
{
return (x.native == type.native && x.is_own == type.is_own);
});
return (res != last) ? *res : type;
}
inline efl::eolian::eolian_type_instance
type_lookup(const Eolian_Type* type,
lookup_table_type const& lut = type_lookup_table)
{
if (type == NULL) return { efl::eolian::void_type };
size_t n = ::eina_list_count(type->subtypes) + 1;
assert(n > 0);
efl::eolian::eolian_type_instance v(n);
for (size_t i=0; i<n; i++)
{
v[i] = type_find(lut.begin(), lut.end(), type_from_eolian(*type));
assert (i == n-1 || type_is_complex(v[i]));
}
return v;
}
} // namespace eolian_cxx {

View File

@ -0,0 +1,31 @@
#include "type_lookup.hh"
namespace eolian_cxx {
using efl::eolian::eolian_type;
// Keep the table sorted!
// This can help: cat type_lookup_table | LC_ALL=C sort
const lookup_table_type
type_lookup_table
{
{"Ecore_Cb", eolian_type::callback_, {"Ecore.h"}},
{"Ecore_Task_Cb", eolian_type::callback_, {"Ecore.h"}},
{"Ecore_Timeline_Cb", eolian_type::callback_, {"Ecore.h"}},
{"Eina_Accessor *", eolian_type::complex_, false, "efl::eina::accessor", {"eina-cxx/eina_accessor.hh"}},
{"Eina_Bool", eolian_type::simple_, false, "bool", {}},
{"Eina_Inlist *", eolian_type::complex_, false, "efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}},
{"Eina_Inlist *", eolian_type::complex_, true, "efl::eina::inlist", {"eina-cxx/eina_inlist.hh"}},
{"Eina_Iterator *", eolian_type::complex_, false, "efl::eina::iterator", {"eina-cxx/eina_iterator.hh"}},
{"Eina_List *", eolian_type::complex_, false, "efl::eina::range_ptr_list", {"eina-cxx/eina_ptrlist.hh"}},
{"Eina_List *", eolian_type::complex_, true, "efl::eina::ptr_list", {"eina-cxx/eina_ptrlist.hh"}},
//{"Eina_List *", eolian_type::complex_, false, "efl::eina::ptr_list", {"eina-cxx/eina_ptrlist.hh"}},
{"Eo *", eolian_type::simple_, true, "efl::eo::base", {"eo_base.hh"}},
{"Evas_Object *", eolian_type::simple_, false, "evas_object", {"canvas/evas_object.eo.hh"}},
{"char *", eolian_type::simple_, true, "std::unique_ptr<char*>", {"memory"}},
{"const Eina_Inlist *", eolian_type::complex_, false, "efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}},
{"const Eina_List *", eolian_type::complex_, false, "efl::eina::range_ptr_list", {"eina-cxx/eina_ptrlist.hh"}},
{"const char *", eolian_type::simple_, false, "std::string", {"string"}}
};
}

View File

@ -12,6 +12,7 @@
#include <eina_optional.hh>
#include "eo_ops.hh"
#include "eo_event.hh"
namespace efl { namespace eo {

View File

@ -0,0 +1,237 @@
#ifndef EFL_EOLIAN_INTEROP_HH
#define EFL_EOLIAN_INTEROP_HH
#include <string>
#include <tuple>
#include <type_traits>
#include <Eina.hh>
#include <Eo.hh>
namespace efl { namespace eolian {
//// From C++ to C
inline Eo*
to_c(efl::eo::base const& x)
{
return ::eo_ref(x._eo_ptr());
}
inline const char*
to_c(std::string const& x)
{
return x.c_str();
}
inline const char*
to_c(efl::eina::stringshare const& x)
{
return x.c_str();
}
inline Eina_Bool
to_c(bool x)
{
return x ? EINA_TRUE : EINA_FALSE;
}
//// From C to C++
template <typename T>
struct tag {};
template <typename T, typename U, typename O>
T to_cxx(U object, O o);
// XXX
inline void*
to_cxx(void *x, std::tuple<std::false_type>, tag<void*>)
{
return x;
}
// XXX
inline const void*
to_cxx(const void *x, std::tuple<std::false_type>, tag<const void*>)
{
return x;
}
template <typename T>
inline T
to_cxx(Eo* x, std::tuple<std::true_type>, tag<T>)
{
return T(x);
}
template <typename T>
inline T
to_cxx(Eo* x, std::tuple<std::false_type>, tag<T>)
{
return T(::eo_ref(x));
}
#ifdef _EVAS_H
template <typename T>
Evas_Object_Textblock_Node_Format *
to_cxx(Evas_Object_Textblock_Node_Format* x, std::tuple<std::false_type>, tag<T>)
{
return x; // XXX
}
#endif
inline bool
to_cxx(Eina_Bool x, std::tuple<std::false_type>, tag<bool>)
{
return !!x;
}
inline std::string
to_cxx(const char* x, std::tuple<std::false_type>, tag<std::string>)
{
return std::string(x);
}
template <typename T, typename Enable = void>
struct traits
{
typedef T type;
};
template <typename T>
struct traits
<T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type>
{
typedef Eo* type;
};
template <typename T>
struct traits
<T, typename std::enable_if<std::is_base_of<std::basic_string<char>, T>::value>::type>
{
typedef const char* type;
};
template <typename T, typename ...Args>
inline efl::eina::range_ptr_list<T>
to_cxx(const Eina_List* x, std::tuple<std::false_type, Args...>, tag< efl::eina::range_ptr_list<T> >)
{
efl::eina::ptr_list<T> list;
const Eina_List *l;
void *val;
EINA_LIST_FOREACH(x, l, val)
{
typedef typename traits<T>::type type;
list.push_back(new T (to_cxx(static_cast<type>(val), std::tuple<Args...>()
, tag<T>())));
}
return list;
}
template <typename T, typename ...Args>
inline efl::eina::range_ptr_list<T>
to_cxx(Eina_List* x, std::tuple<std::false_type, Args...>, tag< efl::eina::range_ptr_list<T> >)
{
efl::eina::ptr_list<T> list;
Eina_List *l;
void *val;
EINA_LIST_FOREACH(x, l, val)
{
typedef typename traits<T>::type type;
list.push_back(new T (to_cxx(static_cast<type>(val), std::tuple<Args...>()
, tag<T>())));
}
eina_list_free(x);
return list;
}
template <typename T, typename ...Args>
inline efl::eina::ptr_list<T>
to_cxx(Eina_List* x, std::tuple<std::true_type, Args...>, tag< efl::eina::ptr_list<T> >)
{
efl::eina::ptr_list<T> list;
Eina_List *l;
void *val;
EINA_LIST_FOREACH(x, l, val)
{
typedef typename traits<T>::type type;
list.push_back(new T (to_cxx(static_cast<type>(val), std::tuple<Args...>()
, tag<T>())));
}
eina_list_free(x);
return list;
}
inline eina::stringshare
to_cxx(Eina_Stringshare const* x, const std::false_type, tag<eina::stringshare>)
{
return ::eina_stringshare_ref(x);
}
template <typename T, typename ...Args>
inline efl::eina::accessor<T>
to_cxx(Eina_Accessor* x, std::tuple<std::false_type, Args...>, tag< efl::eina::accessor<T> >)
{
return efl::eina::accessor<T>(x);
}
template <typename T, typename ...Args>
inline efl::eina::iterator<T>
to_cxx(Eina_Iterator* x, std::tuple<std::false_type, Args...>, tag< efl::eina::iterator<T> >)
{
return efl::eina::iterator<T>(x);
}
template <typename T, typename U, typename O>
T to_cxx(U object, O o)
{
return to_cxx(object, o, tag<T>());
}
//// Callbacks
template <typename F, typename R, typename V, typename... Args>
R funcall(V* data, Args... args)
{
F const* f = static_cast<F const*>(data);
return (*f)(args...);
}
template <typename T>
struct callback_result_type;
template <typename R, typename... Args>
struct callback_result_type<R(*)(Args...)>
{
typedef R type;
};
template <typename R>
struct callback_args_type;
template <typename R, typename... Args>
struct callback_args_type<R(*)(Args...)>
{
typedef std::tuple<Args...> type;
};
template <typename C, typename F, typename R, typename V, typename... Args>
C get_callback_impl(tag<std::tuple<V*, Args...> >)
{
static_assert(std::is_same<void, typename std::remove_cv<V>::type>::value,
"First argument of callback should be void* or const void*");
return static_cast<C>(&eolian::funcall<F, R, V, Args...>);
}
template <typename C, typename F>
C get_callback()
{
return get_callback_impl<C, F, typename callback_result_type<C>::type>
(tag<typename callback_args_type<C>::type>());
}
} } // namespace efl { namespace eolian {
#endif // EFL_EOLIAN_INTEROP_HH

View File

@ -0,0 +1,130 @@
///
/// @file eo_event.hh
///
#ifndef EFL_CXX_EO_EVENT_HH
#define EFL_CXX_EO_EVENT_HH
#include <Eo.h>
#include <functional>
#include <memory>
namespace efl { namespace eo {
typedef ::Eo_Callback_Priority callback_priority;
namespace callback_priorities
{
static const callback_priority before = -100;
static const callback_priority default_ = 0;
static const callback_priority after = 100;
}
struct signal_connection
{
signal_connection(std::function<void()> deleter)
: _deleter(deleter) {}
void disconnect()
{
if(_deleter)
{
_deleter();
_deleter = std::function<void()>();
}
}
private:
std::function<void()> _deleter;
friend struct scoped_signal_connection;
};
struct scoped_signal_connection
{
scoped_signal_connection(signal_connection const& other)
: _deleter(other._deleter)
{
}
~scoped_signal_connection()
{
disconnect();
}
void disconnect()
{
if(_deleter)
{
_deleter();
_deleter = std::function<void()>();
}
}
scoped_signal_connection(scoped_signal_connection&& other)
: _deleter(other._deleter)
{
other._deleter = std::function<void()>();
}
private:
std::function<void()> _deleter;
scoped_signal_connection& operator=(scoped_signal_connection const&) = delete;
scoped_signal_connection(scoped_signal_connection const&) = delete;
};
template <typename F>
struct _event_deleter
{
_event_deleter(F* data, Eo* eo, ::Eo_Event_Cb cb, Eo_Event_Description const* description)
: _data(data), _eo( ::eo_ref(eo)), _cb(cb), _description(description)
{
}
~_event_deleter()
{
::eo_unref(_eo);
}
_event_deleter(_event_deleter const& other)
: _data(other._data), _eo( ::eo_ref(other._eo)), _cb(other._cb), _description(other._description)
{}
_event_deleter& operator=(_event_deleter const& other)
{
::eo_unref( _eo);
_data = other._data;
_eo = ::eo_ref(other._eo);
_cb = other._cb;
_description = other._description;
return *this;
}
void operator()() const
{
eo_do(_eo, ::eo_event_callback_del(_description, _cb, _data));
delete _data;
}
F* _data;
Eo* _eo;
::Eo_Event_Cb _cb;
Eo_Event_Description const* _description;
};
template <typename F>
signal_connection make_signal_connection(std::unique_ptr<F>& data, Eo* eo, ::Eo_Event_Cb cb, Eo_Event_Description const* description)
{
signal_connection c(_event_deleter<F>(data.get(), eo, cb, description));
data.release();
return std::move(c);
}
namespace _detail {
template <typename T, typename F>
Eina_Bool
event_callback(void *data, Eo *obj, Eo_Event_Description const* desc, void *info)
{
T wrapper(::eo_ref(obj));
F *f = static_cast<F*>(data);
return (*f)(wrapper, *desc, info);
}
}
} }
#endif

View File

@ -21,6 +21,142 @@ typedef std::vector<eo_function> functions_container_type;
typedef std::vector<eo_parameter> parameters_container_type;
typedef std::vector<eo_event> events_container_type;
struct eolian_type
{
enum category_type
{
unknown_, simple_, complex_, callback_
};
eolian_type()
: native("")
, category(unknown_)
, is_own(false)
, binding()
, includes()
{}
eolian_type(std::string native_,
category_type category_,
bool is_own_,
std::string binding_,
includes_container_type includes_)
: native(native_)
, category(category_)
, is_own(is_own_)
, binding(binding_)
, includes(includes_)
{
assert(!native.empty());
assert(category != unknown_);
}
eolian_type(std::string native_,
category_type category_,
includes_container_type const& includes_)
: eolian_type(native_, category_, false, "", includes_)
{
assert(category == callback_);
}
~eolian_type() {}
eolian_type(eolian_type const& other)
: native(other.native)
, category(other.category)
, is_own(other.is_own)
, binding(other.binding)
, includes(other.includes)
{}
eolian_type&
operator=(eolian_type const& rhs)
{
native = rhs.native;
category = rhs.category;
is_own = rhs.is_own;
binding = rhs.binding;
includes = rhs.includes;
return *this;
}
std::string native;
category_type category;
bool is_own;
std::string binding;
includes_container_type includes;
};
typedef std::vector<eolian_type> eolian_type_instance;
const efl::eolian::eolian_type
void_type { "void", efl::eolian::eolian_type::simple_, false, "", {} };
inline bool
type_is_void(eolian_type_instance const& type)
{
return type.empty() || type[0].native.compare("void") == 0;
}
inline bool
type_is_binding(eolian_type const& type)
{
return !type.binding.empty();
}
inline bool
type_is_binding(eolian_type_instance const& type)
{
assert(!type.empty());
return type_is_binding(type.front());
}
inline eolian_type
type_to_native(eolian_type const& type)
{
eolian_type native = type;
native.binding.clear();
native.category = eolian_type::simple_;
return native;
}
inline eolian_type
type_to_native(eolian_type_instance const& type_ins)
{
assert(!type_ins.empty());
return type_to_native(type_ins.front());
}
inline std::string
type_to_native_str(eolian_type_instance const& type_ins)
{
return type_to_native(type_ins).native;
}
inline bool
type_is_complex(eolian_type const& type)
{
return type.category == eolian_type::complex_;
}
template <typename T>
inline bool
type_is_callback(T const&);
template <>
inline bool
type_is_callback(eolian_type const& type)
{
return type.category == eolian_type::callback_;
}
template <>
inline bool
type_is_callback(eolian_type_instance const& type_ins)
{
return type_is_callback(type_ins.front());
}
struct eo_generator_options
{
includes_container_type cxx_headers;
@ -48,7 +184,7 @@ struct eo_class
struct eo_parameter
{
std::string type;
eolian_type_instance type;
std::string name;
};
@ -68,15 +204,24 @@ struct eo_function
eo_function_type type;
std::string name;
std::string impl;
std::string ret;
eolian_type_instance ret;
parameters_container_type params;
std::string comment;
};
struct eo_event
{
std::string name;
std::string eo_name;
//parameters_container_type params; // XXX desirable.
std::string comment;
};
inline bool
function_is_void(eo_function const& func)
{
return func.ret.empty() || func.ret.compare("void") == 0;
return func.ret.empty() || func.ret[0].native.compare("void") == 0;
}
inline bool
@ -85,31 +230,28 @@ function_is_static(eo_function const& func)
return func.type == eo_function::class_;
}
struct eo_event
inline unsigned int
parameters_count_callbacks(parameters_container_type const& parameters)
{
std::string name;
std::string eo_name;
std::string comment;
};
// XXX mocked implementation. waiting for complex types...
typedef std::string eolian_type_instance;
typedef std::string eolian_type;
inline bool
type_is_void(eolian_type_instance const& type)
{
return type.empty() || type.compare("void") == 0;
unsigned int r = 0u;
for (eo_parameter const& param : parameters)
if(type_is_callback(param.type))
++r;
return r;
}
} }
namespace eolian_cxx {
inline efl::eolian::eolian_type
type_to_native(efl::eolian::eolian_type const& type)
inline parameters_container_type::const_iterator
parameters_find_callback(parameters_container_type const& parameters)
{
return type;
for (auto it = parameters.cbegin(), last = parameters.cend();
it != last; ++it)
{
if (type_is_callback((*it).type))
return it;
}
return parameters.cend();
}
} } // namespace efl { namespace eolian {
#endif // EFL_EOLIAN_CXX_EO_TYPES_HH

View File

@ -16,6 +16,39 @@ _is_valid(std::string const& value)
return !value.empty() and isalpha(value[0]);
}
inline bool
_is_valid(eolian_type_instance const& type)
{
if (type.empty() || (*type.rbegin()).category == eolian_type::complex_)
return false;
for (auto rit = ++type.rbegin(), last = type.rend(); rit != last; ++rit)
{
if ((*rit).binding.empty() || (*rit).category != eolian_type::complex_)
return false;
else if (rit != type.rbegin() && (*rit).category != eolian_type::complex_)
return false;
}
return true;
}
inline bool
_is_valid(parameters_container_type const& parameters)
{
unsigned int n_callbacks = parameters_count_callbacks(parameters);
return n_callbacks == 0 || n_callbacks == 1;
}
inline bool
_is_valid(events_container_type const& events)
{
for (eo_event event : events)
{
if (event.name.empty() || event.eo_name.empty())
return false;
}
return true;
}
template <typename T>
inline void
_validate(T val, const eo_class& cls)
@ -44,6 +77,7 @@ eo_class_validate(const eo_class& cls)
it != last; ++it)
{
_validate((*it).name, cls);
_validate((*it).params, cls);
// parameters
for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
it_p != last_p; ++it_p)
@ -59,6 +93,7 @@ eo_class_validate(const eo_class& cls)
_validate((*it).name, cls);
_validate((*it).impl, cls);
_validate((*it).ret, cls);
_validate((*it).params, cls);
// parameters
for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
it_p != last_p; ++it_p)
@ -67,6 +102,8 @@ eo_class_validate(const eo_class& cls)
_validate((*it_p).type, cls);
}
}
// events
_validate(cls.events, cls);
}
} } // namespace efl { namespace eolian {

View File

@ -114,14 +114,16 @@ operator<<(std::ostream& out, constructors const& x)
for (it = first; it != last; ++it)
{
eo_constructor const& ctor = *it;
out << comment(ctor.comment, 1)
<< tab(1)
out << comment(ctor.comment, 1);
if (parameters_count_callbacks(ctor.params))
out << tab(1) << "template <typename F>" << endl;
out << tab(1)
<< x._cls.name
<< '(' << parameters_declaration(ctor.params)
<< (ctor.params.size() > 0 ? ", " : "")
<< "efl::eo::parent_type _p = (efl::eo::parent = nullptr))" << endl
<< tab(2) << ": " << class_name(x._cls.name)
<< "(_c" << (it - first) << "(" << parameters_list(ctor.params)
<< "(_c" << (it - first) << "(" << parameters_cxx_list(ctor.params)
<< (ctor.params.size() > 0 ? ", " : "")
<< "_p))" << endl
<< tab(1) << "{}" << endl << endl;
@ -180,14 +182,26 @@ operator<<(std::ostream& out, eo_class_constructors const& x)
last = x._cls.constructors.end();
for (it = first; it != last; ++it)
{
if (parameters_count_callbacks((*it).params))
out << tab(1) << "template <typename F>" << endl;
out << tab(1)
<< "static Eo* _c" << (it - first) << "("
<< parameters_declaration((*it).params)
<< ((*it).params.size() > 0 ? ", " : "")
<< "efl::eo::parent_type _p"
<< ')' << endl
<< tab(1) << "{" << endl
<< tab(2) << "return eo_add_custom("
<< tab(1) << "{" << endl;
parameters_container_type::const_iterator callback_iter =
parameters_find_callback((*it).params);
if (callback_iter != (*it).params.cend())
{
out << tab(2)
<< "F* _tmp_f = new F(std::move("
<< (*callback_iter).name << "));"
<< endl;
}
out << tab(2) << "return eo_add_custom("
<< x._cls.eo_name << ", _p._eo_raw, " << (*it).name
<< "(" << parameters_list((*it).params) << "));" << endl
<< tab(1) << "}" << endl << endl;

View File

@ -4,88 +4,76 @@
#include <iosfwd>
#include <algorithm> // std::transform()
#include <ctype.h> // ::toupper()
#include "eo_types.hh"
#include "tab.hh"
#include "comment.hh"
#include "parameters_generator.hh"
namespace efl { namespace eolian { namespace grammar {
struct event_callback_add
{
eo_event const& _event;
std::string const& _ev_name;
event_callback_add(eo_event const& event, std::string const& ev_name)
: _event(event),
_ev_name(ev_name)
eo_class const& _cls;
event_callback_add(eo_event const& event, eo_class const& cls)
: _event(event), _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, event_callback_add const& x)
{
// TODO implement
return out;
}
struct event_callback_del
{
eo_event const& _event;
std::string const& _ev_name;
event_callback_del(eo_event const& event, std::string const& ev_name)
: _event(event),
_ev_name(ev_name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, event_callback_del const& x)
{
// TODO: implement
out << tab(1) << "template <typename F>" << endl
<< tab(1) << "::efl::eo::signal_connection" << endl
<< tab(1) << "event_" << x._event.name << "_callback_add(F && callback_," << endl
<< tab(11) << "::efl::eo::callback_priority priority_ =" << endl
<< tab(11) << "::efl::eo::callback_priorities::default_)" << endl
<< tab(1) << "{" << endl
<< tab(2) << "::std::unique_ptr<F> f ( new F(std::move(callback_)) );" << endl
<< tab(2) << "eo_do(_eo_ptr()," << endl
<< tab(4) << "eo_event_callback_priority_add" << endl
<< tab(4) << "(" << x._event.eo_name << ", priority_," << endl
<< tab(4) << "&efl::eo::_detail::event_callback<" << x._cls.name << ", F>, f.get()));" << endl
<< tab(2) << "return ::efl::eo::make_signal_connection" << endl
<< tab(3) << "(f, this->_eo_ptr(), &efl::eo::_detail::event_callback<" << x._cls.name << ", F>," << endl
<< tab(3) << x._event.eo_name << " );" << endl
<< tab(1) << "}" << endl;
return out;
}
struct event_callback_call
{
eo_event const& _event;
std::string const& _ev_name;
event_callback_call(eo_event const& event, std::string const& ev_name)
: _event(event),
_ev_name(ev_name)
event_callback_call(eo_event const& event)
: _event(event)
{}
};
inline std::ostream&
operator<<(std::ostream& out, event_callback_call const& x)
{
// TODO implement
out << tab(1) << "template <typename T>" << endl
<< tab(1) << "void" << endl
<< tab(1) << "event_" << x._event.name << "_callback_call(T* info)" << endl
<< tab(1) << "{" << endl
<< tab(2) << "eo_do(_eo_ptr(), eo_event_callback_call" << endl
<< tab(4) << "(" << x._event.eo_name << ", info));" << endl
<< tab(1) << "}" << endl;
return out;
}
struct events
{
events_container_type const& _events;
events(events_container_type const& events) : _events(events) {}
eo_class const& _cls;
events(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, events const& x)
{
std::string prefix = x._cls.name + "_EVENT_";
std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper());
events_container_type::const_iterator it,
first = x._events.begin(),
last = x._events.end();
for (it = first; it != last; ++it)
for (eo_event const& e : x._cls.events)
{
std::string ev_name = (*it).name;
std::transform(ev_name.begin(), ev_name.end(), ev_name.begin(), ::toupper());
out << event_callback_add((*it), prefix+ev_name)
<< event_callback_del((*it), prefix+ev_name)
<< event_callback_call((*it), prefix+ev_name);
out << event_callback_add(e, x._cls) << endl
<< event_callback_call(e);
}
return out;
}

View File

@ -8,6 +8,7 @@
#include "tab.hh"
#include "comment.hh"
#include "parameters_generator.hh"
#include "type_generator.hh"
namespace efl { namespace eolian { namespace grammar {
@ -21,10 +22,9 @@ inline std::ostream&
operator<<(std::ostream& out, function_call const& x)
{
bool is_void = function_is_void(x._func);
out << (!is_void ? "_tmp_ret = " : "")
<< "::" << x._func.impl
<< "(" << parameters_list(x._func.params) << ")";
return out;
return out << (!is_void ? "_tmp_ret = " : "")
<< "::" << x._func.impl
<< "(" << parameters_list(x._func.params) << ")";
}
struct function
@ -37,25 +37,30 @@ inline std::ostream&
operator<<(std::ostream& out, function const& x)
{
eo_function const& func = x._func;
bool is_void = function_is_void(func);
out << comment(x._func.comment, 1)
<< tab(1)
<< ( func.type == eo_function::class_ ? "static " : "" )
<< func.ret << " " << func.name << "("
out << comment(x._func.comment, 1);
if (parameters_count_callbacks(x._func.params) == 1)
out << tab(1) << "template <typename F>" << endl;
if (function_is_static(func))
out << tab(1) << "static ";
out << tab(1)
<< reinterpret_type(func.ret) << " " << func.name << "("
<< parameters_declaration(func.params)
<< ") const" << endl
<< tab(1) << "{" << endl;
if (!is_void)
{
out << tab(2) << func.ret << " _tmp_ret;" << endl;
}
out << tab(2) << "eo_do(_eo_ptr(), "
<< function_call(x._func)
<< ");" << endl;
if (!is_void)
{
out << tab(2) << "return _tmp_ret;" << endl;
}
if (!function_is_void(func))
out << tab(2)
<< func.ret.front().native << " _tmp_ret;" << endl;
out << tab(2)
<< "eo_do(_eo_ptr(), " << function_call(x._func) << ");" << endl;
if (!function_is_void(func))
out << tab(2) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl;
out << tab(1) << "}" << endl;
return out;
}

View File

@ -10,6 +10,7 @@
#include "comment.hh"
#include "eo_class_constructors_generator.hh"
#include "eo_class_functions_generator.hh"
#include "eo_class_events_generator.hh"
namespace efl { namespace eolian { namespace grammar {
@ -41,6 +42,7 @@ eo_class_generator(std::ostream& out, eo_class const& cls)
<< copy_constructor(cls)
<< destructor(cls)
<< functions(cls.functions)
<< events(cls)
<< eo_class_getter(cls)
<< "private:" << endl
<< eo_class_constructors(cls)

View File

@ -38,6 +38,42 @@ _onceguard_key(efl::eolian::eo_class const& cls)
namespace efl { namespace eolian { namespace grammar {
struct include_dependencies
{
eo_class const& _cls;
include_dependencies(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, include_dependencies const& x)
{
std::set<std::string> headers;
eo_class const& cls = x._cls;
for (auto it = cls.constructors.cbegin(), last = cls.constructors.cend();
it != last; ++it)
for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
it_p != last_p; ++it_p)
for (eolian_type const& subtype : (*it_p).type)
for (std::string header : subtype.includes)
headers.insert(header);
for (auto it = cls.functions.begin(), last = cls.functions.end();
it != last; ++it)
for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
it_p != last_p; ++it_p)
for (eolian_type const& subtype : (*it_p).type)
for (std::string header : subtype.includes)
headers.insert(header);
for (std::string header : headers)
out << "#include <" << header << ">" << endl;
return out;
}
inline void
onceguard_head(std::ostream& out, eo_class const& cls)
{
@ -91,6 +127,7 @@ include_headers(std::ostream& out,
eo_generator_options const& opts)
{
out << "#include <Eo.hh>" << endl << endl
<< "#include <eo_cxx_interop.hh>" << endl << endl
<< "extern \"C\"" << endl
<< "{" << endl;
for (auto c_header : opts.c_headers)
@ -102,6 +139,7 @@ include_headers(std::ostream& out,
{
out << "#include \"" << cxx_header << "\"" << endl;
}
out << include_dependencies(cls) << endl;
}
inline void

View File

@ -96,7 +96,7 @@ inline std::ostream&
operator<<(std::ostream& out, inheritance_wrapper const& x)
{
out << "template <typename T>" << endl
<< x._func.ret << " "
<< reinterpret_type(x._func.ret) << " "
<< _ns_as_prefix(x._cls) << "_"
<< x._cls.name << "_" << x._func.name
<< "_wrapper(Eo* objid EINA_UNUSED, "
@ -130,7 +130,7 @@ operator<<(std::ostream& out, inheritance_wrappers const& x)
{
eo_function const& func = *it;
out << "template <typename T>" << endl
<< func.ret << " "
<< reinterpret_type(func.ret) << " "
<< _ns_as_prefix(x._cls) << "_"
<< x._cls.name << "_" << func.name
<< "_wrapper(Eo* objid EINA_UNUSED, "
@ -186,13 +186,13 @@ operator<<(std::ostream& out, inheritance_base_operations_function const& x)
eo_function const& func = x._func;
bool is_void = function_is_void(func);
out << tab(2) << "virtual " << func.ret << " "
out << tab(2) << "virtual " << reinterpret_type(func.ret) << " "
<< func.name << "("
<< parameters_declaration(func.params) << ")" << endl
<< tab(2) << "{" << endl;
if (!is_void)
{
out << tab(3) << func.ret << " _tmp_ret = {};" << endl;
out << tab(3) << reinterpret_type(func.ret) << " _tmp_ret = {};" << endl;
}
out << tab(3)
<< "eo_do_super(static_cast<T*>(this)->_eo_ptr()" << endl
@ -301,7 +301,7 @@ operator<<(std::ostream& out, inheritance_extension_function const& x)
{
bool is_void = function_is_void(x._func);
out << tab(2)
<< x._func.ret << " "
<< reinterpret_type(x._func.ret) << " "
<< x._func.name << "("
<< parameters_declaration(x._func.params)
<< ")" << endl
@ -309,7 +309,7 @@ operator<<(std::ostream& out, inheritance_extension_function const& x)
if (!is_void)
{
out << tab(3) << x._func.ret << " _tmp_ret = {};" << endl;
out << tab(3) << reinterpret_type(x._func.ret) << " _tmp_ret = {};" << endl;
}
out << tab(3) << "eo_do(static_cast<T*>(this)->_eo_ptr(), "

View File

@ -6,6 +6,7 @@
#include "tab.hh"
#include "eo_types.hh"
#include "type_generator.hh"
namespace efl { namespace eolian { namespace grammar {
@ -21,12 +22,20 @@ parameters_declaration
inline std::ostream&
operator<<(std::ostream& out, parameters_declaration const& x)
{
parameters_container_type::const_iterator it, first = x._params.cbegin();
parameters_container_type::const_iterator last = x._params.cend();
for (it = first; it != last; ++it)
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first) out << ", ";
out << (*it).type << " " << (*it).name;
if (it != first)
out << ", ";
if (type_is_callback((*it).type))
{
out << "F && " << (*it).name;
assert(it+1 != last);
++it; // skip next.
}
else
out << reinterpret_type((*it).type) << " " << (*it).name;
}
return out;
}
@ -49,7 +58,7 @@ operator<<(std::ostream& out, parameters_types const& x)
for (it = first; it != last; ++it)
{
if(it != first) out << ", ";
out << (*it).type;
out << reinterpret_type((*it).type);
}
return out;
}
@ -66,16 +75,52 @@ parameters_list
inline std::ostream&
operator<<(std::ostream& out, parameters_list const& x)
{
parameters_container_type::const_iterator it, first = x._params.cbegin();
parameters_container_type::const_iterator last = x._params.cend();
for (it = first; it != last; ++it)
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first) out << ", ";
out << (*it).name;
if (it != first)
out << ", ";
out << to_c((*it).type, (*it).name);
if (type_is_callback((*it).type))
{
out << ", _tmp_f";
++it; // skip next
}
}
return out;
}
struct
parameters_cxx_list
{
parameters_container_type const& _params;
parameters_cxx_list(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_cxx_list const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
if (type_is_callback((*it).type))
{
out << "std::move(" << (*it).name << ")";
assert(it+1 != last);
++it; // skip next.
}
else
out << (*it).name;
}
return out;
}
} } } // namespace efl { namespace eolian { namespace grammar {

View File

@ -0,0 +1,106 @@
#ifndef EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH
#define EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH
#include <ostream>
#include <iosfwd>
#include "eo_types.hh"
namespace efl { namespace eolian { namespace grammar {
using std::endl;
struct reinterpret_type
{
eolian_type_instance const& _list;
reinterpret_type(eolian_type_instance const& list)
: _list(list)
{}
};
inline std::ostream&
operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x)
{
assert(x._list.size() > 0);
std::string res;
for (auto rit = x._list.rbegin(), last = x._list.rend(); rit != last; ++rit)
{
if (type_is_complex(*rit))
res = (*rit).binding + "< " + res + " >";
else
res = type_is_binding(*rit) ? (*rit).binding : (*rit).native;
}
assert(!res.empty());
return out << res;
}
struct type_ownership
{
eolian_type_instance const& _type;
type_ownership(eolian_type_instance const& type)
: _type(type)
{}
};
inline std::ostream&
operator<<(std::ostream& out, type_ownership const& x)
{
out << "std::tuple<";
for (auto it=x._type.begin(), last=x._type.end(); it != last; ++it)
{
if (it != x._type.begin())
out << ", ";
out << ((*it).is_own ? "std::true_type" : "std::false_type");
}
return out << ">()";
}
struct to_cxx
{
eolian_type_instance const& _type;
std::string const& _varname;
to_cxx(eolian_type_instance const& type, std::string const& varname)
: _type(type), _varname(varname)
{}
};
inline std::ostream&
operator<<(std::ostream& out, to_cxx const& x)
{
if (type_is_binding(x._type))
{
out << "efl::eolian::to_cxx<"
<< reinterpret_type(x._type)
<< ">(" << x._varname
<< ", " << type_ownership(x._type) << ");";
}
else
out << "_ret";
return out;
}
struct to_c
{
eolian_type_instance const& _type;
std::string const& _varname;
to_c(eolian_type_instance const& type, std::string const& varname)
: _type(type), _varname(varname)
{}
};
inline std::ostream&
operator<<(std::ostream& out, to_c const& x)
{
if (type_is_callback(x._type))
out << "efl::eolian::get_callback<" << type_to_native_str(x._type) << ", F>()";
else if (type_is_binding(x._type))
out << "efl::eolian::to_c(" << x._varname << ")";
else
out << x._varname;
return out;
}
} } }
#endif // EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH