eolian-cxx: Rewrite to accomodate new features of the C++ binding

This commit is contained in:
Felipe Magno de Almeida 2016-06-06 02:54:36 -03:00
parent 4d1b3191d9
commit 2a3d7860db
98 changed files with 5810 additions and 5664 deletions

View File

@ -7,15 +7,15 @@ installed_eocxxheadersdir = $(includedir)/eo-cxx-@VMAJ@/
nodist_installed_eocxxheaders_DATA = $(eo_eolian_cxx_hh) $(eo_eolian_cxx_impl)
dist_installed_eocxxheaders_DATA = \
bindings/cxx/eo_cxx/eo_concrete.hh \
bindings/cxx/eo_cxx/eo_event.hh \
bindings/cxx/eo_cxx/eo_init.hh \
bindings/cxx/eo_cxx/eo_wref.hh \
bindings/cxx/eo_cxx/eo_inherit.hh \
bindings/cxx/eo_cxx/eo_ops.hh \
bindings/cxx/eo_cxx/eo_private.hh \
bindings/cxx/eo_cxx/eo_inherit_bindings.hh \
bindings/cxx/eo_cxx/eo_cxx_interop.hh \
bindings/cxx/eo_cxx/Eo.hh
bindings/cxx/eo_cxx/eo_event.hh \
bindings/cxx/eo_cxx/Eo.hh \
bindings/cxx/eo_cxx/eo_inherit.hh \
bindings/cxx/eo_cxx/eo_inherit_bindings.hh \
bindings/cxx/eo_cxx/eo_init.hh \
bindings/cxx/eo_cxx/eo_ops.hh \
bindings/cxx/eo_cxx/eo_wref.hh \
bindings/cxx/eo_cxx/eo_private.hh
### Elementary C++
installed_elementarycxxmainheadersdir = $(includedir)/elementary-cxx-@VMAJ@/
@ -138,6 +138,7 @@ bindings/cxx/eina_cxx/eina_accessor.hh \
bindings/cxx/eina_cxx/eina_array.hh \
bindings/cxx/eina_cxx/eina_clone_allocators.hh \
bindings/cxx/eina_cxx/eina_error.hh \
bindings/cxx/eina_cxx/eina_future.hh \
bindings/cxx/eina_cxx/eina_eo_concrete_fwd.hh \
bindings/cxx/eina_cxx/eina_fold.hh \
bindings/cxx/eina_cxx/eina_function.hh \

View File

@ -6,40 +6,53 @@ installed_eoliancxxmainheadersdir = $(includedir)/eolian-cxx-@VMAJ@/
dist_installed_eoliancxxmainheaders_DATA = \
lib/eolian_cxx/Eolian_Cxx.hh
installed_eoliancxxheadersdir = $(includedir)/eolian-cxx-@VMAJ@/
dist_installed_eoliancxxheaders_DATA = \
lib/eolian_cxx/eo_generate.hh \
lib/eolian_cxx/eo_types.hh \
lib/eolian_cxx/eo_validate.hh
installed_eoliancxxgrammarheadersdir = $(includedir)/eolian-cxx-@VMAJ@/grammar/
dist_installed_eoliancxxgrammarheaders_DATA = \
lib/eolian_cxx/grammar/comment.hh \
lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh \
lib/eolian_cxx/grammar/eo_class_constructors_generator.hh \
lib/eolian_cxx/grammar/eo_class_events_generator.hh \
lib/eolian_cxx/grammar/eo_class_functions_generator.hh \
lib/eolian_cxx/grammar/namespace_generator.hh \
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
lib/eolian_cxx/grammar/address_of.hpp \
lib/eolian_cxx/grammar/alternative.hpp \
lib/eolian_cxx/grammar/attribute_conditional.hpp \
lib/eolian_cxx/grammar/attribute_reorder.hpp \
lib/eolian_cxx/grammar/attribute_replace.hpp \
lib/eolian_cxx/grammar/attributes.hpp \
lib/eolian_cxx/grammar/base_class_definition.hpp \
lib/eolian_cxx/grammar/case.hpp \
lib/eolian_cxx/grammar/class_declaration.hpp \
lib/eolian_cxx/grammar/class_definition.hpp \
lib/eolian_cxx/grammar/class_implementation.hpp \
lib/eolian_cxx/grammar/container.hpp \
lib/eolian_cxx/grammar/context.hpp \
lib/eolian_cxx/grammar/converting_argument.hpp \
lib/eolian_cxx/grammar/c_type.hpp \
lib/eolian_cxx/grammar/eps.hpp \
lib/eolian_cxx/grammar/function_declaration.hpp \
lib/eolian_cxx/grammar/function_definition.hpp \
lib/eolian_cxx/grammar/generator.hpp \
lib/eolian_cxx/grammar/header_guards.hpp \
lib/eolian_cxx/grammar/header.hpp \
lib/eolian_cxx/grammar/header_include_directive.hpp \
lib/eolian_cxx/grammar/implementation_include_directive.hpp \
lib/eolian_cxx/grammar/impl_header.hpp \
lib/eolian_cxx/grammar/indentation.hpp \
lib/eolian_cxx/grammar/keyword.hpp \
lib/eolian_cxx/grammar/klass_def.hpp \
lib/eolian_cxx/grammar/kleene.hpp \
lib/eolian_cxx/grammar/list.hpp \
lib/eolian_cxx/grammar/meta.hpp \
lib/eolian_cxx/grammar/namespace.hpp \
lib/eolian_cxx/grammar/parameter.hpp \
lib/eolian_cxx/grammar/qualifier_def.hpp \
lib/eolian_cxx/grammar/sequence.hpp \
lib/eolian_cxx/grammar/string.hpp \
lib/eolian_cxx/grammar/type.hpp \
lib/eolian_cxx/grammar/type_impl.hpp \
lib/eolian_cxx/grammar/type_traits.hpp \
lib/eolian_cxx/grammar/variant.hpp
### Binary
bin_PROGRAMS += bin/eolian_cxx/eolian_cxx
bin_eolian_cxx_eolian_cxx_SOURCES = \
bin/eolian_cxx/convert_comments.cc \
bin/eolian_cxx/convert_comments.hh \
bin/eolian_cxx/convert.cc \
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_table.cc \
bin/eolian_cxx/eolian_cxx.cc
bin_eolian_cxx_eolian_cxx_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
@ -63,32 +76,29 @@ TESTS += tests/eolian_cxx/eolian_cxx_suite
tests_eolian_cxx_eolian_cxx_suite_SOURCES = \
tests/eolian_cxx/eolian_cxx_suite.cc \
tests/eolian_cxx/eolian_cxx_test_parse.cc \
tests/eolian_cxx/callback.c \
tests/eolian_cxx/a.c \
tests/eolian_cxx/b.c \
tests/eolian_cxx/c.c \
tests/eolian_cxx/d.c \
tests/eolian_cxx/eolian_cxx_test_binding.cc \
tests/eolian_cxx/eolian_cxx_test_callback.cc \
tests/eolian_cxx/eolian_cxx_test_address_of.cc \
tests/eolian_cxx/eolian_cxx_test_wrapper.cc \
tests/eolian_cxx/simple.c \
tests/eolian_cxx/name_name.c \
tests/eolian_cxx/name_name_cxx.cc \
tests/eolian_cxx/generic.c \
tests/eolian_cxx/name1_name2_type_generation.c \
tests/eolian_cxx/eolian_cxx_test_inheritance.cc \
tests/eolian_cxx/eolian_cxx_test_generate.cc \
tests/eolian_cxx/complex.c \
tests/eolian_cxx/complex_cxx.cc \
tests/eolian_cxx/eolian_cxx_suite.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_wrapper.$(OBJEXT): tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_callback.$(OBJEXT): tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.h
tests/eolian_cxx/name1_name2_type_generation.$(OBJEXT): tests/eolian_cxx/name1_name2_type_generation.eo.h tests/eolian_cxx/name1_name2_type_generation.eo.c
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_inheritance.$(OBJEXT): tests/eolian_cxx/simple.eo.hh tests/eolian_cxx/simple.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_binding.$(OBJEXT): tests/eolian_cxx/generic.eo.hh tests/eolian_cxx/generic.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_binding.$(OBJEXT): tests/eolian_cxx/generic.eo.hh tests/eolian_cxx/generic.eo.h tests/eolian_cxx/name1_name2_type_generation.eo.hh tests/eolian_cxx/name1_name2_type_generation.eo.h tests/eolian_cxx/name1_name2_type_generation.eo.c
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_address_of.$(OBJEXT): tests/eolian_cxx/a.eo.hh tests/eolian_cxx/b.eo.hh tests/eolian_cxx/c.eo.hh tests/eolian_cxx/d.eo.hh tests/eolian_cxx/a.eo.h tests/eolian_cxx/b.eo.h tests/eolian_cxx/c.eo.h tests/eolian_cxx/d.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-callback.$(OBJEXT): tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-simple.$(OBJEXT): tests/eolian_cxx/simple.eo.c tests/eolian_cxx/simple.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-generic.$(OBJEXT): tests/eolian_cxx/generic.eo.c tests/eolian_cxx/generic.eo.h
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-a.$(OBJEXT): tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h
@ -103,10 +113,6 @@ tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-complex.$(OBJEXT): tests/eoli
tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-complex_cxx.$(OBJEXT): tests/eolian_cxx/complex.eo.h tests/eolian_cxx/complex.eo.hh
CLEANFILES += \
tests/eolian_cxx/callback.eo.hh \
tests/eolian_cxx/callback.eo.c \
tests/eolian_cxx/callback.eo.h \
tests/eolian_cxx/callback.eo.impl.hh \
tests/eolian_cxx/simple.eo.c \
tests/eolian_cxx/simple.eo.h \
tests/eolian_cxx/simple.eo.hh \
@ -134,7 +140,11 @@ tests/eolian_cxx/ns_name_other.eo.impl.hh \
tests/eolian_cxx/complex.eo.hh \
tests/eolian_cxx/complex.eo.c \
tests/eolian_cxx/complex.eo.h \
tests/eolian_cxx/complex.eo.impl.hh
tests/eolian_cxx/complex.eo.impl.hh \
tests/eolian_cxx/name1_name2_type_generation.eo.hh \
tests/eolian_cxx/name1_name2_type_generation.eo.impl.hh \
tests/eolian_cxx/name1_name2_type_generation.eo.h \
tests/eolian_cxx/name1_name2_type_generation.eo.c
tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \
@ -159,7 +169,7 @@ tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
endif
EXTRA_DIST += tests/eolian_cxx/callback.eo \
EXTRA_DIST += \
tests/eolian_cxx/simple.eo \
tests/eolian_cxx/generic.eo \
tests/eolian_cxx/a.eo \
@ -169,6 +179,7 @@ tests/eolian_cxx/d.eo \
tests/eolian_cxx/name_name.eo \
tests/eolian_cxx/ns_name.eo \
tests/eolian_cxx/ns_name_other.eo \
tests/eolian_cxx/name1_name2_type_generation.eo \
tests/eolian_cxx/complex.eo
include Makefile_Eolian_Cxx_Helper.am

View File

@ -1,373 +0,0 @@
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>
#include <cstddef>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eina.hh>
#include <Eolian.h>
#include "eo_types.hh"
#include "eo_validate.hh"
#include "safe_strings.hh"
#include "convert_comments.hh"
#include "eolian_wrappers.hh"
namespace eolian_cxx {
extern efl::eina::log_domain domain;
typedef std::map<efl::eolian::eo_event, bool> event_map;
void
add_ancestor_recursive(const char* klass_name, std::set<std::string>& ancestor)
{
if (!klass_name)
return;
Eolian_Class const* klass = ::eolian_class_get_by_name(klass_name);
if (!klass)
{
std::cerr << "Error: could not get eolian class name `" << klass_name << "'" << std::endl;
return;
}
ancestor.insert(class_format_cxx(safe_str(klass_name)));
Eina_Iterator* inheritances = ::eolian_class_inherits_get(klass);
void* curr = 0;
EINA_ITERATOR_FOREACH(inheritances, curr)
{
add_ancestor_recursive(static_cast<const char*>(curr), ancestor);
}
eina_iterator_free(inheritances);
}
void
add_events_recursive(event_map& events, Eolian_Class const& klass, std::set<std::string>& ancestors)
{
for (efl::eolian::eo_event const& e : event_list(klass))
{
auto it = events.find(e);
if (it == events.end())
events[e] = true;
else
it->second = false;
}
Eina_Iterator* inheritances = ::eolian_class_inherits_get(&klass);
void* curr = 0;
EINA_ITERATOR_FOREACH(inheritances, curr)
{
const char* ancestor_name = static_cast<const char*>(curr);
if (!ancestor_name || ancestors.find(ancestor_name) != ancestors.end())
continue;
Eolian_Class const* ancestor_klass = ::eolian_class_get_by_name(ancestor_name);
if (!ancestor_klass)
{
std::cerr << "Error: could not get eolian class name `" << ancestor_name << "'" << std::endl;
continue;
}
ancestors.insert(ancestor_name);
add_events_recursive(events, *ancestor_klass, ancestors);
}
eina_iterator_free(inheritances);
}
static efl::eolian::parameters_container_type
_convert_eolian_parameters(Eina_Iterator *parameters,
Eolian_Function_Type func_type)
{
if (parameters == NULL) return {};
assert(func_type != EOLIAN_PROPERTY);
void *curr;
efl::eolian::parameters_container_type list;
EINA_ITERATOR_FOREACH(parameters, curr)
{
const Eolian_Function_Parameter *id =
(static_cast<const Eolian_Function_Parameter*>(curr));
list.push_back
({
parameter_type(*id),
parameter_name(*id)
});
}
eina_iterator_free(parameters);
return list;
}
static efl::eolian::parameters_container_type
_convert_eolian_parameters(Eina_Iterator *parameters, getter_t func_type)
{
return _convert_eolian_parameters(parameters, func_type.value);
}
static efl::eolian::parameters_container_type
_convert_eolian_parameters(Eina_Iterator *parameters, setter_t func_type)
{
return _convert_eolian_parameters(parameters, func_type.value);
}
static efl::eolian::parameters_container_type
_convert_eolian_parameters(Eolian_Function const& func)
{
assert(function_op_type(func) != EOLIAN_PROPERTY);
return _convert_eolian_parameters
(::eolian_function_parameters_get(&func), function_op_type(func));
}
static efl::eolian::eo_function
_convert_property_set_to_function(Eolian_Class const& klass,
Eolian_Function const& prop_)
{
efl::eolian::eo_function set_ =
{
efl::eolian::eo_function::regular_,
function_scope(prop_),
function_is_beta(prop_),
function_name(prop_) + "_set",
function_impl(prop_) + "_set",
function_return_type(prop_, eolian_cxx::setter),
_convert_eolian_parameters(::eolian_property_values_get(&prop_, EOLIAN_PROP_SET),
eolian_cxx::setter),
convert_comments_function(klass, prop_, eolian_cxx::setter)
};
efl::eolian::parameters_container_type keys =
_convert_eolian_parameters(::eolian_property_keys_get(&prop_, EOLIAN_PROP_SET),
eolian_cxx::setter);
if (!keys.empty())
{
keys.reserve(keys.size() + set_.params.size());
keys.insert(keys.end(), set_.params.begin(),
set_.params.end());
set_.params = keys;
}
return set_;
}
static efl::eolian::eo_function
_convert_property_get_to_function(Eolian_Class const& klass,
Eolian_Function const& prop_)
{
efl::eolian::eo_function get_ =
{
efl::eolian::eo_function::regular_,
function_scope(prop_),
function_is_beta(prop_),
function_name(prop_) + "_get",
function_impl(prop_) + "_get",
function_return_type(prop_, eolian_cxx::getter),
_convert_eolian_parameters(::eolian_property_values_get(&prop_, EOLIAN_PROP_GET),
eolian_cxx::getter),
convert_comments_function(klass, prop_, eolian_cxx::getter)
};
// if the getter has a single parameter and a void return
// it is transformed into a getter with no parameters
// that actually returns what would be the first argument.
if (get_.params.size() == 1 && efl::eolian::type_is_void(get_.ret) &&
!function_return_is_explicit_void(prop_, eolian_cxx::getter))
{
get_.ret = get_.params[0].type;
get_.params.clear();
}
else // otherwise just create the described getter
{
std::transform
(get_.params.begin(), get_.params.end(), get_.params.begin(),
[](efl::eolian::eo_parameter const& param)
{
efl::eolian::eolian_type getter_param_type =
type_to_native(param.type);
getter_param_type.native += "*";
return efl::eolian::eo_parameter
{ { getter_param_type }, param.name };
});
}
efl::eolian::parameters_container_type keys =
_convert_eolian_parameters(::eolian_property_keys_get(&prop_, EOLIAN_PROP_GET),
eolian_cxx::getter);
if (!keys.empty())
{
keys.reserve(keys.size() + get_.params.size());
keys.insert(keys.end(), get_.params.begin(),
get_.params.end());
get_.params = keys;
}
return get_;
}
static efl::eolian::eo_function
_convert_function(Eolian_Class const& klass, Eolian_Function const& func)
{
return {
function_type(func),
function_scope(func),
function_is_beta(func),
function_name(func),
function_impl(func),
function_return_type(func),
_convert_eolian_parameters(func),
convert_comments_function(klass, func, eolian_cxx::method)
};
}
void
convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
Eina_Iterator *inheritances =
::eolian_class_inherits_get(&klass);
void *curr;
std::set<std::string> ancestors;
EINA_ITERATOR_FOREACH(inheritances, curr)
{
const char* klass_name = static_cast<const char*>(curr);
cls.parents.push_back(class_format_cxx(safe_str(klass_name)));
add_ancestor_recursive(klass_name, ancestors);
}
eina_iterator_free(inheritances);
cls.ancestors.assign(ancestors.begin(), ancestors.end());
}
void
convert_eolian_events(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
efl::eolian::events_container_type events = event_list(klass);
cls.own_events.reserve(cls.own_events.size() + events.size());
cls.own_events.insert(cls.own_events.end(), events.begin(), events.end());
event_map concrete_events;
std::set<std::string> ancestors;
add_events_recursive(concrete_events, klass, ancestors);
for (auto const& e : events)
{
concrete_events[e] = true;
}
for (auto const& pair : concrete_events)
{
if (pair.second)
cls.concrete_events.push_back(pair.first);
}
}
efl::eolian::eo_class
convert_eolian_class_new(Eolian_Class const& klass)
{
efl::eolian::eo_class cls;
cls.type = class_type(klass);
cls.name = class_name(klass);
cls.name_space = class_namespace_full(klass);
if(cls.name_space.empty())
cls.name_space = "nonamespace";
cls.eo_name = class_eo_name(klass);
cls.comment = convert_comments_class(klass);
return cls;
}
void
convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
for(efl::eina::iterator<const Eolian_Function> first ( ::eolian_class_functions_get(&klass, EOLIAN_METHOD))
, last; first != last; ++first)
{
Eolian_Function const& func = *first;
if (function_is_visible(func, function_op_type(func)) &&
!function_is_constructor(klass, func))
{
cls.functions.push_back(_convert_function(klass, func));
}
}
if (class_eo_name(klass) != "EO_BASE_CLASS")
for(efl::eina::iterator<const Eolian_Constructor> first ( ::eolian_class_constructors_get(&klass))
, last; first != last; ++first)
{
Eolian_Constructor const& ctor = *first;
Eolian_Function const& func = *(::eolian_constructor_function_get(&ctor));
efl::eolian::eo_function f;
if (function_op_type(func) == EOLIAN_METHOD)
f = _convert_function(klass, func);
else
f = _convert_property_set_to_function(klass, func);
(::eolian_constructor_is_optional(&ctor) ?
cls.optional_constructors :
cls.constructors
).push_back({
function_name(func),
f.impl,
f.params,
f.comment
});
}
cls.all_constructors = cls.constructors;
cls.all_constructors.insert(cls.all_constructors.end(),
cls.optional_constructors.begin(), cls.optional_constructors.end());
for(efl::eina::iterator<const Eolian_Function> first ( ::eolian_class_functions_get(&klass, EOLIAN_PROPERTY))
, last; first != last; ++first)
{
Eolian_Function const& func = *first;
Eolian_Function_Type t = ::eolian_function_type_get(&func);
if (!function_is_visible(func, t))
continue;
if(t == EOLIAN_PROP_GET)
{
cls.functions.push_back
(_convert_property_get_to_function(klass, func));
}
else if(t == EOLIAN_PROP_SET)
{
cls.functions.push_back
(_convert_property_set_to_function(klass, func));
}
else if(t == EOLIAN_PROPERTY)
{
cls.functions.push_back
(_convert_property_get_to_function(klass, func));
cls.functions.push_back
(_convert_property_set_to_function(klass, func));
}
else
{
std::cerr << "Error: Inconsistent type for Eolian function \'" << ::eolian_function_name_get(&func) << "\'." << std::endl;
throw std::runtime_error("Invalid Eolian function type");
}
}
}
efl::eolian::eo_class
convert_eolian_class(const Eolian_Class& klass)
{
efl::eolian::eo_class cls(eolian_cxx::convert_eolian_class_new(klass));
eolian_cxx::convert_eolian_inheritances(cls, klass);
eolian_cxx::convert_eolian_functions(cls, klass);
eolian_cxx::convert_eolian_events(cls, klass);
efl::eolian::eo_class_validate(cls);
return cls;
}
} // namespace eolian_cxx {

View File

@ -1,19 +0,0 @@
#ifndef EOLIAN_CXX_EOLIAN_CONVERT_CLASSES_HH
#define EOLIAN_CXX_EOLIAN_CONVERT_CLASSES_HH
#include "eo_types.hh"
namespace eolian_cxx
{
///
/// @brief Retrieve a efl::eolian::eo_class from an Eolian_Class* name.
/// @param cls The Eolian class.
/// @return The @p eo_class describing @p classname.
///
efl::eolian::eo_class convert_eolian_class(const Eolian_Class& klass);
}
#endif // EOLIAN_CXX_EOLIAN_CONVERT_CLASSES_HH

View File

@ -1,95 +0,0 @@
#include "convert_comments.hh"
#include "safe_strings.hh"
namespace eolian_cxx {
static std::string
_comment_parameter(Eolian_Function_Parameter *param)
{
Eolian_Parameter_Dir direction = eolian_parameter_direction_get(param);
std::string doc = "@param";
if (direction == EOLIAN_IN_PARAM) doc += " ";
else if (direction == EOLIAN_OUT_PARAM) doc += "[out] ";
else if (direction == EOLIAN_INOUT_PARAM) doc += "[inout] ";
else assert(false);
doc += safe_str(::eolian_parameter_name_get(param));
doc += " ";
/* FIXME */
doc += safe_str(NULL);
return doc;
}
static std::string
_comment_parameters_list(Eina_Iterator *params)
{
std::string doc = "";
void *curr;
EINA_ITERATOR_FOREACH(params, curr)
{
doc += _comment_parameter
(static_cast<Eolian_Function_Parameter*>(curr)) + "\n";
}
eina_iterator_free(params);
return doc;
}
static std::string
_comment_brief_and_params(Eolian_Function const& function, Eolian_Function_Type)
{
std::string doc = "";
/* FIXME */
std::string func = safe_str(NULL);
if (func != "")
{
doc += "@brief " + func + "\n\n";
}
std::string params = _comment_parameters_list(::eolian_function_parameters_get(&function));
if (params != "")
{
doc += params + "\n";
}
return doc;
}
static std::string
_comment_return(Eolian_Function const& function,
Eolian_Function_Type rettype)
{
const Eolian_Type *rettypet = ::eolian_function_return_type_get(&function, rettype);
const char *rettypes = NULL;
if (rettypet) rettypes = ::eolian_type_c_type_get(rettypet);
std::string doc = "";
std::string ret = safe_str(rettypes);
if (rettypes) eina_stringshare_del(rettypes);
/* FIXME */
std::string comment = safe_str(NULL);
if (ret != "void" && ret != "" && comment != "")
{
doc = "@return " + comment;
}
return doc;
}
std::string
convert_comments_class(Eolian_Class const&)
{
/* FIXME */
return safe_str(NULL);
}
std::string
convert_comments_function(Eolian_Class const& klass,
Eolian_Function const& function,
Eolian_Function_Type func_type)
{
std::string doc = _comment_brief_and_params(function, func_type);
if (!function_is_constructor(klass, function))
doc += _comment_return(function, func_type);
return doc;
}
} // namespace eolian_cxx

View File

@ -1,46 +0,0 @@
#ifndef EOLIAN_CXX_CONVERT_COMMENTS_HH
#define EOLIAN_CXX_CONVERT_COMMENTS_HH
#include <string>
#include <Eolian.h>
#include <Eolian_Cxx.hh>
#include "eolian_wrappers.hh"
namespace eolian_cxx {
std::string convert_comments_class(Eolian_Class const& klass);
std::string convert_comments_function(Eolian_Class const& klass,
Eolian_Function const& function,
Eolian_Function_Type func_type);
inline std::string
convert_comments_function(Eolian_Class const& klass, Eolian_Function const& function_, method_t func_type_)
{
return convert_comments_function(klass, function_, func_type_.value);
}
inline std::string
convert_comments_function(Eolian_Class const& klass, Eolian_Function const& property_, getter_t func_type_)
{
return convert_comments_function(klass, property_, func_type_.value);
}
inline std::string
convert_comments_function(Eolian_Class const& klass, Eolian_Function const& property_, setter_t func_type_)
{
return convert_comments_function(klass, property_, func_type_.value);
}
inline std::string
convert_comments_function(Eolian_Class const& klass, Eolian_Function const& function_)
{
return convert_comments_function(klass, function_, eolian_cxx::method);
}
}
#endif // EOLIAN_CXX_CONVERT_COMMENTS_HH

View File

