summaryrefslogtreecommitdiff
path: root/src/bin/eolian
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2019-02-15 17:15:36 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2019-02-15 17:17:15 +0100
commit8952c05ddd6299d35dbfe51b4dbdec1c482d4783 (patch)
treed4bc6b4cbbfbfa854aa8375859b3d8540273046b /src/bin/eolian
parent4935202caab9485c0b62006ffece5b85c334773a (diff)
eolian gen: initial support for reflection api
This adds support for generating reflection functions for properties. This support is basic for now, supporting only primitive types and string(shares), it will be expanded later as required. @feature
Diffstat (limited to 'src/bin/eolian')
-rw-r--r--src/bin/eolian/sources.c215
1 files changed, 197 insertions, 18 deletions
diff --git a/src/bin/eolian/sources.c b/src/bin/eolian/sources.c
index 76f8c64..e4491a2 100644
--- a/src/bin/eolian/sources.c
+++ b/src/bin/eolian/sources.c
@@ -322,11 +322,118 @@ _gen_function_param_fallback(Eina_Iterator *itr, Eina_Strbuf *fallback_free_owne
322 return owners; 322 return owners;
323} 323}
324 324
325static const char *
326_get_reflect_initf(const Eolian_Type *abtp)
327{
328 Eolian_Type_Builtin_Type btp = eolian_type_builtin_type_get(abtp);
329 const char *initf = NULL;
330 switch (btp)
331 {
332 case EOLIAN_TYPE_BUILTIN_BYTE:
333 case EOLIAN_TYPE_BUILTIN_CHAR:
334 initf = "char"; break;
335 case EOLIAN_TYPE_BUILTIN_UBYTE:
336 initf = "uchar"; break;
337 case EOLIAN_TYPE_BUILTIN_SHORT:
338 case EOLIAN_TYPE_BUILTIN_USHORT:
339 case EOLIAN_TYPE_BUILTIN_INT:
340 case EOLIAN_TYPE_BUILTIN_UINT:
341 case EOLIAN_TYPE_BUILTIN_LONG:
342 case EOLIAN_TYPE_BUILTIN_ULONG:
343 case EOLIAN_TYPE_BUILTIN_INT64:
344 case EOLIAN_TYPE_BUILTIN_UINT64:
345 case EOLIAN_TYPE_BUILTIN_TIME:
346 case EOLIAN_TYPE_BUILTIN_FLOAT:
347 case EOLIAN_TYPE_BUILTIN_DOUBLE:
348 case EOLIAN_TYPE_BUILTIN_BOOL:
349 case EOLIAN_TYPE_BUILTIN_STRING:
350 case EOLIAN_TYPE_BUILTIN_STRINGSHARE:
351 initf = eolian_type_name_get(abtp); break;
352 default:
353 break;
354 }
355 return initf;
356}
357
358static void
359_gen_reflect_get(Eina_Strbuf *buf, const char *cnamel, const Eolian_Type *valt,
360 const Eolian_Function *fid, Eina_Hash *refh)
361{
362 if (eolian_type_is_ptr(valt))
363 return;
364
365 const Eolian_Type *abtp = eolian_type_aliased_base_get(valt);
366 const char *initf = _get_reflect_initf(abtp);
367 if (!initf)
368 return;
369
370 Eolian_Function_Type et = (Eolian_Function_Type)eina_hash_find(refh, &fid);
371 if (et == EOLIAN_PROP_SET)
372 eina_hash_set(refh, &fid, (void *)EOLIAN_PROPERTY);
373 else
374 eina_hash_set(refh, &fid, (void *)EOLIAN_PROP_GET);
375
376 eina_strbuf_append(buf, "\nstatic Eina_Value\n");
377 eina_strbuf_append_printf(buf, "__eolian_%s_%s_get_reflect(Eo *obj)\n",
378 cnamel, eolian_function_name_get(fid));
379 eina_strbuf_append(buf, "{\n");
380
381 Eina_Stringshare *ct = eolian_type_c_type_get(valt, EOLIAN_C_TYPE_RETURN);
382 const char *starsp = (ct[strlen(ct) - 1] != '*') ? " " : "";
383
384 Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, EOLIAN_PROP_GET, EINA_FALSE);
385 eina_strbuf_append_printf(buf, " %s%sval = %s(obj);\n", ct, starsp, fcn);
386 eina_stringshare_del(fcn);
387 eina_stringshare_del(ct);
388
389 eina_strbuf_append_printf(buf, " return eina_value_%s_init(val);\n", initf);
390 eina_strbuf_append(buf, "}\n\n");
391}
392
393static void
394_gen_reflect_set(Eina_Strbuf *buf, const char *cnamel, const Eolian_Type *valt,
395 const Eolian_Function *fid, Eina_Hash *refh)
396{
397 if (eolian_type_is_ptr(valt))
398 return;
399
400 const Eolian_Type *abtp = eolian_type_aliased_base_get(valt);
401 const char *initf = _get_reflect_initf(abtp);
402 if (!initf)
403 return;
404
405 Eolian_Function_Type et = (Eolian_Function_Type)eina_hash_find(refh, &fid);
406 if (et == EOLIAN_PROP_GET)
407 eina_hash_set(refh, &fid, (void *)EOLIAN_PROPERTY);
408 else
409 eina_hash_set(refh, &fid, (void *)EOLIAN_PROP_SET);
410
411 eina_strbuf_append(buf, "\nstatic void\n");
412 eina_strbuf_append_printf(buf, "__eolian_%s_%s_set_reflect(Eo *obj, Eina_Value val)\n",
413 cnamel, eolian_function_name_get(fid));
414 eina_strbuf_append(buf, "{\n");
415
416 Eina_Stringshare *ct = eolian_type_c_type_get(valt, EOLIAN_C_TYPE_PARAM);
417 const char *starsp = (ct[strlen(ct) - 1] != '*') ? " " : "";
418 eina_strbuf_append_printf(buf, " %s%scval;\n", ct, starsp);
419 eina_stringshare_del(ct);
420
421 eina_strbuf_append_printf(buf, " eina_value_%s_convert(&val, &cval);\n", initf);
422
423 Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, EOLIAN_PROP_SET, EINA_FALSE);
424 eina_strbuf_append_printf(buf, " %s(obj, cval);\n", fcn);
425 eina_stringshare_del(fcn);
426
427 eina_strbuf_append(buf, " eina_value_flush(&val);\n");
428
429 eina_strbuf_append(buf, "}\n\n");
430}
325 431
326static void 432static void
327_gen_func(const Eolian_Class *cl, const Eolian_Function *fid, 433_gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
328 Eolian_Function_Type ftype, Eina_Strbuf *buf, 434 Eolian_Function_Type ftype, Eina_Strbuf *buf,
329 const Eolian_Implement *impl, Eina_Strbuf *lbuf) 435 const Eolian_Implement *impl, Eina_Strbuf *lbuf,
436 Eina_Hash *refh)
330{ 437{
331 Eina_Bool is_empty = eolian_implement_is_empty(impl, ftype); 438 Eina_Bool is_empty = eolian_implement_is_empty(impl, ftype);
332 Eina_Bool is_auto = eolian_implement_is_auto(impl, ftype); 439 Eina_Bool is_auto = eolian_implement_is_auto(impl, ftype);
@@ -336,6 +443,8 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
336 443
337 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET); 444 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
338 Eina_Bool var_as_ret = EINA_FALSE; 445 Eina_Bool var_as_ret = EINA_FALSE;
446 /* assume we're not generating reflection api by default */
447 const Eolian_Type *reflect_type = NULL;
339 448
340 const Eolian_Expression *def_ret = NULL; 449 const Eolian_Expression *def_ret = NULL;
341 const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype); 450 const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype);
@@ -357,6 +466,8 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
357 { 466 {
358 Eolian_Function_Parameter *pr = d1; 467 Eolian_Function_Parameter *pr = d1;
359 rtp = eolian_parameter_type_get(pr); 468 rtp = eolian_parameter_type_get(pr);
469 /* reflect only when returning 1 val */
470 reflect_type = rtp;
360 var_as_ret = EINA_TRUE; 471 var_as_ret = EINA_TRUE;
361 def_ret = eolian_parameter_default_value_get(pr); 472 def_ret = eolian_parameter_default_value_get(pr);
362 } 473 }
@@ -364,7 +475,18 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
364 } 475 }
365 } 476 }
366 else if (ftype == EOLIAN_PROP_SET) 477 else if (ftype == EOLIAN_PROP_SET)
367 func_suffix = "_set"; 478 {
479 func_suffix = "_set";
480 Eina_Iterator *itr = eolian_property_values_get(fid, ftype);
481 void *d1, *d2;
482 /* reflect with 1 value */
483 if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2))
484 {
485 Eolian_Function_Parameter *pr = d1;
486 reflect_type = eolian_parameter_type_get(pr);
487 }
488 eina_iterator_free(itr);
489 }
368 490
369 Eina_Strbuf *params = eina_strbuf_new(); /* par1, par2, par3, ... */ 491 Eina_Strbuf *params = eina_strbuf_new(); /* par1, par2, par3, ... */
370 Eina_Strbuf *params_full = eina_strbuf_new(); /* T par1, U par2, ... for decl */ 492 Eina_Strbuf *params_full = eina_strbuf_new(); /* T par1, U par2, ... for decl */
@@ -375,6 +497,8 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
375 /* property keys */ 497 /* property keys */
376 { 498 {
377 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype); 499 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
500 if (itr) /* has keys: no reflection */
501 reflect_type = NULL;
378 Eolian_Function_Parameter *pr; 502 Eolian_Function_Parameter *pr;
379 EINA_ITERATOR_FOREACH(itr, pr) 503 EINA_ITERATOR_FOREACH(itr, pr)
380 { 504 {
@@ -650,6 +774,15 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
650 774
651 if (impl_same_class && !eolian_function_is_class(fid)) 775 if (impl_same_class && !eolian_function_is_class(fid))
652 { 776 {
777 /* generate reflection implementation */
778 if (reflect_type)
779 {
780 if (ftype == EOLIAN_PROP_GET)
781 _gen_reflect_get(buf, cnamel, reflect_type, fid, refh);
782 else
783 _gen_reflect_set(buf, cnamel, reflect_type, fid, refh);
784 }
785
653 void *data; 786 void *data;
654 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype); 787 Eina_Iterator *itr = eolian_property_keys_get(fid, ftype);
655 Eina_Bool has_params = eina_iterator_next(itr, &data); 788 Eina_Bool has_params = eina_iterator_next(itr, &data);
@@ -832,7 +965,33 @@ _gen_opfunc(const Eolian_Function *fid, Eolian_Function_Type ftype,
832} 965}
833 966
834static void 967static void
835_gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf) 968_gen_reflop(const Eolian_Function *fid, Eina_Strbuf *buf, const char *cnamel, Eina_Hash *refh)
969{
970 Eolian_Function_Type aftype = (Eolian_Function_Type)eina_hash_find(refh, &fid);
971 if (aftype == EOLIAN_UNRESOLVED)
972 return;
973
974 eina_strbuf_append_printf(buf, " {\"%s\", ", eolian_function_name_get(fid));
975
976 if (aftype == EOLIAN_PROP_SET || aftype == EOLIAN_PROPERTY)
977 {
978 eina_strbuf_append_printf(buf, "__eolian_%s_%s_set_reflect, ",
979 cnamel, eolian_function_name_get(fid));
980 }
981 else
982 eina_strbuf_append(buf, "NULL, ");
983
984 if (aftype == EOLIAN_PROP_GET || aftype == EOLIAN_PROPERTY)
985 {
986 eina_strbuf_append_printf(buf, "__eolian_%s_%s_get_reflect},\n",
987 cnamel, eolian_function_name_get(fid));
988 }
989 else
990 eina_strbuf_append(buf, "NULL},\n");
991}
992
993static void
994_gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf, Eina_Hash *refh)
836{ 995{
837 char *cnamel = NULL, *cnameu = NULL; 996 char *cnamel = NULL, *cnameu = NULL;
838 eo_gen_class_names_get(cl, NULL, &cnameu, &cnamel); 997 eo_gen_class_names_get(cl, NULL, &cnameu, &cnamel);
@@ -841,8 +1000,10 @@ _gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf)
841 eina_strbuf_append(buf, cnamel); 1000 eina_strbuf_append(buf, cnamel);
842 eina_strbuf_append(buf, "_class_initializer(Efl_Class *klass)\n{\n"); 1001 eina_strbuf_append(buf, "_class_initializer(Efl_Class *klass)\n{\n");
843 eina_strbuf_append(buf, " const Efl_Object_Ops *opsp = NULL;\n\n"); 1002 eina_strbuf_append(buf, " const Efl_Object_Ops *opsp = NULL;\n\n");
1003 eina_strbuf_append(buf, " const Efl_Object_Property_Reflection_Ops *ropsp = NULL;\n\n");
844 1004
845 Eina_Strbuf *ops = eina_strbuf_new(); 1005 Eina_Strbuf *ops = eina_strbuf_new();
1006 Eina_Strbuf *refls = eina_strbuf_new();
846 1007
847 /* start over with clean itearator */ 1008 /* start over with clean itearator */
848 const Eolian_Implement *imp; 1009 const Eolian_Implement *imp;
@@ -855,10 +1016,8 @@ _gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf)
855 1016
856 if (eolian_function_is_class(fid)) continue; 1017 if (eolian_function_is_class(fid)) continue;
857 1018
858 Eina_Strbuf *obuf = ops; 1019 if (!eina_strbuf_length_get(ops))
859 1020 eina_strbuf_append_printf(ops, " EFL_OPS_DEFINE(ops,\n");
860 if (!eina_strbuf_length_get(obuf))
861 eina_strbuf_append_printf(obuf, " EFL_OPS_DEFINE(ops,\n");
862 1021
863 Eina_Bool found_get = !!eina_hash_find(_funcs_params_init_get, &imp); 1022 Eina_Bool found_get = !!eina_hash_find(_funcs_params_init_get, &imp);
864 Eina_Bool found_set = !!eina_hash_find(_funcs_params_init_set, &imp); 1023 Eina_Bool found_set = !!eina_hash_find(_funcs_params_init_set, &imp);
@@ -869,17 +1028,20 @@ _gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf)
869 switch (ftype) 1028 switch (ftype)
870 { 1029 {
871 case EOLIAN_PROP_GET: 1030 case EOLIAN_PROP_GET:
872 _gen_opfunc(fid, EOLIAN_PROP_GET, obuf, imp, found_get, cnamel, ocnamel); 1031 _gen_opfunc(fid, EOLIAN_PROP_GET, ops, imp, found_get, cnamel, ocnamel);
1032 _gen_reflop(fid, refls, cnamel, refh);
873 break; 1033 break;
874 case EOLIAN_PROP_SET: 1034 case EOLIAN_PROP_SET:
875 _gen_opfunc(fid, EOLIAN_PROP_SET, obuf, imp, found_set, cnamel, ocnamel); 1035 _gen_opfunc(fid, EOLIAN_PROP_SET, ops, imp, found_set, cnamel, ocnamel);
1036 _gen_reflop(fid, refls, cnamel, refh);
876 break; 1037 break;
877 case EOLIAN_PROPERTY: 1038 case EOLIAN_PROPERTY:
878 _gen_opfunc(fid, EOLIAN_PROP_SET, obuf, imp, found_set, cnamel, ocnamel); 1039 _gen_opfunc(fid, EOLIAN_PROP_SET, ops, imp, found_set, cnamel, ocnamel);
879 _gen_opfunc(fid, EOLIAN_PROP_GET, obuf, imp, found_get, cnamel, ocnamel); 1040 _gen_opfunc(fid, EOLIAN_PROP_GET, ops, imp, found_get, cnamel, ocnamel);
1041 _gen_reflop(fid, refls, cnamel, refh);
880 break; 1042 break;
881 default: 1043 default:
882 _gen_opfunc(fid, EOLIAN_METHOD, obuf, imp, found_get, cnamel, ocnamel); 1044 _gen_opfunc(fid, EOLIAN_METHOD, ops, imp, found_get, cnamel, ocnamel);
883 break; 1045 break;
884 } 1046 }
885 1047
@@ -907,7 +1069,18 @@ _gen_initializer(const Eolian_Class *cl, Eina_Strbuf *buf)
907 eina_strbuf_append(buf, "#endif\n\n"); 1069 eina_strbuf_append(buf, "#endif\n\n");
908 } 1070 }
909 1071
910 eina_strbuf_append(buf, " return efl_class_functions_set(klass, opsp, NULL);\n"); 1072 if (eina_strbuf_length_get(refls))
1073 {
1074 eina_strbuf_append(buf, " static const Efl_Object_Property_Reflection refl_table[] = {\n");
1075 eina_strbuf_append_buffer(buf, refls);
1076 eina_strbuf_append(buf, " };\n");
1077 eina_strbuf_append(buf, " static const Efl_Object_Property_Reflection_Ops rops = {\n");
1078 eina_strbuf_append(buf, " refl_table, EINA_C_ARRAY_LENGTH(refl_table)\n");
1079 eina_strbuf_append(buf, " };\n");
1080 eina_strbuf_append(buf, " ropsp = &rops;\n\n");
1081 }
1082
1083 eina_strbuf_append(buf, " return efl_class_functions_set(klass, opsp, ropsp);\n");
911 1084
912 eina_strbuf_free(ops); 1085 eina_strbuf_free(ops);
913 1086
@@ -951,6 +1124,11 @@ eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf)
951 1124
952 Eina_Strbuf *lbuf = eina_strbuf_new(); 1125 Eina_Strbuf *lbuf = eina_strbuf_new();
953 1126
1127 /* Eolian_Function -> Eolian_Function_Type
1128 * maps which parts of which functions are qualified for reflection
1129 */
1130 Eina_Hash *refh = eina_hash_pointer_new(NULL);
1131
954 /* method section */ 1132 /* method section */
955 { 1133 {
956 Eina_Iterator *itr = eolian_class_implements_get(cl); 1134 Eina_Iterator *itr = eolian_class_implements_get(cl);
@@ -963,21 +1141,22 @@ eo_gen_source_gen(const Eolian_Class *cl, Eina_Strbuf *buf)
963 { 1141 {
964 case EOLIAN_PROP_GET: 1142 case EOLIAN_PROP_GET:
965 case EOLIAN_PROP_SET: 1143 case EOLIAN_PROP_SET:
966 _gen_func(cl, fid, ftype, buf, imp, lbuf); 1144 _gen_func(cl, fid, ftype, buf, imp, lbuf, refh);
967 break; 1145 break;
968 case EOLIAN_PROPERTY: 1146 case EOLIAN_PROPERTY:
969 _gen_func(cl, fid, EOLIAN_PROP_SET, buf, imp, lbuf); 1147 _gen_func(cl, fid, EOLIAN_PROP_SET, buf, imp, lbuf, refh);
970 _gen_func(cl, fid, EOLIAN_PROP_GET, buf, imp, lbuf); 1148 _gen_func(cl, fid, EOLIAN_PROP_GET, buf, imp, lbuf, refh);
971 break; 1149 break;
972 default: 1150 default:
973 _gen_func(cl, fid, EOLIAN_METHOD, buf, imp, lbuf); 1151 _gen_func(cl, fid, EOLIAN_METHOD, buf, imp, lbuf, refh);
974 } 1152 }
975 } 1153 }
976 eina_iterator_free(itr); 1154 eina_iterator_free(itr);
977 } 1155 }
978 1156
979 /* class initializer - contains method defs */ 1157 /* class initializer - contains method defs */
980 _gen_initializer(cl, buf); 1158 _gen_initializer(cl, buf, refh);
1159 eina_hash_free(refh);
981 1160
982 /* class description */ 1161 /* class description */
983 eina_strbuf_append(buf, "static const Efl_Class_Description _"); 1162 eina_strbuf_append(buf, "static const Efl_Class_Description _");