LCOV - code coverage report
Current view: top level - codegen - valaccodedelegatemodule.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 95.0 % 278 264
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valaccodedelegatemodule.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       6              :  * This library is free software; you can redistribute it and/or
       7              :  * modify it under the terms of the GNU Lesser General Public
       8              :  * License as published by the Free Software Foundation; either
       9              :  * version 2.1 of the License, or (at your option) any later version.
      10              : 
      11              :  * This library is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              : 
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this library; if not, write to the Free Software
      18              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : 
      26              : /**
      27              :  * The link between an assignment and generated code.
      28              :  */
      29         2938 : public class Vala.CCodeDelegateModule : CCodeArrayModule {
      30         3594 :         public override void generate_delegate_declaration (Delegate d, CCodeFile decl_space) {
      31         3318 :                 if (add_symbol_declaration (decl_space, d, get_ccode_name (d))) {
      32              :                         return;
      33              :                 }
      34              : 
      35              :                 // internally generated delegates don't require a typedef
      36          310 :                 if (d.sender_type != null) {
      37              :                         return;
      38              :                 }
      39              : 
      40          276 :                 var creturn_type = get_callable_creturn_type (d);
      41          276 :                 if (creturn_type is DelegateType && ((DelegateType) creturn_type).delegate_symbol == d) {
      42              :                         // recursive delegate
      43            3 :                         creturn_type = new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("Callback"));
      44              :                 }
      45              : 
      46          276 :                 generate_type_declaration (creturn_type, decl_space);
      47              : 
      48          276 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
      49              : 
      50          276 :                 var cfundecl = new CCodeFunctionDeclarator (get_ccode_name (d));
      51          566 :                 foreach (Parameter param in d.get_parameters ()) {
      52          145 :                         generate_parameter (param, decl_space, cparam_map, null);
      53              :                 }
      54              : 
      55              :                 // FIXME partial code duplication with CCodeMethodModule.generate_cparameters
      56              : 
      57          280 :                 if (d.return_type.is_real_non_null_struct_type ()) {
      58              :                         // structs are returned via out parameter
      59            4 :                         var cparam = new CCodeParameter ("result", get_ccode_name (d.return_type) + "*");
      60            4 :                         cparam_map.set (get_param_pos (-3), cparam);
      61          280 :                 } else if (get_ccode_array_length (d) && d.return_type is ArrayType) {
      62              :                         // return array length if appropriate
      63         2059 :                         var array_type = (ArrayType) d.return_type;
      64            8 :                         var length_ctype = get_ccode_array_length_type (d) + "*";
      65              : 
      66           24 :                         for (int dim = 1; dim <= array_type.rank; dim++) {
      67            8 :                                 var cparam = new CCodeParameter (get_array_length_cname ("result", dim), length_ctype);
      68            8 :                                 cparam_map.set (get_param_pos (get_ccode_array_length_pos (d) + 0.01 * dim), cparam);
      69              :                         }
      70          269 :                 } else if (get_ccode_delegate_target (d) && d.return_type is DelegateType) {
      71              :                         // return delegate target if appropriate
      72            5 :                         var deleg_type = (DelegateType) d.return_type;
      73           10 :                         if (deleg_type.delegate_symbol.has_target) {
      74            5 :                                 generate_type_declaration (delegate_target_type, decl_space);
      75            5 :                                 var cparam = new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (delegate_target_type) + "*");
      76            5 :                                 cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (d)), cparam);
      77            5 :                                 if (deleg_type.is_disposable ()) {
      78            5 :                                         generate_type_declaration (delegate_target_destroy_type, decl_space);
      79            5 :                                         cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), get_ccode_name (delegate_target_destroy_type) + "*");
      80            5 :                                         cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (d)), cparam);
      81              :                                 }
      82              :                         }
      83              :                 }
      84              : 
      85          473 :                 if (d.has_target) {
      86          197 :                         generate_type_declaration (delegate_target_type, decl_space);
      87          197 :                         var cparam = new CCodeParameter ("user_data", get_ccode_name (delegate_target_type));
      88          197 :                         cparam_map.set (get_param_pos (get_ccode_instance_pos (d)), cparam);
      89              :                 }
      90          289 :                 if (d.tree_can_fail) {
      91           13 :                         generate_type_declaration (gerror_type, decl_space);
      92           13 :                         var cparam = new CCodeParameter ("error", "GError**");
      93           13 :                         cparam_map.set (get_param_pos (get_ccode_error_pos (d)), cparam);
      94              :                 }
      95              : 
      96              :                 // append C parameters in the right order
      97              :                 int last_pos = -1;
      98              :                 int min_pos;
      99          680 :                 while (true) {
     100          680 :                         min_pos = -1;
     101         2698 :                         foreach (int pos in cparam_map.get_keys ()) {
     102         1338 :                                 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
     103          582 :                                         min_pos = pos;
     104              :                                 }
     105              :                         }
     106          680 :                         if (min_pos == -1) {
     107              :                                 break;
     108              :                         }
     109          404 :                         cfundecl.add_parameter (cparam_map.get (min_pos));
     110              :                         last_pos = min_pos;
     111              :                 }
     112              : 
     113          276 :                 var ctypedef = new CCodeTypeDefinition (get_ccode_name (creturn_type), cfundecl);
     114              : 
     115          276 :                 if (d.version.deprecated) {
     116            4 :                         if (context.profile == Profile.GOBJECT) {
     117            4 :                                 decl_space.add_include ("glib.h");
     118              :                         }
     119            4 :                         ctypedef.modifiers |= CCodeModifiers.DEPRECATED;
     120              :                 }
     121              : 
     122          276 :                 decl_space.add_type_declaration (ctypedef);
     123              :         }
     124              : 
     125          128 :         public override void visit_delegate (Delegate d) {
     126          128 :                 generate_delegate_declaration (d, cfile);
     127              : 
     128          128 :                 if (!d.is_internal_symbol ()) {
     129           29 :                         generate_delegate_declaration (d, header_file);
     130              :                 }
     131          128 :                 if (!d.is_private_symbol ()) {
     132          126 :                         generate_delegate_declaration (d, internal_header_file);
     133              :                 }
     134              : 
     135          128 :                 d.accept_children (this);
     136              :         }
     137              : 
     138          738 :         public override string get_delegate_target_cname (string delegate_cname) {
     139          738 :                 return "%s_target".printf (delegate_cname);
     140              :         }
     141              : 
     142          704 :         public override CCodeExpression get_delegate_target_cexpression (Expression delegate_expr, out CCodeExpression delegate_target_destroy_notify) {
     143          704 :                 delegate_target_destroy_notify = get_delegate_target_destroy_notify_cvalue (delegate_expr.target_value);
     144          704 :                 return get_delegate_target_cvalue (delegate_expr.target_value);
     145              :         }
     146              : 
     147         1396 :         public override CCodeExpression get_delegate_target_cvalue (TargetValue value) {
     148         2861 :                 return ((GLibValue) value).delegate_target_cvalue;
     149              :         }
     150              : 
     151         1354 :         public override CCodeExpression get_delegate_target_destroy_notify_cvalue (TargetValue value) {
     152         1354 :                 return ((GLibValue) value).delegate_target_destroy_notify_cvalue;
     153              :         }
     154              : 
     155          443 :         public override string get_delegate_target_destroy_notify_cname (string delegate_cname) {
     156          443 :                 return "%s_target_destroy_notify".printf (delegate_cname);
     157              :         }
     158              : 
     159        89700 :         public override CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, CodeNode? node) {
     160        89712 :                 if (target_type is DelegateType && expression_type is MethodType) {
     161          541 :                         var dt = (DelegateType) target_type;
     162          541 :                         var mt = (MethodType) expression_type;
     163              : 
     164          541 :                         var method = mt.method_symbol;
     165          541 :                         if (method.base_method != null) {
     166            0 :                                 method = method.base_method;
     167          541 :                         } else if (method.base_interface_method != null) {
     168            4 :                                 method = method.base_interface_method;
     169              :                         }
     170              : 
     171          541 :                         if (method.is_variadic ()) {
     172           12 :                                 Report.warning (node.source_reference, "internal: Variadic method requires a direct cast to delegate");
     173              :                         } else {
     174          529 :                                 return new CCodeIdentifier (generate_delegate_wrapper (method, dt, node));
     175              :                         }
     176              :                 }
     177              : 
     178        89171 :                 return base.get_implicit_cast_expression (source_cexpr, expression_type, target_type, node);
     179              :         }
     180              : 
     181          531 :         public string generate_delegate_wrapper (Method m, DelegateType dt, CodeNode? node) {
     182          531 :                 var d = dt.delegate_symbol;
     183              :                 string delegate_name;
     184          531 :                 var sig = d.parent_symbol as Signal;
     185          531 :                 var dynamic_sig = sig as DynamicSignal;
     186          531 :                 if (dynamic_sig != null) {
     187            6 :                         delegate_name = get_dynamic_signal_cname (dynamic_sig);
     188          525 :                 } else if (sig != null) {
     189           77 :                         delegate_name = get_ccode_lower_case_prefix (sig.parent_symbol) + get_ccode_lower_case_name (sig);
     190              :                 } else {
     191          448 :                         delegate_name = Symbol.camel_case_to_lower_case (get_ccode_name (d));
     192              :                 }
     193              : 
     194          531 :                 string wrapper_name = "_%s_%s".printf (get_ccode_name (m), delegate_name);
     195              : 
     196          531 :                 if (!add_wrapper (wrapper_name)) {
     197              :                         // wrapper already defined
     198           62 :                         return wrapper_name;
     199              :                 }
     200              : 
     201              :                 // declaration
     202          469 :                 var creturn_type = get_callable_creturn_type (d);
     203              : 
     204          469 :                 var function = new CCodeFunction (wrapper_name, get_ccode_name (creturn_type));
     205          469 :                 function.modifiers = CCodeModifiers.STATIC;
     206              : 
     207          469 :                 push_function (function);
     208              : 
     209          469 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     210              : 
     211          919 :                 if (d.has_target) {
     212          450 :                         var cparam = new CCodeParameter ("self", get_ccode_name (delegate_target_type));
     213          450 :                         cparam_map.set (get_param_pos (get_ccode_instance_pos (d)), cparam);
     214              :                 }
     215              : 
     216          549 :                 if (d.sender_type != null) {
     217           80 :                         var param = new Parameter ("_sender", d.sender_type);
     218           80 :                         generate_parameter (param, cfile, cparam_map, null);
     219              :                 }
     220              : 
     221          469 :                 var d_params = d.get_parameters ();
     222         1091 :                 foreach (Parameter param in d_params) {
     223          311 :                         if (dynamic_sig != null
     224            4 :                             && param.variable_type is ArrayType
     225            0 :                             && ((ArrayType) param.variable_type).element_type.type_symbol == string_type.type_symbol) {
     226              :                                 // use null-terminated string arrays for dynamic signals for compatibility reasons
     227            0 :                                 param.set_attribute_bool ("CCode", "array_length", false);
     228            0 :                                 param.set_attribute_bool ("CCode", "array_null_terminated", true);
     229              :                         }
     230              : 
     231          311 :                         generate_parameter (param, cfile, cparam_map, null);
     232              :                 }
     233          472 :                 if (get_ccode_array_length (d) && d.return_type is ArrayType) {
     234              :                         // return array length if appropriate
     235            3 :                         var array_type = (ArrayType) d.return_type;
     236            3 :                         var length_ctype = get_ccode_array_length_type (d) + "*";
     237              : 
     238            9 :                         for (int dim = 1; dim <= array_type.rank; dim++) {
     239            3 :                                 var cparam = new CCodeParameter (get_array_length_cname ("result", dim), length_ctype);
     240            3 :                                 cparam_map.set (get_param_pos (get_ccode_array_length_pos (d) + 0.01 * dim), cparam);
     241              :                         }
     242          467 :                 } else if (d.return_type is DelegateType) {
     243              :                         // return delegate target if appropriate
     244            1 :                         var deleg_type = (DelegateType) d.return_type;
     245              : 
     246            2 :                         if (get_ccode_delegate_target (d) && deleg_type.delegate_symbol.has_target) {
     247            1 :                                 var cparam = new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (delegate_target_type) + "*");
     248            1 :                                 cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (d)), cparam);
     249            1 :                                 if (deleg_type.is_disposable ()) {
     250            1 :                                         cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), get_ccode_name (delegate_target_destroy_type) + "*");
     251            1 :                                         cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (d)), cparam);
     252              :                                 }
     253              :                         }
     254          468 :                 } else if (d.return_type.is_real_non_null_struct_type ()) {
     255            3 :                         var cparam = new CCodeParameter ("result", "%s*".printf (get_ccode_name (d.return_type)));
     256            3 :                         cparam_map.set (get_param_pos (-3), cparam);
     257              :                 }
     258              : 
     259          608 :                 if (m.tree_can_fail) {
     260          139 :                         var cparam = new CCodeParameter ("error", "GError**");
     261          139 :                         cparam_map.set (get_param_pos (get_ccode_error_pos (d)), cparam);
     262              :                 }
     263              : 
     264              :                 // append C parameters in the right order
     265              :                 int last_pos = -1;
     266              :                 int min_pos;
     267         1469 :                 while (true) {
     268         1469 :                         min_pos = -1;
     269         6528 :                         foreach (int pos in cparam_map.get_keys ()) {
     270         3590 :                                 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
     271         1619 :                                         min_pos = pos;
     272              :                                 }
     273              :                         }
     274         1469 :                         if (min_pos == -1) {
     275              :                                 break;
     276              :                         }
     277         1000 :                         function.add_parameter (cparam_map.get (min_pos));
     278              :                         last_pos = min_pos;
     279              :                 }
     280              : 
     281              : 
     282              :                 // definition
     283              : 
     284          469 :                 var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
     285              : 
     286          469 :                 int i = 0;
     287          786 :                 if (m.binding == MemberBinding.INSTANCE || m.closure) {
     288              :                         CCodeExpression arg;
     289          317 :                         if (d.has_target) {
     290          315 :                                 arg = new CCodeIdentifier ("self");
     291          315 :                                 if (!m.closure && m.this_parameter != null) {
     292          206 :                                         arg = convert_from_generic_pointer (arg, m.this_parameter.variable_type);
     293              :                                 }
     294              :                         } else {
     295              :                                 // use first delegate parameter as instance
     296            2 :                                 if (d_params.size == 0 || m.closure) {
     297            0 :                                         Report.error (node != null ? node.source_reference : null, "internal: Cannot create delegate wrapper");
     298            0 :                                         arg = new CCodeInvalidExpression ();
     299              :                                 } else {
     300            2 :                                         arg = new CCodeIdentifier (get_ccode_name (d_params.get (0)));
     301              :                                         i = 1;
     302              :                                 }
     303              :                         }
     304          317 :                         carg_map.set (get_param_pos (get_ccode_instance_pos (m)), arg);
     305              :                 }
     306              : 
     307          469 :                 bool first = true;
     308              : 
     309         1045 :                 foreach (Parameter param in m.get_parameters ()) {
     310          294 :                         if (first && d.sender_type != null && m.get_parameters ().size == d.get_parameters ().size + 1) {
     311              :                                 // sender parameter
     312           12 :                                 carg_map.set (get_param_pos (get_ccode_pos (param)), new CCodeIdentifier ("_sender"));
     313              : 
     314           12 :                                 first = false;
     315           12 :                                 continue;
     316              :                         }
     317              : 
     318          282 :                         var d_param = d_params.get (i);
     319              :                         CCodeExpression arg;
     320          282 :                         arg = new CCodeIdentifier (get_ccode_name (d_param));
     321          282 :                         if (d_param.variable_type is GenericType) {
     322           20 :                                 arg = convert_from_generic_pointer (arg, param.variable_type);
     323              :                         }
     324          282 :                         carg_map.set (get_param_pos (get_ccode_pos (param)), arg);
     325              : 
     326              :                         // handle array arguments
     327          287 :                         if (get_ccode_array_length (param) && param.variable_type is ArrayType) {
     328           10 :                                 var array_type = (ArrayType) param.variable_type;
     329           19 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     330              :                                         CCodeExpression clength;
     331            7 :                                         if (get_ccode_array_null_terminated (d_param) && !get_ccode_array_length (d_param)) {
     332            1 :                                                 requires_array_length = true;
     333            1 :                                                 var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
     334            1 :                                                 len_call.add_argument (new CCodeIdentifier (d_param.name));
     335            2 :                                                 clength = len_call;
     336            6 :                                         } else if (!get_ccode_array_length (d_param)) {
     337            0 :                                                 clength = new CCodeConstant ("-1");
     338              :                                         } else {
     339            6 :                                                 clength = new CCodeIdentifier (get_variable_array_length_cname (d_param, dim));
     340              :                                         }
     341            7 :                                         carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), clength);
     342              :                                 }
     343          280 :                         } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) {
     344            3 :                                 var deleg_type = (DelegateType) param.variable_type;
     345              : 
     346            6 :                                 if (deleg_type.delegate_symbol.has_target) {
     347            3 :                                         var ctarget = new CCodeIdentifier (get_ccode_delegate_target_name (d_param));
     348            3 :                                         carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), ctarget);
     349            5 :                                         if (deleg_type.is_disposable ()) {
     350            2 :                                                 var ctarget_destroy_notify = new CCodeIdentifier (get_ccode_delegate_target_destroy_notify_name (d_param));
     351            2 :                                                 carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), ctarget_destroy_notify);
     352              :                                         }
     353              :                                 }
     354              :                         }
     355              : 
     356          282 :                         i++;
     357              :                 }
     358          473 :                 if (get_ccode_array_length (m) && m.return_type is ArrayType) {
     359            8 :                         var array_type = (ArrayType) m.return_type;
     360           12 :                         for (int dim = 1; dim <= array_type.rank; dim++) {
     361              :                                 CCodeExpression clength;
     362            4 :                                 if (!get_ccode_array_length (d)) {
     363            1 :                                         clength = new CCodeConstant ("NULL");
     364              :                                 } else {
     365            3 :                                         clength = new CCodeIdentifier (get_array_length_cname ("result", dim));
     366              :                                 }
     367            4 :                                 carg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), clength);
     368              :                         }
     369          466 :                 } else if (get_ccode_delegate_target (m) && m.return_type is DelegateType) {
     370            1 :                         var deleg_type = (DelegateType) m.return_type;
     371              : 
     372            2 :                         if (deleg_type.delegate_symbol.has_target) {
     373            1 :                                 var ctarget = new CCodeIdentifier (get_delegate_target_cname ("result"));
     374            1 :                                 carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), ctarget);
     375            2 :                                 if (deleg_type.is_disposable ()) {
     376            1 :                                         var ctarget_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname ("result"));
     377            1 :                                         carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), ctarget_destroy_notify);
     378              :                                 }
     379              :                         }
     380          464 :                 } else if (m.return_type.is_real_non_null_struct_type ()) {
     381            3 :                         carg_map.set (get_param_pos (-3), new CCodeIdentifier ("result"));
     382              :                 }
     383              : 
     384          469 :                 if (m.tree_can_fail) {
     385          139 :                         carg_map.set (get_param_pos (get_ccode_error_pos (m)), new CCodeIdentifier ("error"));
     386              :                 }
     387              : 
     388          469 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
     389              : 
     390              :                 // append C arguments in the right order
     391          469 :                 last_pos = -1;
     392         1240 :                 while (true) {
     393         1240 :                         min_pos = -1;
     394         4976 :                         foreach (int pos in carg_map.get_keys ()) {
     395         2496 :                                 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
     396         1089 :                                         min_pos = pos;
     397              :                                 }
     398              :                         }
     399         1240 :                         if (min_pos == -1) {
     400              :                                 break;
     401              :                         }
     402          771 :                         ccall.add_argument (carg_map.get (min_pos));
     403              :                         last_pos = min_pos;
     404              :                 }
     405              : 
     406          469 :                 if (m.coroutine) {
     407            1 :                         ccall.add_argument (new CCodeConstant ("NULL"));
     408            1 :                         ccall.add_argument (new CCodeConstant ("NULL"));
     409              :                 }
     410              : 
     411          579 :                 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
     412          359 :                         ccode.add_expression (ccall);
     413          359 :                         if (!(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type ())) {
     414              :                                 // return a default value
     415            0 :                                 ccode.add_declaration (get_ccode_name (creturn_type), new CCodeVariableDeclarator ("result", default_value_for_type (d.return_type, true)));
     416              :                         }
     417              :                 } else {
     418          110 :                         CCodeExpression result = ccall;
     419          110 :                         if (d.return_type is GenericType) {
     420            8 :                                 result = convert_to_generic_pointer (result, m.return_type);
     421              :                         }
     422          110 :                         ccode.add_declaration (get_ccode_name (creturn_type), new CCodeVariableDeclarator ("result", result));
     423              :                 }
     424              : 
     425          485 :                 if (d.has_target /* TODO: && dt.value_owned */ && dt.is_called_once) {
     426              :                         // destroy notify "self" after the call
     427           26 :                         CCodeExpression? destroy_notify = null;
     428           26 :                         if (m.closure) {
     429           16 :                                 int block_id = get_block_id (current_closure_block);
     430           16 :                                 destroy_notify = new CCodeIdentifier ("block%d_data_unref".printf (block_id));
     431           10 :                         } else if (get_this_type () != null && m.binding != MemberBinding.STATIC && !m.is_async_callback && is_reference_counting (m.this_parameter.variable_type.type_symbol)) {
     432            0 :                                 destroy_notify = get_destroy_func_expression (m.this_parameter.variable_type);
     433              :                         }
     434              : 
     435           32 :                         if (destroy_notify != null) {
     436           16 :                                 var unref_call = new CCodeFunctionCall (destroy_notify);
     437           16 :                                 unref_call.add_argument (new CCodeIdentifier ("self"));
     438           16 :                                 ccode.add_expression (unref_call);
     439              :                         }
     440              :                 }
     441              : 
     442          469 :                 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) ||
     443          359 :                         !(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type ())) {
     444          110 :                         ccode.add_return (new CCodeIdentifier ("result"));
     445              :                 }
     446              : 
     447          469 :                 pop_function ();
     448              : 
     449              :                 // append to file
     450          469 :                 cfile.add_function_declaration (function);
     451          469 :                 cfile.add_function (function);
     452              : 
     453          469 :                 return wrapper_name;
     454              :         }
     455              : 
     456         4145 :         public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
     457         4145 :                 if (!(param.variable_type is DelegateType || param.variable_type is MethodType)) {
     458         3820 :                         return base.generate_parameter (param, decl_space, cparam_map, carg_map);
     459              :                 }
     460              : 
     461          325 :                 var param_type = param.variable_type;
     462          325 :                 if (param_type is DelegateType && ((DelegateType) param_type).delegate_symbol == param.parent_symbol) {
     463              :                         // recursive delegate
     464            3 :                         param_type = new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("Callback"));
     465              :                 }
     466              : 
     467          325 :                 generate_type_declaration (param_type, decl_space);
     468              : 
     469          325 :                 string ctypename = get_ccode_name (param_type);
     470          325 :                 string target_ctypename = get_ccode_name (delegate_target_type);
     471          325 :                 string target_destroy_notify_ctypename = get_ccode_name (delegate_target_destroy_type);
     472              : 
     473          325 :                 if (param.direction != ParameterDirection.IN) {
     474            9 :                         ctypename += "*";
     475            9 :                         target_ctypename += "*";
     476            9 :                         target_destroy_notify_ctypename += "*";
     477              :                 }
     478              : 
     479          325 :                 var main_cparam = new CCodeParameter (get_ccode_name (param), ctypename);
     480              : 
     481          325 :                 cparam_map.set (get_param_pos (get_ccode_pos (param)), main_cparam);
     482          325 :                 if (carg_map != null) {
     483          165 :                         carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param));
     484              :                 }
     485              : 
     486          325 :                 if (param_type is DelegateType) {
     487          325 :                         unowned DelegateType deleg_type = (DelegateType) param_type;
     488          571 :                         if (get_ccode_delegate_target (param) && deleg_type.delegate_symbol.has_target) {
     489          246 :                                 var cparam = new CCodeParameter (get_ccode_delegate_target_name (param), target_ctypename);
     490          246 :                                 cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), cparam);
     491          246 :                                 if (carg_map != null) {
     492          132 :                                         carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_cexpression (cparam.name));
     493              :                                 }
     494          246 :                                 if (deleg_type.is_disposable ()) {
     495          119 :                                         cparam = new CCodeParameter (get_ccode_delegate_target_destroy_notify_name (param), target_destroy_notify_ctypename);
     496          119 :                                         cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), cparam);
     497          119 :                                         if (carg_map != null) {
     498           60 :                                                 carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), get_cexpression (cparam.name));
     499              :                                         }
     500              :                                 }
     501              :                         }
     502            0 :                 } else if (param_type is MethodType) {
     503            0 :                         var cparam = new CCodeParameter (get_ccode_delegate_target_name (param), target_ctypename);
     504            0 :                         cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), cparam);
     505            0 :                         if (carg_map != null) {
     506            0 :                                 carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_cexpression (cparam.name));
     507              :                         }
     508              :                 }
     509              : 
     510          325 :                 return main_cparam;
     511              :         }
     512              : }
        

Generated by: LCOV version 2.0-1