@ -21,12 +21,9 @@
#include <Eina.hh>
#include <Eolian_Cxx.hh>
#include "convert.hh"
#include "type_lookup.hh"
#include "convert.hh"
#include "eolian_wrappers.hh"
#include "safe_strings.hh"
#include "grammar/klass_def.hpp"
#include "grammar/header.hpp"
#include "grammar/impl_header.hpp"
namespace eolian_cxx {
@ -36,20 +33,6 @@ struct options_type
std::vector<std::string> include_dirs;
std::string in_file;
std::string out_file;
std::string out_dir;
std::string classname;
bool recurse;
bool generate_all;
options_type()
: include_dirs()
, in_file()
, out_file()
, out_dir()
, classname()
, recurse(false)
, generate_all(false)
{}
};
efl::eina::log_domain domain("eolian_cxx");
@ -57,29 +40,11 @@ efl::eina::log_domain domain("eolian_cxx");
static bool
opts_check(eolian_cxx::options_type const& opts)
{
if (!opts.generate_all && opts.in_file.empty())
if (opts.in_file.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Nothing to generate?" << std::endl;
}
else if (opts.generate_all && !opts.in_file.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Didn't expect to receive input files (" << opts.in_file
<< ") with parameter -a."
<< std::endl;
}
else if (opts.generate_all && !opts.out_file.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Can't use -a and -o together." << std::endl;
}
else if (opts.generate_all && opts.include_dirs.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Option -a requires at least one include directory (-I)."
<< std::endl;
}
else
{
return true; // valid.
@ -87,39 +52,11 @@ opts_check(eolian_cxx::options_type const& opts)
return false;
}
efl::eolian::eo_generator_options
generator_options(const Eolian_Class& klass)
{
efl::eolian::eo_generator_options gen_opts;
gen_opts.c_headers.push_back(class_base_file(klass) + ".h");
void *cur = NULL;
Eina_Iterator *inheritances = ::eolian_class_inherits_get(&klass);
EINA_ITERATOR_FOREACH(inheritances, cur)
{
const Eolian_Class *ext = ::eolian_class_get_by_name(static_cast<const char*>(cur));
std::string eo_parent_file = class_base_file(*ext);
if (!eo_parent_file.empty())
{
gen_opts.cxx_headers.push_back(eo_parent_file + ".hh");
}
else
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Couldn't find source file for class '" << ext << "'"
<< std::endl;
}
}
eina_iterator_free(inheritances);
return gen_opts;
}
static bool
generate(const Eolian_Class& klass, eolian_cxx::options_type const& opts)
generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
{
efl::eolian::eo_class cls = eolian_cxx::convert_eolian_class(klass);
efl::eolian::eo_generator_options gen_opts = generator_options(klass);
std::string header_decl_file_name = opts.out_file.empty() ? (class_base_file(klass) + ".hh") : opts.out_file;
std::string header_decl_file_name = opts.out_file.empty()
? (::eolian_class_file_get(klass) + std::string(".hh")) : opts.out_file;
std::string header_impl_file_name = header_decl_file_name;
std::size_t dot_pos = header_impl_file_name.rfind(".hh");
@ -128,24 +65,101 @@ generate(const Eolian_Class& klass, eolian_cxx::options_type const& opts)
else
header_impl_file_name.insert(header_impl_file_name.size(), ".impl");
std::size_t slash_pos = header_decl_file_name.rfind('/');
gen_opts.header_decl_file_name = (slash_pos == std::string::npos) ?
header_decl_file_name :
header_decl_file_name.substr(slash_pos+1);
efl::eolian::grammar::attributes::klass_def klass_def(klass);
std::vector<efl::eolian::grammar::attributes::klass_def> klasses{klass_def};
slash_pos = header_impl_file_name.rfind('/');
gen_opts.header_impl_file_name = (slash_pos == std::string::npos) ?
header_impl_file_name :
header_impl_file_name.substr(slash_pos+1);
if (!opts.out_dir.empty())
std::set<std::string> c_headers;
std::set<std::string> cpp_headers;
c_headers.insert(eolian_class_file_get(klass) + std::string(".h"));
std::function<void(efl::eolian::grammar::attributes::type_def const&)>
variant_function;
auto klass_name_function
= [&] (efl::eolian::grammar::attributes::klass_name const& name)
{
header_decl_file_name = opts.out_dir + "/" + header_decl_file_name;
header_impl_file_name = opts.out_dir + "/" + header_impl_file_name;
}
Eolian_Class const* klass = get_klass(name);
assert(klass);
c_headers.insert(eolian_class_file_get(klass) + std::string(".h"));
cpp_headers.insert(eolian_class_file_get(klass) + std::string(".hh"));
};
auto complex_function
= [&] (efl::eolian::grammar::attributes::complex_type_def const& complex)
{
for(auto&& t : complex.subtypes)
{
variant_function(t);
}
};
variant_function = [&] (efl::eolian::grammar::attributes::type_def const& type)
{
if(efl::eolian::grammar::attributes::klass_name const*
name = efl::eolian::grammar::attributes::get<efl::eolian::grammar::attributes::klass_name>
(&type.original_type))
klass_name_function(*name);
else if(efl::eolian::grammar::attributes::complex_type_def const*
complex = efl::eolian::grammar::attributes::get<efl::eolian::grammar::attributes::complex_type_def>
(&type.original_type))
complex_function(*complex);
};
std::function<void(Eolian_Class const*)> klass_function
= [&] (Eolian_Class const* klass)
{
for(efl::eina::iterator<const char> inherit_iterator ( ::eolian_class_inherits_get(klass))
, inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
{
Eolian_Class const* inherit = ::eolian_class_get_by_name(&*inherit_iterator);
c_headers.insert(eolian_class_file_get(inherit) + std::string(".h"));
cpp_headers.insert(eolian_class_file_get(inherit) + std::string(".hh"));
klass_function(inherit);
}
efl::eolian::grammar::attributes::klass_def klass_def(klass);
for(auto&& f : klass_def.functions)
{
variant_function(f.return_type);
for(auto&& p : f.parameters)
{
variant_function(p.type);
}
}
for(auto&& e : klass_def.events)
{
if(e.type)
variant_function(*e.type);
}
};
klass_function(klass);
cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh"));
std::string guard_name;
as_generator(*(efl::eolian::grammar::string << "_") << efl::eolian::grammar::string << "_EO_HH")
.generate(std::back_insert_iterator<std::string>(guard_name)
, std::make_tuple(klass_def.namespaces, klass_def.eolian_name)
, efl::eolian::grammar::context_null{});
std::tuple<std::string, std::set<std::string>&, std::set<std::string>&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
> attributes
{guard_name, c_headers, cpp_headers, klasses, klasses, klasses, klasses};
if(opts.out_file == "-")
{
efl::eolian::generate(std::cout, std::cout, cls, gen_opts);
std::ostream_iterator<char> iterator(std::cout);
efl::eolian::grammar::class_header.generate(iterator, attributes, efl::eolian::grammar::context_null());
std::endl(std::cout);
efl::eolian::grammar::impl_header.generate(iterator, klasses, efl::eolian::grammar::context_null());
std::endl(std::cout);
std::flush(std::cout);
std::flush(std::cerr);
}
else
{
@ -167,10 +181,18 @@ generate(const Eolian_Class& klass, eolian_cxx::options_type const& opts)
return false;
}
efl::eolian::generate(header_decl, header_impl, cls, gen_opts);
#if 1
efl::eolian::grammar::class_header.generate
(std::ostream_iterator<char>(header_decl), attributes, efl::eolian::grammar::context_null());
efl::eolian::grammar::impl_header.generate
(std::ostream_iterator<char>(header_impl), klasses, efl::eolian::grammar::context_null());
#else
efl::eolian::generate(header_decl, header_impl, cls, gen_opts);
#endif
header_decl.close();
header_impl.close();
header_decl.close();
}
return true;
}
@ -179,34 +201,23 @@ static void
run(options_type const& opts)
{
const Eolian_Class *klass = NULL;
if (!opts.classname.empty())
klass = class_from_name(opts.classname);
else if (!opts.in_file.empty())
klass = class_from_file(opts.in_file);
char* dup = strdup(opts.in_file.c_str());
char* base = basename(dup);
klass = ::eolian_class_get_by_file(base);
free(dup);
if (klass)
{
if (!generate(*klass, opts))
if (!generate(klass, opts))
goto err;
}
else
{
efl::eina::iterator<const Eolian_Class> it(class_list_all());
efl::eina::iterator<const Eolian_Class> end;
while (it != end)
{
Eolian_Class c = (*it);
if (!generate(c, opts))
{
klass = &c;
goto err;
}
++it;
}
std::abort();
}
return;
err:
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Error generating: " << class_name(*klass)
<< "Error generating: " << ::eolian_class_name_get(klass)
<< std::endl;
assert(false && "error generating class");
}
@ -228,20 +239,17 @@ database_load(options_type const& opts)
<< "Eolian failed parsing eot files";
assert(false && "Error parsing eot files");
}
if (!opts.in_file.empty())
if (opts.in_file.empty())
{
if (!::eolian_file_parse(opts.in_file.c_str()))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Failed parsing: " << opts.in_file << ".";
assert(false && "Error parsing input file");
}
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "No input file.";
assert(false && "Error parsing input file");
}
else if (!::eolian_all_eo_files_parse())
if (!::eolian_file_parse(opts.in_file.c_str()))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Eolian failed parsing input files";
assert(false && "Error parsing input files");
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Failed parsing: " << opts.in_file << ".";
assert(false && "Error parsing input file");
}
if (!::eolian_database_validate(EINA_FALSE))
{
@ -299,11 +307,7 @@ opts_get(int argc, char **argv)
const struct option long_options[] =
{
{ "in", required_argument, 0, 'I' },
{ "out-dir", required_argument, 0, 'D' },
{ "out-file", required_argument, 0, 'o' },
{ "class", required_argument, 0, 'c' },
{ "all", no_argument, 0, 'a' },
{ "recurse", no_argument, 0, 'r' },
{ "version", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
@ -317,29 +321,11 @@ opts_get(int argc, char **argv)
{
opts.include_dirs.push_back(optarg);
}
else if (c == 'D')
{
_assert_not_dup("D", opts.out_dir);
opts.out_dir = optarg;
}
else if (c == 'o')
{
_assert_not_dup("o", opts.out_file);
opts.out_file = optarg;
}
else if (c == 'c')
{
_assert_not_dup("c", opts.classname);
opts.classname = optarg;
}
else if (c == 'a')
{
opts.generate_all = true;
}
else if (c == 'r')
{
opts.recurse = true;
}
else if (c == 'h')
{
_usage(argv[0]);

View File

@ -1,430 +0,0 @@
#ifndef EOLIAN_CXX_EOLIAN_WRAPPERS_HH
#define EOLIAN_CXX_EOLIAN_WRAPPERS_HH
#include <cassert>
#include <libgen.h>
#include <Eolian.h>
#include "eo_types.hh"
#include "safe_strings.hh"
#include "type_lookup.hh"
namespace eolian_cxx
{
struct property_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROPERTY; };
property_t const property = {};
struct setter_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROP_SET; };
setter_t const setter = {};
struct getter_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROP_GET; };
getter_t const getter = {};
struct method_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_METHOD; };
method_t const method = {};
inline efl::eolian::eolian_scope
eolian_scope_cxx(Eolian_Object_Scope s)
{
using efl::eolian::eolian_scope;
return s == EOLIAN_SCOPE_PRIVATE ? eolian_scope::private_ :
s == EOLIAN_SCOPE_PROTECTED ? eolian_scope::protected_ :
eolian_scope::public_;
}
inline const Eolian_Class*
class_from_file(std::string const& file)
{
char *dup = strdup(file.c_str());
char *bn = basename(dup);
const Eolian_Class *cl = ::eolian_class_get_by_file(bn);
free(dup);
return cl;
}
inline std::string
class_file(Eolian_Class const& klass)
{
return safe_str(::eolian_class_file_get(&klass));
}
inline std::string
class_base_file(Eolian_Class const& klass)
{
return path_base(safe_str(::eolian_class_file_get(&klass)));
}
inline std::string
class_name(Eolian_Class const& klass)
{
return ::eolian_class_name_get(&klass);
}
inline std::string
class_full_name(Eolian_Class const& klass)
{
return safe_str(::eolian_class_full_name_get(&klass));
}
inline const Eolian_Class *
class_from_name(std::string const& classname)
{
return ::eolian_class_get_by_name(classname.c_str());
}
inline std::string
class_eo_name(Eolian_Class const& klass)
{
std::string suffix;
switch (::eolian_class_type_get(&klass))
{
case EOLIAN_CLASS_REGULAR:
case EOLIAN_CLASS_ABSTRACT:
suffix = "CLASS";
break;
case EOLIAN_CLASS_MIXIN:
suffix = "MIXIN";
break;
case EOLIAN_CLASS_INTERFACE:
suffix = "INTERFACE";
break;
default:
break;
}
return safe_upper
(find_replace(class_full_name(klass) + "_" + suffix, ".", "_"));
}
inline efl::eolian::eo_class::eo_class_type
class_type(Eolian_Class const& klass)
{
efl::eolian::eo_class::eo_class_type type = {};
Eolian_Class_Type cls_type = ::eolian_class_type_get(&klass);
if (cls_type == EOLIAN_CLASS_REGULAR)
type = efl::eolian::eo_class::regular_;
else if (cls_type == EOLIAN_CLASS_ABSTRACT)
type = efl::eolian::eo_class::regular_noninst_;
else if (cls_type == EOLIAN_CLASS_MIXIN)
type = efl::eolian::eo_class::mixin_;
else if (cls_type == EOLIAN_CLASS_INTERFACE)
type = efl::eolian::eo_class::interface_;
else { assert(false); }
return type;
}
inline std::string
class_namespace_full(Eolian_Class const& klass)
{
std::string s;
Eina_Iterator* itr = ::eolian_class_namespaces_get(&klass);
void* name;
EINA_ITERATOR_FOREACH(itr, name)
{
s += static_cast<const char*>(name);
s += "::";
}
eina_iterator_free(itr);
if (s.size() >= 2)
s = s.substr(0, s.size()-2);
return safe_lower(s);
}
inline efl::eina::iterator<const Eolian_Class>
class_list_all()
{
return efl::eina::iterator<const Eolian_Class>(::eolian_all_classes_get());
}
inline Eolian_Function const&
constructor_function(Eolian_Constructor const& ctor)
{
assert(!!::eolian_constructor_function_get(&ctor));
return * ::eolian_constructor_function_get(&ctor);
}
inline efl::eina::iterator<const Eolian_Function>
functions_get(Eolian_Class const& cls)
{
Eina_Iterator *itr = ::eolian_class_functions_get(&cls, EOLIAN_METHOD); // XXX
return itr
? efl::eina::iterator<const Eolian_Function>(itr)
: efl::eina::iterator<const Eolian_Function>();
}
inline std::string
function_name(Eolian_Function const& func)
{
return keyword_avoid(::eolian_function_name_get(&func));
}
inline std::string
function_impl(Eolian_Function const& func)
{
const char *s = ::eolian_function_full_c_name_get(&func, EOLIAN_METHOD, EINA_FALSE);
std::string ret(s);
::eina_stringshare_del(s);
return ret;
}
inline Eolian_Function_Type
function_op_type(Eolian_Function const& func)
{
return ::eolian_function_type_get(&func);
}
inline efl::eolian::eo_function::eo_function_type
function_type(Eolian_Function const& func)
{
return ::eolian_function_is_class(&func)
? efl::eolian::eo_function::class_
: efl::eolian::eo_function::regular_
;
}
inline bool
function_is_constructor(Eolian_Class const& cls, Eolian_Function const& func)
{
return ::eolian_function_is_constructor(&func, &cls);
}
inline bool
function_is_beta(Eolian_Function const& func)
{
return ::eolian_function_is_beta(&func);
}
inline efl::eolian::eolian_scope
function_scope(Eolian_Function const& func)
{
return eolian_scope_cxx(::eolian_function_scope_get(&func));
}
inline bool
function_is_visible(Eolian_Function const& func, Eolian_Function_Type func_type)
{
Eolian_Object_Scope s = ::eolian_function_scope_get(&func);
return ((s == EOLIAN_SCOPE_PUBLIC || s == EOLIAN_SCOPE_PROTECTED) &&
!::eolian_function_is_legacy_only(&func, func_type));
}
inline bool
function_is_visible(Eolian_Function const& func, method_t)
{
return function_is_visible(func, method_t::value);
}
inline bool
function_is_visible(Eolian_Function const& func)
{
return function_is_visible(func, function_op_type(func));
}
inline bool
function_is_visible(Eolian_Constructor const& ctor_)
{
Eolian_Function const* func = ::eolian_constructor_function_get(&ctor_);
Eolian_Class const* cls = ::eolian_constructor_class_get(&ctor_);
assert(!!func);
assert(!!cls);
return (::eolian_class_ctor_enable_get(cls) &&
function_is_visible(*func, method_t::value));
}
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));
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& func, setter_t func_type)
{
return function_return_type(func, func_type.value);
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& func, getter_t func_type)
{
return function_return_type(func, func_type.value);
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& func, method_t func_type)
{
return function_return_type(func, func_type.value);
}
inline bool
function_return_is_explicit_void(Eolian_Function const& func, getter_t func_type)
{
// XXX This function shouldn't exist. Eolian should
// forge functions a priori. Bindings generators
// shouldn't be required to convert such thing.
Eolian_Type const* type =
::eolian_function_return_type_get(&func, func_type.value);
return !!type && type->type == EOLIAN_TYPE_VOID;
}
inline efl::eina::iterator<const Eolian_Function>
properties_get(Eolian_Class const& cls)
{
Eina_Iterator *itr = ::eolian_class_functions_get(&cls, EOLIAN_PROPERTY); // XXX
return itr
? efl::eina::iterator<const Eolian_Function>(itr)
: efl::eina::iterator<const Eolian_Function>();
}
inline bool
property_is_getter(Eolian_Function_Type func_type)
{
return func_type == property_t::value || func_type == getter_t::value;
}
inline bool
property_is_getter(Eolian_Function const& func)
{
return property_is_getter(function_op_type(func));
}
inline bool
property_is_setter(Eolian_Function_Type func_type)
{
return func_type == property_t::value || func_type == setter_t::value;
}
inline bool
property_is_setter(Eolian_Function const& func)
{
return property_is_setter(function_op_type(func));
}
inline std::string
parameter_name(Eolian_Function_Parameter const& parameter)
{
return safe_str(::eolian_parameter_name_get(&parameter)) + "_";
}
inline bool
parameter_is_out(Eolian_Function_Parameter const& parameter)
{
Eolian_Parameter_Dir direction = eolian_parameter_direction_get(&parameter);
return direction == EOLIAN_OUT_PARAM || direction == EOLIAN_INOUT_PARAM;
}
inline efl::eolian::eolian_type_instance
parameter_type(Eolian_Function_Parameter const& parameter)
{
efl::eolian::eolian_type_instance type
(type_lookup(::eolian_parameter_type_get(&parameter)));
assert(!type.empty());
if (parameter_is_out(parameter))
{
if (type.front().native.find("char") != std::string::npos)
type = { efl::eolian::type_to_native(type) };
type.is_out = true;
type.front().native += "*";
}
type.is_optional = ::eolian_parameter_is_optional(&parameter) ||
::eolian_parameter_is_nullable(&parameter);
return type;
}
inline efl::eolian::eo_event
event_create(const Eolian_Event *event_)
{
efl::eolian::eo_event event;
const char *name = ::eolian_event_name_get(event_);
if (name)
{
std::string name_ = safe_str(name);
std::transform(name_.begin(), name_.end(), name_.begin(),
[](int c) { return c != ',' ? c : '_'; });
event.scope = eolian_scope_cxx(::eolian_event_scope_get(event_));
event.is_beta = (::eolian_event_is_beta(event_) != EINA_FALSE);
event.name = normalize_spaces(name_);
event.eo_name = safe_str(::eolian_event_c_name_get(event_));
/* FIXME: use doc api */
event.comment = safe_str("");
}
return event;
}
inline efl::eolian::events_container_type
event_list(Eolian_Class const& klass)
{
efl::eolian::events_container_type events;
Eina_Iterator *itr = ::eolian_class_events_get(&klass);
Eolian_Event *e;
EINA_ITERATOR_FOREACH(itr, e)
{
events.push_back(event_create(e));
}
eina_iterator_free(itr);
return events;
}
inline efl::eina::iterator<const Eolian_Implement>
implements_get(Eolian_Class const& cls)
{
Eina_Iterator *itr = ::eolian_class_implements_get(&cls);
return itr
? efl::eina::iterator<const Eolian_Implement>(itr)
: efl::eina::iterator<const Eolian_Implement>();
}
inline bool
implement_is_property_get(Eolian_Implement const& impl)
{
return ::eolian_implement_is_prop_get(&impl);
}
inline bool
implement_is_property_set(Eolian_Implement const& impl)
{
return ::eolian_implement_is_prop_set(&impl);
}
inline bool
implement_is_property(Eolian_Implement const& impl)
{
return implement_is_property_get(impl) ||
implement_is_property_set(impl);
}
inline Eolian_Function const*
implement_function(Eolian_Implement const& impl)
{
return ::eolian_implement_function_get(&impl, nullptr);
}
inline Eolian_Class const*
implement_class(Eolian_Implement const& impl)
{
return ::eolian_implement_class_get(&impl);
}
// XXX This function shouldn't exist. Eolian should provide some way
// to determine if a method is a destructor.
inline bool
implement_is_destructor(Eolian_Implement const& impl)
{
return !safe_str
(::eolian_implement_full_name_get(&impl)).compare("Eo.Base.destructor");
}
inline bool
implement_is_visible(Eolian_Implement const& impl)
{
return function_is_visible(*implement_function(impl)) &&
!::eolian_implement_is_virtual(&impl) &&
!::eolian_implement_is_empty(&impl) &&
!implement_is_destructor(impl);
}
}
#endif // EOLIAN_CXX_EOLIAN_WRAPPERS_HH

View File

@ -1,160 +0,0 @@
#ifndef EOLIAN_CXX_BIN_SAFE_STRINGS_HH
#define EOLIAN_CXX_BIN_SAFE_STRINGS_HH
#include <string>
#include <algorithm>
#include <cstddef>
#include <cctype>
#include <iterator>
extern "C"
{
#include <Eina.h>
}
/// @brief Safely convert const char* to std::string.
///
inline std::string
safe_str(const char* str)
{
return (str != NULL) ? str : "";
}
/// @brief Safely convert Eina_Stringshare to std::string.
///
inline std::string
safe_strshare(Eina_Stringshare* strsh)
{
std::string ret = strsh != NULL ? strsh : "";
eina_stringshare_del(strsh);
return ret;
}
/// @brief Get a lower-case copy of string.
///
inline std::string
safe_lower(std::string const& s)
{
std::string res;
res.resize(s.size());
std::transform(s.begin(), s.end(), res.begin(), ::tolower);
return res;
}
/// @brief Get a lower-case copy of string.
///
inline std::string
safe_lower(const char *s)
{
return safe_lower(safe_str(s));
}
/// @brief Get a upper-case copy of string.
///
inline std::string
safe_upper(std::string const& s)
{
std::string res;
res.resize(s.size());
std::transform(s.begin(), s.end(), res.begin(), ::toupper);
return res;
}
/// @brief Get a upper-case copy of string.
///
inline std::string
safe_upper(const char* s)
{
return safe_upper(safe_str(s));
}
/// @brief Trim both ends of the string and replaces any
/// subsequence of contiguous spaces with a single space.
///
inline std::string
normalize_spaces(std::string const& s)
{
std::ostringstream os;
bool prev_is_space = true;
std::remove_copy_if
(s.begin(), s.end(),
std::ostream_iterator<char>(os),
[&prev_is_space] (char c)
{
bool r = ::isspace(c);
if (r && prev_is_space)
return true;
prev_is_space = r;
return false;
});
std::string r = os.str();
if (!r.empty() && ::isspace(r.back()))
r.erase(r.end()-1, r.end());
return r;
}
/// @brief Return the basename of a path.
///
inline std::string
path_base(std::string path)
{
std::string::reverse_iterator
slash = std::find(path.rbegin(), path.rend(), '/');
return std::string(slash.base(), path.end());
}
/// @brief Find-and-replace patterns in a string.
///
inline std::string
find_replace(std::string const& s_,
std::string const& old,
std::string const& new_)
{
std::string s = s_;
std::string::size_type found = s.find(old);
std::string::size_type len = new_.length();
while (found != std::string::npos)
{
s.replace(found, len, new_);
found = s.find(old);
}
return s;
}
/// @brief Append '_' if @p key is a C++ keyword.
///
inline std::string
keyword_avoid(std::string const& name)
{
if (name == "delete" ||
name == "throw" ||
name == "break" ||
name == "friend" ||
name == "goto" ||
name == "default" ||
name == "new" ||
name == "auto" ||
name == "do" ||
name == "sizeof" ||
name == "try" ||
name == "this" ||
name == "virtual" ||
name == "register" ||
name == "typename" ||
name == "template")
{
return name + "_"; // XXX Warn?
}
return name;
}
/// @brief Append '_' if @p key is a C++ keyword.
///
inline std::string
keyword_avoid(const char* name)
{
return keyword_avoid(safe_str(name));
}
#endif // EOLIAN_CXX_BIN_SAFE_STRINGS_HH

View File

@ -1,160 +0,0 @@
#ifndef EOLIAN_CXX_TYPE_LOOKUP_HH
#define EOLIAN_CXX_TYPE_LOOKUP_HH
#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
#include <iterator>
#include <stdexcept>
#include <cassert>
#include <cstddef>
#include <Eolian.h>
#include <eolian_database.h>
#include <Eina.hh>
#include "eo_types.hh"
#include "safe_strings.hh"
namespace eolian_cxx {
typedef std::vector<efl::eolian::eolian_type> lookup_table_type;
extern const lookup_table_type type_lookup_table;
inline std::string
class_format_cxx(std::string const& fullname)
{
auto current = fullname.begin(), last = fullname.end();
auto found = std::find(current, last, '.');
std::string new_string;
if(found == last)
new_string = "nonamespace::" + fullname;
else
while (current != last)
{
if(found == last)
{
new_string.insert(new_string.end(), current, found);
current = found;
}
else
{
new_string += std::tolower(*current);
new_string.insert(new_string.end(), std::next(current), found);
new_string = safe_lower(new_string);
new_string += "::";
current = std::next(found);
found = std::find(current, last, '.');
}
}
return new_string;
}
inline bool
type_is_complex(Eolian_Type const& type)
{
return ::eolian_type_type_get(&type) == EOLIAN_TYPE_COMPLEX;
}
inline efl::eolian::eolian_type
type_from_eolian(Eolian_Type const& type)
{
efl::eolian::eolian_type x;
Eolian_Type_Type tpt = ::eolian_type_type_get(&type);
if (tpt == EOLIAN_TYPE_CLASS)
{
Eolian_Class const* klass = ::eolian_type_class_get(&type);
if (klass)
{
x.category = efl::eolian::eolian_type::simple_;
x.is_class = true;
x.binding_requires_optional = false;
x.binding = "::" + class_format_cxx(safe_str(::eolian_class_full_name_get(klass)));
x.native = "::";
x.native += safe_str( ::eolian_class_full_name_get(klass));
std::replace(x.native.begin(), x.native.end(), '.', '_');
if( ::eolian_type_is_const(&type))
x.native += " const";
x.native += '*';
Eina_Stringshare* klass_file = ::eolian_class_file_get(klass);
if (klass_file)
x.includes = {safe_str(klass_file) + ".hh"};
}
}
if(x.native.empty())
x.native = normalize_spaces(safe_str(::eolian_type_c_type_get(&type)));
x.is_own = ::eolian_type_is_own(&type);
x.is_const = ::eolian_type_is_const(&type);
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 }; // XXX shouldn't
// assert(type != NULL);
std::vector<Eolian_Type const*> types;
types.push_back(type);
if (type_is_complex(*type))
{
efl::eina::iterator<Eolian_Type const> end;
efl::eina::iterator<Eolian_Type const> it
(::eolian_type_subtypes_get(type));
while(it != end)
{
if(Eolian_Type const* t = &*it)
{
types.push_back
/* remove this base type get when pointers are removed */
( ::eolian_type_type_get(t) == EOLIAN_TYPE_POINTER ? ::eolian_type_base_type_get(t)
: t
);
++it;
}
}
}
efl::eolian::eolian_type_instance v(types.size());
for (std::size_t i = 0; i != types.size(); ++i)
{
v.parts[i] = type_find(lut.begin(), lut.end(), type_from_eolian(*types[i]));
}
// Let's degrade to opaque classes when not enough information
// is available for complex types
if(v.parts.size() == 1 && type_is_complex(v.front()))
{
efl::eolian::eolian_type tmp = v.front();
return {efl::eolian::type_to_native(tmp)};
}
return v;
}
} // namespace eolian_cxx {
#endif // EOLIAN_CXX_TYPE_LOOKUP_HH

View File

@ -1,36 +0,0 @@
#include "type_lookup.hh"
namespace eolian_cxx {
using efl::eolian::eolian_type;
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"}},
{"Edje_Signal_Cb", eolian_type::callback_, {"Edje.h"}},
{"Eina_Accessor *", eolian_type::complex_, false, false, true, false, "::efl::eina::accessor", {"eina_accessor.hh"}},
{"Eina_Bool", eolian_type::simple_, false, false, false, false, "bool", {}},
{"Eina_Bool *", eolian_type::simple_, false, false, false, false, "bool*", {}},
{"Eina_Inlist *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_inlist", {"eina_inlist.hh"}},
{"Eina_Inlist *", eolian_type::complex_, false, true, true, true, "::efl::eina::inlist", {"eina_inlist.hh"}},
{"Eina_Iterator *", eolian_type::complex_, false, false, true, true, "::efl::eina::iterator", {"eina_iterator.hh"}},
{"Eina_List *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_list", {"eina_list.hh"}},
{"Eina_List *", eolian_type::complex_, false, true, true, true, "::efl::eina::list", {"eina_list.hh"}},
{"const Eina_List *", eolian_type::complex_, true, false, true, true, "::efl::eina::crange_list", {"eina_list.hh"}},
{"Eina_Array *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_array", {"eina_array.hh"}},
{"Eina_Array *", eolian_type::complex_, false, true, true, true, "::efl::eina::array", {"eina_array.hh"}},
{"const Eina_Array *", eolian_type::complex_, true, false, true, true, "::efl::eina::crange_array", {"eina_array.hh"}},
{"Eio_Filter_Direct_Cb", eolian_type::callback_, {"Eio.h"}},
{"Eo *", eolian_type::simple_, false, true, true, false, "::efl::eo::concrete", {"eo_concrete.hh"}},
{"Eo *", eolian_type::simple_, false, false, true, false, "::efl::eo::concrete", {"eo_concrete.hh"}},
//{"Evas_Object_Box_Layout", eolian_type::callback_, {"Evas.h"}},
//{"char *", eolian_type::simple_, false, true, true, false, "std::unique_ptr<char*>", {"memory"}},
{"const Eina_Inlist *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_inlist", {"eina_inlist.hh"}},
{"const Eina_List *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_list", {"eina_ptrlist.hh"}},
{"const char *", eolian_type::simple_, false, false, true, true, "::efl::eina::string_view", {"string"}},
};
}

View File

@ -4,6 +4,9 @@
#include <eo_concrete.hh>
#include <eo_init.hh>
#include <eo_wref.hh>
#include <eo_inherit.hh>
// #include <eo_inherit.hh>
//#include <eo_own_ptr.hh>
#include <eo_cxx_interop.hh>
#include <eo_event.hh>
#endif // EFL_CXX_EO_HH

View File

@ -11,7 +11,6 @@
#include <eina_optional.hh>
#include "eo_ops.hh"
#include "eo_event.hh"
#ifndef EFL_CXX_THROW
#if defined ( EFL_CXX_NO_EXCEPTIONS )
@ -22,9 +21,9 @@
#endif
#if !defined(EFL_DOXYGEN) && !defined(EO_CXX_INHERIT)
# define EO_CXX_INHERIT(name) ::eo_cxx::name
# define EO_CXX_INHERIT(name) ::eo_cxx name
#elif !defined(EO_CXX_INHERIT)
# define EO_CXX_INHERIT(name) ::name
# define EO_CXX_INHERIT(name) name
#endif
namespace efl { namespace eo {
@ -137,53 +136,11 @@ struct concrete
_eo_raw = _ptr;
}
/// @brief Get the reference count of this object.
///
/// @return The referencer count of this object.
///
int ref_get() const { return detail::ref_get(_eo_raw); }
/// @brief Set the parent of this object.
///
/// @param parent The new parent.
///
void parent_set(concrete parent)
{
detail::parent_set(_eo_raw, parent._eo_ptr());
}
/// @brief Get the parent of this object.
///
/// @return An @ref efl::eo::concrete instance that binds the parent
/// object. Returns NULL if there is no parent.
///
eina::optional<concrete> parent_get()
{
Eo *r = detail::parent_get(_eo_raw);
if(!r) return nullptr;
else
{
detail::ref(r); // XXX eo_parent_get does not call eo_ref so we may.
return concrete(r);
}
}
/// @brief Get debug information of this object.
///
/// @return The root node of the debug information tree.
///
Eo_Dbg_Info dbg_info_get()
{
Eo_Dbg_Info info;
detail::dbg_info_get(_eo_raw, &info);
return info;
}
explicit operator bool() const
{
return _eo_raw;
}
protected:
protected:
Eo* _eo_raw; ///< The opaque <em>EO Object</em>.
};
@ -223,20 +180,6 @@ struct extension_inheritance<concrete>
};
};
struct concrete_address_of
{
explicit concrete_address_of(void* p) : p(p) {}
operator void*() { return p; }
void* p;
};
struct concrete_address_const_of
{
explicit concrete_address_const_of(void const* p) : p(p) {}
operator void const*() { return p; }
void const* p;
};
}
/// @brief Downcast @p U to @p T.
@ -264,42 +207,17 @@ T downcast(U object)
}
}
///
/// @brief Type used to hold the parent passed to concrete Eo C++
/// constructors.
///
struct parent_type
{
Eo* _eo_raw;
};
///
/// @brief The expression type declaring the assignment operator used
/// in the parent argument of the concrete Eo C++ class.
///
struct parent_expr
{
parent_type operator=(efl::eo::concrete const& parent) const
{
return { parent._eo_ptr() };
}
template <typename T>
parent_type operator=(T const& parent) const
{
return { parent._eo_ptr() };
}
parent_type operator=(std::nullptr_t) const
{
return { nullptr };
}
};
///
/// @brief Placeholder for the parent argument.
///
parent_expr const parent = {};
template <typename T>
struct is_eolian_object : std::false_type {};
template <typename T>
struct is_eolian_object<T const> : is_eolian_object<T> {};
template <typename T>
struct is_eolian_object<T const&> : is_eolian_object<T> {};
template <typename T>
struct is_eolian_object<T&> : is_eolian_object<T> {};
template <>
struct is_eolian_object<eo::concrete> : std::true_type {};
/// @}
} } // namespace efl { namespace eo {

File diff suppressed because it is too large Load Diff

View File

@ -8,11 +8,13 @@
#include <Eo.h>
#include <Ecore.h>
#include "eo_concrete.hh"
#include "eo_cxx_interop.hh"
#include <functional>
#include <memory>
namespace efl { namespace eo {
namespace efl { namespace eolian {
typedef ::Eo_Callback_Priority callback_priority;
namespace callback_priorities
@ -121,30 +123,77 @@ signal_connection make_signal_connection(std::unique_ptr<F>& data, Eo* eo, ::Eo_
namespace _detail {
template <typename T, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, Eo_Event_Description const& desc, void *info
, std::true_type)
template <typename T, typename P, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, void *, std::true_type, std::true_type)
{
f(wrapper, desc, info);
f(wrapper);
return true;
}
template <typename T, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, Eo_Event_Description const& desc, void *info
, std::false_type)
template <typename T, typename P, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, void *info, std::true_type, std::false_type)
{
return f(wrapper, desc, info);
f(wrapper, convert_to_event<P>(info));
return true;
}
template <typename T, typename P, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, void *, std::false_type, std::true_type)
{
return f(wrapper);
}
template <typename T, typename P, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, void *info, std::false_type, std::false_type)
{
return f(wrapper, convert_to_event<P>(info));
}
template <typename T, typename P, typename F, typename Enable = void>
struct is_void;
template <typename T, typename P, typename F>
struct is_void<T, P, F, typename std::enable_if
<std::is_void<decltype(std::declval<F>()(std::declval<T>(), std::declval<P>()))>::value>::type>
: std::true_type {};
template <typename T, typename P, typename F>
struct is_void<T, P, F, typename std::enable_if
<!std::is_void<decltype(std::declval<F>()(std::declval<T>(), std::declval<P>()))>::value>::type>
: std::false_type {};
template <typename T, typename F>
struct is_void<T, void, F, typename std::enable_if
<std::is_void<decltype(std::declval<F>()(std::declval<T>()))>::value>::type>
: std::true_type {};
template <typename T, typename F>
struct is_void<T, void, F, typename std::enable_if
<!std::is_void<decltype(std::declval<F>()(std::declval<T>()))>::value>::type>
: std::false_type {};
template <typename T, typename P, typename F>
Eina_Bool
event_callback(void *data, ::Eo_Event const* event)
{
T wrapper(::eo_ref(event->object));
F *f = static_cast<F*>(data);
return _detail::really_call_event(wrapper, *f, *event->desc, event->info
, std::is_void<decltype((*f)(wrapper, *event->desc, event->info))>());
return _detail::really_call_event<T, P>
(wrapper, *f, event->info, is_void<T, P, F>(), std::is_void<P>{});
}
}
template <typename Event, typename Object, typename F>
signal_connection event_add(Event event, Object object, F&& function)
{
static_assert((eo::is_eolian_object<Object>::value), "Type is not an object");
typedef typename std::remove_reference<F>::type function_type;
std::unique_ptr<function_type> f(new function_type(std::forward<F>(function)));
::eo_event_callback_priority_add
(object._eo_ptr(), event.description(), 0
, static_cast<Eo_Event_Cb>
(&_detail::event_callback<Object, typename Event::parameter_type, function_type>)
, f.get());
return make_signal_connection
(f, object._eo_ptr()
, static_cast<Eo_Event_Cb>
(&_detail::event_callback<Object, typename Event::parameter_type, function_type>)
, event.description());
}
} }

View File

@ -1,155 +1,155 @@
///
/// @file eo_inherit.hh
///
// ///
// /// @file eo_inherit.hh
// ///
#ifndef EFL_CXX_EO_INHERIT_HH
#define EFL_CXX_EO_INHERIT_HH
// #ifndef EFL_CXX_EO_INHERIT_HH
// #define EFL_CXX_EO_INHERIT_HH
#include <tuple>
#include <cassert>
// #include <tuple>
// #include <cassert>
#include <eina_integer_sequence.hh>
// #include <eina_integer_sequence.hh>
#include "eo_ops.hh"
#include "eo_private.hh"
#include "eo_cxx_interop.hh"
// #include "eo_ops.hh"
// #include "eo_private.hh"
// #include "eo_cxx_interop.hh"
namespace efl { namespace eo {
// namespace efl { namespace eo {
namespace detail {
// namespace detail {
template <typename D, typename... E, std::size_t... S>
Eo_Class const* create_class(eina::index_sequence<S...>);
// template <typename D, typename... E, std::size_t... S>
// Eo_Class const* create_class(eina::index_sequence<S...>);
/// @internal
///
/// @brief Find the correct function for the <em>"constructor"</em>
/// operation and invoke it.
///
/// @param this_ The <em>user data</em> to be passed to the resolved function.
/// @param args An heterogeneous sequence of arguments.
///
inline EO_VOID_FUNC_BODYV(inherit_constructor, EO_FUNC_CALL(this_), void* this_);
// /// @internal
// ///
// /// @brief Find the correct function for the <em>"constructor"</em>
// /// operation and invoke it.
// ///
// /// @param this_ The <em>user data</em> to be passed to the resolved function.
// /// @param args An heterogeneous sequence of arguments.
// ///
// inline EO_VOID_FUNC_BODYV(inherit_constructor, EO_FUNC_CALL(this_), void* this_);
}
// }
/// @addtogroup Efl_Cxx_API
/// @{
// /// @addtogroup Efl_Cxx_API
// /// @{
/// @brief Template-class that allows client code to inherit from
/// <em>EO C++ Classes</em> without the need to make explicit calls to
/// <em>EO</em> methods --- that would naturally be necessary to
/// register itself in the <em>EO Subsystem</em>.
///
/// @param D The derived class
/// @param O The parent class
/// @param E Class extensions (either mixins or interfaces)
///
/// The derived class @p D will inherit all EO operations and event
/// callbacks from the parent class @p P, as well as from the <c>Base
/// Class</c> (@ref efl::eo::concrete) since every EO C++ Class must
/// inherit from it.
///
/// efl::eo::inherit makes use of meta-template elements to build (in
/// compile-time) code capable of registering @p D as an <em>EO
/// Class</em> within <em>EO Subsystem</em>. Each class is registered
/// only once upon instantiation of an object of its type.
///
/// @note Function overriding is currently not supported.
///
template <typename D, typename... E>
struct inherit;
// /// @brief Template-class that allows client code to inherit from
// /// <em>EO C++ Classes</em> without the need to make explicit calls to
// /// <em>EO</em> methods --- that would naturally be necessary to
// /// register itself in the <em>EO Subsystem</em>.
// ///
// /// @param D The derived class
// /// @param O The parent class
// /// @param E Class extensions (either mixins or interfaces)
// ///
// /// The derived class @p D will inherit all EO operations and event
// /// callbacks from the parent class @p P, as well as from the <c>Base
// /// Class</c> (@ref efl::eo::concrete) since every EO C++ Class must
// /// inherit from it.
// ///
// /// efl::eo::inherit makes use of meta-template elements to build (in
// /// compile-time) code capable of registering @p D as an <em>EO
// /// Class</em> within <em>EO Subsystem</em>. Each class is registered
// /// only once upon instantiation of an object of its type.
// ///
// /// @note Function overriding is currently not supported.
// ///
// template <typename D, typename... E>
// struct inherit;
/// @}
// /// @}
/// @addtogroup Efl_Cxx_API
/// @{
// /// @addtogroup Efl_Cxx_API
// /// @{
template <typename D, typename... E>
struct inherit
: detail::operations<E>::template type<inherit<D, E...> > ...
, detail::conversion_operator<inherit<D, E...>, E>...
{
/// @typedef inherit_base
///
typedef inherit<D, E...> inherit_base;
// template <typename D, typename... E>
// struct inherit
// : detail::operations<E>::template type<inherit<D, E...> > ...
// , detail::conversion_operator<inherit<D, E...>, E>...
// {
// /// @typedef inherit_base
// ///
// typedef inherit<D, E...> inherit_base;
//@{
/// @brief Class constructor.
///
/// @ref inherit has a "variadic" constructor implementation that
/// allows from zero to EFL_MAX_ARGS heterogeneous parameters.
///
template<typename... Args>
inherit(efl::eo::parent_type _p, Args&& ... args)
{
_eo_cls = detail::create_class<D, E...> (eina::make_index_sequence<sizeof...(E)>());
_eo_raw = eo_add_ref(_eo_cls, _p._eo_raw, detail::inherit_constructor(eo_self, this), ::efl::eolian::call_ctors(eo_self, args...));
::efl::eolian::register_ev_del_free_callback(_eo_raw, args...);
}
// //@{
// /// @brief Class constructor.
// ///
// /// @ref inherit has a "variadic" constructor implementation that
// /// allows from zero to EFL_MAX_ARGS heterogeneous parameters.
// ///
// template<typename... Args>
// inherit(efl::eo::parent_type _p, Args&& ... args)
// {
// _eo_cls = detail::create_class<D, E...> (eina::make_index_sequence<sizeof...(E)>());
// _eo_raw = eo_add_ref(_eo_cls, _p._eo_raw, detail::inherit_constructor(eo_self, this), ::efl::eolian::call_ctors(eo_self, args...));
// ::efl::eolian::register_ev_del_free_callback(_eo_raw, args...);
// }
template<typename... Args>
inherit(Args&& ... args)
: inherit(::efl::eo::parent = nullptr, std::forward<Args>(args)...)
{}
//@}
// template<typename... Args>
// inherit(Args&& ... args)
// : inherit(::efl::eo::parent = nullptr, std::forward<Args>(args)...)
// {}
// //@}
/// @brief Class destructor.
///
~inherit()
{
detail::unref(_eo_raw);
}
// /// @brief Class destructor.
// ///
// ~inherit()
// {
// detail::unref(_eo_raw);
// }
/// @brief Gets the <em>EO Object</em> corresponding to this <em>EO
/// C++ Object</em>.
///
/// @return A pointer to the <em>EO Object</em>.
///
Eo* _eo_ptr() const { return _eo_raw; }
// /// @brief Gets the <em>EO Object</em> corresponding to this <em>EO
// /// C++ Object</em>.
// ///
// /// @return A pointer to the <em>EO Object</em>.
// ///
// Eo* _eo_ptr() const { return _eo_raw; }
/// @brief Gets the <em>EO Class</em> corresponding to this <em>EO
/// C++ Class</em>.
///
/// @return A pointer to the <em>EO Class</em>.
///
Eo_Class const* _eo_class() const { return _eo_cls; }
// /// @brief Gets the <em>EO Class</em> corresponding to this <em>EO
// /// C++ Class</em>.
// ///
// /// @return A pointer to the <em>EO Class</em>.
// ///
// Eo_Class const* _eo_class() const { return _eo_cls; }
Eo* _release()
{
Eo* tmp = _eo_raw;
_eo_raw = nullptr;
return tmp;
}
// Eo* _release()
// {
// Eo* tmp = _eo_raw;
// _eo_raw = nullptr;
// return tmp;
// }
protected:
/// @brief Copy constructor.
///
inherit(inherit const& other)
: _eo_cls(other._eo_cls)
, _eo_raw(other._eo_raw)
{ detail::ref(_eo_raw); }
// protected:
// /// @brief Copy constructor.
// ///
// inherit(inherit const& other)
// : _eo_cls(other._eo_cls)
// , _eo_raw(other._eo_raw)
// { detail::ref(_eo_raw); }
/// @brief Assignment Operator
///
inherit& operator=(inherit const& other)
{
_eo_cls = other._eo_cls;
_eo_raw = other._eo_raw;
detail::ref(_eo_raw);
return *this;
}
// /// @brief Assignment Operator
// ///
// inherit& operator=(inherit const& other)
// {
// _eo_cls = other._eo_cls;
// _eo_raw = other._eo_raw;
// detail::ref(_eo_raw);
// return *this;
// }
private:
Eo_Class const* _eo_cls; ///< The <em>EO Class</em>.
Eo* _eo_raw; ///< The <em>EO Object</em>.
};
// private:
// Eo_Class const* _eo_cls; ///< The <em>EO Class</em>.
// Eo* _eo_raw; ///< The <em>EO Object</em>.
// };
/// @}
// /// @}
} } // namespace efl { namespace eo {
// } } // namespace efl { namespace eo {
#include "eo_inherit_bindings.hh"
// #include "eo_inherit_bindings.hh"
#endif // EFL_CXX_INHERIT_HH
// #endif // EFL_CXX_INHERIT_HH

