diff options
author | Felipe Magno de Almeida <felipe@expertisesolutions.com.br> | 2018-01-17 21:39:42 -0200 |
---|---|---|
committer | Felipe Magno de Almeida <felipe@expertisesolutions.com.br> | 2018-01-17 21:39:42 -0200 |
commit | 1440ff4c9be3a01f889b78cb0713e65252153f59 (patch) | |
tree | d09083d5602303b41f49fe9728d52df64e97fa5f | |
parent | 166c371e93505adfcc6217c706ec704c30b99450 (diff) | |
download | efl-1440ff4c9be3a01f889b78cb0713e65252153f59.tar.gz |
eolian-js: Add parameter passing code
-rw-r--r-- | src/bin/eolian_js/eolian/grammar/class_registration.hpp | 15 | ||||
-rw-r--r-- | src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp | 112 | ||||
-rw-r--r-- | src/bin/eolian_js/eolian/grammar/parameter.hpp | 102 | ||||
-rw-r--r-- | src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp | 32 | ||||
-rw-r--r-- | src/bin/eolian_js/main.cc | 38 | ||||
-rw-r--r-- | src/bindings/js/eina_js/eina_js_get_value.hh | 42 | ||||
-rw-r--r-- | src/lib/eolian_cxx/grammar/empty_generator.hpp | 34 | ||||
-rw-r--r-- | src/lib/eolian_cxx/grammar/if.hpp | 131 |
8 files changed, 488 insertions, 18 deletions
diff --git a/src/bin/eolian_js/eolian/grammar/class_registration.hpp b/src/bin/eolian_js/eolian/grammar/class_registration.hpp index d6e5cac4b4..f9b072f077 100644 --- a/src/bin/eolian_js/eolian/grammar/class_registration.hpp +++ b/src/bin/eolian_js/eolian/grammar/class_registration.hpp @@ -7,6 +7,8 @@ #include <grammar/attribute_reorder.hpp> #include <grammar/attributed.hpp> #include <grammar/attribute_replace.hpp> +#include <grammar/if.hpp> +#include <grammar/empty_generator.hpp> #include <eolian/grammar/stub_function_definition.hpp> namespace eolian { namespace js { namespace grammar { @@ -49,12 +51,15 @@ struct class_registration_generator ( attribute_reorder<0, 1, 2, 3, 0, 1, 0, 1> ( - "static void register_prototype_" + "static void register_prototype_" << lower_case[*(string << "_")] << lower_case[string] << "(v8::Handle<v8::Object> global, v8::Local<v8::ObjectTemplate> prototype, v8::Isolate* isolate)\n" << "{\n" - << *attribute_reorder<1, 1, 1, 1> + << * + if_([] (attributes::function_def const& f) { return !f.is_beta && !f.is_protected; }) + [ + attribute_reorder<1, 1, 1, 1> ( scope_tab << "prototype->Set( ::efl::eina::js::compatibility_new<v8::String>(isolate, \"" << attribute_replace(&eolian::js::format::format_method)[string] << "\")\n" @@ -66,8 +71,9 @@ struct class_registration_generator << lower_case[string] << "_" ] << lower_case[string] - << "));\n" + << "));\n" ) + ][empty_generator] << *( scope_tab << "register_prototype_" @@ -88,7 +94,8 @@ struct class_registration_generator << lower_case[string] << "(global, prototype, isolate);\n" << "}\n" - )).generate(sink, std::make_tuple(cls.namespaces, cls.cxx_name, cls.functions, cls.immediate_inherits), context); + )).generate(sink, std::make_tuple(cls.namespaces, cls.cxx_name, cls.functions, cls.immediate_inherits + , cls.eolian_name), context); as_generator ( diff --git a/src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp b/src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp new file mode 100644 index 0000000000..a90b1a5408 --- /dev/null +++ b/src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp @@ -0,0 +1,112 @@ +#ifndef EOLIAN_JS_OUT_PARAMETER_DEFINITION_HPP +#define EOLIAN_JS_OUT_PARAMETER_DEFINITION_HPP + +#include <grammar/klass_def.hpp> +#include <grammar/indentation.hpp> +#include <grammar/string.hpp> +#include <grammar/attribute_reorder.hpp> +#include <grammar/attributed.hpp> +#include <grammar/attribute_replace.hpp> +#include <eolian/grammar/stub_function_definition.hpp> + +namespace eolian { namespace js { namespace grammar { + +namespace attributes = efl::eolian::grammar::attributes; + +template <typename ParameterContainer, typename Generator> +struct out_parameter_definition_generator +{ + out_parameter_definition_generator(attributes::klass_def const& cls, ParameterContainer const& container + , Generator prefix_generator) + : klass(cls), container(container), prefix_generator(prefix_generator) {} + + template <typename OutputIterator, typename Context> + bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const + { + using namespace efl::eolian::grammar; + using efl::eolian::grammar::attributes::unused; + namespace attributes = efl::eolian::grammar::attributes; + + std::size_t index; + { + auto iterator = std::find(container.begin(), container.end(), param); + assert(iterator != container.end()); + index = std::distance(container.begin(), iterator); + } + + switch(param.direction) + { + case attributes::parameter_direction::in: + break; + case attributes::parameter_direction::inout: + case attributes::parameter_direction::out: + attributes::generate(prefix_generator, sink, param, context); + + as_generator(string + << " __out_" + << string + ).generate(sink, std::make_tuple(param.type.c_type, param.param_name), context); + + if(param.direction == attributes::parameter_direction::inout) + as_generator(" = ::efl::eina::js::get_value_from_javascript(args[" + << string + << "], isolate, \"\", ::efl::eina::js::value_tag< " + << string + << " >{})" + ).generate(sink, std::make_tuple(std::to_string(index), param.type.c_type), context); + + *sink++ = ';'; + *sink++ = '\n'; + break; + }; + + + return true; + } + + attributes::klass_def klass; + ParameterContainer const& container; + Generator prefix_generator; +}; + +template <typename ParameterContainer> +struct out_parameter_definition_directive +{ + template <typename Generator> + out_parameter_definition_generator<ParameterContainer, Generator> + operator[](Generator const& gen) const + { + return {klass, container, gen}; + } + + attributes::klass_def klass; + ParameterContainer const& container; +}; + +template <typename ParameterContainer> +out_parameter_definition_directive<ParameterContainer> +out_parameter_definition(attributes::klass_def const& cls, ParameterContainer const& container) +{ + return {cls, container}; +} + +} } } + +namespace efl { namespace eolian { namespace grammar { + +template <typename ParameterContainer, typename Generator> +struct is_generator< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator> > : std::true_type {}; +template <typename ParameterContainer, typename Generator> +struct is_eager_generator< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator>> : std::true_type {}; + +namespace type_traits { + +template <typename ParameterContainer, typename Generator> +struct attributes_needed< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator>> : std::integral_constant<int, 1> {}; +template <typename ParameterContainer, typename Generator> +struct accepts_specific_tuple< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator> + , ::efl::eolian::grammar::attributes::parameter_def > : std::true_type {}; + +} } } } + +#endif diff --git a/src/bin/eolian_js/eolian/grammar/parameter.hpp b/src/bin/eolian_js/eolian/grammar/parameter.hpp new file mode 100644 index 0000000000..5c22715874 --- /dev/null +++ b/src/bin/eolian_js/eolian/grammar/parameter.hpp @@ -0,0 +1,102 @@ +#ifndef EOLIAN_JS_PARAMETER_HPP +#define EOLIAN_JS_PARAMETER_HPP + +#include <grammar/klass_def.hpp> +#include <grammar/indentation.hpp> +#include <grammar/string.hpp> +#include <grammar/attribute_reorder.hpp> +#include <grammar/attributed.hpp> +#include <grammar/attribute_replace.hpp> +#include <eolian/grammar/stub_function_definition.hpp> + +namespace eolian { namespace js { namespace grammar { + +namespace attributes = efl::eolian::grammar::attributes; + +template <typename ParameterContainer> +struct parameter_generator +{ + parameter_generator(attributes::klass_def const& cls, ParameterContainer const& container) + : klass(cls), container(container) {} + + template <typename OutputIterator, typename Context> + bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const + { + using namespace efl::eolian::grammar; + using efl::eolian::grammar::attributes::unused; + namespace attributes = efl::eolian::grammar::attributes; + + std::size_t index; + { + auto iterator = std::find(container.begin(), container.end(), param); + assert(iterator != container.end()); + index = std::distance(container.begin(), iterator); + } + + bool is_function_ptr = false; + if(attributes::regular_type_def const* def + = ::efl::eina::get<attributes::regular_type_def>(¶m.type.original_type)) + { + is_function_ptr = def->is_function_ptr(); + } + + if(is_function_ptr) + { + as_generator(" NULL, NULL, NULL").generate(sink, unused, context); + } + else + { + switch(param.direction) + { + case attributes::parameter_direction::in: + as_generator(" ::efl::eina::js::get_value_from_javascript(args[" + << string + << "], isolate, \"\", ::efl::eina::js::value_tag< " + << string + << " >{})" + ).generate(sink, std::make_tuple(std::to_string(index), param.type.c_type), context); + break; + case attributes::parameter_direction::inout: + case attributes::parameter_direction::out: + as_generator("&__out_" + << string + ).generate(sink, param.param_name, context); + break; + }; + } + + return true; + } + + attributes::klass_def klass; + ParameterContainer const& container; +}; + + +template <typename ParameterContainer> +parameter_generator<ParameterContainer> +parameter(attributes::klass_def const& cls, ParameterContainer const& container) +{ + return {cls, container}; +} + +} } } + +namespace efl { namespace eolian { namespace grammar { + +template <typename ParameterContainer> +struct is_generator< ::eolian::js::grammar::parameter_generator<ParameterContainer> > : std::true_type {}; +template <typename ParameterContainer> +struct is_eager_generator< ::eolian::js::grammar::parameter_generator<ParameterContainer>> : std::true_type {}; + +namespace type_traits { + +template <typename ParameterContainer> +struct attributes_needed< ::eolian::js::grammar::parameter_generator<ParameterContainer>> : std::integral_constant<int, 1> {}; +template <typename ParameterContainer> +struct accepts_specific_tuple< ::eolian::js::grammar::parameter_generator<ParameterContainer> + , ::efl::eolian::grammar::attributes::parameter_def > : std::true_type {}; + +} } } } + +#endif diff --git a/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp b/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp index d5d7169431..f3ba9f084b 100644 --- a/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp +++ b/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp @@ -5,6 +5,8 @@ #include <grammar/indentation.hpp> #include <grammar/string.hpp> #include <grammar/attribute_reorder.hpp> +#include <eolian/grammar/parameter.hpp> +#include <eolian/grammar/out_parameter_definition.hpp> namespace eolian { namespace js { namespace grammar { @@ -21,6 +23,9 @@ struct stub_function_definition_generator using namespace efl::eolian::grammar; using efl::eolian::grammar::attributes::unused; + if(f.is_beta || f.is_protected) + return true; + // std::string suffix; // switch(cls.type) // { @@ -45,7 +50,7 @@ struct stub_function_definition_generator as_generator ( - //attribute_reorder<0, 1, 0, 1, 0, 1> + attribute_reorder<0, 1, 2, 3, 4, 3> ( "eina::js::compatibility_return_type stub_function_" << lower_case[*(string << "_")] @@ -54,14 +59,21 @@ struct stub_function_definition_generator << lower_case[string] << "(eina::js::compatibility_callback_info_type args)\n" << "{\n" - << scope_tab << "if(/*input_parameters*/" << std::to_string(ins) << " != args.Length())\n" + << scope_tab << "if(/*input_parameters*/" << std::to_string(ins) << " == args.Length())\n" << scope_tab << "{\n" + << scope_tab(2) << "v8::Isolate* isolate = args.GetIsolate(); static_cast<void>(isolate);\n" << scope_tab(2) << "v8::Local<v8::Object> self = args.This();\n" << scope_tab(2) << "v8::Local<v8::Value> external = self->GetInternalField(0);\n" << scope_tab(2) << "Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());\n" << scope_tab(2) << "try\n" << scope_tab(2) << "{\n" - << scope_tab(3) << ";" + << *(out_parameter_definition(klass, f.parameters)[scope_tab(3)]) + << scope_tab(3) << "::" << lower_case[string] + << "(" + << "eo" + << *(", " << parameter(klass, f.parameters)) + << ")" + << ";\n" << scope_tab(2) << "}\n" << scope_tab(2) << "catch(std::logic_error const&)\n" << scope_tab(2) << "{\n" @@ -75,7 +87,8 @@ struct stub_function_definition_generator << scope_tab(4) << "(eina::js::compatibility_new<v8::String>(nullptr, \"Expected more arguments for this call\")));\n" << scope_tab << "}\n" << "}\n" - )).generate(sink, std::make_tuple(klass.namespaces, klass.cxx_name, f.name), context); + )).generate(sink, std::make_tuple(klass.namespaces, klass.cxx_name, f.name, f.parameters + , f.c_name), context); // methods @@ -104,7 +117,16 @@ template <> struct is_generator< ::eolian::js::grammar::stub_function_definition_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian::js::grammar::stub_function_definition_generator> : std::true_type {}; + +namespace type_traits { + +template <> +struct attributes_needed< ::eolian::js::grammar::stub_function_definition_generator> : std::integral_constant<int, 1> {}; +template <> +struct accepts_specific_tuple< ::eolian::js::grammar::stub_function_definition_generator + , ::efl::eolian::grammar::attributes::function_def> : std::true_type {}; + -} } } +} } } } #endif diff --git a/src/bin/eolian_js/main.cc b/src/bin/eolian_js/main.cc index 6d755da249..7dced737d2 100644 --- a/src/bin/eolian_js/main.cc +++ b/src/bin/eolian_js/main.cc @@ -702,17 +702,21 @@ int main(int argc, char** argv) } }; - os << "extern \"C\" {\n\n"; - - auto includes_fun = [&os] (Eolian_Class const* klass) + auto generate_includes = + [&] { + os << "extern \"C\" {\n\n"; + + auto includes_fun = [&os] (Eolian_Class const* klass) + { + os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n"; + }; + // generate include for all inheritance + recurse_inherits(klass, includes_fun); os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n"; - }; - // generate include for all inheritance - recurse_inherits(klass, includes_fun); - os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n"; - os << "}\n\n"; + os << "}\n\n"; + }; using efl::eolian::grammar::attributes::unused; using efl::eolian::grammar::context_null; @@ -720,9 +724,26 @@ int main(int argc, char** argv) using efl::eolian::grammar::lower_case; using efl::eolian::grammar::string; using efl::eolian::grammar::as_generator; + using efl::eolian::grammar::attribute_reorder; + using efl::eolian::grammar::upper_case; if(!dummy_generation) { context_null context; + + // as_generator + // (attribute_reorder<0, 1, 0, 1> + // ( + // "#define " + // << *(upper_case[string] << "_") + // << upper_case[string] + // << "_BETA\n" + // "#define " + // << *(upper_case[string] << "_") + // << upper_case[string] + // << "_PROTECTED\n" + // )).generate(iterator, std::make_tuple(klass_def.namespaces, klass_def.eolian_name), context); + + generate_includes(); as_generator("namespace efl { namespace js { namespace binding { namespace {\n") .generate(iterator, unused, context); @@ -753,6 +774,7 @@ int main(int argc, char** argv) } else { + generate_includes(); as_generator ( "namespace efl { namespace js { namespace binding { namespace {\n" diff --git a/src/bindings/js/eina_js/eina_js_get_value.hh b/src/bindings/js/eina_js/eina_js_get_value.hh index 450ba067fc..c7aa483bea 100644 --- a/src/bindings/js/eina_js/eina_js_get_value.hh +++ b/src/bindings/js/eina_js/eina_js_get_value.hh @@ -35,6 +35,18 @@ inline int get_value_from_javascript return 0; } +template <typename T> +inline T get_value_from_javascript + (v8::Local<v8::Value> v + , v8::Isolate* isolate + , const char* + , value_tag<T> + , bool throw_js_exception = true + , typename std::enable_if<(std::is_pointer<T>::value && std::is_function<typename std::remove_pointer<T>::type>::value)>::type* = 0) +{ + return 0; +} + inline char* get_value_from_javascript (v8::Local<v8::Value> v , v8::Isolate* isolate @@ -262,7 +274,35 @@ inline T get_value_from_javascript !std::is_same<T, const Eina_Array*>::value && !std::is_same<T, const Eina_Iterator*>::value && !std::is_same<T, const Eina_Hash*>::value && - !std::is_same<T, const Eina_List*>::value + !std::is_same<T, const Eina_List*>::value && + !std::is_function<typename std::remove_pointer<T>::type>::value + >::type* = 0) +{ + if (throw_js_exception) + eina::js::compatibility_throw + (isolate, v8::Exception::TypeError + (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet"))); + throw std::logic_error(""); +} + +// TODO: +template <typename T> +inline T get_value_from_javascript + (v8::Local<v8::Value>, v8::Isolate* isolate, const char*, value_tag<T> + , bool throw_js_exception = true + , typename std::enable_if< + std::is_same<T, Eina_Accessor*>::value || + std::is_same<T, Eina_Array*>::value || + std::is_same<T, Eina_Iterator*>::value || + std::is_same<T, Eina_Hash*>::value || + std::is_same<T, Eina_List*>::value || + std::is_same<T, const Eina_Accessor*>::value || + std::is_same<T, const Eina_Array*>::value || + std::is_same<T, const Eina_Iterator*>::value || + std::is_same<T, const Eina_Hash*>::value || + std::is_same<T, const Eina_List*>::value || + std::is_same<T, Eina_Iterator*>::value || + std::is_same<T, const Eina_Iterator*>::value >::type* = 0) { if (throw_js_exception) diff --git a/src/lib/eolian_cxx/grammar/empty_generator.hpp b/src/lib/eolian_cxx/grammar/empty_generator.hpp new file mode 100644 index 0000000000..30077f54b9 --- /dev/null +++ b/src/lib/eolian_cxx/grammar/empty_generator.hpp @@ -0,0 +1,34 @@ +#ifndef EOLIAN_CXX_EMPTY_GENERATOR_HH +#define EOLIAN_CXX_EMPTY_GENERATOR_HH + +#include "grammar/generator.hpp" + +namespace efl { namespace eolian { namespace grammar { + +struct empty_generator +{ + template <typename OutputIterator, typename Attribute, typename Context> + bool generate(OutputIterator const&, Attribute const&, Context const&) const + { + return true; + } +}; + +struct empty_generator const empty_generator = {}; + +template <> +struct is_eager_generator<struct ::efl::eolian::grammar::empty_generator> : std::true_type {}; +template <> +struct is_generator<struct ::efl::eolian::grammar::empty_generator> : std::true_type {}; + +namespace type_traits { + +template <> +struct attributes_needed<struct ::efl::eolian::grammar::empty_generator> + : std::integral_constant<int, 0> {}; + +} + +} } } + +#endif diff --git a/src/lib/eolian_cxx/grammar/if.hpp b/src/lib/eolian_cxx/grammar/if.hpp new file mode 100644 index 0000000000..401a81a0d7 --- /dev/null +++ b/src/lib/eolian_cxx/grammar/if.hpp @@ -0,0 +1,131 @@ +#ifndef EOLIAN_CXX_IF_HH +#define EOLIAN_CXX_IF_HH + +#include "grammar/generator.hpp" + +namespace efl { namespace eolian { namespace grammar { + +template <typename F, typename TrueGenerator, typename FalseGenerator> +struct if_true_false_generator +{ + template <typename OutputIterator, typename Attribute, typename Context> + bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const + { + if(f(attribute)) + { + return true_generator.generate(sink, attribute, ctx); + } + else + { + return false_generator.generate(sink, attribute, ctx); + } + } + + F f; + TrueGenerator true_generator; + FalseGenerator false_generator; +}; + +template <typename F, typename TrueGenerator> +struct if_true_generator +{ + template <typename FalseGenerator> + if_true_false_generator<F, TrueGenerator, FalseGenerator> operator[](FalseGenerator false_g) const + { + return {f, true_generator, false_g}; + } + + template <typename OutputIterator, typename Attribute, typename Context> + bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const + { + if(f(attribute)) + { + return true_generator.generate(sink, attribute, context); + } + else + { + return false; + } + } + + F f; + TrueGenerator true_generator; +}; + +template <typename F> +struct if_generator +{ + template <typename TrueGenerator> + if_true_generator<F, TrueGenerator> operator[](TrueGenerator true_g) const + { + return {f, true_g}; + } + + template <typename OutputIterator, typename Attribute, typename Context> + bool generate(OutputIterator, Attribute const& attribute, Context const&) const + { + return f(attribute); + } + + F f; +}; + +struct if_terminal +{ + template <typename F> + if_generator<F> operator()(F f) const + { + return {f}; + } +} const if_ = {}; + +template <typename F> +struct is_eager_generator<if_generator<F>> : std::true_type {}; +template <typename F, typename TrueGenerator> +struct is_eager_generator<if_true_generator<F, TrueGenerator>> : std::true_type {}; +template <typename F, typename TrueGenerator, typename FalseGenerator> +struct is_eager_generator<if_true_false_generator<F, TrueGenerator, FalseGenerator>> : std::true_type {}; + +template <typename F> +struct is_generator<if_generator<F>> : std::true_type {}; +template <typename F, typename TrueGenerator> +struct is_generator<if_true_generator<F, TrueGenerator>> : std::true_type {}; +template <typename F, typename TrueGenerator, typename FalseGenerator> +struct is_generator<if_true_false_generator<F, TrueGenerator, FalseGenerator>> : std::true_type {}; + +namespace type_traits { + +template <typename F> +struct attributes_needed<if_generator<F>> + : std::integral_constant<int, 1> {}; + +template <typename F, typename TrueGenerator> +struct attributes_needed<if_true_generator<F, TrueGenerator>> : attributes_needed<TrueGenerator> {}; +template <typename F, typename TrueGenerator, typename FalseGenerator> +struct attributes_needed<if_true_false_generator<F, TrueGenerator, FalseGenerator>> + : std::conditional<(attributes_needed<TrueGenerator>::value >= attributes_needed<FalseGenerator>::value) + , attributes_needed<TrueGenerator>, attributes_needed<FalseGenerator>>::type +{}; + +template <typename F, typename TrueGenerator, typename T> +struct accepts_specific_tuple<if_true_generator<F, TrueGenerator>, T> + : accepts_specific_tuple<TrueGenerator, T> {}; +template <typename F, typename TrueGenerator, typename FalseGenerator, typename T> +struct accepts_specific_tuple<if_true_false_generator<F, TrueGenerator, FalseGenerator>, T> + : std::integral_constant<bool, accepts_specific_tuple<TrueGenerator, T>::value + ||accepts_specific_tuple<FalseGenerator, T>::value> +{}; + +template <typename F, typename TrueGenerator> +struct accepts_tuple<if_true_generator<F, TrueGenerator>> + : accepts_tuple<TrueGenerator> {}; +template <typename F, typename TrueGenerator, typename FalseGenerator> +struct accepts_tuple<if_true_false_generator<F, TrueGenerator, FalseGenerator>> + : std::integral_constant<bool, accepts_tuple<TrueGenerator>::value || accepts_tuple<FalseGenerator>::value> +{}; + +} + +} } } + +#endif |