summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2019-08-23 14:00:26 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2019-08-23 14:07:09 -0300
commit1aa05ab41be00da32fcc3cc83a95c605dbeb9a58 (patch)
treefb46f24e81ef1f8f0f9b129c768e9a39df2bb02d /src
parent8aae656b8003f3f3cf4dd0dbed9aae92eee521ef (diff)
eolian-mono: Add support for multi-value properties with tuples
Summary: T8133 Reviewers: woohyun, segfaultxavi, felipealmeida Reviewed By: felipealmeida Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9577
Diffstat (limited to 'src')
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh156
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh1
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh24
-rw-r--r--src/lib/eolian_cxx/grammar/counter.hpp59
-rw-r--r--src/tests/efl_mono/Eo.cs8
-rw-r--r--src/tests/efl_mono/dummy_test_object.c14
-rw-r--r--src/tests/efl_mono/dummy_test_object.eo9
7 files changed, 245 insertions, 26 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index f010f6d..b8b811f 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -6,10 +6,12 @@
6#include "grammar/generator.hpp" 6#include "grammar/generator.hpp"
7#include "grammar/klass_def.hpp" 7#include "grammar/klass_def.hpp"
8 8
9#include "grammar/kleene.hpp"
9#include "grammar/indentation.hpp" 10#include "grammar/indentation.hpp"
10#include "grammar/list.hpp" 11#include "grammar/list.hpp"
11#include "grammar/alternative.hpp" 12#include "grammar/alternative.hpp"
12#include "grammar/attribute_reorder.hpp" 13#include "grammar/attribute_reorder.hpp"
14#include "grammar/counter.hpp"
13#include "logging.hh" 15#include "logging.hh"
14#include "type.hh" 16#include "type.hh"
15#include "name_helpers.hh" 17#include "name_helpers.hh"
@@ -292,6 +294,11 @@ struct property_wrapper_definition_generator
292 template<typename OutputIterator, typename Context> 294 template<typename OutputIterator, typename Context>
293 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const 295 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
294 { 296 {
297 using efl::eolian::grammar::attribute_reorder;
298 using efl::eolian::grammar::counter;
299 using efl::eolian::grammar::attributes::parameter_direction;
300 using efl::eolian::grammar::attributes::parameter_def;
301
295 if (blacklist::is_property_blacklisted(property, *implementing_klass, context)) 302 if (blacklist::is_property_blacklisted(property, *implementing_klass, context))
296 return true; 303 return true;
297 304
@@ -304,7 +311,7 @@ struct property_wrapper_definition_generator
304 return true; 311 return true;
305 312
306 auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0; 313 auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0;
307 auto set_params = property.setter.is_engaged() ? property.setter->parameters.size() : 0; 314 //auto set_params = property.setter.is_engaged() ? property.setter->parameters.size() : 0;
308 315
309 // C# properties must have a single value. 316 // C# properties must have a single value.
310 // 317 //
@@ -312,16 +319,62 @@ struct property_wrapper_definition_generator
312 // meaning they should have 0 parameters. 319 // meaning they should have 0 parameters.
313 // 320 //
314 // For setters, we ignore the return type - usually boolean. 321 // For setters, we ignore the return type - usually boolean.
315 if (get_params > 0 || set_params > 1) 322 // if (get_params > 0 || set_params > 1)
323 // return true;
324
325 if (property.getter
326 && std::find_if (property.getter->parameters.begin()
327 , property.getter->parameters.end()
328 , [] (parameter_def const& p)
329 {
330 return p.direction != parameter_direction::out;
331 }) != property.getter->parameters.end())
332 return true;
333 if (property.setter
334 && std::find_if (property.setter->parameters.begin()
335 , property.setter->parameters.end()
336 , [] (parameter_def const& p)
337 {
338 return p.direction != parameter_direction::in;
339 }) != property.setter->parameters.end())
316 return true; 340 return true;
317 341
318 attributes::type_def prop_type; 342 if (property.getter && property.setter)
343 {
344 if (get_params != 0 && property.setter->parameters.size() != property.getter->parameters.size())
345 return true;
346 }
319 347
320 if (property.getter.is_engaged()) 348 std::vector<attributes::parameter_def> parameters;
321 prop_type = property.getter->return_type; 349
322 else if (property.setter.is_engaged()) 350 if (property.setter.is_engaged())
323 prop_type = property.setter->parameters[0].type; 351 {
324 else 352 std::transform (property.setter->parameters.begin(), property.setter->parameters.end()
353 , std::back_inserter(parameters)
354 , [] (parameter_def p) -> parameter_def
355 {
356 //p.direction = efl::eolian::attributes::parameter_direction::in;
357 return p;
358 });
359 }
360 else if (property.getter.is_engaged())
361 {
362 // if getter has parameters, then we ignore return type, otherwise
363 // we use the return type.
364 if (get_params == 0)
365 parameters.push_back({parameter_direction::in
366 , property.getter->return_type, "propertyResult", {}
367 , property.getter->unit});
368 else
369 std::transform (property.getter->parameters.begin(), property.getter->parameters.end()
370 , std::back_inserter(parameters)
371 , [] (parameter_def p) -> parameter_def
372 {
373 p.direction = parameter_direction::in;
374 return p;
375 });
376 }
377 else
325 { 378 {
326 EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Property must have either a getter or a setter." << std::endl; 379 EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Property must have either a getter or a setter." << std::endl;
327 return false; 380 return false;
@@ -365,21 +418,88 @@ struct property_wrapper_definition_generator
365 set_scope = ""; 418 set_scope = "";
366 } 419 }
367 420
368 if (!as_generator( 421 if (parameters.size() == 1)
369 documentation(1) 422 {
370 << scope_tab << scope << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n" 423 if (!as_generator(
371 ).generate(sink, std::make_tuple(property, prop_type), context)) 424 documentation(1)
372 return false; 425 << scope_tab << scope << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n"
426 ).generate(sink, std::make_tuple(property, parameters[0].type), context))
427 return false;
428 }
429 else
430 {
431 if (!as_generator
432 (
433 documentation(1)
434 << scope_tab << scope << (is_static ? "static (" : "(")
435 << (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") "
436 << managed_name << " {\n"
437 ).generate(sink, std::make_tuple(property, parameters), context))
438 return false;
439 }
373 440
374 if (property.getter.is_engaged()) 441 if (property.getter.is_engaged() && interface)
375 if (!as_generator(scope_tab << scope_tab << get_scope << "get " << (interface ? ";" : "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }") << "\n" 442 {
443 if (!as_generator(scope_tab << scope_tab << set_scope << "get;\n"
444 ).generate(sink, attributes::unused, context))
445 return false;
446 }
447 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
448 {
449 if (!as_generator
450 (scope_tab << scope_tab << get_scope
451 << "get " << "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }\n"
376 ).generate(sink, attributes::unused, context)) 452 ).generate(sink, attributes::unused, context))
377 return false; 453 return false;
378 454 }
379 if (property.setter.is_engaged()) 455 else if (parameters.size() >= 1 && property.getter)
380 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << (interface ? ";" : "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }") << "\n" 456 {
457 if (!as_generator
458 (scope_tab << scope_tab << get_scope << "get "
459 << "{\n"
460 << *attribute_reorder<1, -1, 1>
461 (scope_tab(3) << type(true) << " _out_"
462 << argument(false) << " = default(" << type(true) << ");\n"
463 )
464 << scope_tab(3) << name_helpers::managed_method_name(*property.getter)
465 << "(" << (("out _out_" << argument(false)) % ",") << ");\n"
466 << scope_tab(3) << "return (" << (("_out_"<< argument(false)) % ",") << ");\n"
467 << scope_tab(2) << "}" << "\n"
468 ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
469 return false;
470 }
471 // else if (parameters.size() == 1)
472 // {
473 // if (!as_generator
474 // (scope_tab << scope_tab << get_scope << "get "
475 // << "{\n"
476 // << *attribute_reorder<1, -1, 1>(scope_tab(3) << type(true) << " _out_" << argument(false) << " = default(" << type(true) << ");\n")
477 // << scope_tab(3) << name_helpers::managed_method_name(*property.getter)
478 // << "(" << (("out _out_" << argument(false)) % ",") << ");\n"
479 // << scope_tab(3) << "return " << (("_out_"<< argument(false)) % ",") << ";\n"
480 // << scope_tab(2) << "}" << "\n"
481 // ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
482 // return false;
483 // }
484
485 if (property.setter.is_engaged() && interface)
486 {
487 if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
488 ).generate(sink, attributes::unused, context))
489 return false;
490 }
491 else if (parameters.size() == 1 && property.setter.is_engaged())
492 {
493 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }\n"
381 ).generate(sink, attributes::unused, context)) 494 ).generate(sink, attributes::unused, context))
382 return false; 495 return false;
496 }
497 else if (parameters.size() > 1 && property.setter.is_engaged())
498 {
499 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << ("{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod) << ((" value.Item" << counter(1)) % ", ") << "); }" << "\n"
500 ).generate(sink, parameters, context))
501 return false;
502 }
383 503
384 if (!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, context)) 504 if (!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, context))
385 return false; 505 return false;
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index ca36d04..d6064b2 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -60,6 +60,7 @@ inline std::string escape_keyword(std::string const& name)
60 || is_equal(name, "string") 60 || is_equal(name, "string")
61 || is_equal(name, "internal") 61 || is_equal(name, "internal")
62 || is_equal(name, "fixed") 62 || is_equal(name, "fixed")
63 || is_equal(name, "var")
63 || is_equal(name, "base")) 64 || is_equal(name, "base"))
64 return "kw_" + name; 65 return "kw_" + name;
65 66
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
index 954ac25..52afaf4 100644
--- a/src/bin/eolian_mono/eolian/mono/parameter.hh
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -488,23 +488,31 @@ struct marshall_parameter_generator
488// FIXME This seems to be used only in the else branch of the native function definition. Is it really needed? 488// FIXME This seems to be used only in the else branch of the native function definition. Is it really needed?
489struct argument_generator 489struct argument_generator
490{ 490{
491 bool generate_direction;
492 argument_generator () : generate_direction(true) {}
493 argument_generator (bool r) : generate_direction(r) {}
494
491 template <typename OutputIterator, typename Context> 495 template <typename OutputIterator, typename Context>
492 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const 496 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
493 { 497 {
494 std::string param_name = escape_keyword(param.param_name); 498 std::string param_name = escape_keyword(param.param_name);
495 std::string direction = marshall_direction_modifier(param); 499 std::string direction = marshall_direction_modifier(param);
496 500
497 if (!param.type.original_type.visit(is_fp_visitor{})) 501 if (generate_direction && !param.type.original_type.visit(is_fp_visitor{}))
498 return as_generator( 502 return as_generator(direction << param_name).generate(sink, attributes::unused, context);
499 direction << param_name 503 if (!generate_direction && !param.type.original_type.visit(is_fp_visitor{}))
500 ).generate(sink, attributes::unused, context); 504 return as_generator(param_name).generate(sink, attributes::unused, context);
501 505 else
502 return as_generator( 506 return as_generator
503 param_name << "_data, " << param_name << ", " << param_name << "_free_cb" 507 (param_name << "_data, " << param_name << ", " << param_name << "_free_cb"
504 ).generate(sink, attributes::unused, context); 508 ).generate(sink, attributes::unused, context);
505 509
506 } 510 }
507 511
512 argument_generator operator ()(bool r) const
513 {
514 return {r};
515 }
508} const argument {}; 516} const argument {};
509 517
510struct native_argument_invocation_generator 518struct native_argument_invocation_generator
diff --git a/src/lib/eolian_cxx/grammar/counter.hpp b/src/lib/eolian_cxx/grammar/counter.hpp
new file mode 100644
index 0000000..d5af506
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/counter.hpp
@@ -0,0 +1,59 @@
1#ifndef EOLIAN_CXX_COUNTER_HH_HH
2#define EOLIAN_CXX_COUNTER_HH_HH
3
4#include <cstdlib>
5#include <cstring>
6
7#include "grammar/generator.hpp"
8#include "grammar/attributes.hpp"
9#include "grammar/case.hpp"
10#include "grammar/integral.hpp"
11
12namespace efl { namespace eolian { namespace grammar {
13
14namespace detail {
15
16}
17
18struct counter_generator
19{
20 std::shared_ptr<std::size_t> count;
21
22 template <typename OutputIterator, typename Attribute, typename Context>
23 bool generate(OutputIterator sink, Attribute const&, Context const&) const
24 {
25 detail::generate_integral(sink, *count);
26 ++*count;
27 return true;
28 }
29};
30
31struct counter_terminal
32{
33 counter_generator operator()(std::size_t initial) const
34 {
35 return {std::shared_ptr<std::size_t>{new std::size_t{initial}}};
36 }
37} const counter = {};
38
39counter_generator as_generator(counter_terminal) { return {std::shared_ptr<std::size_t>{new std::size_t{0u}}}; }
40
41template <>
42struct is_eager_generator<counter_generator> : std::true_type {};
43template <>
44struct is_eager_generator<counter_terminal> : std::true_type {};
45template <>
46struct is_generator<counter_terminal> : std::true_type {};
47template <>
48struct is_generator<counter_generator> : std::true_type {};
49
50namespace type_traits {
51template <>
52struct attributes_needed<counter_generator> : std::integral_constant<int, 0> {};
53template <>
54struct attributes_needed<counter_terminal> : std::integral_constant<int, 0> {};
55}
56
57} } }
58
59#endif
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs
index aa3565d..56813b3 100644
--- a/src/tests/efl_mono/Eo.cs
+++ b/src/tests/efl_mono/Eo.cs
@@ -348,6 +348,14 @@ class TestCsharpProperties
348 iface.IfaceProp = val; 348 iface.IfaceProp = val;
349 Test.AssertEquals(val, iface.IfaceProp); 349 Test.AssertEquals(val, iface.IfaceProp);
350 } 350 }
351
352 public static void test_csharp_multi_valued_prop()
353 {
354 var obj = new Dummy.TestObject();
355 obj.MultiValuedProp = (1, 2);
356 var ret = obj.MultiValuedProp;
357 Test.AssertEquals(ret, (1, 2));
358 }
351} 359}
352 360
353class TestEoGrandChildrenFinalize 361class TestEoGrandChildrenFinalize
diff --git a/src/tests/efl_mono/dummy_test_object.c b/src/tests/efl_mono/dummy_test_object.c
index 8ba7536..6c32f80 100644
--- a/src/tests/efl_mono/dummy_test_object.c
+++ b/src/tests/efl_mono/dummy_test_object.c
@@ -16,6 +16,8 @@ typedef struct Dummy_Test_Object_Data
16 int iface_prop; 16 int iface_prop;
17 Eo *provider; 17 Eo *provider;
18 Eo *iface_provider; 18 Eo *iface_provider;
19 int prop1;
20 int prop2;
19 21
20 // Containers passed to C# as iterator/accessors 22 // Containers passed to C# as iterator/accessors
21 Eina_Array *out_array; 23 Eina_Array *out_array;
@@ -4570,6 +4572,18 @@ Dummy_MyInt _dummy_test_object_bypass_typedef(EINA_UNUSED Eo *obj, EINA_UNUSED D
4570 return data; 4572 return data;
4571} 4573}
4572 4574
4575void _dummy_test_object_multi_valued_prop_get(Eo const* obj EINA_UNUSED, Dummy_Test_Object_Data* pd, int* prop1, int* prop2)
4576{
4577 *prop1 = pd->prop1;
4578 *prop2 = pd->prop2;
4579}
4580
4581void _dummy_test_object_multi_valued_prop_set(Eo* obj EINA_UNUSED, Dummy_Test_Object_Data* pd, int prop1, int prop2)
4582{
4583 pd->prop1 = prop1;
4584 pd->prop2 = prop2;
4585}
4586
4573/* Class Properties */ 4587/* Class Properties */
4574static int _dummy_test_object_klass_prop = 0; 4588static int _dummy_test_object_klass_prop = 0;
4575 4589
diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo
index b6841db..2e5cbfc 100644
--- a/src/tests/efl_mono/dummy_test_object.eo
+++ b/src/tests/efl_mono/dummy_test_object.eo
@@ -1569,6 +1569,15 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
1569 return: Dummy.MyInt; 1569 return: Dummy.MyInt;
1570 } 1570 }
1571 1571
1572 @property multi_valued_prop {
1573 get {}
1574 set {}
1575 values {
1576 prop1: int;
1577 prop2: int;
1578 }
1579 }
1580
1572 @property klass_prop @static { 1581 @property klass_prop @static {
1573 get {} 1582 get {}
1574 set {} 1583 set {}