View File

@ -1,3 +1,5 @@
#define EFL_EO_API_SUPPORT
#include <Elementary.hh>
EAPI_MAIN int
@ -5,16 +7,11 @@ elm_main (int argc, char *argv[])
{
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
::elm::win_standard win;
win.title_set("Bg Plain");
::elm::win::Standard win;
// win.title_set("Bg Plain");
win.autohide_set(true);
::elm::bg bg(efl::eo::parent = win);
bg.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
win.resize_object_add(bg);
bg.visible_set(true);
win.size_set(320,320);
win.eo_cxx::efl::Gfx::size_set(320,320);
win.visible_set(true);
elm_run();

View File

@ -1,3 +1,5 @@
#define EFL_EO_API_SUPPORT
#include <Elementary.hh>
EAPI_MAIN int
@ -5,28 +7,23 @@ elm_main (int argc, char *argv[])
{
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
::elm::win_standard win;
win.title_set("Hello, World!");
::elm::win::Standard win;
//win.title_set("Hello, World!");
win.autohide_set(true);
::elm::bg bg(efl::eo::parent = win);
bg.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
win.resize_object_add(bg);
bg.visible_set(true);
::elm::button btn(efl::eo::parent = win);
::elm::Button btn(win);
btn.text_set("elm.text","Good-Bye, World!");
btn.size_set(120, 30);
btn.position_set(60, 15);
btn.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
btn.size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL);
btn.eo_cxx::efl::Gfx::size_set(120, 30);
btn.eo_cxx::efl::Gfx::position_set(60, 15);
// btn.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
// btn.size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL);
btn.visible_set(true);
auto on_click = std::bind([] () { elm_exit(); });
btn.callback_clicked_add( on_click );
efl::eolian::event_add(evas::Clickable_Interface::clicked_event, btn, on_click);
win.size_set(240, 60);
win.eo_cxx::efl::Gfx::size_set(240, 60);
win.visible_set(true);
elm_run();

View File

@ -93,15 +93,15 @@ IMPL = \
SRCS = \
eolian_cxx_simple_01.cc \
eolian_cxx_inherit_01.cc \
eolian_cxx_callbacks_01.cc \
$(IMPL)
# eolian_cxx_inherit_01.cc
EXTRA_PROGRAMS = \
eolian_cxx_simple_01 \
eolian_cxx_simple_01_cxx_impl \
eolian_cxx_inherit_01 \
eolian_cxx_callbacks_01
# eolian_cxx_inherit_01
DATA_FILES = Makefile.examples $(ECXX_EXAMPLE_EOS)
EXTRA_DIST = $(DATA_FILES)
@ -120,11 +120,11 @@ eolian_cxx_simple_01_cxx_impl_SOURCES = \
colourablesquare_cxx.cc
eolian_cxx_simple_01_cxx_impl.$(OBJEXT): $(GENERATED)
eolian_cxx_inherit_01_SOURCES = \
eolian_cxx_inherit_01.cc \
colourable.c \
colourablesquare.c
eolian_cxx_inherit_01.$(OBJEXT): $(GENERATED)
# eolian_cxx_inherit_01_SOURCES = \
# eolian_cxx_inherit_01.cc \
# colourable.c \
# colourablesquare.c
# eolian_cxx_inherit_01.$(OBJEXT): $(GENERATED)
eolian_cxx_callbacks_01_SOURCES = eolian_cxx_callbacks_01.cc

View File

@ -63,7 +63,6 @@ _ns_colourable_rgb_24bits_constructor(Eo *obj, Colourable_Data *self, int rgb)
self->g = (rgb & 0x0000ff00) >> 8;
self->b = rgb & 0x000000ff;
DBG("_ns_colourable_rgb_24bits_constructor(0x%.6x)\n", (int)rgb);
eo_constructor(eo_super(obj, MY_CLASS));
}
void

View File

@ -42,7 +42,6 @@ _colourable_rgb_24bits_constructor(Eo *obj, Colourable_Data *self, int rgb)
self->r = (rgb & 0x00ff0000) >> 16;
self->g = (rgb & 0x0000ff00) >> 8;
self->b = rgb & 0x000000ff;
eo_constructor(eo_super(obj, MY_CLASS));
}
void

View File

@ -35,7 +35,6 @@ _ns_colourablesquare_size_constructor(Eo *obj, ColourableSquare_Data *self, int
}
self->size = size;
DBG("_ns_colourablesquare_constructor(%d)\n", size);
eo_constructor(eo_super(obj, MY_CLASS));
}
static int

View File

@ -25,7 +25,6 @@ _colourablesquare_size_constructor(Eo *obj, ColourableSquare_Data *self, int siz
{
self->size = size;
EINA_CXX_DOM_LOG_DBG(domain) << __func__ << " [ size = " << size << " ]" << std::endl;
eo_constructor(eo_super(obj, MY_CLASS));
}
int

View File

@ -18,15 +18,13 @@ main()
eina_log_domain_level_set("colourablesquare", EINA_LOG_LEVEL_DBG);
int r, g, b;
::ns::Colourable obj1(
obj1.rgb_24bits_constructor(0x123456)
);
::ns::Colourable obj1
([&] { obj1.rgb_24bits_constructor(0x123456); });
obj1.colour_set(0xc0ffee);
obj1.composite_colour_get(&r, &g, &b);
obj1.composite_colour_get(r, g, b);
::ns::ColourableSquare obj2(
obj2.size_constructor(10)
);
::ns::ColourableSquare obj2
([&] { obj2.size_constructor(10); });
obj2.composite_colour_set(r, g, b);
obj2.size_set(11);
assert(obj1.colour_get() == obj2.colour_get());

View File

@ -1,7 +1,6 @@
class Ns.Colourable (Eo.Base)
{
[[Colourable class.]]
legacy_prefix: legacy;
data: Colourable_Data;
methods {
rgb_24bits_constructor {

View File

@ -1,6 +1,5 @@
class Ns.ColourableSquare (Ns.Colourable)
{
legacy_prefix: legacy;
data: ColourableSquare_Data;
methods {
@property size {

View File

@ -26,12 +26,4 @@ struct eolian_init
} }
#ifdef EFL_BETA_API_SUPPORT
#include "eo_types.hh"
#include "eo_validate.hh"
#include "eo_generate.hh"
#endif
#endif // EOLIAN_CXX_LIB_HH

View File

@ -1,23 +0,0 @@
#ifndef EOLIAN_CXX_EO_GENERATE_HH
#define EOLIAN_CXX_EO_GENERATE_HH
#include <iosfwd>
#include "eo_types.hh"
#include "grammar/eo_header_generator.hh"
namespace efl { namespace eolian {
inline void
generate(std::ostream& header_decl,
std::ostream& header_impl,
eo_class const& cls,
eo_generator_options const& opts)
{
grammar::eo_headers_generator(header_decl, header_impl, cls, opts);
}
} }
#endif // EOLIAN_CXX_EO_GENERATE_HH

View File

@ -1,350 +0,0 @@
#ifndef EOLIAN_CXX_EO_TYPES_HH
#define EOLIAN_CXX_EO_TYPES_HH
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
namespace efl { namespace eolian {
struct eo_constructor;
struct eo_parameter;
struct eo_function;
struct eo_event;
typedef std::vector<std::string> ancestors_container_type;
typedef std::vector<std::string> includes_container_type;
typedef std::vector<eo_constructor> constructors_container_type;
typedef std::vector<eo_function> functions_container_type;
typedef std::vector<eo_parameter> parameters_container_type;
typedef std::vector<eo_event> events_container_type;
enum class eolian_scope
{
public_, protected_, private_
};
struct eolian_type
{
enum category_type
{
unknown_, simple_, complex_, callback_
};
eolian_type()
: native("")
, category(unknown_)
, is_const(false)
, is_own(false)
, is_class(false)
, binding_requires_optional(false)
, binding()
, includes()
{}
eolian_type(std::string native_,
category_type category_,
bool is_const_,
bool is_own_,
bool is_class_,
bool binding_requires_optional_,
std::string binding_,
includes_container_type includes_)
: native(native_)
, category(category_)
, is_const(is_const_)
, is_own(is_own_)
, is_class(is_class_)
, binding_requires_optional(binding_requires_optional_)
, 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, false, false, false, "", includes_)
{
assert(category == callback_);
}
std::string native;
category_type category;
bool is_const;
bool is_own;
bool is_class;
bool binding_requires_optional;
std::string binding;
includes_container_type includes;
};
typedef std::vector<eolian_type> eolian_type_container;
struct eolian_type_instance
{
eolian_type_instance()
: is_out(false)
, is_optional(false)
, parts()
{}
eolian_type_instance(std::initializer_list<eolian_type> il,
bool is_out_ = false,
bool is_optional_ = false)
: is_out(is_out_)
, is_optional(is_optional_)
, parts(il)
{}
explicit eolian_type_instance(std::size_t size)
: is_out(false)
, is_optional(false)
, parts(size)
{}
bool empty() const { return parts.empty(); }
std::size_t size() const { return parts.size(); }
eolian_type& front() { return parts.front(); }
eolian_type const& front() const { return parts.front(); }
bool is_out;
bool is_optional;
eolian_type_container parts;
};
const efl::eolian::eolian_type
void_type { "void", efl::eolian::eolian_type::simple_, false, false, false, false, "", {} };
inline bool
type_is_void(eolian_type_instance const& type)
{
return type.empty() || type.front().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 bool
type_is_out(eolian_type_instance const& type)
{
return type.is_out;
}
inline bool
type_is_class(eolian_type const& type)
{
return type.is_class;
}
inline bool
type_is_class(eolian_type_instance const& type)
{
assert(!type.empty());
return type_is_class(type.front());
}
inline bool
type_binding_requires_optional(eolian_type const& type)
{
return type.binding_requires_optional;
}
inline bool
type_binding_requires_optional(eolian_type_instance const& type)
{
assert(!type.empty());
return type_binding_requires_optional(type.front());
}
inline bool
type_is_optional(eolian_type_instance const& type)
{
return type.is_optional;
}
inline eolian_type
type_to_native(eolian_type const& type)
{
eolian_type native(type);
native.binding.clear();
native.category = eolian_type::simple_;
native.is_class = false;
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_;
}
inline bool
type_is_complex(eolian_type_instance const& type_ins)
{
assert(!type_ins.empty());
return type_is_complex(type_ins.front());
}
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
{
std::string header_decl_file_name;
std::string header_impl_file_name;
includes_container_type cxx_headers;
includes_container_type c_headers;
};
struct eo_class
{
enum eo_class_type
{
regular_, regular_noninst_, interface_, mixin_
};
eo_class_type type;
std::string name;
std::string eo_name;
ancestors_container_type parents;
ancestors_container_type ancestors;
constructors_container_type constructors;
constructors_container_type optional_constructors;
constructors_container_type all_constructors;
functions_container_type functions;
events_container_type own_events;
events_container_type concrete_events;
std::string comment;
std::string name_space;
};
struct eo_parameter
{
eolian_type_instance type;
std::string name;
};
struct eo_constructor
{
std::string name;
std::string impl;
parameters_container_type params;
std::string comment;
};
struct eo_function
{
enum eo_function_type
{
regular_, class_
};
eo_function_type type;
eolian_scope scope;
bool is_beta;
std::string name;
std::string impl;
eolian_type_instance ret;
parameters_container_type params;
std::string comment;
};
struct eo_event
{
eo_event() : scope(eolian_scope::public_), is_beta(false), name(),
eo_name(), comment()
{}
eolian_scope scope;
bool is_beta;
std::string name;
std::string eo_name;
//parameters_container_type params; // XXX desirable.
std::string comment;
bool operator<(eo_event const& other) const { return name < other.name; }
};
inline bool
function_is_void(eo_function const& func)
{
return func.ret.empty() || func.ret.front().native.compare("void") == 0;
}
inline bool
function_is_static(eo_function const& func)
{
return func.type == eo_function::class_;
}
inline unsigned int
parameters_count_callbacks(parameters_container_type const& parameters)
{
unsigned int r = 0u;
for (auto first = parameters.begin(), last = parameters.end()
; first != last ; ++first)
if(type_is_callback(first->type) && first + 1 != last)
++r;
return r;
}
inline parameters_container_type::const_iterator
parameters_find_callback(parameters_container_type const& parameters)
{
for (auto it = parameters.cbegin(), last = parameters.cend();
it != last; ++it)
{
if (type_is_callback((*it).type) && it + 1 != last)
return it;
}
return parameters.cend();
}
} } // namespace efl { namespace eolian {
#endif // EFL_EOLIAN_CXX_EO_TYPES_HH

View File

@ -1,116 +0,0 @@
#ifndef EOLIAN_CXX_EO_CLASS_VALIDATE_HH
#define EOLIAN_CXX_EO_CLASS_VALIDATE_HH
#include <algorithm>
#include <string>
#include <cassert>
#include <cstdlib>
#include "eo_types.hh"
#include <iostream>
namespace efl { namespace eolian {
inline bool
_is_valid(std::string const& value)
{
return !value.empty() and (isalpha(value[0]) || 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.parts.rbegin(), last = type.parts.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_)
// {
// std::cout << "begin " << (rit != type.rbegin()) << std::endl;
// std::cout << "category " << rit->category << std::endl;
// 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 const& val, eo_class const& cls)
{
if(!_is_valid(val))
{
static_cast<void>(cls);
assert(false && "Failed identifier validation");
}
}
inline void
eo_class_validate(const eo_class& cls)
{
// class name and type
_validate(cls.name, cls);
assert(cls.type == eo_class::regular_ ||
cls.type == eo_class::regular_noninst_ ||
cls.type == eo_class::interface_ ||
cls.type == eo_class::mixin_);
// constructors
for (auto it = cls.constructors.cbegin(), last = cls.constructors.cend();
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)
{
_validate((*it_p).name, cls);
_validate((*it_p).type, cls);
}
}
// functions
for (auto it = cls.functions.begin(), last = cls.functions.end();
it != last; ++it)
{
_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)
{
_validate((*it_p).name, cls);
_validate((*it_p).type, cls);
}
}
// events
_validate(cls.own_events, cls);
_validate(cls.concrete_events, cls);
}
} } // namespace efl { namespace eolian {
#endif // EOLIAN_CXX_EO_CLASS_VALIDATE_HH

View File

@ -0,0 +1,74 @@
#ifndef EOLIAN_CXX_ADDRESS_OF_HH
#define EOLIAN_CXX_ADDRESS_OF_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_declaration.hpp"
#include "grammar/case.hpp"
namespace efl { namespace eolian { namespace grammar {
struct address_of_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
{
std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
if(!as_generator
(
scope_tab << " ::efl::eolian::address_of_operator<" << string
).generate(sink, cls.cxx_name, context)) return false;
for(auto&& i : cls.inherits)
{
if(!as_generator(", " << *("::" << lower_case[string]) << "::" << string)
.generate(sink, std::make_tuple(attributes::cpp_namespaces(i.namespaces), i.eolian_name), context))
return false;
}
if(!as_generator
(
"> operator&() { return {this}; }\n"
).generate(sink, attributes::unused, context)) return false;
if(!as_generator
(
scope_tab << " ::efl::eolian::address_of_operator<" << string << " const "
).generate(sink, cls.cxx_name, context)) return false;
for(auto&& i : cls.inherits)
{
if(!as_generator(", " << *("::" << lower_case[string]) << "::" << string << " const ")
.generate(sink, std::make_tuple(attributes::cpp_namespaces(i.namespaces), i.eolian_name), context))
return false;
}
if(!as_generator
(
"> operator&() const { return {this}; }\n"
).generate(sink, attributes::unused, context)) return false;
return true;
}
};
template <>
struct is_eager_generator<address_of_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<address_of_generator> : std::integral_constant<int, 1> {};
}
address_of_generator const address_of;
} } }
#endif

View File

@ -0,0 +1,52 @@
#ifndef EOLIAN_CXX_ALTERNATIVE_HH
#define EOLIAN_CXX_ALTERNATIVE_HH
#include "grammar/generator.hpp"
#include "grammar/meta.hpp"
#include "grammar/variant.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename L, typename R>
struct alternative_generator
{
template <typename OutputIterator, typename...Args, typename Context>
bool generate(OutputIterator /*sink*/, attributes::variant<Args...> const& /*attribute*/, Context const& /*context*/) const
{
// return grammar::alternative_sequence(left, right, sink, attribute);
return false;
}
template <typename OutputIterator, typename Attribute, typename...Args, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
if(!attributes::generate(as_generator(left), sink, attribute, context))
return attributes::generate(as_generator(right), sink, attribute, context);
else
return true;
}
L left;
R right;
};
template <typename L, typename R>
struct is_eager_generator<alternative_generator<L, R> > : std::true_type {};
namespace type_traits {
template <typename L, typename R>
struct attributes_needed<alternative_generator<L, R> > : std::integral_constant
<int, meta::max<attributes_needed<L>::value, attributes_needed<R>::value>::value> {};
template <typename L, typename R>
struct accepts_tuple<alternative_generator<L, R> > : std::true_type {};
}
template <typename L, typename R>
typename std::enable_if<grammar::is_generator<L>::value && grammar::is_generator<R>::value, alternative_generator<L, R>>::type
operator|(L l, R r)
{
return alternative_generator<L, R>{l, r};
}
} } }
#endif

View File

@ -0,0 +1,66 @@
#ifndef EOLIAN_CXX_ATTRIBUTE_CONDITIONAL_HH
#define EOLIAN_CXX_ATTRIBUTE_CONDITIONAL_HH
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename F, typename G>
struct functional_attribute_conditional_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
{
if(f(attribute))
return as_generator(g).generate(sink, attribute, ctx);
else
return false;
}
F f;
G g;
};
template <typename F, typename G>
struct is_eager_generator<functional_attribute_conditional_generator<F, G>> : std::true_type {};
template <typename F>
struct functional_attribute_conditional_directive
{
template <typename G>
functional_attribute_conditional_generator<F, G> operator[](G g) const
{
return {f, g};
}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator, Attribute const& attribute, Context const&) const
{
return f(attribute);
}
F f;
};
template <typename F>
struct is_eager_generator<functional_attribute_conditional_directive<F>> : std::true_type {};
struct attribute_conditional_terminal
{
template <typename F>
functional_attribute_conditional_directive<F> operator()(F f) const
{
return {f};
}
} const attribute_conditional;
namespace type_traits {
template <typename F, typename G>
struct attributes_needed<functional_attribute_conditional_generator<F, G>> : attributes_needed<G> {};
template <typename F>
struct attributes_needed<functional_attribute_conditional_directive<F>> : std::integral_constant<int, 1> {};
}
} } }
#endif

View File

@ -0,0 +1,87 @@
#ifndef EOLIAN_CXX_ATTRIBUTE_REORDER_HH
#define EOLIAN_CXX_ATTRIBUTE_REORDER_HH
#include "grammar/generator.hpp"
#include "grammar/attributes.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename Tuple, int...S>
struct reorder_tuple
{
Tuple* tuple;
};
namespace impl {
template <int N, typename T>
struct index_calc;
template <int N, typename Tuple, int...S>
struct index_calc<0, reorder_tuple<Tuple, N, S...>> : std::integral_constant<int, N> {};
template <int I, int N, typename Tuple, int...S>
struct index_calc<I, reorder_tuple<Tuple, N, S...>> : index_calc<I-1, reorder_tuple<Tuple, S...>> {};
}
namespace attributes {
template <int N, typename Tuple, int...S>
struct tuple_element<N, reorder_tuple<Tuple, S...>>
{
template <typename T>
struct identity { typedef T type; };
typedef impl::index_calc<N, reorder_tuple<Tuple, S...>> index;
typedef typename std::conditional
<index::value == -1
, identity<Tuple>
, tuple_element<index::value, typename std::remove_const<Tuple>::type>>::type::type type;
static type const& get_impl(reorder_tuple<Tuple, S...> const& t
, std::integral_constant<int, -1>)
{ return *t.tuple; }
template <int I>
static type const& get_impl(reorder_tuple<Tuple, S...> const& t
, std::integral_constant<int, I>)
{ using std::get; return get<index::value>(*t.tuple); }
static type const& get(reorder_tuple<Tuple, S...> const& t)
{ return get_impl(t, index{}); }
};
}
template <int N, typename Tuple, int...S>
typename attributes::tuple_element<N, reorder_tuple<Tuple, S...>>::type const& get(reorder_tuple<Tuple, S...>const& t)
{
return attributes::tuple_element<N, reorder_tuple<Tuple, S...>>::get(t);
}
template <typename G, int...S>
struct attribute_reorder_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
{
return attributes::generate(as_generator(g), sink, reorder_tuple<Attribute const, S...>{&attribute}, ctx);
}
G g;
};
template <typename G, int...S>
struct is_eager_generator<attribute_reorder_generator<G, S...>> : std::true_type {};
template <int...S, typename G>
attribute_reorder_generator<G, S...> attribute_reorder(G g)
{
return {g};
}
namespace type_traits {
template <typename G, int...S>
struct attributes_needed<attribute_reorder_generator<G, S...>> : attributes_needed<G> {};
template <int...S, typename Tuple>
struct is_explicit_tuple<reorder_tuple<Tuple, S...>> : std::true_type {};
template <int...S, typename Tuple>
struct is_tuple<reorder_tuple<Tuple, S...>> : std::true_type {};
}
} } }
#endif

View File

@ -0,0 +1,63 @@
#ifndef EOLIAN_CXX_ATTRIBUTE_REPLACE_HH
#define EOLIAN_CXX_ATTRIBUTE_REPLACE_HH
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename F, typename G>
struct functional_attribute_replace_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
{
return as_generator(g).generate(sink, f(attribute), ctx);
}
F f;
G g;
};
template <typename F, typename G>
struct is_eager_generator<functional_attribute_replace_generator<F, G>> : std::true_type {};
template <typename F>
struct functional_attribute_replace_directive
{
template <typename G>
functional_attribute_replace_generator<F, G> operator[](G g) const
{
return {f, g};
}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator, Attribute const& attribute, Context const&) const
{
return f(attribute);
}
F f;
};
template <typename F>
struct is_eager_generator<functional_attribute_replace_directive<F>> : std::true_type {};
struct attribute_replace_terminal
{
template <typename F>
functional_attribute_replace_directive<F> operator()(F f) const
{
return {f};
}
} const attribute_replace;
namespace type_traits {
template <typename F, typename G>
struct attributes_needed<functional_attribute_replace_generator<F, G>> : attributes_needed<G> {};
template <typename F>
struct attributes_needed<functional_attribute_replace_directive<F>> : std::integral_constant<int, 1> {};
}
} } }
#endif

View File

@ -0,0 +1,185 @@
#ifndef EOLIAN_CXX_ATTRIBUTES_HH
#define EOLIAN_CXX_ATTRIBUTES_HH
#include <tuple>
#include <type_traits>
#include "grammar/type_traits.hpp"
namespace efl { namespace eolian { namespace grammar {
namespace attributes {
struct unused_type {};
unused_type const unused;
template <int N, typename Tuple, typename Enable = void>
struct tuple_element;
template <int N, typename Tuple>
struct tuple_element<N, Tuple, typename std::enable_if
<type_traits::is_std_tuple<Tuple>::value>::type> : std::tuple_element<N, Tuple>
{};
template <int N, typename Tuple>
typename tuple_element<N, typename std::remove_const<Tuple>::type>::type get_adl(Tuple& tuple)
{
using std::get;
return get<N>(tuple);
}
template <int I, typename Tuple>
struct lazy_offset_tuple
{
lazy_offset_tuple(Tuple& tuple)
: tuple(tuple) {}
template <int N>
typename tuple_element<N+I, typename std::remove_const<Tuple>::type>::type get() const
{
return attributes::get_adl<N+I>(tuple);
}
Tuple& tuple;
};
}
namespace type_traits {
template <int N, typename T>
struct is_tuple<attributes::lazy_offset_tuple<N, T>> : std::true_type {};
template <int N, typename T>
struct is_explicit_tuple<attributes::lazy_offset_tuple<N, T>> : std::true_type {};
}
namespace attributes {
template <typename T>
struct infinite_tuple
{
T object;
};
template <typename T>
infinite_tuple<T> make_infinite_tuple(T&& object)
{
return infinite_tuple<T>{std::forward<T>(object)};
}
template <int N, typename T>
struct tuple_element<N, infinite_tuple<T>>
{
typedef T type;
static type& get(infinite_tuple<T>& tuple) { return tuple.object; }
static type const& get(infinite_tuple<T> const& tuple) { return tuple.object; }
};
template <int N, typename T>
struct tuple_element<N, infinite_tuple<T> const> : tuple_element<N, infinite_tuple<T>> {};
template <int N, typename T>
typename tuple_element<N, infinite_tuple<T>>::type&
get(infinite_tuple<T>& tuple)
{
return tuple_element<N, infinite_tuple<T>>::get(tuple);
}
template <int N, typename T>
typename tuple_element<N, infinite_tuple<T>>::type const&
get(infinite_tuple<T> const& tuple)
{
return tuple_element<N, infinite_tuple<T>>::get(tuple);
}
}
namespace type_traits {
template <typename T>
struct is_tuple<attributes::infinite_tuple<T>> : std::true_type {};
template <typename T>
struct is_explicit_tuple<attributes::infinite_tuple<T>> : std::true_type {};
}
namespace attributes {
template <int N, int I, typename Tuple>
struct tuple_element<N, lazy_offset_tuple<I, Tuple>> : tuple_element<N+I, typename std::remove_const<Tuple>::type>
{};
template <int N, int I, typename Tuple>
struct tuple_element<N, lazy_offset_tuple<I, Tuple> const> : tuple_element<N+I, typename std::remove_const<Tuple>::type>
{};
template <int N, int I, typename Tuple>
typename tuple_element<N, lazy_offset_tuple<I, Tuple> const>::type
get(lazy_offset_tuple<I, Tuple> const& tuple)
{
return tuple.template get<N>();
}
template <typename Tuple>
lazy_offset_tuple<1, Tuple> pop_front(Tuple& tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value>::type* = 0)
{
return lazy_offset_tuple<1, Tuple>(tuple);
}
template <int N, typename Tuple>
lazy_offset_tuple<N + 1, Tuple> pop_front(lazy_offset_tuple<N, Tuple> tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value>::type* = 0)
{
return lazy_offset_tuple<N + 1, Tuple>(tuple.tuple);
}
template <int I, typename Tuple>
lazy_offset_tuple<I, Tuple> pop_front_n(Tuple& tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value && I>::type* = 0)
{
return lazy_offset_tuple<I, Tuple>(tuple);
}
template <int I, typename Tuple>
Tuple& pop_front_n(Tuple& tuple, typename std::enable_if<I == 0>::type* = 0)
{
return tuple;
}
template <int I, int N, typename Tuple>
lazy_offset_tuple<N + I, Tuple> pop_front_n(lazy_offset_tuple<N, Tuple> tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value>::type* = 0)
{
return lazy_offset_tuple<N + I, Tuple>(tuple.tuple);
}
template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
bool generate(Generator const& gen, OutputIterator sink, Attribute const& attribute, Context const& context
, typename std::enable_if
<type_traits::is_explicit_tuple<Attribute>::value
&& !type_traits::accepts_tuple<Generator>::value
&& type_traits::attributes_needed<Generator>::value != 0
>::type* = 0)
{
return gen.generate(sink, get<0>(attribute), context);
}
template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
bool generate(Generator const& gen, OutputIterator sink, Attribute const& attribute, Context const& context
, typename std::enable_if
<type_traits::is_explicit_tuple<Attribute>::value
&& type_traits::accepts_tuple<Generator>::value
&& type_traits::attributes_needed<Generator>::value != 0
>::type* = 0)
{
return gen.generate(sink, attribute, context);
}
template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
bool generate(Generator const& gen, OutputIterator sink, Attribute const&
, Context const& context
, typename std::enable_if
<type_traits::attributes_needed<Generator>::value == 0
>::type* = 0)
{
return gen.generate(sink, unused, context);
}
template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
bool generate(Generator const& gen, OutputIterator sink, Attribute const& attribute, Context const& context
, typename std::enable_if
<!type_traits::is_explicit_tuple<Attribute>::value
&& type_traits::attributes_needed<Generator>::value != 0
>::type* = 0)
{
return gen.generate(sink, attribute, context);
}
} } } }
#endif

View File

@ -0,0 +1,112 @@
#ifndef EOLIAN_CXX_BASE_CLASS_DEFINITION_HH
#define EOLIAN_CXX_BASE_CLASS_DEFINITION_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_declaration.hpp"
#include "grammar/namespace.hpp"
#include "grammar/case.hpp"
#include "grammar/address_of.hpp"
namespace efl { namespace eolian { namespace grammar {
struct base_class_definition_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
{
std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
// static_assert(std::is_same<OutputIterator, void>::value, "");
auto open_namespace = *("namespace " << string << " { ") << "\n";
if(!as_generator(open_namespace).generate
(sink, cpp_namespaces, add_lower_case_context(context))) return false;
if(!as_generator
(
"struct " << string << " {\n"
).generate(sink, cls.cxx_name, context)) return false;
if(!as_generator(*(scope_tab << function_declaration))
.generate(sink, cls.functions, context)) return false;
// static Eo_Class const* _eo_class();
std::string suffix;
switch(cls.type)
{
case attributes::class_type::regular:
case attributes::class_type::abstract_:
suffix = "CLASS";
break;
case attributes::class_type::mixin:
suffix = "MIXIN";
break;
case attributes::class_type::interface_:
suffix = "INTERFACE";
break;
}
if(!as_generator
(
scope_tab << "static Eo_Class const* _eo_class()\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "return "
).generate(sink, attributes::unused, context)) return false;
if(!as_generator
(*(lower_case[string] << "_") << string << "_" << string)
.generate(sink, std::make_tuple(cls.namespaces, cls.eolian_name, suffix), add_upper_case_context(context)))
return false;
if(!as_generator(";\n" << scope_tab << "}\n").generate(sink, attributes::unused, context)) return false;
if(!as_generator
(
scope_tab << "Eo* _eo_ptr() const { return *(Eo**)this; }\n"
).generate(sink, attributes::unused, context)) return false;
// operator ::ns::Class_Name() const;
// operator ::ns::Class_Name&();
// operator ::ns::Class_Name const&() const;
if(!as_generator
(
scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "() const;\n"
<< scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "&();\n"
<< scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << " const&() const;\n"
).generate(sink, std::make_tuple
(cpp_namespaces, cls.cxx_name, cpp_namespaces, cls.cxx_name, cpp_namespaces, cls.cxx_name)
, context))
return false;
// /// @cond LOCAL
if(!as_generator(scope_tab << "/// @cond LOCAL\n").generate(sink, attributes::unused, context)) return false;
if(!as_generator(address_of).generate(sink, cls, context)) return false;
// /// @endcond
if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, attributes::unused, context)) return false;
if(!as_generator("};\n").generate(sink, attributes::unused, context)) return false;
auto close_namespace = *(lit("} ")) << "\n";
if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
return true;
}
};
template <>
struct is_eager_generator<base_class_definition_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<base_class_definition_generator> : std::integral_constant<int, 1> {};
}
base_class_definition_generator const base_class_definition;
} } }
#endif

View File

@ -0,0 +1,74 @@
#ifndef EOLIAN_CXX_C_TYPE_HH
#define EOLIAN_CXX_C_TYPE_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/string.hpp"
namespace efl { namespace eolian { namespace grammar { namespace attributes {
struct c_type_visitor
{
std::string const* c_type;
typedef std::string result_type;
std::string operator()(attributes::klass_name const& name) const
{
std::string n;
as_generator(" ::" << *(string << "_") << string << string << "*")
.generate(std::back_insert_iterator<std::string>(n)
, std::make_tuple(name.namespaces, name.eolian_name
, std::string{is_const(name.base_qualifier) ? " const" : ""})
, context_null {});
return n;
}
template <typename T>
std::string operator()(T const&) const
{
return *c_type;
}
};
inline std::string c_type(parameter_def const& param)
{
switch(param.direction)
{
case parameter_direction::in:
return param.type.original_type.visit(c_type_visitor{&param.c_type});
case parameter_direction::out:
case parameter_direction::inout:
return param.type.original_type.visit(c_type_visitor{&param.c_type}) + "*";
default:
throw std::runtime_error("Unknown parameter direction");
};
}
}
struct c_type_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& attribute, Context const& context) const
{
return as_generator(attributes::c_type(attribute)).generate(sink, attributes::unused, context);
}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& attribute, Context const& context) const
{
return as_generator(attribute.original_type.visit(attributes::c_type_visitor{&attribute.c_type}))
.generate(sink, attributes::unused, context);
}
};
template <>
struct is_eager_generator<c_type_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<c_type_generator> : std::integral_constant<int, 1> {};
}
c_type_generator const c_type;
} } }
#endif

View File

@ -0,0 +1,86 @@
#ifndef EOLIAN_CXX_CASE_HH
#define EOLIAN_CXX_CASE_HH
#include "grammar/context.hpp"
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
struct upper_case_tag {};
struct lower_case_tag {};
template <typename Context>
context_cons<upper_case_tag, Context>
add_upper_case_context(Context const& context)
{
return context_add_tag(upper_case_tag{}, context);
}
template <typename Context>
context_cons<lower_case_tag, Context>
add_lower_case_context(Context const& context)
{
return context_add_tag(lower_case_tag{}, context);
}
template <typename G>
struct lower_case_generator
{
lower_case_generator(G g) : g(g) {}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
return as_generator(g).generate(sink, attribute, add_lower_case_context(context));
}
G g;
};
template <typename G>
struct upper_case_generator
{
upper_case_generator(G g) : g(g) {}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
return as_generator(g).generate(sink, attribute, add_upper_case_context(context));
}
G g;
};
template <typename G>
struct is_eager_generator<lower_case_generator<G>> : std::true_type {};
template <typename G>
struct is_eager_generator<upper_case_generator<G>> : std::true_type {};
namespace type_traits {
template <typename G>
struct attributes_needed<lower_case_generator<G>> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<upper_case_generator<G>> : attributes_needed<G> {};
}
struct lower_case_directive
{
template <typename G>
lower_case_generator<G> operator[](G&& g) const
{
return lower_case_generator<G>{g};
}
} const lower_case;
struct upper_case_directive
{
template <typename G>
upper_case_generator<G> operator[](G&& g) const
{
return upper_case_generator<G>{g};
}
} const upper_case;
} } }
#endif

View File

@ -0,0 +1,56 @@
#ifndef EOLIAN_CXX_CLASS_DECLARATION_HH
#define EOLIAN_CXX_CLASS_DECLARATION_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_declaration.hpp"
namespace efl { namespace eolian { namespace grammar {
struct class_declaration_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
{
std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
auto open_namespace = *("namespace " << string << " { ") << "\n";
if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false;
if(!as_generator
(
"struct " << string << ";\n"
).generate(sink, cls.cxx_name, context)) return false;
auto close_namespace = *(lit("} ")) << "\n";
if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
if(!as_generator
(
"namespace efl { namespace eo { template<> struct is_eolian_object< "
"::" << *(lower_case[string] << "::") << string << "> : ::std::true_type {}; } }\n"
).generate(sink, std::make_tuple(cpp_namespaces, cls.cxx_name), context)) return false;
return true;
}
};
template <>
struct is_eager_generator<class_declaration_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<class_declaration_generator> : std::integral_constant<int, 1> {};
}
class_declaration_generator const class_declaration;
} } }
#endif

View File

@ -0,0 +1,176 @@
#ifndef EOLIAN_CXX_CLASS_DEFINITION_HH
#define EOLIAN_CXX_CLASS_DEFINITION_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_declaration.hpp"
#include "grammar/case.hpp"
#include "grammar/address_of.hpp"
#include "grammar/attribute_reorder.hpp"
#include "grammar/attribute_conditional.hpp"
#include "grammar/attribute_replace.hpp"
namespace efl { namespace eolian { namespace grammar {
struct class_definition_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
{
std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
auto open_namespace = *("namespace " << string << " { ") << "\n";
if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false;
if(!as_generator
(
"struct " << string << " : ::efl::eo::concrete"
)
.generate(sink, cls.cxx_name, context))
return false;
for(auto&& i : cls.inherits)
{
if(!as_generator("\n" << scope_tab << ", EO_CXX_INHERIT(" << *(" ::" << lower_case[string]) << "::" << string << ")")
.generate(sink, std::make_tuple(attributes::cpp_namespaces(i.namespaces), i.eolian_name), context))
return false;
}
if(!as_generator("\n{\n").generate(sink, attributes::unused, context)) return false;
// constructors
if(!as_generator
(
scope_tab << "explicit " << string << "( ::Eo* eo)\n"
<< scope_tab << scope_tab << ": ::efl::eo::concrete(eo) {}\n"
<< scope_tab << "explicit " << string << "(std::nullptr_t)\n"
<< scope_tab << scope_tab << ": ::efl::eo::concrete(nullptr) {}\n"
<< scope_tab << string << "(" << string << " const& other) = default;\n"
<< scope_tab << string << "(" << string << "&& other) = default;\n"
<< scope_tab << string << "& operator=(" << string << " const& other) = default;\n"
<< scope_tab << string << "& operator=(" << string << "&& other) = default;\n"
<< scope_tab << string << "()\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "::efl::eolian::do_eo_add( ::efl::eo::concrete::_eo_raw, ::efl::eo::concrete{nullptr}, _eo_class());\n"
<< scope_tab << "}\n"
<< scope_tab << string << "( ::efl::eo::concrete parent)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "::efl::eolian::do_eo_add( ::efl::eo::concrete::_eo_raw, parent, _eo_class());\n"
<< scope_tab << "}\n"
<< scope_tab << "template <typename F> " << string << "(F f, typename ::std::enable_if< ::efl::eolian::is_callable<F>::value>::type* = 0)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "::efl::eolian::do_eo_add( ::efl::eo::concrete::_eo_raw, ::efl::eo::concrete{nullptr}, _eo_class(), f);\n"
<< scope_tab << "}\n"
// << scope_tab << "explicit " << string << "( ::efl::eo::concrete const& parent)\n"
// << scope_tab << scope_tab << ": ::efl::eo::concrete( ::efl::eo::do_eo_add(parent)) {}\n"
// << scope_tab << "template <typename F>\n"
// << scope_tab << "explicit " << string << "( ::efl::eo::concrete const& parent, F f)\n"
// << scope_tab << scope_tab << ": ::efl::eo::concrete( ::efl::eo::do_eo_add(parent, f)) {}\n"
// << scope_tab << "template <typename F>\n"
// << scope_tab << "explicit " << string << "(F f)\n"
// << scope_tab << scope_tab << ": ::efl::eo::concrete( ::efl::eo::do_eo_add( ::efl::eo::concrete{nullptr}, f)) {}\n"
).generate(sink, attributes::make_infinite_tuple(cls.cxx_name), context)) return false;
if(!as_generator(*(scope_tab << function_declaration))
.generate(sink, cls.functions, context)) return false;
// static Eo_Class const* _eo_class();
std::string suffix;
switch(cls.type)
{
case attributes::class_type::regular:
case attributes::class_type::abstract_:
suffix = "CLASS";
break;
case attributes::class_type::mixin:
suffix = "MIXIN";
break;
case attributes::class_type::interface_:
suffix = "INTERFACE";
break;
}
if(!as_generator
(
scope_tab << "static Eo_Class const* _eo_class()\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "return "
).generate(sink, attributes::unused, context)) return false;
if(!as_generator
(*(string << "_") << string << "_" << string)
.generate(sink, std::make_tuple(cls.namespaces, cls.eolian_name, suffix), add_upper_case_context(context)))
return false;
if(!as_generator(";\n" << scope_tab << "}\n").generate(sink, attributes::unused, context)) return false;
if(!as_generator
(
scope_tab << "Eo* _eo_ptr() const { return *(Eo**)this; }\n"
).generate(sink, attributes::unused, context)) return false;
// operator ::ns::Class_Name() const;
// operator ::ns::Class_Name&();
// operator ::ns::Class_Name const&() const;
if(!as_generator
(
scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "() const;\n"
<< scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "&();\n"
<< scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << " const&() const;\n"
).generate(sink, std::make_tuple(cpp_namespaces, cls.cxx_name, cpp_namespaces, cls.cxx_name
, cpp_namespaces, cls.cxx_name), context))
return false;
if(!as_generator
(
*attribute_reorder<1, 2, 0, 1>
((scope_tab << "static struct " << string_replace(',', '_') << "_event\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "static Eo_Event_Description const* description()\n"
<< scope_tab << scope_tab << "{ return " << string << "; }\n"
<< scope_tab << scope_tab << "typedef "
<< (attribute_conditional([] (eina::optional<attributes::type_def> t) { return !!t; })
[attribute_replace([] (eina::optional<attributes::type_def> t) { return *t; }) [type]]
| "void")
<< " parameter_type;\n"
<< scope_tab << "} const " << string_replace(',', '_') << "_event;\n"
))).generate(sink, cls.events, context))
return false;
// /// @cond LOCAL
if(!as_generator(scope_tab << "/// @cond LOCAL\n").generate(sink, attributes::unused, context)) return false;
if(!as_generator(address_of).generate(sink, cls, context)) return false;
// /// @endcond
if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, attributes::unused, context)) return false;
if(!as_generator("};\n").generate(sink, attributes::unused, context)) return false;
// static asserts
if(!as_generator("static_assert(sizeof(" << string << ") == sizeof(Eo*), \"\");\n")
.generate(sink, cls.cxx_name, context)) return false;
if(!as_generator("static_assert(std::is_standard_layout<" << string << ">::value, \"\");\n")
.generate(sink, cls.cxx_name, context)) return false;
auto close_namespace = *(lit("} ")) << "\n";
if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
return true;
}
};
template <>
struct is_eager_generator<class_definition_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<class_definition_generator> : std::integral_constant<int, 1> {};
}
class_definition_generator const class_definition;
} } }
#endif

View File

@ -0,0 +1,56 @@
#ifndef EOLIAN_CXX_CLASS_IMPLEMENTATION_HH
#define EOLIAN_CXX_CLASS_IMPLEMENTATION_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/string.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_definition.hpp"
#include "grammar/namespace.hpp"
#include "grammar/type_impl.hpp"
#include "grammar/attribute_reorder.hpp"
namespace efl { namespace eolian { namespace grammar {
struct class_implementation_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& ctx) const
{
return as_generator
(
(namespaces
[*function_definition(get_klass_name(cls))]
// << "namespace eo_cxx {\n"
// << namespaces
// [*function_definition(get_klass_name(cls))]
// << "}\n\n"
)).generate(sink, std::make_tuple(cls.namespaces, cls.functions), ctx)
&& as_generator
(
"namespace eo_cxx {\n"
<< namespaces
[*function_definition(get_klass_name(cls))]
<< "}\n\n"
).generate(sink, std::make_tuple(cls.namespaces, cls.functions), ctx);
}
};
template <>
struct is_eager_generator<class_implementation_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<class_implementation_generator> : std::integral_constant<int, 1> {};
}
class_implementation_generator const class_implementation;
} } }
#endif

View File

@ -1,45 +0,0 @@
#ifndef EOLIAN_CXX_STD_COMMENT_HH
#define EOLIAN_CXX_STD_COMMENT_HH
#include <string>
#include <sstream>
#include <iosfwd>
#include <ostream>
#include "tab.hh"
namespace efl { namespace eolian { namespace grammar {
using std::endl;
const std::string comment_prefix("///");
struct comment
{
std::string _doc;
int _tab;
std::string _if_empty;
comment(std::string const& doc, int tab = 0, std::string const& if_empty = "")
: _doc(doc), _tab(tab), _if_empty(if_empty)
{}
};
inline std::ostream&
operator<<(std::ostream& out, comment const& x)
{
std::string const& doc = !x._doc.empty() ? x._doc : x._if_empty;
std::istringstream ss(doc);
std::string line;
while(std::getline(ss, line))
{
out << tab(x._tab) << comment_prefix
<< (line.size() ? (" " + line) : "")
<< endl;
}
return out;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_COMMENT_HH

View File

@ -0,0 +1,46 @@
#ifndef EOLIAN_CXX_CONTAINER_HH
#define EOLIAN_CXX_CONTAINER_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/case.hpp"
#include "grammar/type.hpp"
namespace efl { namespace eolian { namespace grammar {
struct container_subtype_modify
{
typedef void result_type;
void operator()(attributes::complex_type_def& /*x*/) const
{
}
void operator()(attributes::regular_type_def& x) const
{
if(x.base_type == "string")
remove_own(x.base_qualifier);
else if(!x.pointers.empty())
x.pointers.pop_back();
}
template <typename T>
void operator()(T& /*x*/) const
{
}
};
template <typename OutputIterator, typename Context>
void generate_container(OutputIterator sink, attributes::complex_type_def const& complex, Context const& context
, std::string const& name)
{
if(!complex.subtypes.empty())
{
attributes::type_def subtype = complex.subtypes[0];
subtype.original_type.visit(container_subtype_modify{});
as_generator(" "<< name << "<" << type << ">").generate(sink, subtype, context);
}
}
} } }
#endif

View File

@ -0,0 +1,46 @@
#ifndef EOLIAN_CXX_CONTEXT_HH
#define EOLIAN_CXX_CONTEXT_HH
namespace efl { namespace eolian { namespace grammar {
struct context_null {};
template <typename Tag, typename Tail = context_null>
struct context_cons
{
Tag tag;
Tail const& tail;
};
template <typename Tag>
struct context_cons<Tag, context_null>
{
Tag tag;
context_null tail;
};
template <typename NewTag, typename Tag, typename Tail>
context_cons<NewTag, context_cons<Tag, Tail>>
context_add_tag(NewTag tag, context_cons<Tag, Tail> const& context)
{
return context_cons<NewTag, context_cons<Tag, Tail>>{tag, context};
}
template <typename NewTag>
context_cons<NewTag, context_null>
context_add_tag(NewTag tag, context_null context)
{
return context_cons<NewTag, context_null>{tag, context};
}
template <typename Tag, typename Context>
struct tag_check;
template <typename Tag, typename Tail>
struct tag_check<Tag, context_cons<Tag, Tail>> : std::true_type {};
template <typename Tag>
struct tag_check<Tag, context_null> : std::false_type {};
template <typename Tag, typename OtherTag, typename Context>
struct tag_check<Tag, context_cons<OtherTag, Context>> : tag_check<Tag, Context> {};
} } }
#endif

View File

@ -0,0 +1,47 @@
#ifndef EOLIAN_CXX_CONVERTING_ARGUMENT_HH
#define EOLIAN_CXX_CONVERTING_ARGUMENT_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/string.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_definition.hpp"
#include "grammar/namespace.hpp"
#include "grammar/c_type.hpp"
#include "grammar/attribute_reorder.hpp"
namespace efl { namespace eolian { namespace grammar {
struct converting_argument_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& ctx) const
{
return as_generator
(
attribute_reorder<1, -1, 2>
(
" ::efl::eolian::convert_to_c<" << c_type << ", " << parameter_type << ">(" << string << ")"
)
).generate(sink, param, ctx);
}
};
template <>
struct is_eager_generator<converting_argument_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<converting_argument_generator> : std::integral_constant<int, 1> {};
}
converting_argument_generator const converting_argument;
} } }
#endif

View File

@ -1,603 +0,0 @@
#ifndef EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
#include <iosfwd>
#include <string>
#include "eo_types.hh"
#include "tab.hh"
#include "comment.hh"
#include "parameters_generator.hh"
#include "namespace_generator.hh"
namespace efl { namespace eolian { namespace grammar {
struct class_name
{
std::string _name;
class_name(std::string name)
: _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, class_name const& x)
{
out << x._name;
return out;
}
struct class_inheritance
{
eo_class const& _cls;
class_inheritance(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, class_inheritance const& x)
{
eo_class const& cls = x._cls;
ancestors_container_type::const_iterator it,
first = cls.ancestors.cbegin(),
last = cls.ancestors.cend();
for (it = first; it != last; ++it)
{
out << tab(2) << ", EO_CXX_INHERIT(" << *it << ")" << endl;
}
return out;
}
struct constructor_functor_type_name
{
eo_constructor const& _ctor;
constructor_functor_type_name(eo_constructor const& ctor)
: _ctor(ctor)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_functor_type_name const& x)
{
out << "_c_" << x._ctor.name;
return out;
}
struct constructor_functor_type_decl
{
eo_constructor const& _ctor;
constructor_functor_type_decl(eo_constructor const& ctor)
: _ctor(ctor)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_functor_type_decl const& x)
{
out << constructor_functor_type_name(x._ctor);
if (parameters_count_callbacks(x._ctor.params) == 0)
return out;
bool comma = false;
out << "<";
auto first = x._ctor.params.cbegin(), last = x._ctor.params.cend();
for(auto it = first; it != last; ++it)
{
if (type_is_callback((*it).type) && it+1 != last)
{
if (comma)
out << ", ";
else
comma = true;
out << template_parameter_type((*it).type, (*it).name);
}
}
return out << ">";
}
struct functors_constructor_methods
{
eo_class const& _cls;
functors_constructor_methods(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, functors_constructor_methods const& x)
{
constructors_container_type::const_iterator it,
first = x._cls.all_constructors.cbegin(),
last = x._cls.all_constructors.cend();
for (it = first; it != last; ++it)
{
eo_constructor const& c = *it;
// Hide documentation condition
out << comment("@cond LOCAL", 1);
// Struct declaration
out << template_parameters_declaration(c.params, 1)
<< tab(1) << "struct " << constructor_functor_type_name(c) << endl
<< tab(1) << "{" << endl;
// Callbacks typedefs
out << parameters_cxx_generic(c.params,
[](param_data d)
{
if (d.is_cb)
d.out << tab(2)
<< parameter_remove_reference_typedef(d.type, d.name)
<< endl;
}
)
<< endl;
// Struct constructor
out << tab(2) << "explicit " << constructor_functor_type_name(c) << "("
<< parameters_declaration(c.params) << ")"
<< parameters_cxx_generic(c.params,
[](param_data d)
{
if(d.pos == 0u)
d.out << endl << tab(3) << ": ";
else
d.out << ", ";
if (d.is_cb)
d.out << callback_tmp(d.name) << "(new "
<< template_parameter_type(d.type, d.name)
<< "(" << parameter_forward(d.type, d.name) << "))";
else
d.out << d.name << "(" << parameter_forward(d.type, d.name) << ")";
}
)
<< endl
<< tab(2) << "{}" << endl;
// Struct operator()
out << tab(2) << "void operator()(Eo* _obj_eo_self)" << endl
<< tab(2) << "{" << endl
<< tab(3) << "::" << c.impl << "(_obj_eo_self" << (c.params.empty() ? "" : ", ")
<< parameters_forward_to_c(c.params) << ");" << endl
<< tab(2) << "}" << endl;
// Register event to free allocated callbacks when the Eo* is deleted
out << tab(2) << "void register_ev_del_free_callback(Eo* _eoptr)" << endl
<< tab(2) << "{" << endl
<< tab(3) << "(void) _eoptr;" << endl
<< parameters_cxx_generic(c.params,
[](param_data d)
{
if (d.is_cb)
d.out << tab(3)
<< "eo_event_callback_add(_eoptr, EO_EVENT_DEL, "
<< "&::efl::eolian::free_callback_callback<"
<< parameter_no_ref_type(d.type, d.name)
<< ">, " << callback_tmp(d.name) << ");" << endl;
})
<< tab(2) << "}" << endl;
// Struct member variables
out << endl
<< parameters_cxx_generic(c.params,
[](param_data d)
{
d.out << tab(2);
if (d.is_cb)
d.out << parameter_no_ref_type(d.type, d.name) << "* "
<< callback_tmp(d.name);
else
d.out << parameter_type(d.type, d.name) << " " << d.name;
d.out << ";" << endl;
}
);
// Close struct
out << tab(1) << "};" << endl;
// End documentation condition
out << comment("@endcond", 1) << endl;
}
return out;
}
struct constructor_method_function_declarations
{
eo_class const& _cls;
constructor_method_function_declarations(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_method_function_declarations const& x)
{
constructors_container_type::const_iterator it,
first = x._cls.all_constructors.cbegin(),
last = x._cls.all_constructors.cend();
for (it = first; it != last; ++it)
{
eo_constructor const& c = *it;
// "eo_constructor" is already called in the eo_add_ref macro (used in
// _ctors_call).
// Creating a function with this name yields an error in the eo_add_ref
// macro expansion, because "eo_constructor" will refers to the class
// function instead of the Eo.Base function which is intended.
if (c.name == "eo_constructor")
{
continue;
}
out << comment(c.comment, 1)
<< template_parameters_declaration(c.params, 1)
<< tab(1) << "static " << constructor_functor_type_decl(c)
<< " " << c.name << "("
<< parameters_declaration(c.params) << ");" << endl << endl;
}
return out;
}
struct constructor_method_function_definitions
{
eo_class const& _cls;
constructor_method_function_definitions(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_method_function_definitions const& x)
{
constructors_container_type::const_iterator it,
first = x._cls.all_constructors.cbegin(),
last = x._cls.all_constructors.cend();
for (it = first; it != last; ++it)
{
eo_constructor const& c = *it;
// Same explanation as the one in constructor_method_function_declarations
if (c.name == "eo_constructor")
{
continue;
}
out << template_parameters_declaration(c.params, 0)
<< "inline " << full_name(x._cls)
<< "::" << constructor_functor_type_decl(c) << " "
<< full_name(x._cls, false) << "::" << c.name << "("
<< parameters_declaration(c.params) << ")" << endl
<< "{" << endl
<< tab(1) << "return " << constructor_functor_type_decl(c) << "("
<< parameters_forward(c.params) << ");" << endl
<< "}" << endl << endl;
}
return out;
}
struct comment_constructor_with_constructor_methods
{
eo_class const& _cls;
comment_constructor_with_constructor_methods(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, comment_constructor_with_constructor_methods const& x)
{
out << tab(1) << "/**" << endl
<< tab(2) << "@brief Constructs a new " << full_name(x._cls, false) << " object." << endl
<< endl
<< tab(2) << "Constructs a new " << full_name(x._cls, false) << " object. If you want this object to be a child" << endl
<< tab(2) << "of another Eo object, use an @ref efl::eo::parent expression, like the example." << endl
<< endl;
if (x._cls.constructors.size())
{
bool singular = (x._cls.constructors.size() == 1);
out << tab(2) << "Since this class have " << (singular ? "a " : "")
<< "necessary constructor method" << (singular ? "" : "s")
<< ", you must call " << (singular ? "it" : "each one of them") << endl
<< tab(2) << "in the right place within this constructor parameters." << endl
<< endl;
}
if (!x._cls.optional_constructors.empty())
{
out << tab(2) << "Optional constructors may be called in any combination as the" << endl
<< tab(2) << "last parameters." << endl
<< endl;
}
out << tab(2) << "Example:" << endl
<< tab(2) << "@code" << endl
<< tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(efl::eo::parent = parent_object";
for (eo_constructor const& c : x._cls.all_constructors)
out << "," << endl
<< tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")";
out << ");" << endl
<< tab(2) << "@endcode" << endl
<< endl;
for (eo_constructor const& c : x._cls.all_constructors)
out << tab(2) << "@see " << x._cls.name << "::" << c.name << endl;
out << tab(2) << "@see " << x._cls.name << "(Eo* eo)" << endl;
return out << tab(1) << "*/" << endl;
}
struct constructor_with_constructor_methods
{
eo_class const& _cls;
bool _with_parent;
constructor_with_constructor_methods(eo_class const& cls, bool with_parent)
: _cls(cls)
, _with_parent(with_parent)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_with_constructor_methods const& x)
{
unsigned cb_count = 0;
constructors_container_type::const_iterator it,
first = x._cls.constructors.cbegin(),
last = x._cls.constructors.cend();
for (it = first; it != last; ++it)
{
cb_count += parameters_count_callbacks((*it).params);
}
if (cb_count != 0 || !x._cls.optional_constructors.empty())
{
out << tab(1) << "template <";
for (unsigned i = 0; i != cb_count; ++i)
{
if (i != 0)
out << ", ";
out << "typename F" << i;
}
if (!x._cls.optional_constructors.empty())
{
if (cb_count != 0)
out << ", ";
out << "typename... FOpts";
}
out << ">" << endl;
}
out << tab(1) << "explicit " << x._cls.name << "(";
if (x._with_parent)
out << "::efl::eo::parent_type _p";
{
unsigned cb_idx = 0;
for (it = first; it != last; ++it)
{
if (x._with_parent || it != first)
out << ", ";
out << constructor_functor_type_name(*it);
if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
{
out << "<"
<< parameters_cxx_generic((*it).params,
[&cb_idx](param_data d)
{
if (d.is_cb)
d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
})
<< ">";
}
out << " _c" << (it-first);
}
assert(cb_idx == cb_count);
}
if (!x._cls.optional_constructors.empty())
{
if (x._with_parent || first != last)
out << ", ";
out << "FOpts&&... _opts";
}
out << ")" << endl
<< tab(2) << ": " << x._cls.name << "(_ctors_call("
<< (x._with_parent ? "_p" : "::efl::eo::parent = nullptr");
for (it = first; it != last; ++it)
{
out << ", _c" << (it-first);
}
if (!x._cls.optional_constructors.empty())
{
out << ", std::forward<FOpts>(_opts)...";
}
out << "))" << endl
<< tab(1) << "{}" << endl;
return out;
}
struct constructors_with_constructor_methods
{
eo_class const& _cls;
constructors_with_constructor_methods(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructors_with_constructor_methods const& x)
{
out << tab(1) << "//@{" << endl
<< comment_constructor_with_constructor_methods(x._cls)
<< constructor_with_constructor_methods(x._cls, true) << endl
<< constructor_with_constructor_methods(x._cls, false)
<< tab(1) << "//@}" << endl << endl;
return out;
}
struct constructor_eo
{
eo_class const& _cls;
constructor_eo(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_eo const& x)
{
std::string doc = "@brief Eo Constructor.\n\n"
"Constructs the object from an Eo* pointer stealing its ownership.\n\n"
"@param eo The Eo object pointer.\n\n";
out << comment(doc, 1)
<< tab(1)
<< "explicit " << x._cls.name << "(Eo* eo)" << endl
<< tab(2) << ": ::efl::eo::concrete(eo)" << endl
<< tab(1) << "{}" << endl << endl;
out << comment(
"@brief nullptr_t Constructor.\n\n"
"Constructs an empty (null) object.\n\n"
, 1
)
<< tab(1)
<< "explicit " << x._cls.name << "(std::nullptr_t)" << endl
<< tab(2) << ": ::efl::eo::concrete(nullptr)" << endl
<< tab(1) << "{}" << endl << endl;
return out;
}
struct copy_constructor
{
eo_class const& _cls;
copy_constructor(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, copy_constructor const& x)
{
std::string doc = "@brief Copy Constructor.\n\n";
out << comment(doc, 1)
<< tab(1)
<< x._cls.name << "(" << x._cls.name << " const& other)" << endl
<< tab(2) << ": " << x._cls.name
<< "(eo_ref(other._eo_ptr()))" << endl
<< tab(1) << "{}" << endl << endl;
return out;
}
struct destructor
{
eo_class const& _cls;
destructor(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, destructor const& x)
{
out << tab(1)
<< '~' << x._cls.name << "() {}" << endl << endl;
return out;
}
struct function_call_constructor_methods
{
eo_class const& _cls;
function_call_constructor_methods(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, function_call_constructor_methods const& x)
{
out << comment("@internal", 1);
unsigned cb_count = 0;
constructors_container_type::const_iterator it,
first = x._cls.constructors.cbegin(),
last = x._cls.constructors.cend();
for (it = first; it != last; ++it)
{
cb_count += parameters_count_callbacks((*it).params);
}
if (cb_count != 0 || !x._cls.optional_constructors.empty())
{
out << tab(1) << "template <";
for (unsigned i = 0; i != cb_count; ++i)
{
if (i != 0)
out << ", ";
out << "typename F" << i;
}
if (!x._cls.optional_constructors.empty())
{
if (cb_count != 0)
out << ", ";
out << "typename... FOpts";
}
out << ">" << endl;
}
unsigned cb_idx = 0;
out << tab(1) << "static Eo* _ctors_call(::efl::eo::parent_type _p";
for (it = first; it != last; ++it)
{
out << ", " << constructor_functor_type_name(*it);
if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
{
out << "<"
<< parameters_cxx_generic((*it).params,
[&cb_idx](param_data d)
{
if (d.is_cb)
d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
})
<< ">";
}
out << " _c" << (it-first);
}
assert(cb_idx == cb_count);
if (!x._cls.optional_constructors.empty())
out << ", FOpts&&... _opts";
out << ")" << endl
<< tab(1) << "{" << endl
<< tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw";
for (it = first; it != last; ++it)
{
out << ", _c" << (it-first) << "(eo_self)";
}
if (!x._cls.optional_constructors.empty())
out << ", ::efl::eolian::call_ctors(eo_self, _opts...)";
out << ");" << endl << endl;
for (it = first; it != last; ++it)
out << tab(2) << "_c" << (it-first) << ".register_ev_del_free_callback(_ret_eo);" << endl;
if (!x._cls.optional_constructors.empty())
out << tab(2) << "::efl::eolian::register_ev_del_free_callback(_ret_eo, _opts...);" << endl;
out << tab(2) << "return _ret_eo;" << endl
<< tab(1) << "}" << endl << endl;
return out;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH

View File

@ -1,117 +0,0 @@
#ifndef EOLIAN_CXX_STD_EO_CLASS_EVENTS_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_CLASS_EVENTS_GENERATOR_HH
#include <iosfwd>
#include "type_generator.hh"
#include "eo_class_scope_guard_generator.hh"
#include "tab.hh"
#include "comment.hh"
namespace efl { namespace eolian { namespace grammar {
struct add_cast_to_t
{
add_cast_to_t(bool b)
: _b(b)
{
}
bool _b;
};
inline std::ostream&
operator<<(std::ostream& out, add_cast_to_t x)
{
if(x._b)
out << "static_cast<U*>(this)->";
return out;
}
struct event_callback_add
{
eo_event const& _event;
eo_class const& _cls;
bool _add_cast_to_t;
event_callback_add(eo_event const& event, eo_class const& cls
, bool add_cast_to_t)
: _event(event), _cls(cls), _add_cast_to_t(add_cast_to_t)
{}
};
inline std::ostream&
operator<<(std::ostream& out, event_callback_add const& x)
{
out << comment(x._event.comment, 1)
<< tab(1) << "template <typename F>" << endl
<< tab(1) << "::efl::eo::signal_connection" << endl
<< tab(1) << "callback_" << x._event.name << "_add(F && callback_," << endl
<< tab(8) << "::efl::eo::callback_priority priority_ =" << endl
<< tab(8) << "::efl::eo::callback_priorities::default_)" << endl
<< tab(1) << "{" << endl
<< tab(2) << "typedef typename std::remove_reference<F>::type function_type;" << endl
<< tab(2) << "::std::unique_ptr<function_type> f ( new function_type(std::forward<F>(callback_)) );" << endl
<< tab(2) << "eo_event_callback_priority_add(" << add_cast_to_t(x._add_cast_to_t) << "_concrete_eo_ptr()," << endl
<< tab(2) << x._event.eo_name << ", priority_," << endl
<< tab(2) << "&::efl::eo::_detail::event_callback<" << full_name(x._cls) << ", function_type>, f.get());" << endl
<< tab(2) << "return ::efl::eo::make_signal_connection" << endl
<< tab(3) << "(f, " << add_cast_to_t(x._add_cast_to_t)
<< "_concrete_eo_ptr(), &::efl::eo::_detail::event_callback<"
<< full_name(x._cls) << ", function_type>," << endl
<< tab(3) << x._event.eo_name << " );" << endl
<< tab(1) << "}" << endl;
return out;
}
struct event_callback_call
{
eo_event const& _event;
bool _add_cast_to_t;
event_callback_call(eo_event const& event, bool add_cast_to_t)
: _event(event), _add_cast_to_t(add_cast_to_t)
{}
};
inline std::ostream&
operator<<(std::ostream& out, event_callback_call const& x)
{
out << comment(x._event.comment, 1)
<< tab(1) << "template <typename T>" << endl
<< tab(1) << "void" << endl
<< tab(1) << "callback_" << x._event.name << "_call(T* info)" << endl
<< tab(1) << "{" << endl
<< tab(2) << "eo_event_callback_call" << endl
<< tab(4) << "(" << add_cast_to_t(x._add_cast_to_t) << "_concrete_eo_ptr(), " << x._event.eo_name << ", info);" << endl
<< tab(1) << "}" << endl;
return out;
}
struct events
{
eo_class const& _cls;
events_container_type const& _events;
bool _add_cast_to_t;
events(eo_class const& cls, events_container_type const& evts, bool add_cast_to_t = false)
: _cls(cls), _events(evts), _add_cast_to_t(add_cast_to_t) {}
};
inline std::ostream&
operator<<(std::ostream& out, events const& x)
{
for (eo_event const& e : x._events)
{
out << scope_guard_head(x._cls, e);
out << event_callback_add(e, x._cls, x._add_cast_to_t) << endl
<< event_callback_call(e, x._add_cast_to_t);
out << scope_guard_tail(x._cls, e) << endl;
}
out << endl;
return out;
}
} } }
#endif // EOLIAN_CXX_STD_EO_CLASS_EVENTS_GENERATOR_HH

View File

@ -1,173 +0,0 @@
#ifndef EOLIAN_CXX_STD_EO_CLASS_FUNCTIONS_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_CLASS_FUNCTIONS_GENERATOR_HH
#include <iosfwd>
#include "eo_types.hh"
#include "tab.hh"
#include "comment.hh"
#include "parameters_generator.hh"
#include "type_generator.hh"
#include "namespace_generator.hh"
#include "eo_class_scope_guard_generator.hh"
namespace efl { namespace eolian { namespace grammar {
struct function_call
{
eo_function const& _func;
function_call(eo_function const& func) : _func(func) {}
};
struct parameterized_obj_function_call
{
eo_function const& _func;
std::string obj;
parameterized_obj_function_call(eo_function const& func, std::string obj) : _func(func), obj(obj) {}
};
inline std::ostream&
operator<<(std::ostream& out, function_call const& x)
{
bool is_void = function_is_void(x._func);
bool is_static = function_is_static(x._func);
return out << (!is_void ? "_tmp_ret = " : "")
<< "::" << x._func.impl
<< "("
<< (is_static ? "const_cast<Eo*>(_eo_class())" : "_concrete_eo_ptr()")
<< (x._func.params.empty() ? "" : ",")
<< parameters_forward_to_c(x._func.params) << ")";
}
inline std::ostream&
operator<<(std::ostream& out, parameterized_obj_function_call const& x)
{
bool is_void = function_is_void(x._func);
return out << (!is_void ? "_tmp_ret = " : "")
<< "::" << x._func.impl
<< "("
<< x.obj
<< (x._func.params.empty() ? "" : ",")
<< parameters_forward_to_c(x._func.params) << ")";
}
struct function_declaration
{
eo_class const& _cls;
eo_function const& _func;
function_declaration(eo_class const& cls, eo_function const& func)
: _cls(cls), _func(func)
{}
};
inline std::ostream&
operator<<(std::ostream& out, function_declaration const& x)
{
eo_function const& func = x._func;
out << comment(x._func.comment, 1)
<< template_parameters_declaration(func.params, 1)
<< tab(1);
bool is_static = function_is_static(func);
if (is_static)
out << "static ";
out << reinterpret_type(func.ret) << " " << func.name << "("
<< parameters_declaration(func.params)
<< (is_static ? ");" : ") const;") << endl;
return out;
}
struct function_definition
{
eo_class const& _cls;
eo_function const& _func;
bool _concrete;
function_definition(eo_class const& cls, eo_function const& func, bool concrete)
: _cls(cls), _func(func), _concrete(concrete)
{}
};
inline std::ostream&
operator<<(std::ostream& out, function_definition const& x)
{
eo_function const& func = x._func;
bool is_static = function_is_static(func);
out << template_parameters_declaration(func.params, 0)
<< "inline " << reinterpret_type(func.ret) << " ";
if (x._concrete)
out << full_name(x._cls, false);
else
out << abstract_full_name(x._cls, false);
out << "::" << func.name << "("
<< parameters_declaration(func.params)
<< (is_static ? ")" : ") const") << endl
<< "{" << endl;
if (!function_is_void(func))
out << tab(1)
<< func.ret.front().native << " _tmp_ret;" << endl;
out << callbacks_heap_alloc("_concrete_eo_ptr()", func.params, is_static, 1);
out << tab(1) << function_call(x._func) << ";" << endl;
if (!function_is_void(func))
out << tab(1) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl;
out << "}" << endl;
return out;
}
struct function_declarations
{
eo_class const& _cls;
function_declarations(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, function_declarations const& x)
{
for (eo_function const& f : x._cls.functions)
{
out << scope_guard_head(x._cls, f)
<< function_declaration(x._cls, f)
<< scope_guard_tail(x._cls, f) << endl;
}
return out;
}
struct function_definitions
{
eo_class const& _cls;
bool _concrete;
function_definitions(eo_class const& cls, bool concrete)
: _cls(cls)
, _concrete(concrete)
{}
};
inline std::ostream&
operator<<(std::ostream& out, function_definitions const& x)
{
for (eo_function const& f : x._cls.functions)
{
out << scope_guard_head(x._cls, f)
<< function_definition(x._cls, f, x._concrete)
<< scope_guard_tail(x._cls, f) << endl;
}
return out;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_EO_CLASS_FUNCTIONS_GENERATOR_HH

View File

@ -1,265 +0,0 @@
#ifndef EOLIAN_CXX_EO_CLASS_GENERATOR_HH
#define EOLIAN_CXX_EO_CLASS_GENERATOR_HH
#include <iosfwd>
#include <string>
#include "eo_types.hh"
#include "tab.hh"
#include "comment.hh"
#include "namespace_generator.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 {
struct eo_class_getter
{
eo_class const& _cls;
eo_class_getter(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, eo_class_getter const& x)
{
out << tab(1) << "static Eo_Class const* _eo_class()" << endl
<< tab(1) << "{" << endl
<< tab(2) << "return("<< x._cls.eo_name << ");" << endl
<< tab(1) << "}" << endl << endl;
return out;
}
struct concrete_eo_ptr_getter
{
eo_class const& _cls;
concrete_eo_ptr_getter(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, concrete_eo_ptr_getter const&)
{
out << comment("@internal", 1)
<< tab(1) << "Eo* _concrete_eo_ptr() const" << endl
<< tab(1) << "{" << endl
<< tab(2) << "return static_cast<::efl::eo::concrete const*>(static_cast<void const*>(this))->_eo_ptr();" << endl
<< tab(1) << "}" << endl << endl;
return out;
}
struct class_implicit_conversion_declaration
{
eo_class const& _cls;
class_implicit_conversion_declaration(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, class_implicit_conversion_declaration const& x)
{
out << tab(1) << "operator " << full_name(x._cls) << "() const;" << endl;
out << tab(1) << "operator " << full_name(x._cls) << "&();" << endl;
out << tab(1) << "operator " << full_name(x._cls) << " const&() const;" << endl;
return out << endl;
}
struct class_implicit_conversion_definition
{
eo_class const& _cls;
class_implicit_conversion_definition(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, class_implicit_conversion_definition const& x)
{
out << "inline " << abstract_full_name(x._cls) << "::operator "
<< full_name(x._cls) << "() const" << endl
<< "{" << endl
<< tab(1) << "return *static_cast<" << full_name(x._cls)
<< " const*>(static_cast<void const*>(this));" << endl
<< "}" << endl << endl;
out << "inline " << abstract_full_name(x._cls) << "::operator "
<< full_name(x._cls) << "&()" << endl
<< "{" << endl
<< tab(1) << "return *static_cast<" << full_name(x._cls)
<< "*>(static_cast<void*>(this));" << endl
<< "}" << endl << endl;
out << "inline " << abstract_full_name(x._cls) << "::operator "
<< full_name(x._cls) << " const&() const" << endl
<< "{" << endl
<< tab(1) << "return *static_cast<" << full_name(x._cls)
<< " const*>(static_cast<void const*>(this));" << endl
<< "}" << endl << endl;
return out;
}
struct address_of_to_pointer
{
eo_class const& _cls;
bool _is_const;
address_of_to_pointer(eo_class const& cls, bool is_const)
: _cls(cls), _is_const(is_const)
{}
};
inline std::ostream&
operator<<(std::ostream& out, address_of_to_pointer const& x)
{
out << "operator " << full_name(x._cls) << (x._is_const ? " const" : "")
<< "*() const { return static_cast<" << full_name(x._cls)
<< (x._is_const ? " const" : "")
<< "*>(static_cast<D const*>(this)->p); }";
return out;
}
struct abstract_address_of
{
eo_class const& _cls;
abstract_address_of(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, abstract_address_of const& x)
{
out << comment("@cond LOCAL", 1);
out << tab(1) << "template <typename D>" << endl
<< tab(1) << "struct address_of" << endl
<< tab(1) << "{" << endl
<< tab(2) << address_of_to_pointer(x._cls, false) << endl
<< tab(2) << address_of_to_pointer(x._cls, true) << endl
<< tab(1) << "};" << endl << endl;
out << tab(1) << "template <typename D>" << endl
<< tab(1) << "struct address_const_of" << endl
<< tab(1) << "{" << endl
<< tab(2) << address_of_to_pointer(x._cls, true) << endl
<< tab(1) << "};" << endl;
out << comment("@endcond", 1) << endl;
return out;
}
struct address_of_inheritance
{
eo_class const& _cls;
std::string _struct_name;
address_of_inheritance(eo_class const& cls, std::string const& struct_name)
: _cls(cls), _struct_name(struct_name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, address_of_inheritance const& x)
{
for (std::string const& parent : x._cls.ancestors)
{
out << tab(2) << ", ::" << abstract_namespace << "::" << parent << "::"
<< x._struct_name << "<" << x._struct_name << ">" << endl;
}
return out;
}
struct concrete_address_of
{
eo_class const& _cls;
concrete_address_of(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, concrete_address_of const& x)
{
out << comment("@cond LOCAL", 1);
std::vector<std::string> names {"address_of", "address_const_of"};
for (int is_const = 0; is_const != 2; ++is_const)
{
std::string const& name = names[is_const];
out << tab(1) << "struct " << name << endl
<< tab(2) << ": " << abstract_full_name(x._cls) << "::"
<< name << "<" << name << ">" << endl
<< address_of_inheritance(x._cls, name)
<< tab(2) << ", ::efl::eo::detail::concrete_" << name << endl
<< tab(1) << "{" << endl
<< tab(2) << "explicit " << name << "(" << full_name(x._cls)
<< (is_const ? " const" : "")
<< "* p)" << endl
<< tab(3) << ": ::efl::eo::detail::concrete_" << name << "(p)" << endl
<< tab(2) << "{}" << endl
<< tab(1) << "};" << endl
<< tab(1) << name << " operator&()"
<< (is_const ? " const" : "")
<< " { return " << name << "(this); }" << endl << endl;
}
out << comment("@endcond", 1) << endl;
return out;
}
inline void
eo_class_declarations_generator(std::ostream& out, eo_class const& cls)
{
out << namespace_head(cls)
<< "struct " << cls.name << ";" << endl << endl
<< namespace_tail(cls)
<< comment("@cond EO_CXX_ABSTRACT")
<< "namespace " << abstract_namespace << " {" << endl << endl
<< namespace_head(cls)
<< comment(cls.comment)
<< "struct " << cls.name << endl
<< '{' << endl
<< function_declarations(cls)
<< events(cls, cls.own_events) << endl
<< eo_class_getter(cls)
<< class_implicit_conversion_declaration(cls)
<< abstract_address_of(cls)
<< "private:" << endl << endl
<< concrete_eo_ptr_getter(cls)
<< "};" << endl << endl
<< namespace_tail(cls)
<< "}" << endl
<< comment("@endcond") << endl
<< namespace_head(cls)
<< comment(cls.comment, 0, "@brief Class " + cls.name)
<< "struct " << cls.name << endl
<< tab(2) << ": ::efl::eo::concrete" << endl
<< class_inheritance(cls)
<< '{' << endl
<< functors_constructor_methods(cls)
<< constructors_with_constructor_methods(cls)
<< constructor_eo(cls)
<< copy_constructor(cls)
<< destructor(cls)
<< constructor_method_function_declarations(cls)
<< function_declarations(cls)
<< events(cls, cls.concrete_events) << endl
<< eo_class_getter(cls)
<< concrete_address_of(cls)
<< "private:" << endl << endl
<< function_call_constructor_methods(cls)
<< comment("@internal", 1)
<< tab(1) << "Eo* _concrete_eo_ptr() const { return _eo_ptr(); }" << endl
<< "};" << endl << endl
<< "static_assert(sizeof(" << full_name(cls) << ") == sizeof(Eo*), \"\");" << endl
<< "static_assert(std::is_standard_layout<" << full_name(cls) << ">::value, \"\");" << endl
<< endl
<< namespace_tail(cls)
<< endl;
}
inline void
eo_class_definitions_generator(std::ostream& out, eo_class const& cls)
{
out << constructor_method_function_definitions(cls)
<< function_definitions(cls, true)
<< function_definitions(cls, false)
<< class_implicit_conversion_definition(cls);
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_EO_CLASS_GENERATOR_HH

View File

@ -1,65 +0,0 @@
#ifndef EOLIAN_CXX_STD_EO_CLASS_SCOPE_GUARD_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_CLASS_SCOPE_GUARD_GENERATOR_HH
#include <cassert>
#include "type_generator.hh"
namespace efl { namespace eolian { namespace grammar {
template <typename T>
struct _scope_guard_head
{
eo_class const& _cls;
T const& _e;
_scope_guard_head(eo_class const& cls, T const& e)
: _cls(cls), _e(e) {}
};
template <typename T>
_scope_guard_head<T> scope_guard_head(eo_class const& cls, T const& e)
{
return _scope_guard_head<T>(cls, e);
}
template <typename T>
inline std::ostream&
operator<<(std::ostream& out, _scope_guard_head<T> const& x)
{
assert(x._e.scope != eolian_scope::private_);
if (x._e.scope == eolian_scope::protected_)
out << "#ifdef " << name_upper(x._cls) << "_PROTECTED" << endl;
if (x._e.is_beta)
out << "#ifdef " << name_upper(x._cls) << "_BETA" << endl;
return out;
}
template <typename T>
struct _scope_guard_tail
{
eo_class const& _cls;
T const& _e;
_scope_guard_tail(eo_class const& cls, T const& e)
: _cls(cls), _e(e) {}
};
template <typename T>
struct _scope_guard_tail<T> scope_guard_tail(eo_class const& cls, T const& e)
{
return _scope_guard_tail<T>(cls, e);
}
template <typename T>
inline std::ostream&
operator<<(std::ostream& out, _scope_guard_tail<T> const& x)
{
if (x._e.scope == eolian_scope::protected_)
out << "#endif" << endl;
if (x._e.is_beta)
out << "#endif" << endl;
return out;
}
} } }
#endif

View File

@ -1,150 +0,0 @@
#ifndef EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
#include <set>
#include <algorithm>
#include <string>
#include <ostream>
#include <iosfwd>
#include <cctype>
#include "eo_types.hh"
#include "tab.hh"
#include "eo_class_generator.hh"
#include "inheritance_base_generator.hh"
namespace {
std::string
_onceguard_key(efl::eolian::eo_class const& cls)
{
std::string key;
if (cls.name_space != "")
{
std::string ns = cls.name_space;
size_t pos = 0;
while ((pos = ns.find("::")) != std::string::npos)
{
key += ns.substr(0, pos) + "_";
ns.erase(0, pos+2);
}
key += ns + "_";
}
key += cls.name;
std::transform(key.begin(), key.end(), key.begin(), ::toupper);
return key;
}
}
namespace efl { namespace eolian { namespace grammar {
struct include_dependencies
{
eo_class const& _cls;
eo_generator_options const& _opts;
include_dependencies(eo_class const& cls, eo_generator_options const& opts)
: _cls(cls)
, _opts(opts)
{}
};
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.parts)
for (std::string header : subtype.includes)
if (header != x._opts.header_decl_file_name)
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.parts)
for (std::string header : subtype.includes)
if (header != x._opts.header_decl_file_name)
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)
{
std::string key = ::_onceguard_key(cls);
out << "#ifndef EFL_GENERATED_" << key << "_HH" << endl
<< "#define EFL_GENERATED_" << key << "_HH" << endl << endl;
}
inline void
onceguard_tail(std::ostream& out, eo_class const& cls)
{
std::string key = ::_onceguard_key(cls);
out << "#endif // EFL_GENERATED_" << key << "_HH" << endl;
}
inline void
include_headers(std::ostream& out,
eo_class const& cls EINA_UNUSED,
eo_generator_options const& opts)
{
out << "extern \"C\"" << endl
<< "{" << endl
<< "#include <Efl.h>" << endl
<< "}" << endl
<< "#include <Eo.hh>" << endl << endl
<< "#include <eo_cxx_interop.hh>" << endl << endl
<< "extern \"C\"" << endl
<< "{" << endl;
for (auto c_header : opts.c_headers)
{
out << "#include \"" << c_header << "\"" << endl;
}
out << "}" << endl << endl;
for (auto cxx_header : opts.cxx_headers)
{
out << "#include \"" << cxx_header << "\"" << endl;
}
out << include_dependencies(cls, opts) << endl;
}
inline void
include_header_impl(std::ostream& out,
eo_class const& cls EINA_UNUSED,
eo_generator_options const& opts)
{
out << "#include \"" << opts.header_impl_file_name << "\"" << endl << endl;
}
inline void
eo_headers_generator(std::ostream& header_decl,
std::ostream& header_impl,
eo_class const& cls,
eo_generator_options const& opts)
{
onceguard_head(header_decl, cls);
include_headers(header_decl, cls, opts);
eo_class_declarations_generator(header_decl, cls);
include_header_impl(header_decl, cls, opts);
onceguard_tail(header_decl, cls);
header_decl << endl;
header_impl << comment("@cond EO_CXX_EO_IMPL") << endl;
eo_class_definitions_generator(header_impl, cls);
eo_inheritance_detail_generator(header_impl, cls);
header_impl << endl << comment("@endcond") << endl;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH

View File

@ -0,0 +1,24 @@
#ifndef EOLIAN_CXX_EPS_HH
#define EOLIAN_CXX_EPS_HH
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
struct eps_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator, Attribute const&, Context const&) const
{
return true;
}
};
template <>
struct is_eager_generator<eps_generator> : std::true_type {};
eps_generator const eps;
} } }
#endif

View File

@ -0,0 +1,39 @@
#ifndef EOLIAN_CXX_FUNCTION_DECLARATION_HH
#define EOLIAN_CXX_FUNCTION_DECLARATION_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/keyword.hpp"
namespace efl { namespace eolian { namespace grammar {
struct function_declaration_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
{
return as_generator
(grammar::type << " " << string << "(" << (parameter % ", ") << ") const;\n")
.generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context);
}
};
template <>
struct is_eager_generator<function_declaration_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<function_declaration_generator> : std::integral_constant<int, 1> {};
}
function_declaration_generator const function_declaration;
} } }
#endif

View File

@ -0,0 +1,155 @@
#ifndef EOLIAN_CXX_FUNCTION_DEFINITION_HH
#define EOLIAN_CXX_FUNCTION_DEFINITION_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/string.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_declaration.hpp"
#include "grammar/converting_argument.hpp"
#include "grammar/case.hpp"
#include "grammar/keyword.hpp"
#include "grammar/attribute_conditional.hpp"
#include "grammar/attribute_reorder.hpp"
#include "grammar/type_impl.hpp"
namespace efl { namespace eolian { namespace grammar {
struct function_definition_generator
{
function_definition_generator(attributes::klass_name const& name)
: _klass_name(name)
{}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& ctx) const
{
std::string suffix;
switch(_klass_name.type)
{
case attributes::class_type::regular:
case attributes::class_type::abstract_:
suffix = "CLASS";
break;
case attributes::class_type::mixin:
suffix = "MIXIN";
break;
case attributes::class_type::interface_:
suffix = "INTERFACE";
break;
}
if(f.is_beta &&
!as_generator("#ifdef " << *(string << "_") << string << "_" << string << "_BETA\n")
.generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name, suffix), add_upper_case_context(ctx)))
return false;
if(f.is_protected &&
!as_generator("#ifdef " << *(string << "_") << string << "_" << string << "_PROTECTED\n")
.generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name, suffix), add_upper_case_context(ctx)))
return false;
if(!as_generator
("inline " << grammar::type << " " << string << "::" << string << "(" << (parameter % ", ") << ") const\n{\n")
.generate(sink, std::make_tuple(f.return_type, _klass_name.eolian_name, escape_keyword(f.name), f.parameters), ctx))
return false;
auto out_declaration =
attribute_conditional([] (attributes::parameter_def const& p) -> bool
{ return p.direction == attributes::parameter_direction::out; })
[
attribute_reorder<1, 2>
(scope_tab << c_type << " __out_param_" << string << " = {};\n")
]
| attribute_conditional([] (attributes::parameter_def const& p) -> bool
{ return p.direction == attributes::parameter_direction::inout; })
[
attribute_reorder<1, 2, 1, 1, 2>
(scope_tab << c_type << " __out_param_" << string << " = ::efl::eolian::convert_inout<" << c_type
<< ", " << type << ">(" << string << ");\n")
]
| eps
;
if(!as_generator(*(out_declaration))
.generate(sink, f.parameters, ctx)) return false;
if(!as_generator(scope_tab).generate(sink, attributes::unused, ctx)) return false;
if(f.return_type != attributes::void_
&& !as_generator(attributes::c_type({attributes::parameter_direction::in, f.return_type, "", f.return_type.c_type})
<< " __return_value = "
).generate(sink, attributes::unused, ctx)) return false;
if(!as_generator
(" ::" << string << "(this->_eo_ptr()"
<<
*(
"\n" << scope_tab << scope_tab << ", "
<<
(
attribute_conditional([] (attributes::parameter_def const& p)
{ return p.direction == attributes::parameter_direction::in; })
[converting_argument]
| ("& __out_param_" << attribute_reorder<2>(string))
)
)
<< ");\n"
).generate(sink, std::make_tuple(f.c_name, f.parameters), ctx))
return false;
auto out_assignments =
attribute_conditional([] (attributes::parameter_def const& p) -> bool
{ return p.direction != attributes::parameter_direction::in; })
[
attribute_reorder<-1, 1, 2, 2>
(scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", " << c_type
<< ">(" << string << ", __out_param_" << string << ");\n")
]
| eps
;
if(!as_generator(*(out_assignments))
.generate(sink, f.parameters, ctx)) return false;
if(f.return_type != attributes::void_
&& !as_generator(scope_tab << "return ::efl::eolian::convert_to_return<"
<< type<< ">(__return_value);\n"
).generate(sink, f.return_type, ctx)) return false;
if(!as_generator("}\n").generate(sink, attributes::unused, ctx))
return false;
if(f.is_beta &&
!as_generator("#endif\n").generate(sink, attributes::unused, ctx))
return false;
if(f.is_protected &&
!as_generator("#endif\n").generate(sink, attributes::unused, ctx))
return false;
return true;
}
attributes::klass_name _klass_name;
};
template <>
struct is_eager_generator<function_definition_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<function_definition_generator> : std::integral_constant<int, 1> {};
}
struct function_definition_terminal
{
function_definition_generator operator()(attributes::klass_name name) const
{
return function_definition_generator{name};
}
} const function_definition;
} } }
#endif

View File

@ -0,0 +1,50 @@
#ifndef EOLIAN_CXX_GENERATOR_HH
#define EOLIAN_CXX_GENERATOR_HH
#include <type_traits>
namespace efl { namespace eolian { namespace grammar {
template <typename T, typename Enable = void>
struct is_generator : std::false_type {};
template <typename T, typename Enable = void>
struct is_eager_generator : std::false_type {};
template <typename T>
struct is_generator<T&> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T&> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T const&> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T const&> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T const> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T const> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T volatile> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T volatile> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T volatile&> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T volatile&> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T volatile const> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T volatile const> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T volatile const&> : is_generator<T> {};
template <typename T>
struct is_eager_generator<T volatile const&> : is_eager_generator<T> {};
template <typename T>
struct is_generator<T> : is_eager_generator<T> {};
template <typename G, typename Enable = typename std::enable_if<is_eager_generator<G>::value>::type>
G as_generator(G&& g) { return g; }
} } }
#endif

View File

@ -0,0 +1,38 @@
#ifndef EOLIAN_CXX_HEADER_HH
#define EOLIAN_CXX_HEADER_HH
#include "header_guards.hpp"
#include "eps.hpp"
#include "string.hpp"
#include "sequence.hpp"
#include "kleene.hpp"
#include "header_include_directive.hpp"
#include "base_class_definition.hpp"
#include "class_definition.hpp"
#include "class_declaration.hpp"
#include "implementation_include_directive.hpp"
namespace efl { namespace eolian { namespace grammar {
auto class_header =
header_guards // class name
[
"#include <Eo.h>\n"
"\nextern \"C\" {\n"
<< *header_include_directive // sequence<string>
<< "}\n"
<< "#include <Eina.hh>\n"
"#include <Eo.hh>\n"
<< *header_include_directive // sequence<string>
<< *class_declaration // sequence<class> | class
<< "\nnamespace eo_cxx {\n"
<< *base_class_definition // sequence<class> | class
<< "}\n"
<< *class_definition // sequence<class> | class
<< *implementation_include_directive
]
;
} } }
#endif

View File

@ -0,0 +1,79 @@
#ifndef EOLIAN_CXX_HEADER_GUARDS_HH
#define EOLIAN_CXX_HEADER_GUARDS_HH
#include <utility>
#include <tuple>
#include <algorithm>
#include "grammar/generator.hpp"
#include "grammar/attributes.hpp"
#include "grammar/string.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename Generator>
struct header_guards_generator
{
header_guards_generator(Generator generator)
: generator(std::move(generator))
{}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
using std::get;
auto&& v = get<0>(attribute);
const char ifndef_directive[] = "#ifndef ";
const char define_directive[] = "#define ";
const char endif_directive[] = "#endif\n";
std::copy(&ifndef_directive[0],
&ifndef_directive[0] + sizeof(ifndef_directive)-1,
sink);
std::transform(std::begin(v), std::end(v), sink, ::toupper);
*sink++ = '\n';
std::copy(&define_directive[0],
&define_directive[0] + sizeof(define_directive)-1,
sink);
std::transform(std::begin(v), std::end(v), sink, ::toupper);
*sink++ = '\n';
bool b = as_generator(generator).generate(sink, attributes::pop_front(attribute), context);
if(!b)
return false;
else
{
std::copy(&endif_directive[0],
&endif_directive[0] + sizeof(endif_directive)-1,
sink);
return true;
}
}
Generator generator;
};
template <typename G>
struct is_eager_generator<header_guards_generator<G> > : std::true_type {};
namespace type_traits {
template <typename G>
struct attributes_needed<header_guards_generator<G> >
: std::integral_constant<int, 1 + attributes_needed<G>::value> {};
}
struct header_guards_directive
{
template <typename Generator>
header_guards_generator<Generator> operator[](Generator generator) const
{
return header_guards_generator<Generator>(generator);
}
};
header_guards_directive const header_guards;
} } }
#endif

View File

@ -0,0 +1,34 @@
#ifndef EOLIAN_CXX_HEADER_INCLUDE_DIRECTIVE_HH
#define EOLIAN_CXX_HEADER_INCLUDE_DIRECTIVE_HH
#include "generator.hpp"
namespace efl { namespace eolian { namespace grammar {
struct header_include_directive_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const&) const
{
const char include_directive[] = "#include \"";
std::copy(include_directive, include_directive + sizeof(include_directive)-1, sink);
std::copy(std::begin(attribute), std::end(attribute), sink);
*sink++ = '\"';
*sink++ = '\n';
return true;
}
};
template <>
struct is_eager_generator<header_include_directive_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<header_include_directive_generator> : std::integral_constant<int, 1> {};
}
header_include_directive_generator const header_include_directive;
} } }
#endif

View File

@ -0,0 +1,21 @@
#ifndef EOLIAN_CXX_IMPL_HEADER_HH
#define EOLIAN_CXX_IMPL_HEADER_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/kleene.hpp"
#include "grammar/class_implementation.hpp"
namespace efl { namespace eolian { namespace grammar {
auto impl_header =
*(class_implementation)
;
} } }
#endif

View File

@ -0,0 +1,39 @@
#ifndef EOLIAN_CXX_IMPLEMENTATION_INCLUDE_DIRECTIVE_HH
#define EOLIAN_CXX_IMPLEMENTATION_INCLUDE_DIRECTIVE_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/string.hpp"
#include "grammar/indentation.hpp"
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "grammar/type.hpp"
#include "grammar/parameter.hpp"
#include "grammar/function_declaration.hpp"
namespace efl { namespace eolian { namespace grammar {
struct implementation_include_directive_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& ctx) const
{
return as_generator("#include \"" << string << ".impl.hh\"\n")
.generate(sink, std::string(eolian_class_file_get(get_klass(get_klass_name(cls)))), add_lower_case_context(ctx));
}
};
template <>
struct is_eager_generator<implementation_include_directive_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<implementation_include_directive_generator> : std::integral_constant<int, 1> {};
}
implementation_include_directive_generator const implementation_include_directive;
} } }
#endif

View File

@ -0,0 +1,50 @@
#ifndef EOLIAN_CXX_GRAMMAR_INDENTATION_HPP
#define EOLIAN_CXX_GRAMMAR_INDENTATION_HPP
#include "grammar/generator.hpp"
#include "grammar/attributes.hpp"
namespace efl { namespace eolian { namespace grammar {
struct scope_tab_generator
{
scope_tab_generator(int n)
: n(n) {}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::unused_type, Context const&) const
{
for(int i = 0; i != n; ++i)
{
*sink++ = ' ';
*sink++ = ' ';
*sink++ = ' ';
}
return true;
}
int n;
};
template <>
struct is_eager_generator<scope_tab_generator> : std::true_type {};
struct scope_tab_terminal
{
scope_tab_generator operator()(int n) const
{
return scope_tab_generator(n);
}
} const scope_tab;
template <>
struct is_generator<scope_tab_terminal> : std::true_type {};
scope_tab_generator as_generator(scope_tab_terminal)
{
return scope_tab_generator(1);
}
} } }
#endif

View File

@ -1,339 +0,0 @@
#ifndef EOLIAN_CXX_STD_INHERITANCE_GENERATOR_HH
#define EOLIAN_CXX_STD_INHERITANCE_GENERATOR_HH
#include <iosfwd>
#include <cassert>
#include <algorithm>
#include "eo_types.hh"
#include "tab.hh"
#include "parameters_generator.hh"
#include "eo_class_functions_generator.hh"
namespace efl { namespace eolian { namespace grammar {
inline std::string
_ns_as_prefix(eo_class const& cls)
{
// XXX Use eolian_cxx::find_replace() instead.
std::string s = cls.name_space;
std::string::size_type found = s.find("::");
while (found != std::string::npos)
{
s.replace(found, 2, "_");
found = s.find("::");
}
return s;
}
struct inheritance_operation
{
eo_class const& _cls;
eo_function const& _func;
inheritance_operation(eo_class const& cls, eo_function const& func)
: _cls(cls), _func(func)
{}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_operation const& x)
{
eo_function const& func = x._func;
out << scope_guard_head(x._cls, func)
<< tab(1)
<< "ops[i].func = reinterpret_cast<void*>(& ::"
<< _ns_as_prefix(x._cls) << "_"
<< x._cls.name << "_" << func.name << "_wrapper<T>);" << endl
<< tab(1) << "ops[i].api_func = reinterpret_cast<void*>(& ::"
<< func.impl << ");" << endl
<< tab(1) << "ops[i].op_type = EO_OP_TYPE_REGULAR;" << endl // XXX class ops
<< tab(1) << "++i;" << endl
<< scope_guard_tail(x._cls, func)
<< endl;
return out;
}
struct inheritance_operations_description
{
eo_class const& _cls;
inheritance_operations_description(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_operations_description const& x)
{
std::string s;
out << "template <typename T>"
<< endl << "int initialize_operation_description(::efl::eo::detail::tag<"
<< full_name(x._cls) << ">" << endl
<< tab(11)
<< ", Eo_Op_Description* ops)" << endl
<< "{" << endl
<< tab(1) << "int i = 0;" << endl
<< tab(1) << "(void)i;" << endl
<< tab(1) << "(void)ops;" << endl;
for (auto const& f : x._cls.functions)
{
out << inheritance_operation(x._cls, f);
}
for (std::string const& parent : x._cls.parents)
{
out << tab(1)
<< "initialize_operation_description<T>(::efl::eo::detail::tag<::"
<< parent << ">(), &ops[operation_description_class_size< "
<< full_name(x._cls) << " >::value" << s << "]);" << endl;
s += " + operation_description_class_size<::" + parent + ">::value";
}
out << tab(1) << "return 0;" << endl
<< "}" << endl;
return out;
}
struct inheritance_wrappers
{
eo_class const& _cls;
inheritance_wrappers(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_wrappers const& x)
{
functions_container_type::const_iterator it,
first = x._cls.functions.begin(),
last = x._cls.functions.end();
for (it = first; it != last; ++it)
{
eo_function const& func = *it;
out << scope_guard_head(x._cls, func);
out << "template <typename T>" << endl
<< reinterpret_type(func.ret) << " "
<< _ns_as_prefix(x._cls) << "_"
<< x._cls.name << "_" << func.name
<< "_wrapper(Eo* objid EINA_UNUSED, "
<< "::efl::eo::detail::Inherit_Private_Data* self"
<< (func.params.size() ? ", " : "")
<< parameters_c_declaration(func.params)
<< ")" << endl
<< "{" << endl;
out << tab(1)
<< "try" << endl
<< tab(2) << "{" << endl
<< tab(3)
<< (!function_is_void(func) ? "return ": "")
<< "static_cast<T*>(self->this_)->"
<< func.name << "(" << parameters_cxx_list(func.params) << ");" << endl
<< tab(2) << "}" << endl
<< tab(1) << "catch (...)" << endl
<< tab(2) << "{" << endl
<< tab(3) << "eina_error_set( ::efl::eina::unknown_error() );" << endl;
if (!function_is_void(func))
out << tab(3) << func.ret.front().native << " _tmp_ret{};" << endl
<< tab(3) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl;
out << tab(2) << "}" << endl
<< "}" << endl;
out << scope_guard_tail(x._cls, func) << endl;
}
return out;
}
struct inheritance_base_operations_size
{
eo_class const& _cls;
inheritance_base_operations_size(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_base_operations_size const& x)
{
int pcted = 0;
int beta = 0;
int pcted_beta = 0;
auto funcs = x._cls.functions;
for (auto const& f : funcs)
{
if (f.is_beta && f.scope != eolian_scope::public_)
++pcted_beta;
if (f.scope != eolian_scope::public_)
++pcted;
if (f.is_beta)
++beta;
}
auto all = funcs.size();
out << "template<>"
<< endl << "struct operation_description_class_size< "
<< full_name(x._cls) << " >" << endl
<< "{" << endl
<< tab(1) << "static constexpr int value = " << endl
<< "#if defined(" << name_upper(x._cls) << "_PROTECTED)"
<< " && defined(" << name_upper(x._cls) << "_BETA)" << endl
<< tab(2) << all << endl
<< "#elif defined(" << name_upper(x._cls) << "_PROTECTED)" << endl
<< tab(2) << (all - beta) << endl
<< "#elif defined(" << name_upper(x._cls) << "_BETA)" << endl
<< tab(2) << (all - pcted) << endl
<< "#else" << endl
<< tab(2) << (all + pcted_beta - beta - pcted) << endl
<< "#endif" << endl;
for (std::string const& parent : x._cls.parents)
{
out << tab(2) << "+ operation_description_class_size<::" << parent << " >::value";
}
out << ";" << endl
<< "};" << endl
<< endl;
return out;
}
struct inheritance_base_operations_extensions
{
eo_class const& _cls;
inheritance_base_operations_extensions(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_base_operations_extensions const& x)
{
eo_class const& cls = x._cls;
ancestors_container_type::const_iterator it, first = cls.parents.begin();
ancestors_container_type::const_iterator last = cls.parents.end();
for (it = first; it != last; ++it)
{
out << endl
<< tab(3) << (it == first ? ": " : ", ")
<< "virtual operations< ::" << *it
<< " >::template type<T>";
}
return out << endl;
}
struct inheritance_base_operations_function
{
eo_class const& _cls;
eo_function const& _func;
inheritance_base_operations_function(eo_class const& cls, eo_function const& func)
: _cls(cls) , _func(func)
{}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_base_operations_function const& x)
{
eo_function const& func = x._func;
bool is_void = function_is_void(func);
if (parameters_count_callbacks(func.params))
out << template_parameters_declaration(func.params, 2) << tab(2);
else
out << tab(2) << "virtual ";
out << reinterpret_type(func.ret) << " "
<< func.name << "("
<< parameters_declaration(func.params) << ")" << endl
<< tab(2) << "{" << endl;
if (!is_void)
out << tab(3) << func.ret.front().native << " _tmp_ret = {};" << endl;
out << callbacks_heap_alloc("dynamic_cast<T*>(this)->_eo_ptr()", func.params, function_is_static(x._func), 3)
<< endl;
out << tab(3) << parameterized_obj_function_call(func, "eo_super(dynamic_cast<T*>(this)->_eo_ptr(), dynamic_cast<T*>(this)->_eo_class())") << ";" << endl;
if (!is_void)
out << tab(4) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl;
return out << tab(2) << "}" << endl;
}
struct inheritance_base_operations
{
eo_class const& _cls;
inheritance_base_operations(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_base_operations const& x)
{
out << "template<>" << endl
<< "struct operations< "
<< full_name(x._cls) << " >" << endl
<< "{" << endl
<< tab(1) << "template <typename T>" << endl
<< tab(1) << "struct type" << inheritance_base_operations_extensions(x._cls)
<< tab(1) << "{" << endl;
functions_container_type::const_iterator it,
first = x._cls.functions.begin(),
last = x._cls.functions.end();
for (it = first; it != last; ++it)
{
out << scope_guard_head(x._cls, *it);
out << inheritance_base_operations_function(x._cls, *it);
out << scope_guard_tail(x._cls, *it) << endl;
}
out << tab(1) << "};" << endl
<< "};" << endl << endl;
return out;
}
struct inheritance_eo_class_getter
{
eo_class const& _cls;
inheritance_eo_class_getter(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, inheritance_eo_class_getter const& x)
{
out << "inline Eo_Class const* get_eo_class(tag<"
<< full_name(x._cls) << ">)" << endl
<< "{" << endl
<< tab(1) << "return (" << x._cls.eo_name << ");" << endl
<< "}" << endl << endl;
return out;
}
inline void
eo_inheritance_detail_generator(std::ostream& out, eo_class const& cls)
{
if(cls.eo_name != "EO_BASE_CLASS")
out << inheritance_wrappers(cls)
<< "namespace efl { namespace eo { namespace detail {" << endl << endl
<< inheritance_base_operations(cls) << endl
<< inheritance_base_operations_size(cls)
<< inheritance_operations_description(cls)
<< inheritance_eo_class_getter(cls)
<< "} } }" << endl;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_INHERITANCE_GENERATOR_HH

View File

@ -0,0 +1,15 @@
#ifndef EOLIAN_CXX_KEYWORD_HH
#define EOLIAN_CXX_KEYWORD_HH
namespace efl { namespace eolian { namespace grammar {
inline std::string escape_keyword(std::string const& name)
{
if(name == "delete" || name == "register")
return "cxx_" + name;
return name;
}
} } }
#endif

View File

@ -0,0 +1,704 @@
#ifndef EOLIAN_CXX_KLASS_DEF_HH
#define EOLIAN_CXX_KLASS_DEF_HH
#include "grammar/type_traits.hpp"
#include "grammar/variant.hpp"
#include "grammar/attributes.hpp"
#include "grammar/qualifier_def.hpp"
#include "grammar/string.hpp"
#include "grammar/sequence.hpp"
#include "grammar/kleene.hpp"
#include "grammar/case.hpp"
#include <Eolian.h>
#include <Eina.hh>
#include <vector>
#include <memory>
#include <set>
namespace efl { namespace eolian { namespace grammar { namespace attributes {
template <typename...Args, std::size_t I>
bool lexicographical_compare_impl(std::tuple<Args...> const&
, std::tuple<Args...> const&
, std::integral_constant<std::size_t, I>
, std::true_type)
{
return true;
}
template <typename...Args, std::size_t I>
bool lexicographical_compare_impl(std::tuple<Args...> const& lhs
, std::tuple<Args...> const& rhs
, std::integral_constant<std::size_t, I>
, std::false_type)
{
return std::get<I>(lhs) < std::get<I>(rhs)
|| (!(std::get<I>(rhs) < std::get<I>(lhs))
&& lexicographical_compare_impl(lhs, rhs, std::integral_constant<std::size_t, I+1>()
, std::integral_constant<bool, I + 1 == sizeof...(Args)>())
)
;
}
template <typename...Args>
bool lexicographical_compare(std::tuple<Args...> const& lhs
, std::tuple<Args...> const& rhs)
{
return lexicographical_compare_impl(lhs, rhs, std::integral_constant<std::size_t, 0ul>(), std::false_type());
}
template <typename T, typename U>
bool lexicographical_compare(std::tuple<T, U> const& lhs
, std::tuple<T, U> const& rhs)
{
return std::get<0>(lhs) < std::get<0>(rhs)
|| (!(std::get<0>(rhs) < std::get<0>(lhs))
&& std::get<1>(lhs) < std::get<1>(rhs));
}
struct pointer_indirection
{
qualifier_def qualifier;
bool reference;
};
inline bool operator<(pointer_indirection const& lhs, pointer_indirection const& rhs)
{
return lexicographical_compare(std::make_tuple(lhs.qualifier, lhs.reference)
, std::make_tuple(rhs.qualifier, rhs.reference));
}
inline bool operator==(pointer_indirection const& lhs, pointer_indirection const& rhs)
{
return lhs.qualifier == rhs.qualifier && lhs.reference == rhs.reference;
}
inline bool operator!=(pointer_indirection const& lhs, pointer_indirection const& rhs)
{
return !(lhs == rhs);
}
struct type_def;
bool operator==(type_def const& rhs, type_def const& lhs);
bool operator!=(type_def const& rhs, type_def const& lhs);
enum class class_type
{
regular, abstract_, mixin, interface_
};
struct klass_name
{
std::vector<std::string> namespaces;
std::string eolian_name;
qualifier_def base_qualifier;
std::vector<pointer_indirection> pointers;
class_type type;
klass_name(std::vector<std::string> namespaces
, std::string eolian_name, qualifier_def base_qualifier
, std::vector<pointer_indirection> pointers
, class_type type)
: namespaces(namespaces), eolian_name(eolian_name), base_qualifier(base_qualifier)
, pointers(pointers), type(type) {}
klass_name(Eolian_Class const* klass, qualifier_def base_qualifier
, std::vector<pointer_indirection> pointers)
: eolian_name( ::eolian_class_name_get(klass))
, base_qualifier(base_qualifier), pointers(pointers)
{
for(efl::eina::iterator<const char> namespace_iterator ( ::eolian_class_namespaces_get(klass))
, namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
{
namespaces.push_back(&*namespace_iterator);
}
switch(eolian_class_type_get(klass))
{
case EOLIAN_CLASS_REGULAR:
type = class_type::regular;
break;
case EOLIAN_CLASS_ABSTRACT:
type = class_type::abstract_;
break;
case EOLIAN_CLASS_MIXIN:
type = class_type::mixin;
break;
case EOLIAN_CLASS_INTERFACE:
type = class_type::interface_;
break;
default:
throw std::runtime_error("Class with unknown type");
}
}
};
inline bool operator==(klass_name const& lhs, klass_name const& rhs)
{
return lhs.namespaces == rhs.namespaces && lhs.eolian_name == rhs.eolian_name
&& lhs.base_qualifier == rhs.base_qualifier && lhs.pointers == rhs.pointers;
}
inline bool operator!=(klass_name const& lhs, klass_name const& rhs)
{
return !(lhs == rhs);
}
inline bool operator<(klass_name const& lhs, klass_name const& rhs)
{
typedef std::tuple<std::vector<std::string>const&
, std::string const&
, qualifier_def const&
, std::vector<pointer_indirection> const&
, class_type
> tuple_type;
return lexicographical_compare(tuple_type(lhs.namespaces, lhs.eolian_name
, lhs.base_qualifier, lhs.pointers
, lhs.type)
, tuple_type(rhs.namespaces, rhs.eolian_name
, rhs.base_qualifier, rhs.pointers
, rhs.type));
}
template <>
struct tuple_element<0ul, klass_name>
{
typedef std::vector<std::string> type;
static type& get(klass_name& klass) { return klass.namespaces; }
static type const& get(klass_name const& klass) { return klass.namespaces; }
};
template <>
struct tuple_element<1ul, klass_name>
{
typedef std::string type;
static type& get(klass_name& klass) { return klass.eolian_name; }
static type const& get(klass_name const& klass) { return klass.eolian_name; }
};
template <int N>
struct tuple_element<N, klass_name const> : tuple_element<N, klass_name> {};
template <int N>
typename tuple_element<N, klass_name>::type&
get(klass_name& klass)
{
return tuple_element<N, klass_name>::get(klass);
}
template <int N>
typename tuple_element<N, klass_name>::type const&
get(klass_name const& klass)
{
return tuple_element<N, klass_name>::get(klass);
}
struct regular_type_def
{
std::string base_type;
qualifier_def base_qualifier;
std::vector<pointer_indirection> pointers;
std::vector<std::string> namespaces;
};
inline bool operator==(regular_type_def const& rhs, regular_type_def const& lhs)
{
return rhs.base_type == lhs.base_type && rhs.base_qualifier == lhs.base_qualifier
&& rhs.pointers == lhs.pointers;
}
inline bool operator!=(regular_type_def const& rhs, regular_type_def const& lhs)
{
return !(rhs == lhs);
}
struct complex_type_def
{
regular_type_def outer;
std::vector<type_def> subtypes;
};
inline bool operator==(complex_type_def const& lhs, complex_type_def const& rhs)
{
return lhs.outer == rhs.outer && lhs.subtypes == rhs.subtypes;
}
inline bool operator!=(complex_type_def const& lhs, complex_type_def const& rhs)
{
return !(lhs == rhs);
}
struct type_def
{
typedef attributes::variant<klass_name, regular_type_def, complex_type_def> variant_type;
variant_type original_type;
std::string c_type;
type_def() {}
type_def(variant_type original_type, std::string c_type)
: original_type(original_type), c_type(c_type) {}
type_def(Eolian_Type const* eolian_type)
{
set(eolian_type);
}
struct set_pointer_visitor
{
typedef void result_type;
std::vector<pointer_indirection> pointers;
template <typename T>
void operator()(T& v) const
{
v.pointers = pointers;
}
void operator()(complex_type_def& complex) const
{
(*this)(complex.outer);
}
};
void set(Eolian_Type const* eolian_type);
};
inline bool operator==(type_def const& lhs, type_def const& rhs)
{
return lhs.original_type == rhs.original_type && lhs.c_type == rhs.c_type;
}
inline bool operator!=(type_def const& lhs, type_def const& rhs)
{
return !(lhs == rhs);
}
type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}}, "void"};
inline void type_def::set(Eolian_Type const* eolian_type)
{
c_type = ::eolian_type_c_type_get(eolian_type);
// ::eina_stringshare_del(stringshare); // this crashes
switch( ::eolian_type_type_get(eolian_type))
{
case EOLIAN_TYPE_VOID:
original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type), {}}, {}};
break;
case EOLIAN_TYPE_REGULAR:
{
std::vector<std::string> namespaces;
for(efl::eina::iterator<const char> namespace_iterator( ::eolian_type_namespaces_get(eolian_type))
, namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
namespaces.push_back(&*namespace_iterator);
original_type = {regular_type_def{ ::eolian_type_name_get(eolian_type), {qualifiers(eolian_type), {}}, {}, namespaces}};
}
break;
case EOLIAN_TYPE_POINTER:
{
std::vector<pointer_indirection> pointers
{{ {qualifiers(eolian_type)}, false }};
Eolian_Type const* base_type = eolian_type_base_type_get(eolian_type);
while(eolian_type_type_get(base_type) == EOLIAN_TYPE_POINTER)
{
pointers.push_back({qualifiers(base_type)});
base_type = eolian_type_base_type_get(base_type);
}
set(base_type);
original_type.visit(set_pointer_visitor{pointers});
c_type = ::eolian_type_c_type_get(eolian_type);
break;
}
case EOLIAN_TYPE_CLASS:
{
Eolian_Class const* klass = eolian_type_class_get(eolian_type);
original_type = klass_name(klass, {qualifiers(eolian_type)}, {});
}
break;
case EOLIAN_TYPE_COMPLEX:
{
complex_type_def complex
{{::eolian_type_name_get(eolian_type), {qualifiers(eolian_type), {}}, {}}, {}};
for(efl::eina::iterator<Eolian_Type const> type_iterator( ::eolian_type_subtypes_get(eolian_type))
, type_last; type_iterator != type_last; ++type_iterator)
{
Eolian_Type const* type = &*type_iterator;
complex.subtypes.push_back({type});
}
original_type = complex;
}
break;
default:
std::abort();
break;
}
}
enum class parameter_direction
{
in, inout, out
};
namespace detail {
struct add_optional_qualifier_visitor
{
typedef void result_type;
template <typename T>
void operator()(T& object) const
{
add_optional(object.base_qualifier);
}
void operator()(complex_type_def& complex) const
{
(*this)(complex.outer);
}
};
}
struct parameter_def
{
parameter_direction direction;
type_def type;
std::string param_name;
std::string c_type;
parameter_def(parameter_direction direction, type_def type, std::string param_name, std::string c_type)
: direction(direction), type(type), param_name(param_name), c_type(c_type) {}
parameter_def(Eolian_Function_Parameter const* param)
: type( ::eolian_parameter_type_get(param))
, param_name( ::eolian_parameter_name_get(param))
, c_type( ::eolian_type_c_type_get(::eolian_parameter_type_get(param)))
{
Eolian_Parameter_Dir direction = ::eolian_parameter_direction_get(param);
switch(direction)
{
case EOLIAN_IN_PARAM:
this->direction = parameter_direction::in;
break;
case EOLIAN_INOUT_PARAM:
this->direction = parameter_direction::inout;
break;
case EOLIAN_OUT_PARAM:
this->direction = parameter_direction::out;
break;
}
if( ::eolian_parameter_is_optional(param))
type.original_type.visit(detail::add_optional_qualifier_visitor{});
}
};
template <>
struct tuple_element<0ul, parameter_def>
{
typedef parameter_direction type;
static type const& get(parameter_def const& p) { return p.direction; }
static type& get(parameter_def& p) { return p.direction; }
};
template <>
struct tuple_element<1ul, parameter_def>
{
typedef type_def type;
static type const& get(parameter_def const& p) { return p.type; }
static type& get(parameter_def& p) { return p.type; }
};
template <>
struct tuple_element<2ul, parameter_def>
{
typedef std::string type;
static type const& get(parameter_def const& p) { return p.param_name; }
static type& get(parameter_def& p) { return p.param_name; }
};
template <>
struct tuple_element<3ul, parameter_def>
{
typedef std::string type;
static type const& get(parameter_def const& p) { return p.c_type; }
static type& get(parameter_def& p) { return p.c_type; }
};
template <int I>
typename tuple_element<I, parameter_def>::type const& get(parameter_def const& p)
{ return tuple_element<I, parameter_def>::get(p); }
template <int I>
typename tuple_element<I, parameter_def>::type& get(parameter_def& p)
{ return tuple_element<I, parameter_def>::get(p); }
struct function_def
{
type_def return_type;
std::string name;
std::vector<parameter_def> parameters;
std::string c_name;
bool is_beta;
bool is_protected;
function_def(type_def return_type, std::string name, std::vector<parameter_def> parameters
, std::string c_name, bool is_beta)
: return_type(return_type), name(name), parameters(parameters), c_name(c_name), is_beta(is_beta) {}
function_def() = default;
function_def( ::Eolian_Function const* function, Eolian_Function_Type type)
: return_type(void_)
{
Eolian_Type const* r_type = ::eolian_function_return_type_get(function, type);
name = ::eolian_function_name_get(function);
if(r_type)
return_type.set(r_type);
if(type == EOLIAN_METHOD)
{
for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator ( ::eolian_function_parameters_get(function))
, param_last; param_iterator != param_last; ++param_iterator)
{
parameters.push_back(&*param_iterator);
}
}
else if(type == EOLIAN_PROP_GET || type == EOLIAN_PROP_SET)
{
if(type == EOLIAN_PROP_GET)
name += "_get";
else
name += "_set";
for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator
( ::eolian_property_keys_get(function, type))
, param_last; param_iterator != param_last; ++param_iterator)
{
parameters.push_back(&*param_iterator);
}
std::vector<parameter_def> values;
for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator
( ::eolian_property_values_get(function, type))
, param_last; param_iterator != param_last; ++param_iterator)
{
values.push_back(&*param_iterator);
}
if(type == EOLIAN_PROP_GET && values.size() == 1 && return_type == void_)
{
return_type = values[0].type;
}
else if(type == EOLIAN_PROP_GET)
{
for(auto&& v : values)
{
v.direction = parameter_direction::out;
parameters.push_back(v);
}
}
else
parameters.insert(parameters.end(), values.begin(), values.end());
}
c_name = eolian_function_full_c_name_get(function, type, EINA_FALSE);
is_beta = eolian_function_is_beta(function);
is_protected = eolian_function_scope_get(function) == EOLIAN_SCOPE_PROTECTED;
}
};
template <>
struct tuple_element<0ul, function_def>
{
typedef type_def type;
static type& get(function_def& f) { return f.return_type; }
static type const& get(function_def const& f) { return f.return_type; }
};
template <>
struct tuple_element<1ul, function_def>
{
typedef std::string type;
static type& get(function_def& f) { return f.name; }
static type const& get(function_def const& f) { return f.name; }
};
template <>
struct tuple_element<2ul, function_def>
{
typedef std::vector<parameter_def> type;
static type& get(function_def& f) { return f.parameters; }
static type const& get(function_def const& f) { return f.parameters; }
};
// template <int N>
// struct tuple_element<N, function_def const> : tuple_element<N, function_def> {};
// template <int N>
// struct tuple_element<N, function_def&> : tuple_element<N, function_def> {};
// template <int N>
// struct tuple_element<N, function_def const&> : tuple_element<N, function_def> {};
// template <std::size_t I>
// typename tuple_element<I, function_def>::type const&
// get(function_def const& f)
// {
// return tuple_element<I, function_def>::get(f);
// }
// template <std::size_t I>
// typename tuple_element<I, function_def>::type&
// get(function_def& f)
// {
// return tuple_element<I, function_def>::get(f);
// }
struct compare_klass_name_by_name
{
bool operator()(klass_name const& lhs, klass_name const& rhs) const
{
return lhs.namespaces < rhs.namespaces
|| (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name);
}
};
struct event_def
{
eina::optional<type_def> type;
std::string name, c_name;
event_def(type_def type, std::string name, std::string c_name)
: type(type), name(name), c_name(c_name) {}
event_def(Eolian_Event const* event)
: type( ::eolian_event_type_get(event) ? ::eolian_event_type_get(event) : eina::optional<type_def>{})
, name( ::eolian_event_name_get(event))
, c_name( ::eolian_event_c_name_get(event)) {}
};
template <>
struct tuple_element<0, event_def>
{
typedef eina::optional<type_def> type;
static type& get(event_def& def) { return def.type; }
static type const& get(event_def const& def) { return def.type; }
};
template <>
struct tuple_element<1, event_def>
{
typedef std::string type;
static type& get(event_def& def) { return def.name; }
static type const& get(event_def const& def) { return def.name; }
};
template <>
struct tuple_element<2, event_def>
{
typedef std::string type;
static type& get(event_def& def) { return def.c_name; }
static type const& get(event_def const& def) { return def.c_name; }
};
template <int N>
struct tuple_element<N, event_def const> : tuple_element<N, event_def> {};
template <int N>
auto get(event_def const& def) -> decltype(tuple_element<N, event_def>::get(def))
{
return tuple_element<N, event_def>::get(def);
}
template <int N>
auto get(event_def& def) -> decltype(tuple_element<N, event_def>::get(def))
{
return tuple_element<N, event_def>::get(def);
}
struct klass_def
{
std::string eolian_name;
std::string cxx_name;
std::vector<std::string> namespaces;
std::vector<function_def> functions;
std::set<klass_name, compare_klass_name_by_name> inherits;
class_type type;
std::vector<event_def> events;
klass_def(std::string eolian_name, std::string cxx_name
, std::vector<std::string> namespaces
, std::vector<function_def> functions
, std::set<klass_name, compare_klass_name_by_name> inherits
, class_type type)
: eolian_name(eolian_name), cxx_name(cxx_name)
, namespaces(namespaces)
, functions(functions), inherits(inherits), type(type)
{}
klass_def(Eolian_Class const* klass)
{
for(efl::eina::iterator<const char> namespace_iterator( ::eolian_class_namespaces_get(klass))
, namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
{
this->namespaces.push_back(&*namespace_iterator);
}
cxx_name = eolian_name = eolian_class_name_get(klass);
for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_PROPERTY))
, functions_last; eolian_functions != functions_last; ++eolian_functions)
{
Eolian_Function const* function = &*eolian_functions;
Eolian_Function_Type type = ::eolian_function_type_get(function);
if(type == EOLIAN_PROPERTY)
{
if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET)
&& ::eolian_function_scope_get(function) != EOLIAN_SCOPE_PRIVATE)
functions.push_back({function, EOLIAN_PROP_GET});
if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_SET)
&& ::eolian_function_scope_get(function) != EOLIAN_SCOPE_PRIVATE)
functions.push_back({function, EOLIAN_PROP_SET});
}
else
if(! ::eolian_function_is_legacy_only(function, type)
&& ::eolian_function_scope_get(function) != EOLIAN_SCOPE_PRIVATE)
functions.push_back({function, type});
}
for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD))
, functions_last; eolian_functions != functions_last; ++eolian_functions)
{
Eolian_Function const* function = &*eolian_functions;
if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD)
&& ::eolian_function_scope_get(function) != EOLIAN_SCOPE_PRIVATE)
functions.push_back({function, EOLIAN_METHOD});
}
std::function<void(Eolian_Class const*)> inherit_algo =
[&] (Eolian_Class const* klass)
{
for(efl::eina::iterator<const char> inherit_iterator ( ::eolian_class_inherits_get(klass))
, inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
{
Eolian_Class const* inherit = ::eolian_class_get_by_name(&*inherit_iterator);
inherits.insert({inherit, {qualifier_info::is_none}, {}});
inherit_algo(inherit);
}
};
inherit_algo(klass);
switch(eolian_class_type_get(klass))
{
case EOLIAN_CLASS_REGULAR:
type = class_type::regular;
break;
case EOLIAN_CLASS_ABSTRACT:
type = class_type::abstract_;
break;
case EOLIAN_CLASS_MIXIN:
type = class_type::mixin;
break;
case EOLIAN_CLASS_INTERFACE:
type = class_type::interface_;
break;
default:
throw std::runtime_error("Class with unknown type");
}
for(efl::eina::iterator<Eolian_Event const> event_iterator( ::eolian_class_events_get(klass))
, event_last; event_iterator != event_last; ++event_iterator)
{
events.push_back(&*event_iterator);
}
}
};
inline klass_name get_klass_name(klass_def const& klass)
{
return {klass.namespaces, klass.eolian_name, {qualifier_info::is_none, {}}, {}, klass.type};
}
inline Eolian_Class const* get_klass(klass_name const& klass_name_)
{
std::string klass_name;
if(!as_generator(*(string << ".") << string)
.generate(std::back_insert_iterator<std::string>(klass_name)
, std::make_tuple(klass_name_.namespaces, klass_name_.eolian_name)
, context_null{}))
return nullptr;
else
return ::eolian_class_get_by_name(klass_name.c_str());
}
inline std::vector<std::string> cpp_namespaces(std::vector<std::string> namespaces)
{
if(namespaces.empty())
namespaces.push_back("nonamespace");
return namespaces;
}
}
namespace type_traits {
template <>
struct is_tuple<attributes::parameter_def> : std::true_type {};
template <>
struct is_tuple<attributes::event_def> : std::true_type {};
} } } }
#endif

View File

@ -0,0 +1,47 @@
#ifndef EOLIAN_CXX_KLEENE_HH
#define EOLIAN_CXX_KLEENE_HH
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename Generator>
struct kleene_generator
{
kleene_generator(Generator g)
: generator(g) {}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
bool b;
for(auto&& c : attribute)
{
b = as_generator(generator).generate(sink, c, context);
if(!b)
return false;
}
return true;
}
Generator generator;
};
template <typename Generator>
struct is_eager_generator<kleene_generator<Generator> > : std::true_type {};
namespace type_traits {
template <typename G>
struct attributes_needed<kleene_generator<G> > : std::integral_constant<int, 1> {};
}
template <typename Generator>
typename std::enable_if<grammar::is_generator<Generator>::value, kleene_generator<Generator>>::type
operator*(Generator g)
{
return kleene_generator<Generator>{g};
}
} } }
#endif

View File

@ -0,0 +1,52 @@
#ifndef EOLIAN_CXX_LIST_HH
#define EOLIAN_CXX_LIST_HH
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename G, typename S>
struct list_generator
{
list_generator(G g, S s)
: g(g), s(s) {}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
auto generator = as_generator(g);
auto separator = as_generator(s);
bool first = true;
for(auto&& c : attribute)
{
if(!first)
if(!separator.generate(sink, attributes::unused, context)) return false;
if(!generator.generate(sink, c, context))
return false;
first = false;
}
return true;
}
G g;
S s;
};
template <typename G, typename S>
struct is_eager_generator<list_generator<G, S> > : std::true_type {};
namespace type_traits {
template <typename G, typename S>
struct attributes_needed<list_generator<G, S> > : std::integral_constant<int, 1> {};
}
template <typename G, typename S>
typename std::enable_if<grammar::is_generator<G>::value && grammar::is_generator<S>::value, list_generator<G, S>>::type
operator%(G g, S s)
{
return list_generator<G, S>{g, s};
}
} } }
#endif

View File

@ -0,0 +1,42 @@
#ifndef EOLIAN_CXX_META_HH_
#define EOLIAN_CXX_META_HH_
#include <utility>
#include <type_traits>
namespace efl { namespace eolian { namespace grammar { namespace meta {
template <std::size_t A0, std::size_t A1 = 0, std::size_t...args>
struct max : max<((A0 > A1) ? A0 : A1), args...> {};
template <std::size_t A0, std::size_t A1>
struct max<A0, A1> : std::integral_constant<std::size_t, (A0 > A1 ? A0 : A1)> {};
template <typename T>
struct identity { typedef T type; };
template <typename T, typename U, typename...Others>
struct is_one_of : std::conditional<std::is_same<T, U>::value
, std::is_same<T, U>
, is_one_of<T, Others...> >::type::type
{};
template <typename T, typename U>
struct is_one_of<T, U> : std::is_same<T, U>
{};
template <std::size_t size, typename T, typename U, typename...Args>
struct find_impl : find_impl<size+1, T, Args...>
{};
template <std::size_t size, typename T, typename...Args>
struct find_impl<size, T, T, Args...> : std::integral_constant<std::size_t, size> {};
template <typename T, typename U, typename...Args>
struct find : find_impl<0u, T, U, Args...>
{};
} } } }
#endif

View File

@ -0,0 +1,67 @@
#ifndef EOLIAN_CXX_NAMESPACES_HH
#define EOLIAN_CXX_NAMESPACES_HH
#include "grammar/generator.hpp"
#include "grammar/attributes.hpp"
#include "grammar/type_traits.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename Generator>
struct namespaces_generator
{
template <typename OutputIterator, typename Attributes, typename Context>
bool generate(OutputIterator sink, Attributes const& attributes, Context const& context) const
{
using std::get;
typedef typename attributes::tuple_element<0ul, Attributes>::type namespaces_t;
namespaces_t const& namespaces = attributes::cpp_namespaces(get<0>(attributes));
std::size_t size = namespaces.size();
for(auto&& n : namespaces)
{
const char keyword[] = "namespace ";
const char open[] = " { ";
std::copy(keyword, &keyword[0] + sizeof(keyword)-1, sink);
std::transform(std::begin(n), std::end(n), sink, &::tolower);
std::copy(open, &open[0] + sizeof(open)-1, sink);
}
*sink++ = '\n';
if(!attributes::generate(as_generator(generator), sink, attributes::pop_front(attributes), context))
return false;
for(std::size_t i = 0; i != size; ++i)
{
const char close[] = "} ";
std::copy(close, &close[0] + sizeof(close)-1, sink);
}
return true;
}
Generator generator;
};
struct namespaces_directive
{
template <typename G>
namespaces_generator<G> operator[](G g) const
{
return namespaces_generator<G>{g};
}
} const namespaces;
template <typename G>
struct is_eager_generator<namespaces_generator<G>> : std::true_type {};
namespace type_traits {
template <typename G>
struct attributes_needed<namespaces_generator<G>> : std::integral_constant<int, attributes_needed<G>::value+1> {};
template <typename G>
struct accepts_tuple<namespaces_generator<G> > : std::true_type {};
}
} } }
#endif

View File

@ -1,68 +0,0 @@
#ifndef EOLIAN_CXX_NAMESPACE_GENERATOR_HH
#define EOLIAN_CXX_NAMESPACE_GENERATOR_HH
#include "eo_types.hh"
#include "tab.hh"
namespace efl { namespace eolian { namespace grammar {
struct abstract_namespace_type {};
abstract_namespace_type const abstract_namespace = {};
inline std::ostream&
operator<<(std::ostream& out, abstract_namespace_type const&)
{
return out << "eo_cxx";
}
struct namespace_head
{
namespace_head(eo_class const& cls) : _cls(cls) {}
eo_class const& _cls;
};
inline std::ostream&
operator<<(std::ostream& out, namespace_head const& x)
{
if (x._cls.name_space != "")
{
std::string ns = x._cls.name_space;
size_t pos = 0;
while ((pos = ns.find("::")) != std::string::npos)
{
out << "namespace " << ns.substr(0, pos) << " { ";
ns.erase(0, pos+2);
}
out << "namespace " << ns << " {" << endl << endl;
}
return out;
}
struct namespace_tail
{
namespace_tail(eo_class const& cls) : _cls(cls) {}
eo_class const& _cls;
};
inline std::ostream&
operator<<(std::ostream& out, namespace_tail const& x)
{
if (x._cls.name_space != "")
{
std::string ns = x._cls.name_space;
size_t pos = 0;
while ((pos = ns.find("::")) != std::string::npos)
{
out << "} ";
ns.erase(0, pos+2);
}
out << "}" << endl << endl;
}
return out;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif

View File

@ -0,0 +1,78 @@
#ifndef EOLIAN_CXX_PARAMETER_HH
#define EOLIAN_CXX_PARAMETER_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/type.hpp"
namespace efl { namespace eolian { namespace grammar {
struct add_reference_visitor
{
typedef void result_type;
template <typename T>
void operator()(T& object) const
{
object.pointers.insert(object.pointers.begin(), {{attributes::qualifier_info::is_none}, true});
}
void operator()(attributes::complex_type_def& complex) const
{
(*this)(complex.outer);
}
};
struct parameter_type_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
std::string dir;
switch(param.direction)
{
case attributes::parameter_direction::out:
dir = "out";
break;
case attributes::parameter_direction::inout:
dir = "inout";
break;
case attributes::parameter_direction::in:
dir = "in";
break;
}
return as_generator
(
" ::efl::eolian::" << string << "_traits<"
<< type << ">::type"
).generate(sink, std::make_tuple(dir, param), context);
}
};
template <>
struct is_eager_generator<parameter_type_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<parameter_type_generator> : std::integral_constant<int, 1> {};
}
parameter_type_generator const parameter_type;
struct parameter_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return as_generator(parameter_type << " " << string).generate(sink, std::make_tuple(param, param.param_name), context);
}
};
template <>
struct is_eager_generator<parameter_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<parameter_generator> : std::integral_constant<int, 1> {};
}
parameter_generator const parameter;
} } }
#endif

View File

@ -1,453 +0,0 @@
#ifndef EOLIAN_CXX_STD_PARAMETERS_GENERATOR_HH
#define EOLIAN_CXX_STD_PARAMETERS_GENERATOR_HH
#include <iosfwd>
#include "tab.hh"
#include "eo_types.hh"
#include "type_generator.hh"
namespace efl { namespace eolian { namespace grammar {
struct
parameter_forward
{
eolian_type_instance const& _type;
std::string const& _name;
parameter_forward(eolian_type_instance const& type, std::string const& name)
: _type(type)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameter_forward const& x)
{
if (type_is_callback(x._type))
{
out << "std::forward<" << template_parameter_type(x._type, x._name) << ">(" << x._name << ")";
}
else
out << x._name;
return out;
}
struct param_data
{
std::ostream& out;
unsigned pos;
eolian_type_instance const& type;
std::string const& name;
int cb_idx;
bool is_cb;
param_data(std::ostream& out_, unsigned pos_, eolian_type_instance const& type_, std::string const& name_, int cb_idx_)
: out(out_)
, pos(pos_)
, type(type_)
, name(name_)
, cb_idx(cb_idx_)
, is_cb(cb_idx_ >= 0)
{}
};
template <typename T>
struct
_parameters_cxx_generic
{
parameters_container_type const& _params;
T _fparam;
_parameters_cxx_generic(parameters_container_type const& params, T fparam)
: _params(params)
, _fparam(fparam)
{}
};
template <typename T>
std::ostream&
operator<<(std::ostream& out, _parameters_cxx_generic<T> const& x)
{
int cb_idx = 0u;
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (type_is_callback((*it).type) && it+1 != last)
{
x._fparam(param_data(out, it - first, (*it).type, (*it).name, cb_idx++));
++it; // skip next.
}
else
x._fparam(param_data(out, it - first, (*it).type, (*it).name, -1));
}
return out;
}
template <typename T>
_parameters_cxx_generic<T>
parameters_cxx_generic(parameters_container_type const& params, T fparam)
{
return _parameters_cxx_generic<T>(params, fparam);
}
struct
callback_tmp
{
std::string const& _name;
callback_tmp(std::string const& name)
: _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, callback_tmp const& x)
{
return out << "_tmp_" << x._name;
}
struct
callback_parameter_free_ev_add
{
std::string const& _eo_raw_expr;
eolian_type_instance const& _type;
std::string const& _name;
callback_parameter_free_ev_add(std::string const& eo_raw_expr, eolian_type_instance const& type, std::string const& name)
: _eo_raw_expr(eo_raw_expr)
, _type(type)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, callback_parameter_free_ev_add const& x)
{
out
<< "eo_event_callback_add(" << x._eo_raw_expr
<< ", EO_EVENT_DEL, &::efl::eolian::free_callback_callback<"
<< parameter_no_ref_type(x._type, x._name) << ">, "
<< callback_tmp(x._name) << ");";
return out;
}
struct
callbacks_heap_alloc
{
std::string const& _eo_raw_expr;
parameters_container_type const& _params;
bool _is_static_func;
int _tab;
callbacks_heap_alloc(std::string const& eo_raw_expr, parameters_container_type const& params, bool is_static_func, int tab)
: _eo_raw_expr(eo_raw_expr)
, _params(params)
, _is_static_func(is_static_func)
, _tab(tab)
{}
};
inline std::ostream&
operator<<(std::ostream& out, callbacks_heap_alloc const& x)
{
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
auto type = (*it).type;
auto name = (*it).name;
if (type_is_callback(type) && it+1 != last)
{
out << tab(x._tab) << parameter_remove_reference_typedef(type, name) << endl
<< tab(x._tab) << parameter_no_ref_type(type, name) << "* "
<< callback_tmp(name) << " = ";
if (!x._is_static_func)
{
out << "new " << parameter_no_ref_type(type, name)
<< "(std::forward< "
<< template_parameter_type(type, name) << " >(" << name << "));" << endl
<< tab(x._tab)
<< callback_parameter_free_ev_add(x._eo_raw_expr, type, name)
<< endl << endl;
}
else
{
out << "::efl::eolian::alloc_static_callback< "
<< parameter_no_ref_type(type, name) << " >(std::forward< "
<< template_parameter_type(type, name) << " >(" << name << "));" << endl;
}
++it; // skip next.
}
}
return out;
}
struct
template_parameters_declaration
{
parameters_container_type const& _params;
int _tab;
template_parameters_declaration(parameters_container_type const& params, int tab)
: _params(params)
, _tab(tab)
{}
};
inline std::ostream&
operator<<(std::ostream& out, template_parameters_declaration const& x)
{
if (parameters_count_callbacks(x._params) == 0)
return out;
bool comma = false;
out << tab(x._tab) << "template <";
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (type_is_callback((*it).type) && it+1 != last)
{
if (comma)
out << ", ";
else
comma = true;
out << "typename " << template_parameter_type((*it).type, (*it).name);
++it; // skip next.
}
}
return out << ">" << endl;
}
struct
parameters_declaration
{
parameters_container_type const& _params;
parameters_declaration(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_declaration const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
// TODO What to do when callback happens in the middle of parameters
// and does not have a following userdata pointer ?
if (type_is_callback((*it).type) && it+1 != last)
{
out << template_parameter_type((*it).type, (*it).name) << " && " << (*it).name;
++it; // skip next.
}
else
out << reinterpret_type((*it).type) << " " << (*it).name;
}
return out;
}
struct
parameters_c_declaration
{
parameters_container_type const& _params;
parameters_c_declaration(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_c_declaration const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << c_type(it->type) << " " << (*it).name;
}
return out;
}
struct
parameters_names
{
parameters_container_type const& _params;
parameters_names(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_names const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << it->name;
if (type_is_callback(it->type) && it+1 != last)
++it; // skip next.
}
return out;
}
struct
parameters_c_names
{
parameters_container_type const& _params;
parameters_c_names(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_c_names const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << it->name;
}
return out;
}
struct
parameters_types
{
parameters_container_type const& _params;
parameters_types(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_types const& x)
{
parameters_container_type::const_iterator it,
first = x._params.begin(),
last = x._params.end();
for (it = first; it != last; ++it)
{
if(it != first) out << ", ";
out << reinterpret_type((*it).type);
}
return out;
}
struct
parameters_c_list
{
parameters_container_type const& _params;
parameters_c_list(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_c_list const& x)
{
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << it->name;
}
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 << ", ";
out << to_cxx(it->type, it->name);
}
return out;
}
struct
parameters_forward
{
parameters_container_type const& _params;
parameters_forward(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_forward const& x)
{
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << parameter_forward((*it).type, (*it).name);
if (type_is_callback((*it).type) && it+1 != last)
{
++it; // skip next.
}
}
return out;
}
struct
parameters_forward_to_c
{
parameters_container_type const& _params;
parameters_forward_to_c(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_forward_to_c 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))
{
// TODO: Is it correct to simple not translate the callback type
// when it is the last paramenter?
if(it + 1 != last)
{
out << to_c((*it).type, (*it).name) << ", " << callback_tmp((*it).name);
++it; // skip next
}
else
out << (*it).name;
}
else
out << to_c((*it).type, (*it).name);
}
return out;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_PARAMETERS_GENERATOR_HH

View File

@ -0,0 +1,178 @@
#ifndef EOLIAN_CXX_QUALIFIER_DEF_HH
#define EOLIAN_CXX_QUALIFIER_DEF_HH
#include "grammar/type_traits.hpp"
#include <Eolian.h>
namespace efl { namespace eolian { namespace grammar { namespace attributes {
enum class qualifier_info {
is_none
, is_own = 1
, is_const = 4
, is_const_own
, is_optional = 8
, is_optional_own
, is_optional_const
, is_optional_const_own
};
inline qualifier_info qualifiers(Eolian_Type const* type)
{
bool is_own = ::eolian_type_is_own(type);
bool is_const = ::eolian_type_is_const(type);
if(is_own && is_const)
return qualifier_info::is_const_own;
else if(is_own)
return qualifier_info::is_own;
else if(is_const)
return qualifier_info::is_const;
else
return qualifier_info::is_none;
}
inline bool is_own(qualifier_info i)
{
switch(i)
{
case qualifier_info::is_own:
case qualifier_info::is_const_own:
case qualifier_info::is_optional_own:
case qualifier_info::is_optional_const_own:
return true;
default:
return false;
}
}
inline bool is_const(qualifier_info i)
{
switch(i)
{
case qualifier_info::is_const:
case qualifier_info::is_const_own:
case qualifier_info::is_optional_const:
case qualifier_info::is_optional_const_own:
return true;
default:
return false;
}
}
inline bool is_optional(qualifier_info i)
{
switch(i)
{
case qualifier_info::is_optional:
case qualifier_info::is_optional_own:
case qualifier_info::is_optional_const:
case qualifier_info::is_optional_const_own:
return true;
default:
return false;
}
}
struct qualifier_def
{
qualifier_info qualifier;
std::string free_function;
};
inline bool operator<(qualifier_def const& lhs, qualifier_def const& rhs)
{
return lhs.qualifier < rhs.qualifier ||
(!(rhs.qualifier < lhs.qualifier) && lhs.free_function < rhs.free_function);
}
inline bool operator>(qualifier_def const& lhs, qualifier_def const& rhs)
{
return rhs < lhs;
}
inline bool operator==(qualifier_def const& lhs, qualifier_def const& rhs)
{
return rhs.qualifier == lhs.qualifier && rhs.free_function == lhs.free_function;
}
inline bool operator!=(qualifier_def const& lhs, qualifier_def const& rhs)
{
return !(rhs == lhs);
}
inline void add_optional(qualifier_def& q)
{
switch (q.qualifier)
{
case qualifier_info::is_none:
q.qualifier = qualifier_info::is_optional;
break;
case qualifier_info::is_own:
q.qualifier = qualifier_info::is_optional_own;
break;
case qualifier_info::is_const:
q.qualifier = qualifier_info::is_optional_const;
break;
case qualifier_info::is_const_own:
q.qualifier = qualifier_info::is_optional_const_own;
break;
default:
break;
}
}
inline void remove_optional(qualifier_def& q)
{
switch (q.qualifier)
{
case qualifier_info::is_optional:
q.qualifier = qualifier_info::is_none;
break;
case qualifier_info::is_optional_own:
q.qualifier = qualifier_info::is_own;
break;
case qualifier_info::is_optional_const:
q.qualifier = qualifier_info::is_const;
break;
case qualifier_info::is_optional_const_own:
q.qualifier = qualifier_info::is_const_own;
break;
default:
break;
}
}
inline void remove_own(qualifier_def& q)
{
switch (q.qualifier)
{
case qualifier_info::is_own:
q.qualifier = qualifier_info::is_none;
break;
case qualifier_info::is_const_own:
q.qualifier = qualifier_info::is_const;
break;
case qualifier_info::is_optional_own:
q.qualifier = qualifier_info::is_optional;
break;
case qualifier_info::is_optional_const_own:
q.qualifier = qualifier_info::is_optional_const;
break;
default:
break;
}
}
inline bool is_optional(qualifier_def const& i)
{
return is_optional(i.qualifier);
}
inline bool is_own(qualifier_def const& i)
{
return is_own(i.qualifier);
}
inline bool is_const(qualifier_def const& i)
{
return is_const(i.qualifier);
}
} } } }
#endif

View File

@ -0,0 +1,136 @@
#ifndef EOLIAN_CXX_SEQUENCE_HH
#define EOLIAN_CXX_SEQUENCE_HH
#include "grammar/generator.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename L, typename R>
struct sequence_generator;
template <typename T, typename Enable = void>
struct sequence_size : std::integral_constant<int, 0> {};
template <typename L, typename R>
struct sequence_size<sequence_generator<L, R>> : std::integral_constant<int, 1 + sequence_size<L>::value> {};
template <typename L, typename R, typename OutputIterator, typename Attribute, typename Context>
bool generate_sequence(L const& l, R const& r
, OutputIterator sink, Attribute const& attr, Context const& context
, typename std::enable_if<type_traits::is_tuple<Attribute>::value>::type* = 0)
{
auto gen_left = as_generator(l);
bool b = attributes::generate(gen_left, sink, attr, context);
if(b)
{
return attributes::generate(as_generator(r), sink
, attributes::pop_front_n<type_traits::attributes_needed<decltype(gen_left)>::value>
(attr), context);
}
else
return false;
}
template <typename L, typename R, typename OutputIterator, typename Attribute, typename Context>
bool generate_sequence(L const& l, R const& r
, OutputIterator sink, Attribute const& attr, Context const& context
, typename std::enable_if
<
!type_traits::is_tuple<Attribute>::value
&& type_traits::attributes_needed<L>::value == 0
&& type_traits::attributes_needed<R>::value == 1
>::type* = 0)
{
bool b = as_generator(l).generate(sink, attributes::unused, context);
if(b)
{
return as_generator(r).generate(sink, attr, context);
}
else
return false;
}
template <typename L, typename R, typename OutputIterator, typename Attribute, typename Context>
bool generate_sequence(L const& l, R const& r
, OutputIterator sink, Attribute const&, Context const& context
, typename std::enable_if
<
!type_traits::is_tuple<Attribute>::value
&& type_traits::attributes_needed<L>::value == 0
&& type_traits::attributes_needed<R>::value == 0
>::type* = 0)
{
bool b = as_generator(l).generate(sink, attributes::unused, context);
if(b)
{
return as_generator(r).generate(sink, attributes::unused, context);
}
else
return false;
}
template <typename L, typename R, typename OutputIterator, typename Attribute, typename Context>
bool generate_sequence(L const& l, R const& r
, OutputIterator sink, Attribute const& attr, Context const& context
, typename std::enable_if
<
!type_traits::is_tuple<Attribute>::value
&& type_traits::attributes_needed<L>::value == 1
&& type_traits::attributes_needed<R>::value == 0
>::type* = 0)
{
bool b = as_generator(l).generate(sink, attr, context);
if(b)
{
return as_generator(r).generate(sink, attributes::unused, context);
}
else
return false;
}
template <typename L, typename R, typename OutputIterator, typename Context>
bool generate_sequence(L const& l, R const& r, OutputIterator sink, attributes::unused_type, Context const& context)
{
bool b = as_generator(l).generate(sink, attributes::unused, context);
if(b)
{
return as_generator(r).generate(sink, attributes::unused, context);
}
else
return false;
}
template <typename L, typename R>
struct sequence_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
{
return grammar::generate_sequence(left, right, sink, attribute, context);
}
L left;
R right;
};
template <typename L, typename R>
struct is_eager_generator<sequence_generator<L, R> > : std::true_type {};
namespace type_traits {
template <typename L, typename R>
struct attributes_needed<sequence_generator<L, R> > : std::integral_constant
<int, attributes_needed<L>::value + attributes_needed<R>::value> {};
template <typename L, typename R>
struct accepts_tuple<sequence_generator<L, R> > : std::true_type {};
}
template <typename L, typename R>
typename std::enable_if<grammar::is_generator<L>::value && grammar::is_generator<R>::value, sequence_generator<L, R>>::type
operator<<(L l, R r)
{
return sequence_generator<L, R>{l, r};
}
} } }
#endif

View File

@ -0,0 +1,185 @@
#ifndef EOLIAN_CXX_STRING_HH
#define EOLIAN_CXX_STRING_HH
#include <cstdlib>
#include <cstring>
#include "grammar/generator.hpp"
#include "grammar/attributes.hpp"
#include "grammar/case.hpp"
namespace efl { namespace eolian { namespace grammar {
// literal
struct literal_generator
{
literal_generator(const char* string)
: string(string) {}
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const&, Context const&) const
{
std::copy(string, string + std::strlen(string), sink);
return true;
}
const char* string;
};
template <>
struct is_eager_generator<literal_generator> : std::true_type {};
template <>
struct is_generator<const char*> : std::true_type {};
template <int N>
struct is_generator<const char[N]> : std::true_type {};
literal_generator as_generator(char const* literal) { return literal; }
struct {
literal_generator operator()(const char* literal) const
{
return literal_generator(literal);
}
} const lit;
// string
struct string_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attribute, Context const&) const
{
if(tag_check<upper_case_tag, Context>::value)
{
std::transform(std::begin(attribute), std::end(attribute), sink, &::toupper);
}
else if(tag_check<lower_case_tag, Context>::value)
{
std::transform(std::begin(attribute), std::end(attribute), sink, &::tolower);
}
else
{
std::copy(std::begin(attribute), std::end(attribute), sink);
}
return true;
}
};
struct specific_string_generator
{
specific_string_generator(std::string string) : string(string) {}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::unused_type, Context const&) const
{
if(tag_check<upper_case_tag, Context>::value)
{
std::transform(std::begin(string), std::end(string), sink, &::toupper);
}
else if(tag_check<lower_case_tag, Context>::value)
{
std::transform(std::begin(string), std::end(string), sink, &::tolower);
}
else
{
std::copy(std::begin(string), std::end(string), sink);
}
return true;
}
std::string string;
};
struct string_replace_generator
{
template <typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& string, Context const&) const
{
if(tag_check<upper_case_tag, Context>::value)
{
std::transform(std::begin(string), std::end(string), sink,
[&] (char c) -> char
{
if(c == from)
return to;
else
return ::toupper(c);
}
);
}
else if(tag_check<lower_case_tag, Context>::value)
{
std::transform(std::begin(string), std::end(string), sink,
[&] (char c) -> char
{
if(c == from)
return to;
else
return ::tolower(c);
});
}
else
{
std::transform(std::begin(string), std::end(string), sink
, [&] (char c) { return c == from ? to : c; });
}
return true;
}
char from, to;
};
template <>
struct is_eager_generator<string_generator> : std::true_type {};
template <>
struct is_eager_generator<specific_string_generator> : std::true_type {};
template <>
struct is_eager_generator<string_replace_generator> : std::true_type {};
struct string_generator_terminal
{
specific_string_generator operator[](std::string string) const
{
return specific_string_generator{string};
}
} const string;
struct string_replace_terminal
{
string_replace_generator operator()(char from, char to) const
{
return string_replace_generator{from, to};
}
} const string_replace;
template <>
struct is_generator<string_generator_terminal> : std::true_type {};
template <>
struct is_generator<std::string> : std::true_type {};
string_generator as_generator(string_generator_terminal)
{
return string_generator{};
}
namespace type_traits {
template <>
struct attributes_needed<string_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<string_generator_terminal> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<string_replace_generator> : std::integral_constant<int, 1> {};
}
} } }
namespace std {
::efl::eolian::grammar::specific_string_generator as_generator(std::string string)
{
return ::efl::eolian::grammar::specific_string_generator{string};
}
}
#endif

View File

@ -1,30 +0,0 @@
#ifndef EOLIAN_CXX_STD_TAB_HH
#define EOLIAN_CXX_STD_TAB_HH
#include <ostream>
#include <iosfwd>
namespace efl { namespace eolian { namespace grammar {
using std::endl;
const int tabsize = 3;
struct tab
{
int _n;
tab(int n) : _n(n * tabsize) {}
};
inline std::ostream&
operator<<(std::ostream& out, efl::eolian::grammar::tab tab)
{
for (int i = tab._n; i; --i)
out << ' ';
return out;
}
} } }
#endif // EOLIAN_CXX_STD_TAB_HH

View File

@ -0,0 +1,40 @@
#ifndef EOLIAN_CXX_TYPE_HH
#define EOLIAN_CXX_TYPE_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/case.hpp"
namespace efl { namespace eolian { namespace grammar {
template <typename OutputIterator, typename Context>
struct visitor_generate;
struct type_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
{
return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false});
}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.c_type
, param.direction != attributes::parameter_direction::in});
}
};
template <>
struct is_eager_generator<type_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<type_generator> : std::integral_constant<int, 1> {};
}
type_generator const type;
} } }
#endif

View File

@ -1,266 +0,0 @@
#ifndef EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH
#define EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH
#include <ostream>
#include <iosfwd>
#include "eo_types.hh"
#include "namespace_generator.hh"
namespace efl { namespace eolian { namespace grammar {
using std::endl;
struct full_name
{
eo_class const& _cls;
bool _from_global;
full_name(eo_class const& cls, bool from_global = true)
: _cls(cls), _from_global(from_global) {}
};
inline std::ostream&
operator<<(std::ostream& out, full_name const& x)
{
if (x._from_global)
out << "::";
if(!x._cls.name_space.empty())
out << x._cls.name_space << "::";
return out << x._cls.name;
}
struct abstract_full_name
{
eo_class const& _cls;
bool _from_golbal;
abstract_full_name(eo_class const& cls, bool from_golbal = true)
: _cls(cls), _from_golbal(from_golbal) {}
};
inline std::ostream&
operator<<(std::ostream& out, abstract_full_name const& x)
{
if (x._from_golbal)
out << "::";
return out << abstract_namespace << full_name(x._cls);
}
struct name_upper
{
eo_class const& _cls;
name_upper(eo_class const& cls)
: _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, name_upper const& x)
{
std::string key = x._cls.name;
std::transform(key.begin(), key.end(), key.begin(), ::toupper);
return out << key;
}
struct c_type
{
eolian_type_instance const& _list;
c_type(eolian_type_instance const& list)
: _list(list)
{}
};
inline std::ostream&
operator<<(std::ostream& out, efl::eolian::grammar::c_type const& x)
{
assert(x._list.size() > 0);
std::string res;
for (auto rit = x._list.parts.rbegin(), last = x._list.parts.rend(); rit != last; ++rit)
{
res = (*rit).native;
}
assert(!res.empty());
return out << res;
}
struct reinterpret_type
{
eolian_type_instance const& _type;
reinterpret_type(eolian_type_instance const& type)
: _type(type)
{}
};
inline std::ostream&
operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x)
{
assert(x._type.size() > 0);
std::string res;
for (auto rit = x._type.parts.rbegin(), last = x._type.parts.rend(); rit != last; ++rit)
{
eolian_type const& t = *rit;
if (type_is_complex(t))
res = t.binding + "< " + res + " >";
else
res = type_is_binding(t) ? t.binding
: t.native;
}
assert(!res.empty());
if (type_is_binding(x._type.front()))
{
if (x._type.is_out)
res += "*";
else if (x._type.is_optional && x._type.front().binding_requires_optional)
res = "::efl::eina::optional< " + res + " >";
}
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.parts.begin(), last=x._type.parts.end(); it != last; ++it)
{
if (it != x._type.parts.begin())
out << ", ";
out << ((*it).is_own ? "std::true_type" : "std::false_type");
}
return out << ">()";
}
struct
template_parameter_type
{
eolian_type_instance const& _type;
std::string const& _name;
template_parameter_type(eolian_type_instance const& type, std::string const& name)
: _type(type)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, template_parameter_type const& x)
{
return out << "F_" << x._name;
}
struct
parameter_type
{
eolian_type_instance const& _type;
std::string const& _name;
parameter_type(eolian_type_instance const& t, std::string const& name)
: _type(t)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameter_type const& x)
{
if(type_is_callback(x._type))
out << template_parameter_type(x._type, x._name);
else
out << reinterpret_type(x._type);
return out;
}
struct
parameter_no_ref_type
{
eolian_type_instance const& _type;
std::string const& _name;
parameter_no_ref_type(eolian_type_instance const& type, std::string const& name)
: _type(type)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameter_no_ref_type const& x)
{
return out << "_no_ref_" << parameter_type(x._type, x._name);
}
struct
parameter_remove_reference_typedef
{
eolian_type_instance const& _type;
std::string const& _name;
parameter_remove_reference_typedef(eolian_type_instance const& type, std::string const& name)
: _type(type)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameter_remove_reference_typedef const& x)
{
out << "typedef typename std::remove_reference<"
<< parameter_type(x._type, x._name)
<< ">::type " << parameter_no_ref_type(x._type, x._name) << ";";
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 << x._varname;
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)
<< ", " << parameter_no_ref_type(x._type, x._varname) << " >()";
else if (type_is_complex(x._type) && type_is_binding(x._type))
out << "::efl::eolian::to_native<" << c_type(x._type) << ">(" << x._varname << ")";
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

View File

@ -0,0 +1,333 @@
#ifndef EOLIAN_CXX_TYPE_IMPL_HH
#define EOLIAN_CXX_TYPE_IMPL_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/case.hpp"
#include "grammar/container.hpp"
#include "grammar/type.hpp"
namespace efl { namespace eolian { namespace grammar {
namespace detail {
bool has_own(attributes::regular_type_def const& def)
{
for(auto&& c : def.pointers)
if(is_own(c.qualifier))
return true;
return false;
}
}
namespace detail {
struct swap_pointers_visitor
{
std::vector<attributes::pointer_indirection>* pointers;
typedef void result_type;
template <typename T>
void operator()(T& object) const
{
std::swap(*pointers, object.pointers);
}
void operator()(attributes::complex_type_def& complex) const
{
(*this)(complex.outer);
}
};
template <typename OutputIterator, typename Context>
bool generate_pointers(OutputIterator sink, std::vector<attributes::pointer_indirection> const& pointers, Context const&
, bool no_reference)
{
for(auto first = pointers.rbegin()
, last = pointers.rend(); first != last; ++first)
{
if(std::next(first) == last && first->reference && !no_reference)
*sink++ = '&';
else
*sink++ = '*';
}
return true;
}
}
template <typename T>
T const* as_const_pointer(T* p) { return p; }
attributes::regular_type_def replace_base_type(attributes::regular_type_def v, std::string name)
{
v.base_type = name;
return v;
}
attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular)
{
v.outer = regular;
return v;
}
template <typename Array, typename F, int N, typename A>
eina::optional<bool> call_match(Array const (&array)[N], F f, A a)
{
typedef Array const* iterator_type;
iterator_type match_iterator = &array[0], match_last = match_iterator + N;
match_iterator = std::find_if(match_iterator, match_last, f);
if(match_iterator != match_last)
{
return a(match_iterator->function());
}
return {nullptr};
}
template <typename OutputIterator, typename Context>
struct visitor_generate
{
mutable OutputIterator sink;
Context const* context;
std::string c_type;
bool is_out;
typedef visitor_generate<OutputIterator, Context> visitor_type;
typedef bool result_type;
bool operator()(attributes::regular_type_def const& regular) const
{
using attributes::regular_type_def;
struct match
{
eina::optional<std::string> name;
eina::optional<bool> has_own;
std::function<attributes::type_def::variant_type()> function;
}
const match_table[] =
{
"void_ptr", nullptr, [&]
{
std::vector<attributes::pointer_indirection> pointers = regular.pointers;
pointers.insert(pointers.begin(), {{attributes::qualifier_info::is_none, {}}, false});
return attributes::regular_type_def{"void", regular.base_qualifier, pointers, {}};
}
, {"size", nullptr, [&] { return replace_base_type(regular, " ::std::size_t"); }}
, {"ubyte", nullptr, [&] { return replace_base_type(regular, " unsigned char"); }}
, {"string", true, [&] { return replace_base_type(regular, " ::std::string"); }}
, {"string", false, [&] { return replace_base_type(regular, " ::efl::eina::string_view"); }}
, {"generic_value", nullptr, [&]
{ return regular_type_def{" ::efl::eina::value", regular.base_qualifier
, {regular.pointers.empty()
|| (regular.pointers.size() == 1 && regular.pointers[0].reference)
? regular.pointers
: std::vector<attributes::pointer_indirection>
{regular.pointers.begin(), std::prev(regular.pointers.end())}}
, {}};
}}
};
if(eina::optional<bool> b = call_match
(match_table
, [&] (match const& m)
{
return (!m.name || *m.name == regular.base_type)
&& (!m.has_own || *m.has_own == is_own(regular.base_qualifier))
;
}
, [&] (attributes::type_def::variant_type const& v)
{
return v.visit(*this); // we want to keep is_out info
}))
{
return *b;
}
else if(attributes::is_optional(regular.base_qualifier))
{
if(regular.pointers.empty() || (regular.pointers.size() == 1 && regular.pointers[0].reference == true))
{
attributes::complex_type_def def
{attributes::regular_type_def{" ::efl::eina::optional", attributes::qualifier_info::is_none, {}}};
attributes::regular_type_def no_optional_regular = regular;
attributes::remove_optional(no_optional_regular.base_qualifier);
def.subtypes.push_back({no_optional_regular, c_type});
return (*this)(def);
}
else
{
attributes::regular_type_def no_optional_regular = regular;
attributes::remove_optional(no_optional_regular.base_qualifier);
no_optional_regular.pointers[0].reference = 0;
return (*this)(no_optional_regular);
}
}
// else if(detail::has_own(regular) && !regular.pointers.empty())
// {
// attributes::complex_type_def def
// {attributes::regular_type_def{" ::efl::eolian::own_ptr", attributes::qualifier_info::is_none, {}}};
// attributes::complex_type_def tagged_def
// {attributes::regular_type_def{" ::efl::eolian::own", attributes::qualifier_info::is_none, {}}};
// auto pointer_iterator = regular.pointers.begin()
// , pointer_last = regular.pointers.end();
// for(;pointer_iterator != pointer_last && !attributes::is_own(pointer_iterator->qualifier)
// ;++pointer_iterator)
// {
// tagged_def.outer.pointers.push_back(*pointer_iterator);
// tagged_def.outer.pointers.front().reference = false;
// }
// assert(attributes::is_own(pointer_iterator->qualifier));
// attributes::regular_type_def base_type (regular);
// base_type.pointers.clear();
// for(;pointer_iterator != pointer_last; ++pointer_iterator)
// {
// base_type.pointers.insert(base_type.pointers.begin(), *pointer_iterator);
// attributes::remove_own(base_type.pointers.back().qualifier);
// }
// tagged_def.subtypes.push_back({base_type, c_type});
// def.subtypes.push_back({tagged_def, c_type});
// return (*this)(def);
// }
else if(detail::has_own(regular) && !regular.pointers.empty())
{
attributes::regular_type_def pointee = regular;
std::vector<attributes::pointer_indirection> pointers;
std::swap(pointers, pointee.pointers);
pointers.erase(pointers.begin());
attributes::pointer_indirection reference {{{},{}}, true};
return as_generator(" ::std::unique_ptr<" << type).generate
(sink, attributes::type_def{pointee, c_type}, *context)
&& detail::generate_pointers(sink, pointers, *context, true)
&& as_generator(", void(*)(const void*)>").generate(sink, attributes::unused, *context)
&& (!is_out || detail::generate_pointers(sink, {reference}, *context, false));
}
else
{
auto pointers = regular.pointers;
if(is_out)
pointers.push_back({{{},{}}, true});
if(as_generator(*(string << "_") << string << (is_const(regular.base_qualifier)? " const" : ""))
.generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context))
return detail::generate_pointers(sink, pointers, *context
, regular.base_type == "void");
else
return false;
}
}
bool operator()(attributes::klass_name klass) const
{
if(is_out)
klass.pointers.push_back({{{}, {}}, true});
if(as_generator(" " << *("::" << lower_case[string]) << "::" << string)
.generate(sink, std::make_tuple(attributes::cpp_namespaces(klass.namespaces), klass.eolian_name), *context))
return detail::generate_pointers(sink, klass.pointers, *context, false);
else
return false;
}
bool operator()(attributes::complex_type_def const& complex) const
{
using attributes::regular_type_def;
using attributes::qualifier_info;
struct match
{
eina::optional<std::string> name;
eina::optional<bool> has_own;
eina::optional<bool> is_const;
std::function<attributes::type_def::variant_type()> function;
} const matches[] =
{
{"list", true, nullptr, [&]
{
generate_container(sink, complex, *context, " ::efl::eina::list");
return attributes::type_def::variant_type();
}}
, {"list", false, nullptr, [&]
{
generate_container(sink, complex, *context, " ::efl::eina::range_list");
return attributes::type_def::variant_type();
}}
, {"array", true, nullptr, [&]
{
generate_container(sink, complex, *context, " ::efl::eina::array");
return attributes::type_def::variant_type();
}}
, {"array", false, nullptr, [&]
{
generate_container(sink, complex, *context, " ::efl::eina::range_array");
return attributes::type_def::variant_type();
}}
, {"hash", nullptr, nullptr
, [&]
{ regular_type_def r{"Eina_Hash", complex.outer.base_qualifier, complex.outer.pointers, {}};
r.pointers.push_back({{qualifier_info::is_none, {}}, false});
return r;
}}
, {"promise", nullptr, nullptr, [&]
{
return replace_outer
(complex, regular_type_def{" ::efl::eina::future", complex.outer.base_qualifier, {}, {}});
}
}
, {"iterator", nullptr, nullptr, [&]
{
return replace_outer
(complex, regular_type_def{" ::efl::eina::iterator", complex.outer.base_qualifier, {}, {}});
}
}
, {"accessor", nullptr, nullptr, [&]
{
return replace_outer
(complex, regular_type_def{" ::efl::eina::accessor", complex.outer.base_qualifier, {}, {}});
}
}
};
auto default_match = [&] (attributes::complex_type_def const& complex)
{
regular_type_def no_pointer_regular = complex.outer;
std::vector<attributes::pointer_indirection> pointers;
pointers.swap(no_pointer_regular.pointers);
if(is_out)
pointers.push_back({{{}, {}}, true});
return visitor_type{sink, context, c_type, false}(no_pointer_regular)
&& as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
&& detail::generate_pointers(sink, pointers, *context, false);
};
if(eina::optional<bool> b = call_match
(matches
, [&] (match const& m)
{
return (!m.name || *m.name == complex.outer.base_type)
&& (!m.has_own || *m.has_own == is_own(complex.outer.base_qualifier))
&& (!m.is_const || *m.is_const == is_const(complex.outer.base_qualifier));
}
, [&] (attributes::type_def::variant_type const& v)
{
if(v.empty())
return true;
else if(attributes::complex_type_def const* complex
= attributes::get<attributes::complex_type_def>(&v))
return default_match(*complex);
else
return v.visit(*this);
}))
return *b;
else
{
return default_match(complex);
}
}
};
} } }
#endif

View File

@ -0,0 +1,63 @@
#ifndef EOLIAN_CXX_TYPE_TRAITS_HH
#define EOLIAN_CXX_TYPE_TRAITS_HH
namespace efl { namespace eolian { namespace grammar { namespace type_traits {
template <typename G>
struct accepts_tuple : std::false_type {};
template <typename G>
struct attributes_needed : std::integral_constant<int, 0> {};
template <typename G>
struct attributes_needed<G const> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<G&> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<G const&> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<G volatile> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<G volatile&> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<G const volatile> : attributes_needed<G> {};
template <typename G>
struct attributes_needed<G const volatile&> : attributes_needed<G> {};
template <typename T>
struct is_std_tuple : std::false_type {};
template <typename...Args>
struct is_std_tuple<std::tuple<Args...> > : std::true_type {};
template <typename...Args>
struct is_std_tuple<std::tuple<Args...>&> : std::true_type {};
template <typename...Args>
struct is_std_tuple<const std::tuple<Args...> > : std::true_type {};
template <typename...Args>
struct is_std_tuple<const std::tuple<Args...>&> : std::true_type {};
template <typename T, typename Enable = void>
struct is_explicit_tuple : std::false_type {};
template <typename T>
struct is_explicit_tuple<T, typename std::enable_if<is_std_tuple<T>::value>::type> : std::true_type {};
template <typename T, typename Enable = void>
struct is_tuple : std::false_type {};
template <typename T>
struct is_tuple<T const> : is_tuple<T> {};
template <typename T>
struct is_tuple<T const&> : is_tuple<T> {};
template <typename T>
struct is_tuple<T const volatile> : is_tuple<T> {};
template <typename T>
struct is_tuple<T const volatile&> : is_tuple<T> {};
template <typename T>
struct is_tuple<T volatile> : is_tuple<T> {};
template <typename T>
struct is_tuple<T volatile&> : is_tuple<T> {};
template <typename T>
struct is_tuple<T, typename std::enable_if<!std::is_const<T>::value && is_std_tuple<T>::value>::type> : std::true_type {};
} } } }
#endif

View File

@ -0,0 +1,276 @@
#ifndef EOLIAN_CXX_VARIANT_HH_
#define EOLIAN_CXX_VARIANT_HH_
#include <cstddef>
#include <algorithm>
#include <utility>
#include <type_traits>
#include <tuple>
#include "grammar/meta.hpp"
namespace efl { namespace eolian { namespace grammar { namespace attributes {
template <std::size_t N, std::size_t L, typename Tuple>
struct call_visitor
{
template <typename F>
static typename F::result_type call(int type, void const* buffer, F f)
{
if(type == N)
{
using std::tuple_element;
typedef typename tuple_element<N, Tuple>::type type;
type const* o = static_cast<type const*>(buffer);
return f(*o);
}
else
return call_visitor<N+1, L, Tuple>::call(type, buffer, f);
}
template <typename F>
static typename F::result_type call(int type, void* buffer, F f)
{
if(type == N)
{
using std::tuple_element;
typedef typename tuple_element<N, Tuple>::type type;
type* o = static_cast<type*>(buffer);
return f(*o);
}
else
return call_visitor<N+1, L, Tuple>::call(type, buffer, f);
}
};
template <std::size_t L, typename Tuple>
struct call_visitor<L, L, Tuple>
{
template <typename F>
static typename F::result_type call(int, void const*, F)
{
std::abort();
}
};
struct compare_equal_visitor
{
void const* buffer;
typedef bool result_type;
template <typename T>
bool operator()(T const& other) const
{
return *static_cast<T const*>(buffer) == other;
}
};
struct copy_visitor
{
typedef void result_type;
void* buffer;
template <typename T>
void operator()(T const& other) const
{
new (buffer) T(other);
}
};
struct move_visitor
{
typedef void result_type;
void* buffer;
template <typename T>
void operator()(T& other) const
{
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
new (buffer) type(std::move(other));
}
};
struct assign_visitor
{
typedef void result_type;
void* buffer;
template <typename T>
void operator()(T const& other) const
{
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
type* assigned = static_cast<type*>(buffer);
*assigned = other;
}
};
struct destroy_visitor
{
typedef void result_type;
template <typename T>
void operator()(T&& other) const
{
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
other.~type();
}
};
template <typename T>
struct get_visitor
{
typedef T* result_type;
T* operator()(T& object) const
{
return &object;
}
template <typename U>
T* operator()(U&) const { return nullptr; }
};
template <typename... Args>
struct variant
{
typedef variant<Args...> _self_type; /**< Type for the optional class itself. */
constexpr variant()
: type(-1)
{}
template <typename T>
variant(T object,
typename std::enable_if<meta::is_one_of
<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Args...>::value>::type* = 0)
: type(meta::find<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Args...>::value)
{
construct(object);
}
variant(variant const& other)
: type(other.type)
{
if(other.type != -1)
other.visit(copy_visitor{static_cast<void*>(&buffer)});
}
variant& operator=(variant const& other)
{
if(type == other.type && type != -1)
{
other.visit(assign_visitor{static_cast<void*>(&buffer)});
}
else if(type != other.type)
{
if(type != -1)
destroy_unsafe();
type = other.type;
other.visit(copy_visitor{static_cast<void*>(&buffer)});
}
return *this;
}
~variant()
{
if(type != -1)
destroy_unsafe();
}
void destroy()
{
destroy_unsafe();
type = -1;
}
void destroy_unsafe()
{
visit(destroy_visitor());
}
bool empty() const
{
return type == -1;
}
template <typename F>
typename F::result_type visit(F f) const
{
if(type == -1)
{
throw std::runtime_error("variant is empty");
}
else
return call_visitor<0u, sizeof...(Args), std::tuple<Args...>>::call(type, static_cast<const void*>(&buffer), f);
}
template <typename F>
typename F::result_type visit(F f)
{
if(type == -1)
{
throw std::runtime_error("variant is empty");
}
else
return call_visitor<0u, sizeof...(Args), std::tuple<Args...>>::call(type, static_cast<void*>(&buffer), f);
}
private:
template <typename T>
void construct(T object)
{
new (&buffer) T(std::move(object));
}
typedef typename std::aligned_storage
<
meta::max<sizeof(Args)...>::value
, meta::max<std::alignment_of<Args>::value...>::value
>::type buffer_type;
friend bool operator==(variant<Args...> const& lhs, variant<Args...> const& rhs)
{
return rhs.type == lhs.type
&& (rhs.type == -1
|| rhs.visit(compare_equal_visitor{&lhs.buffer}));
}
int type;
/**
* Member variable for holding the contained value.
*/
buffer_type buffer;
};
template <typename...Args>
inline bool operator!=(variant<Args...>const& lhs, variant<Args...> const& rhs)
{
return !(lhs == rhs);
}
template <typename T, typename...Args>
T* get(variant<Args...>* variant, typename std::enable_if<meta::is_one_of
<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Args...>::value>::type* = 0)
{
return variant->visit(get_visitor<T>{});
}
template <typename T, typename...Args>
T const* get(variant<Args...>const* variant, typename std::enable_if<meta::is_one_of
<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Args...>::value>::type* = 0)
{
return variant->visit(get_visitor<T const>{});
}
template <typename T, typename...Args>
T& get(variant<Args...>& variant, typename std::enable_if<meta::is_one_of
<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Args...>::value>::type* = 0)
{
T* p = variant.visit(get_visitor<T>{});
if(p)
return *p;
else
throw std::logic_error("");
}
template <typename T, typename...Args>
T const& get(variant<Args...>const& variant, typename std::enable_if<meta::is_one_of
<typename std::remove_cv<typename std::remove_reference<T>::type>::type, Args...>::value>::type* = 0)
{
T const* p = variant.visit(get_visitor<T const>{});
if(p)
return *p;
else
throw std::logic_error("");
}
} } } }
#endif

View File

@ -1,56 +0,0 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <Eo.h>
#include <Ecore.h>
#include "callback.eo.h"
struct _Callback_Data
{
int callbacks;
};
typedef struct _Callback_Data Callback_Data;
#define MY_CLASS CALLBACK_CLASS
static Eina_Bool _callback_callback_added(void* data EINA_UNUSED, Eo_Event const* event)
{
Callback_Data* pd = event->info;
++pd->callbacks;
eo_event_callback_call(event->object, CALLBACK_EVENT_CALL_ON_ADD, &pd->callbacks);
return EINA_TRUE;
}
static Eo *_callback_eo_base_constructor(Eo *obj, Callback_Data *pd EINA_UNUSED)
{
pd->callbacks = 0;
obj = eo_constructor(eo_super(obj, MY_CLASS));
eo_event_callback_priority_add(obj, EO_EVENT_CALLBACK_ADD, EO_CALLBACK_PRIORITY_DEFAULT
, &_callback_callback_added, pd);
return obj;
}
static void _callback_onecallback(Eo *obj EINA_UNUSED, Callback_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data)
{
cb(data);
}
static void _callback_twocallback(Eo *obj EINA_UNUSED, Callback_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data
, Ecore_Cb cb2 EINA_UNUSED)
{
cb(data);
}
static void _callback_test_global_callbacks(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED
, Ecore_Cb cb, void *data)
{
cb(data);
}
#include "callback.eo.c"

View File

@ -1,33 +1,19 @@
import ecore_types;
struct Callback_Event
{
field1: int;
field2: list<int*>;
}
class Callback (Eo.Base)
{
data: Callback_Data;
methods {
onecallback {
params {
@in cb: Ecore_Cb;
@in data: void_ptr;
}
}
twocallback {
params {
@in cb: Ecore_Cb;
@in data: void_ptr;
@in cb2: Ecore_Cb;
}
}
test_global_callbacks @class {
params {
@in cb: Ecore_Cb;
@in data: void_ptr;
}
}
}
implements {
Eo.Base.constructor;
}
events {
call_on_add;
prefix,event1;
prefix,event2: Callback;
prefix,event3: int;
prefix,event4: list<int*>;
prefix,event5: Callback_Event;
}
}

View File

@ -1,4 +1,9 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Eina.h>
#include <Eo.h>
struct Complex_Data {};

View File

@ -2,6 +2,68 @@ class Complex (Eo.Base)
{
data: Complex_Data;
methods {
// container test
inptrcont {
params {
l: list<int*>;
}
}
inclasscont {
params {
l: list<Eo.Base>;
}
}
inptrptrcont {
params {
l: list<int**>;
}
}
inptrcontown {
params {
l: own(list<int*>);
}
}
inptrptrcontown {
params {
l: own(list<int**>);
}
}
incontcont {
params {
l: list<list<int*>>;
}
}
incontcontown {
params {
l: own(list<list<int*>>);
}
}
incontowncontown {
params {
l: own(list<own(list<int*>)>);
}
}
incontowncont {
params {
l: list<own(list<int*>)>;
}
}
instringcont {
params {
l: list<string>;
}
}
instringowncont {
params {
l: list<own(string)>;
}
}
instringcontown {
params {
l: own(list<string>);
}
}
foo {
params {
l: list<int*>;
@ -28,6 +90,24 @@ class Complex (Eo.Base)
@out a1: Complex;
}
}
with_promise_r {
return: promise<int>;
}
with_promise_in {
params {
@in p: promise<int>;
}
}
with_promise_out {
params {
@out p: promise<int>;
}
}
with_promise_inout {
params {
@inout p: promise<int>;
}
}
}
}

View File

@ -1,4 +1,9 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Eina.h>
#include <Eo.h>
#include "complex.eo.h"
@ -32,9 +37,22 @@ struct test_param_type<void(T::*)(P), U>
static_assert(std::is_same<P, U>::value, "Wrong type");
};
test_param_type<typeof( & nonamespace::Complex::inptrcont ), efl::eina::range_list<int>> inptrcont;
test_param_type<typeof( & nonamespace::Complex::inclasscont ), efl::eina::range_list<eo::Base>> inclasscont;
test_param_type<typeof( & nonamespace::Complex::inptrptrcont ), efl::eina::range_list<int*>> inptrptrcont;
test_param_type<typeof( & nonamespace::Complex::inptrcontown ), efl::eina::list<int>const&> inptrcontown;
test_param_type<typeof( & nonamespace::Complex::inptrptrcontown ), efl::eina::list<int*>const&> inptrptrcontown;
test_param_type<typeof( & nonamespace::Complex::incontcont ), efl::eina::range_list<efl::eina::range_list<int>>> incontont;
test_param_type<typeof( & nonamespace::Complex::incontcontown ), efl::eina::list<efl::eina::range_list<int>>const&> incontcontown;
test_param_type<typeof( & nonamespace::Complex::incontowncontown ), efl::eina::list<efl::eina::list<int>>const&> incontowncontown;
test_param_type<typeof( & nonamespace::Complex::incontowncont ), efl::eina::range_list<efl::eina::list<int>>> incontowncont;
test_param_type<typeof( & nonamespace::Complex::instringcont ), efl::eina::range_list<efl::eina::string_view>> instringcont;
test_param_type<typeof( & nonamespace::Complex::instringowncont ), efl::eina::range_list<efl::eina::string_view>> instringowncont;
test_param_type<typeof( & nonamespace::Complex::instringcontown ), efl::eina::list<efl::eina::string_view>const&> instringcontown;
test_param_type<typeof( & nonamespace::Complex::foo ), efl::eina::range_list<int>> foo;
test_return_type<typeof( & nonamespace::Complex::bar ), efl::eina::range_array<int>> bar;
test_return_type<typeof( & nonamespace::Complex::wrapper_r ), nonamespace::Complex> wrapper_r;
test_param_type<typeof( & nonamespace::Complex::wrapper_in ), nonamespace::Complex> wrapper_in;
test_param_type<typeof( & nonamespace::Complex::wrapper_inout ), nonamespace::Complex*> wrapper_inout;
test_param_type<typeof( & nonamespace::Complex::wrapper_out ), nonamespace::Complex*> wrapper_out;
test_param_type<typeof( & nonamespace::Complex::wrapper_inout ), nonamespace::Complex&> wrapper_inout;
test_param_type<typeof( & nonamespace::Complex::wrapper_out ), nonamespace::Complex&> wrapper_out;

View File

@ -9,7 +9,6 @@ static const Efl_Test_Case etc[] = {
{ "Eolian-Cxx Parsing", eolian_cxx_test_parse },
{ "Eolian-Cxx Wrapper", eolian_cxx_test_wrapper },
{ "Eolian-Cxx Generation", eolian_cxx_test_generate },
{ "Eolian-Cxx Callback", eolian_cxx_test_callback },
{ "Eolian-Cxx Address_of", eolian_cxx_test_address_of },
{ "Eolian-Cxx Inheritance", eolian_cxx_test_inheritance },
{ "Eolian-Cxx Binding", eolian_cxx_test_binding },

View File

@ -6,7 +6,6 @@
void eolian_cxx_test_parse(TCase* tc);
void eolian_cxx_test_wrapper(TCase* tc);
void eolian_cxx_test_generate(TCase* tc);
void eolian_cxx_test_callback(TCase* tc);
void eolian_cxx_test_address_of(TCase* tc);
void eolian_cxx_test_inheritance(TCase* tc);
void eolian_cxx_test_binding(TCase* tc);

View File

@ -2,7 +2,10 @@
# include <config.h>
#endif
#include <Ecore.h>
#include <generic.eo.hh>
#include <name1_name2_type_generation.eo.hh>
#include "eolian_cxx_suite.h"
@ -10,18 +13,17 @@ START_TEST(eolian_cxx_test_binding_constructor_only_required)
{
efl::eo::eo_init i;
bool called1 = false;
nonamespace::Generic g
(
[&]
{
g.required_ctor_a(1);
g.required_ctor_b(2);
}
);
nonamespace::Generic g(
g.required_ctor_a(1),
g.required_ctor_b(std::bind([&called1] { called1 = true; }))
);
g.call_req_ctor_b_callback();
g.call_opt_ctor_b_callback();
fail_if(!called1);
fail_if(1 != g.req_ctor_a_value_get());
fail_if(2 != g.req_ctor_b_value_get());
}
END_TEST
@ -29,23 +31,142 @@ START_TEST(eolian_cxx_test_binding_constructor_all_optionals)
{
efl::eo::eo_init i;
bool called1 = false;
bool called2 = false;
nonamespace::Generic g
(
[&]
{
g.required_ctor_a(2);
g.required_ctor_b(4);
g.optional_ctor_a(3);
g.optional_ctor_b(5);
}
);
nonamespace::Generic g(
g.required_ctor_a(2),
g.required_ctor_b(std::bind([&called1] { called1 = true; })),
g.optional_ctor_a(3),
g.optional_ctor_b(std::bind([&called2] { called2 = true; }))
);
g.call_req_ctor_b_callback();
g.call_opt_ctor_b_callback();
fail_if(!called1);
fail_if(!called2);
fail_if(2 != g.req_ctor_a_value_get());
fail_if(3 != g.opt_ctor_a_value_get());
fail_if(4 != g.req_ctor_b_value_get());
fail_if(5 != g.opt_ctor_b_value_get());
}
END_TEST
START_TEST(eolian_cxx_test_type_generation)
{
efl::eo::eo_init eo_init;
name1::name2::Type_Generation g;
g.invoidptr(nullptr);
g.inint(42);
std::unique_ptr<int> i (new int(42));
g.inintptr(i.get());
{
int* p = (int*)malloc(sizeof(int));
*p = 42;
std::unique_ptr<int, void(*)(const void*)> inintptrown(p, (void(*)(const void*))&free);
g.inintptrown(std::move(inintptrown));
}
{
int** p = (int**)malloc(sizeof(int*));
*p = (int*)malloc(sizeof(int));
**p = 42;
std::unique_ptr<int*, void(*)(const void*)> inintptrownptr(p, (void(*)(const void*))&free);
g.inintptrownptr(std::move(inintptrownptr));
}
{
int*** p = (int***)malloc(sizeof(int**));
*p = (int**)malloc(sizeof(int*));
**p = (int*)malloc(sizeof(int));
***p = 42;
std::unique_ptr<int**, void(*)(const void*)> inintptrownptrptr(p, (void(*)(const void*))&free);
g.inintptrownptrptr(std::move(inintptrownptrptr));
}
{
int*** p = (int***)malloc(sizeof(int**));
*p = (int**)malloc(sizeof(int*));
**p = (int*)malloc(sizeof(int));
***p = 42;
std::unique_ptr<int**, void(*)(const void*)> inintptrptrownptr(p, (void(*)(const void*))&free);
g.inintptrptrownptr(std::move(inintptrptrownptr));
}
{
int* p = (int*)malloc(sizeof(int));
*p = 42;
std::unique_ptr<int, void(*)(const void*)> inintptrownfree(p, (void(*)(const void*))&free);
g.inintptrownfree(std::move(inintptrownfree));
}
g.instring("foobar");
// {
// efl::eina::string_view v("foobar");
// g.instringptr(&v);
// }
g.instringown("foobar");
// {
// std::string v("foobar");
// g.instringptrown(&v);
// }
// {
// std::unique_ptr<efl::eina::string_view, void(*)(const void*)> v
// ((efl::eina::string_view*)malloc(sizeof(string_view)), (void(*)(const void*))&free);
// g.instringptrown(v);
// }
// {
// std::string v("foobar");
// g.instringptrown(&v);
// }
}
END_TEST
START_TEST(eolian_cxx_test_type_generation_in)
{
efl::eo::eo_init i;
name1::name2::Type_Generation g;
}
END_TEST
START_TEST(eolian_cxx_test_type_callback)
{
efl::eo::eo_init i;
bool event1 = false, event2 = false, event3 = false, event4 = false
, event5 = false;
nonamespace::Generic g;
efl::eolian::event_add(g.prefix_event1_event, g, [&] (nonamespace::Generic)
{
event1 = true;
});
efl::eolian::event_add(g.prefix_event2_event, g, [&] (nonamespace::Generic, nonamespace::Generic)
{
event2 = true;
});
efl::eolian::event_add(g.prefix_event3_event, g, [&] (nonamespace::Generic, int v)
{
event3 = true;
ck_assert(v == 42);
});
efl::eolian::event_add(g.prefix_event4_event, g, [&] (nonamespace::Generic, efl::eina::range_list<int> e)
{
event4 = true;
ck_assert(e.size() == 1);
ck_assert(*e.begin() == 42);
});
efl::eolian::event_add(g.prefix_event5_event, g, [&] (nonamespace::Generic, Generic_Event)
{
event5 = true;
});
g.call_event1();
g.call_event2();
g.call_event3();
g.call_event4();
g.call_event5();
ck_assert(event1);
ck_assert(event2);
ck_assert(event3);
ck_assert(event4);
ck_assert(event5);
}
END_TEST
@ -54,4 +175,7 @@ eolian_cxx_test_binding(TCase* tc)
{
tcase_add_test(tc, eolian_cxx_test_binding_constructor_only_required);
tcase_add_test(tc, eolian_cxx_test_binding_constructor_all_optionals);
tcase_add_test(tc, eolian_cxx_test_type_generation);
tcase_add_test(tc, eolian_cxx_test_type_generation_in);
tcase_add_test(tc, eolian_cxx_test_type_callback);
}

View File

@ -1,184 +0,0 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <Eo.h>
#include <Ecore.h>
#include <callback.eo.hh>
#include "eolian_cxx_suite.h"
void foo(void*) {}
START_TEST(eolian_cxx_test_callback_method)
{
efl::eo::eo_init i;
nonamespace::Callback c;
bool called1 = false, called2 = false;
c.onecallback(std::bind([&called1] { called1 = true; }));
c.twocallback(std::bind([&called2] { called2 = true; }), &foo);
fail_if(!called1);
fail_if(!called2);
}
END_TEST
START_TEST(eolian_cxx_test_callback_event_add)
{
efl::eo::eo_init i;
nonamespace::Callback c;
bool called1 = false, called2 = false;
c.callback_call_on_add_add(std::bind([&called1] { called1 = true; }));
c.callback_call_on_add_add(std::bind([&called2] { called2 = true; }));
fail_if(!called1);
fail_if(!called2);
}
END_TEST
START_TEST(eolian_cxx_test_callback_event_del)
{
efl::eo::eo_init i;
nonamespace::Callback c;
int called1 = 0, called2 = 0, called3 = 0, called4 = 0;
efl::eo::signal_connection s1 = c.callback_call_on_add_add
(std::bind([&]
{
std::cerr << "called1 " << called1 << " called2 " << called2 << " called3 " << called3
<< " called4 " << called4 << " 1" << std::endl;
fail_if(!( (called1 == 0 && called2 == 0 && called3 == 0 && called4 == 0)
|| (called1 == 1 && called2 == 1 && called3 == 0 && called4 == 0)
));
++called1;
}));
efl::eo::signal_connection s2 = c.callback_call_on_add_add
(std::bind([&]
{
std::cerr << "called1 " << called1 << " called2 " << called2 << " called3 " << called3
<< " called4 " << called4 << " 2" << std::endl;
fail_if(!( (called1 == 1 && called2 == 0 && called3 == 0 && called4 == 0)
|| (called1 == 1 && called2 == 1 && called3 == 0 && called4 == 0)
|| (called1 == 2 && called2 == 1 && called3 == 1 && called4 == 0)
));
++called2;
}));
s1.disconnect();
c.callback_call_on_add_add
(
std::bind([&]
{
std::cerr << "called1 " << called1 << " called2 " << called2 << " called3 " << called3
<< " called4 " << called4 << " 3" << std::endl;
fail_if(!( (called1 == 2 && called2 == 1 && called3 == 0 && called4 == 0)
|| (called1 == 2 && called2 == 2 && called3 == 1 && called4 == 1)
));
++called3;
}));
s2.disconnect();
c.callback_call_on_add_add
(
std::bind([&]
{
std::cerr << "called1 " << called1 << " called2 " << called2 << " called3 " << called3
<< " called4 " << called4 << " 4" << std::endl;
fail_if(!( (called1 == 2 && called2 == 2 && called3 == 1 && called4 == 0)
));
++called4;
}));
fail_if(called1 != 2);
fail_if(called2 != 2);
fail_if(called3 != 2);
fail_if(called4 != 1);
}
END_TEST
START_TEST(eolian_cxx_test_global_callback)
{
efl::eo::eo_init i;
bool called = false;
nonamespace::Callback::test_global_callbacks(std::bind([&called] { called = true; }));
fail_if(!called);
}
END_TEST
START_TEST(eolian_cxx_test_disconnect_inside_callback)
{
efl::eo::eo_init i;
nonamespace::Callback c;
std::vector<long> capture_me;
int times_called = 0;
::efl::eo::signal_connection sig(nullptr);
sig = c.callback_callback_add_add(
std::bind([&sig, &capture_me, &times_called](void *info)
{
++times_called;
std::cout << "times_called: " << times_called << std::endl;
std::cout << "&sig: " << &sig << std::endl;
if (times_called <= 1)
return;
sig.disconnect();
long* info_l = static_cast<long*>(info);
std::cout << "info: " << info << std::endl;
std::cout << "*info_l: " << *info_l << std::endl;
fail_if(*info_l != 42);
capture_me = {9, 0, 8, 1, 7, 2, 6, 3, 5, 4};
std::sort(capture_me.begin(), capture_me.end());
capture_me[0] = capture_me[1] + +capture_me[2] + capture_me[9];
std::cout << "&capture_me: " << &capture_me << std::endl;
std::cout << "capture_me [0] [9]: [" << capture_me[0] << "] ["<< capture_me[9] << "]" << std::endl;
fail_if(capture_me.size() != 10);
fail_if(capture_me[0] != 12);
fail_if(times_called != 2);
}, std::placeholders::_3));
long n = 42;
c.callback_callback_add_call(&n);
fail_if(capture_me.size() != 10);
fail_if(capture_me[0] != 12);
fail_if(times_called != 2);
}
END_TEST
void
eolian_cxx_test_callback(TCase* tc)
{
tcase_add_test(tc, eolian_cxx_test_callback_method);
tcase_add_test(tc, eolian_cxx_test_callback_event_add);
tcase_add_test(tc, eolian_cxx_test_callback_event_del);
tcase_add_test(tc, eolian_cxx_test_global_callback);
tcase_add_test(tc, eolian_cxx_test_disconnect_inside_callback);
}

View File

@ -2,15 +2,69 @@
# include <config.h>
#endif
#include <iostream>
#include <cassert>
#include <Eolian_Cxx.hh>
#include <iterator>
#include "eolian_cxx_suite.h"
#include <grammar/header.hpp>
START_TEST(eolian_cxx_test_generate_complex_types)
{
// TODO implement
using efl::eolian::grammar::class_header;
using efl::eolian::grammar::attributes::unused_type;
using efl::eolian::grammar::attributes::regular_type_def;
using efl::eolian::grammar::attributes::klass_name;
using efl::eolian::grammar::attributes::complex_type_def;
using efl::eolian::grammar::attributes::parameter_direction;
using efl::eolian::grammar::attributes::qualifier_info;
using efl::eolian::grammar::context_null;;
// efl::eolian::grammar::attributes::klass_def my_class
// {
// "Class_Name", "Class_Name", {"Namespace1", "Namesapce2"}
// , {
// {{regular_type_def{"int", {qualifier_info::is_none, {}}, {}}}
// , "function_name"
// , {
// {parameter_direction::in, {regular_type_def{"unsigned", {qualifier_info::is_none, {}}, {}}}, "param1", ""}
// , {parameter_direction::out, {klass_name{{"Namespace1","Namesapce2"}, "Class_Name",
// {qualifier_info::is_none, {}}, {}, {}}}
// , "param2", ""}
// , {parameter_direction::inout, {complex_type_def
// {{
// {regular_type_def{"list", {qualifier_info::is_none, {}}, {}}}
// , {regular_type_def{"int", {qualifier_info::is_none, {}}, {}}}
// }}}
// , "param3", ""}
// }
// }
// }
// , {}
// , {}
// };
// std::tuple<std::string, std::vector<std::string>
// , std::vector<std::string>, std::vector<efl::eolian::grammar::attributes::klass_def>
// , std::vector<efl::eolian::grammar::attributes::klass_def>
// , std::vector<efl::eolian::grammar::attributes::klass_def>> attributes
// {"GUARD_HEADER_HH", {"abc.h", "def.h"}, {"abc.hh", "def.hh"}, {my_class}, {my_class}, {my_class}};
// std::vector<char> buffer;
// class_header.generate(std::back_inserter<std::vector<char>>(buffer), attributes, context_null());
// const char result[] =
// "#ifndef GUARD_HEADER_HH\n"
// "#define GUARD_HEADER_HH\n"
// "#endif\n"
// ;
// std::cout << "Beginning of generated file" << std::endl;
// std::copy(buffer.begin(), buffer.end(), std::ostream_iterator<char>(std::cout));
// std::cout << "\n End of generated file" << std::endl;
// ck_assert(buffer.size() == (sizeof(result) - 1));
// ck_assert(std::equal(buffer.begin(), buffer.end(), result));
}
END_TEST

View File

@ -9,35 +9,35 @@
#include "eolian_cxx_suite.h"
struct bar
: efl::eo::inherit<bar, nonamespace::Simple>
{
bar()
: inherit_base(efl::eo::parent = nullptr)
{}
// struct bar
// : efl::eo::inherit<bar, nonamespace::Simple>
// {
// bar()
// : inherit_base(efl::eo::parent = nullptr)
// {}
bool simple_get()
{
printf("calling bar::%s\n", __FUNCTION__);
return false;
}
};
// bool simple_get()
// {
// printf("calling bar::%s\n", __FUNCTION__);
// return false;
// }
// };
void foo(nonamespace::Simple is)
{
fail_if(is.simple_get());
}
// void foo(nonamespace::Simple is)
// {
// fail_if(is.simple_get());
// }
START_TEST(eolian_cxx_test_inheritance_simple)
{
efl::eo::eo_init i;
bar b;
foo(b);
}
END_TEST
// START_TEST(eolian_cxx_test_inheritance_simple)
// {
// efl::eo::eo_init i;
// bar b;
// foo(b);
// }
// END_TEST
void
eolian_cxx_test_inheritance(TCase* tc)
eolian_cxx_test_inheritance(TCase* /*tc*/)
{
tcase_add_test(tc, eolian_cxx_test_inheritance_simple);
// tcase_add_test(tc, eolian_cxx_test_inheritance_simple);
}

View File

@ -5,7 +5,7 @@
#include <Eo.h>
#include <Ecore.h>
#include <callback.eo.hh>
#include <a.eo.hh>
#include "eolian_cxx_suite.h"
@ -14,7 +14,7 @@ START_TEST(eolian_cxx_test_wrapper_size)
efl::eo::eo_init init;
::efl::eo::concrete b(nullptr);
::nonamespace::Callback c;
::nonamespace::A c;
fail_if(sizeof(b) != sizeof(Eo*));
fail_if(sizeof(b) != sizeof(c));

View File

@ -7,14 +7,14 @@
#include "generic.eo.h"
#include <check.h>
struct _Generic_Data
{
int req_ctor_a_val;
Ecore_Cb req_ctor_b_cb;
void *req_ctor_b_data;
int req_ctor_b_val;
int opt_ctor_a_val;
Ecore_Cb opt_ctor_b_cb;
void *opt_ctor_b_data;
int opt_ctor_b_val;
};
typedef struct _Generic_Data Generic_Data;
@ -23,11 +23,7 @@ typedef struct _Generic_Data Generic_Data;
static Eo *_generic_eo_base_constructor(Eo *obj, Generic_Data *pd)
{
pd->req_ctor_a_val = 0;
pd->req_ctor_b_cb = NULL;
pd->req_ctor_b_data = NULL;
pd->opt_ctor_a_val = 0;
pd->opt_ctor_b_cb = NULL;
pd->opt_ctor_b_data = NULL;
return eo_constructor(eo_super(obj, MY_CLASS));
}
@ -36,9 +32,9 @@ static void _generic_required_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int
pd->req_ctor_a_val = value;
}
static void _generic_required_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data)
static void _generic_required_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, int value)
{
cb(data);
pd->req_ctor_b_val = value;
}
static void _generic_optional_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int value)
@ -46,9 +42,9 @@ static void _generic_optional_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int
pd->opt_ctor_a_val = value;
}
static void _generic_optional_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data)
static void _generic_optional_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, int value)
{
cb(data);
pd->opt_ctor_b_val = value;
}
static int _generic_req_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
@ -56,21 +52,78 @@ static int _generic_req_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
return pd->req_ctor_a_val;
}
static int _generic_req_ctor_b_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
{
return pd->req_ctor_b_val;
}
static int _generic_opt_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
{
return pd->opt_ctor_a_val;
}
static void _generic_call_req_ctor_b_callback(Eo *obj EINA_UNUSED, Generic_Data *pd)
static int _generic_opt_ctor_b_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
{
if (pd->req_ctor_b_cb)
pd->req_ctor_b_cb(pd->req_ctor_b_data);
return pd->opt_ctor_b_val;
}
static void _generic_call_opt_ctor_b_callback(Eo *obj EINA_UNUSED, Generic_Data *pd)
/* static void _generic_req_ctor_a_value_set(Eo *obj EINA_UNUSED, Generic_Data* pd EINA_UNUSED, int value EINA_UNUSED) */
/* { */
/* } */
/* static void _generic_opt_ctor_a_value_set(Eo *obj EINA_UNUSED, Generic_Data* pd EINA_UNUSED, int value EINA_UNUSED) */
/* { */
/* } */
static void _generic_out_required_ctor_a(Eo *obj EINA_UNUSED, Generic_Data* pd, int *value)
{
if (pd->opt_ctor_b_cb)
pd->opt_ctor_b_cb(pd->opt_ctor_b_data);
*value = pd->req_ctor_a_val;
}
static void _generic_out_required_ctor_b(Eo *obj EINA_UNUSED, Generic_Data* pd, int *value)
{
*value = pd->req_ctor_b_val;
}
static void _generic_out_optional_ctor_a(Eo *obj EINA_UNUSED, Generic_Data* pd, int *value)
{
*value = pd->opt_ctor_a_val;
}
static void _generic_out_optional_ctor_b(Eo *obj EINA_UNUSED, Generic_Data* pd, int *value)
{
*value = pd->opt_ctor_b_val;
}
static void _generic_call_event1(Eo *obj, Generic_Data* pd EINA_UNUSED)
{
eo_event_callback_call(obj, GENERIC_EVENT_PREFIX_EVENT1, NULL);
}
static void _generic_call_event2(Eo *obj, Generic_Data* pd EINA_UNUSED)
{
eo_event_callback_call(obj, GENERIC_EVENT_PREFIX_EVENT2, obj);
}
static void _generic_call_event3(Eo *obj, Generic_Data* pd EINA_UNUSED)
{
int p = 42;
eo_event_callback_call(obj, GENERIC_EVENT_PREFIX_EVENT3, &p);
}
static void _generic_call_event4(Eo *obj, Generic_Data* pd EINA_UNUSED)
{
int i = 42;
Eina_List* p = eina_list_append(NULL, &i);
ck_assert(p != NULL);
eo_event_callback_call(obj, GENERIC_EVENT_PREFIX_EVENT4, p);
eina_list_free(p);
}
static void _generic_call_event5(Eo *obj, Generic_Data* pd EINA_UNUSED)
{
int i = 42;
Eina_List* p = eina_list_append(NULL, &i);
Generic_Event e = {.field1 = 42, .field2 = p};
eo_event_callback_call(obj, GENERIC_EVENT_PREFIX_EVENT5, &e);
eina_list_free(p);
}
#include "generic.eo.c"

View File

@ -1,4 +1,9 @@
import ecore_types;
struct Generic.Event
{
field1: int;
field2: list<int*>;
}
class Generic (Eo.Base)
{
@ -25,8 +30,7 @@ class Generic (Eo.Base)
}
required_ctor_b {
params {
@in cb: Ecore_Cb;
@in data: void_ptr;
@in value: int;
}
}
optional_ctor_a {
@ -36,13 +40,52 @@ class Generic (Eo.Base)
}
optional_ctor_b {
params {
@in cb: Ecore_Cb;
@in data: void_ptr;
@in value: int;
}
}
call_req_ctor_b_callback {
@property req_ctor_b_value {
get {}
values {
value: int;
}
}
call_opt_ctor_b_callback {
@property opt_ctor_b_value {
get {}
values {
value: int;
}
}
out_required_ctor_a {
params {
@out value: int;
}
}
out_required_ctor_b {
params {
@out value: int;
}
}
out_optional_ctor_a {
params {
@out value: int;
}
}
out_optional_ctor_b {
params {
@out value: int;
}
}
call_event1 {
}
call_event2 {
}
call_event3 {
}
call_event4 {
}
call_event5 {
}
}
constructors {
@ -54,4 +97,11 @@ class Generic (Eo.Base)
implements {
Eo.Base.constructor;
}
events {
prefix,event1;
prefix,event2: Generic;
prefix,event3: int;
prefix,event4: list<int*>;
prefix,event5: Generic.Event;
}
}

View File

@ -0,0 +1,240 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eo.h>
#include <Ecore.h>
#include <check.h>
struct _Type_Generation_Data
{
};
typedef struct _Type_Generation_Data Type_Generation_Data;
#define MY_CLASS TYPE1_TYPE2_TYPE_GENERATION_CLASS
#include "name1_name2_type_generation.eo.h"
void _name1_name2_type_generation_invoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, void *v)
{
ck_assert(v == NULL);
}
void _name1_name2_type_generation_inint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int v EINA_UNUSED)
{
ck_assert(v == 42);
}
void _name1_name2_type_generation_inintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
ck_assert(*v == 42);
}
void _name1_name2_type_generation_inintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
ck_assert(*v == 42);
}
void _name1_name2_type_generation_inintptrownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
ck_assert(**v == 42);
}
void _name1_name2_type_generation_inintptrownptrptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int ***v EINA_UNUSED)
{
ck_assert(***v == 42);
}
void _name1_name2_type_generation_inintptrptrownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int ***v EINA_UNUSED)
{
ck_assert(***v == 42);
}
void _name1_name2_type_generation_inintptrownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
ck_assert(*v == 42);
}
void * _name1_name2_type_generation_returnvoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return NULL;
}
void _name1_name2_type_generation_instring(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char *v EINA_UNUSED)
{
ck_assert_str_eq(v, "foobar");
}
void _name1_name2_type_generation_instringptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char * *v EINA_UNUSED)
{
ck_assert_str_eq(*v, "foobar");
}
void _name1_name2_type_generation_instringown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char *v EINA_UNUSED)
{
ck_assert_str_eq(v, "foobar");
free((void*)v);
}
void _name1_name2_type_generation_instringownptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char **v EINA_UNUSED)
{
ck_assert_str_eq(*v, "foobar");
free(v);
}
void _name1_name2_type_generation_instringownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char * *v EINA_UNUSED)
{
ck_assert_str_eq(*v, "foobar");
free(v);
}
int _name1_name2_type_generation_returnint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return 42;
}
int * _name1_name2_type_generation_returnintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return NULL;
}
int * _name1_name2_type_generation_returnintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return NULL;
}
int ** _name1_name2_type_generation_returnintptrownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return NULL;
}
int *** _name1_name2_type_generation_returnintptrownptrptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return NULL;
}
int *** _name1_name2_type_generation_returnintptrptrownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return NULL;
}
void _name1_name2_type_generation_returnintptrownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
}
const char * _name1_name2_type_generation_returnstring(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
return "foobar";
}
const char * * _name1_name2_type_generation_returnstringptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
static const char* foobar = "foobar";
return &foobar;
}
const char * _name1_name2_type_generation_returnstringown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
const char foobar[] = "foobar";
char* p = malloc(sizeof(foobar));
memcpy(p, foobar, sizeof(foobar));
return p;
}
const char * * _name1_name2_type_generation_returnstringownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED)
{
const char foobar[] = "foobar";
char** p1 = malloc(sizeof(const char*));
char* p = malloc(sizeof(foobar));
memcpy(p, foobar, sizeof(foobar));
*p1 = p;
return (const char**)p1;
}
void _name1_name2_type_generation_outvoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, void **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_outint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_outintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_outintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_outintptrownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_inclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_outclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_inoutclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinvoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, void *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinintptrownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionaloutvoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, void **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionaloutint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionaloutintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionaloutintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionaloutintptrownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation *v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionaloutclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation **v EINA_UNUSED)
{
}
void _name1_name2_type_generation_optionalinoutclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation **v EINA_UNUSED)
{
}
#include "name1_name2_type_generation.eo.c"

View File

@ -0,0 +1,220 @@
class Name1.Name2.Type_Generation (Eo.Base)
{
data: Type_Generation_Data;
methods {
// in void ptr
invoidptr {
params {
@in v: void*;
}
}
inint {
params {
@in v: int;
}
}
inintptr {
params {
@in v: int*;
}
}
inintptrown {
params {
@in v: own(int*);
}
}
inintptrownptr {
params {
@in v: own(int*)*;
}
}
inintptrownptrptr {
params {
@in v: own(int*)**;
}
}
inintptrptrownptr {
params {
@in v: own(int**)*;
}
}
inintptrownfree {
params {
@in v: free(own(int*), free);
}
}
instring {
params {
@in v: string;
}
}
/*
instringptr {
params {
@in v: string*;
}
}*/
instringown {
params {
@in v: own(string);
}
}
/* no sense
instringptrown {
params {
@in v: own(string*);
}
}
instringownptrown {
params {
@in v: own(own(string)*);
}
}*/
// return
returnvoidptr {
return: void*;
}
returnint {
return: int;
}
returnintptr {
return: int*;
}
returnintptrown {
return: own(int*);
}
returnintptrownptr {
return: own(int*)*;
}
returnintptrownptrptr {
return: own(int*)**;
}
returnintptrptrownptr {
return: own(int**)*;
}
returnintptrownfree {
params {
@in v: free(own(int*), free);
}
}
returnstring {
return: string;
}
returnstringptr {
return: string*;
}
returnstringown {
return: own(string);
}
returnstringownptr {
return: own(string*);
}
// out
outvoidptr {
params {
@out v: void*;
}
}
outint {
params {
@out v: int;
}
}
outintptr {
params {
@out v: int*;
}
}
outintptrown {
params {
@out v: own(int*);
}
}
outintptrownfree {
params {
@out v: free(own(int*), free);
}
}
inclassname {
params {
@in v: Name1.Name2.Type_Generation;
}
}
outclassname {
params {
@out v: Name1.Name2.Type_Generation;
}
}
inoutclassname {
params {
@inout v: Name1.Name2.Type_Generation;
}
}
optionalinvoidptr {
params {
@in v: void* @optional;
}
}
optionalinint {
params {
@in v: int @optional;
}
}
optionalinintptr {
params {
@in v: int* @optional;
}
}
optionalinintptrown {
params {
@in v: own(int*) @optional;
}
}
optionalinintptrownfree {
params {
@in v: free(own(int*), free) @optional;
}
}
optionaloutvoidptr {
params {
@out v: void* @optional;
}
}
optionaloutint {
params {
@out v: int @optional;
}
}
optionaloutintptr {
params {
@out v: int* @optional;
}
}
optionaloutintptrown {
params {
@out v: own(int*) @optional;
}
}
optionaloutintptrownfree {
params {
@out v: free(own(int*), free) @optional;
}
}
optionalinclassname {
params {
@in v: Name1.Name2.Type_Generation @optional;
}
}
optionaloutclassname {
params {
@out v: Name1.Name2.Type_Generation @optional;
}
}
optionalinoutclassname {
params {
@inout v: Name1.Name2.Type_Generation @optional;
}
}
}
}

View File

@ -1,4 +1,8 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Eo.h>
#include "name_name.eo.h"