3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
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.
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.
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
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
29 * Represents a type or namespace method.
31 public class Vala
.Method
: Member
{
32 Gee
.List
<TypeParameter
> type_parameters
= new ArrayList
<TypeParameter
> ();
34 public const string DEFAULT_SENTINEL
= "NULL";
37 * The return type of this method.
39 public DataType return_type
{
40 get { return _return_type
; }
43 _return_type
.parent_node
= this
;
57 public BasicBlock entry_block
{ get; set; }
59 public BasicBlock exit_block
{ get; set; }
62 * Specifies whether this method may only be called with an instance of
65 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
68 * The name of the vfunc of this method as it is used in C code.
70 public string vfunc_name
{
72 if (_vfunc_name
== null) {
73 _vfunc_name
= this
.name
;
83 * The sentinel to use for terminating variable length argument lists.
85 public string sentinel
{
87 if (_sentinel
== null) {
88 return DEFAULT_SENTINEL
;
100 * Specifies whether this method is abstract. Abstract methods have no
101 * body, may only be specified within abstract classes, and must be
102 * overriden by derived non-abstract classes.
104 public bool is_abstract
{ get; set; }
107 * Specifies whether this method is virtual. Virtual methods may be
108 * overridden by derived classes.
110 public bool is_virtual
{ get; set; }
113 * Specifies whether this method overrides a virtual or abstract method
116 public bool overrides
{ get; set; }
119 * Specifies whether this method should be inlined.
121 public bool is_inline
{ get; set; }
124 * Specifies whether the C method returns a new instance pointer which
125 * may be different from the previous instance pointer. Only valid for
128 public bool returns_modified_pointer
{ get; set; }
131 * Specifies the virtual or abstract method this method overrides.
132 * Reference must be weak as virtual and abstract methods set
133 * base_method to themselves.
135 public Method base_method
{
137 find_base_methods ();
143 * Specifies the abstract interface method this method implements.
145 public Method base_interface_method
{
147 find_base_methods ();
148 return _base_interface_method
;
152 public bool entry_point
{ get; private set; }
155 * Specifies the generated `this' parameter for instance methods.
157 public FormalParameter this_parameter
{ get; set; }
160 * Specifies the generated `result' variable for postconditions.
162 public LocalVariable result_var
{ get; set; }
165 * Specifies the position of the instance parameter in the C function.
167 public double cinstance_parameter_position
{ get; set; }
170 * Specifies the position of the array length out parameter in the C
173 public double carray_length_parameter_position
{ get; set; }
176 * Specifies the position of the delegate target out parameter in the C
179 public double cdelegate_target_parameter_position
{ get; set; }
182 * Specifies whether the array length should be returned implicitly
183 * if the return type is an array.
185 public bool no_array_length
{ get; set; }
188 * Specifies whether the array is null terminated.
190 public bool array_null_terminated
{ get; set; }
193 * Specified a custom type for the array length parameter.
195 public string? array_length_type
{ get; set; default = null; }
198 * Specifies whether this method expects printf-style format arguments.
200 public bool printf_format
{ get; set; }
203 * Specifies whether this method expects scanf-style format arguments.
205 public bool scanf_format
{ get; set; }
208 * Specifies whether a new function without a GType parameter is
209 * available. This is only applicable to creation methods.
211 public bool has_new_function
{ get; set; default = true; }
214 * Specifies whether a construct function with a GType parameter is
215 * available. This is only applicable to creation methods.
217 public bool has_construct_function
{ get; set; default = true; }
219 public bool has_generic_type_parameter
{ get; set; }
221 public double generic_type_parameter_position
{ get; set; }
223 public weak Signal signal_reference
{ get; set; }
225 public bool closure
{ get; set; }
227 public bool coroutine
{ get; set; }
229 public bool is_async_callback
{ get; set; }
231 private Gee
.List
<FormalParameter
> parameters
= new ArrayList
<FormalParameter
> ();
232 private string cname
;
233 private string _vfunc_name
;
234 private string _sentinel
;
235 private Gee
.List
<Expression
> preconditions
= new ArrayList
<Expression
> ();
236 private Gee
.List
<Expression
> postconditions
= new ArrayList
<Expression
> ();
237 private DataType _return_type
;
240 private weak Method _base_method
;
241 private Method _base_interface_method
;
242 private bool base_methods_valid
;
244 Method? callback_method
;
246 // only valid for closures
247 Gee
.List
<LocalVariable
> captured_variables
;
250 * Creates a new method.
252 * @param name method name
253 * @param return_type method return type
254 * @param source reference to source code
255 * @return newly created method
257 public Method (string? name
, DataType return_type
, SourceReference? source_reference
= null, Comment? comment
= null) {
258 base (name
, source_reference
, comment
);
259 this
.return_type
= return_type
;
261 carray_length_parameter_position
= -3;
262 cdelegate_target_parameter_position
= -3;
266 * Appends parameter to this method.
268 * @param param a formal parameter
270 public void add_parameter (FormalParameter param
) {
271 // default C parameter position
272 param
.cparameter_position
= parameters
.size
+ 1;
273 param
.carray_length_parameter_position
= param
.cparameter_position
+ 0.1;
274 param
.cdelegate_target_parameter_position
= param
.cparameter_position
+ 0.1;
276 parameters
.add (param
);
277 if (!param
.ellipsis
) {
278 scope
.add (param
.name
, param
);
282 public Gee
.List
<FormalParameter
> get_parameters () {
283 return new ReadOnlyList
<FormalParameter
> (parameters
);
287 * Remove all parameters from this method.
289 public void clear_parameters () {
290 foreach (FormalParameter param
in parameters
) {
291 if (!param
.ellipsis
) {
292 scope
.remove (param
.name
);
298 public override void accept (CodeVisitor visitor
) {
299 visitor
.visit_method (this
);
302 public override void accept_children (CodeVisitor visitor
) {
303 if (return_type
!= null) {
304 return_type
.accept (visitor
);
307 foreach (FormalParameter param
in parameters
) {
308 param
.accept (visitor
);
311 foreach (DataType error_type
in get_error_types ()) {
312 error_type
.accept (visitor
);
315 if (result_var
!= null) {
316 result_var
.accept (visitor
);
319 foreach (Expression precondition
in preconditions
) {
320 precondition
.accept (visitor
);
323 foreach (Expression postcondition
in postconditions
) {
324 postcondition
.accept (visitor
);
328 body
.accept (visitor
);
333 * Returns the interface name of this method as it is used in C code.
335 * @return the name to be used in C code
337 public string get_cname () {
339 cname
= get_default_cname ();
344 public string get_finish_cname () {
346 string result
= get_cname ();
347 if (result
.has_suffix ("_async")) {
348 result
= result
.substring (0, result
.length
- "_async".length
);
355 * Returns the default interface name of this method as it is used in C
358 * @return the name to be used in C code by default
360 public virtual string get_default_cname () {
361 if (name
== "main" && parent_symbol
.name
== null) {
362 // avoid conflict with generated main function
364 } else if (name
.has_prefix ("_")) {
365 return "_%s%s".printf (parent_symbol
.get_lower_case_cprefix (), name
.offset (1));
367 return "%s%s".printf (parent_symbol
.get_lower_case_cprefix (), name
);
372 * Returns the implementation name of this data type as it is used in C
375 * @return the name to be used in C code
377 public virtual string get_real_cname () {
378 if (base_method
!= null || base_interface_method
!= null) {
379 return "%sreal_%s".printf (parent_symbol
.get_lower_case_cprefix (), name
);
385 public string get_finish_real_cname () {
387 string result
= get_real_cname ();
388 if (result
.has_suffix ("_async")) {
389 result
= result
.substring (0, result
.length
- "_async".length
);
395 public string get_finish_vfunc_name () {
397 string result
= vfunc_name
;
398 if (result
.has_suffix ("_async")) {
399 result
= result
.substring (0, result
.length
- "_async".length
);
406 * Sets the name of this method as it is used in C code.
408 * @param cname the name to be used in C code
410 public void set_cname (string cname
) {
414 private void process_ccode_attribute (Attribute a
) {
415 if (a
.has_argument ("cname")) {
416 set_cname (a
.get_string ("cname"));
418 if (a
.has_argument ("cheader_filename")) {
419 var val
= a
.get_string ("cheader_filename");
420 foreach (string filename
in val
.split (",")) {
421 add_cheader_filename (filename
);
424 if (a
.has_argument ("vfunc_name")) {
425 this
.vfunc_name
= a
.get_string ("vfunc_name");
427 if (a
.has_argument ("sentinel")) {
428 this
.sentinel
= a
.get_string ("sentinel");
430 if (a
.has_argument ("instance_pos")) {
431 cinstance_parameter_position
= a
.get_double ("instance_pos");
433 if (a
.has_argument ("array_length")) {
434 no_array_length
= !a
.get_bool ("array_length");
436 if (a
.has_argument ("array_length_type")) {
437 array_length_type
= a
.get_string ("array_length_type");
439 if (a
.has_argument ("array_null_terminated")) {
440 array_null_terminated
= a
.get_bool ("array_null_terminated");
442 if (a
.has_argument ("array_length_pos")) {
443 carray_length_parameter_position
= a
.get_double ("array_length_pos");
445 if (a
.has_argument ("delegate_target_pos")) {
446 cdelegate_target_parameter_position
= a
.get_double ("delegate_target_pos");
448 if (a
.has_argument ("has_new_function")) {
449 has_new_function
= a
.get_bool ("has_new_function");
451 if (a
.has_argument ("has_construct_function")) {
452 has_construct_function
= a
.get_bool ("has_construct_function");
454 if (a
.has_argument ("generic_type_pos")) {
455 has_generic_type_parameter
= true;
456 generic_type_parameter_position
= a
.get_double ("generic_type_pos");
461 * Process all associated attributes.
463 public void process_attributes () {
464 foreach (Attribute a
in attributes
) {
465 if (a
.name
== "CCode") {
466 process_ccode_attribute (a
);
467 } else if (a
.name
== "ReturnsModifiedPointer") {
468 returns_modified_pointer
= true;
469 } else if (a
.name
== "FloatingReference") {
470 return_type
.floating_reference
= true;
471 } else if (a
.name
== "PrintfFormat") {
472 printf_format
= true;
473 } else if (a
.name
== "ScanfFormat") {
480 * Checks whether the parameters and return type of this method are
481 * compatible with the specified method
483 * @param base_method a method
484 * @param invalid_match error string about which check failed
485 * @return true if the specified method is compatible to this method
487 public bool compatible (Method base_method
, out string? invalid_match
) {
488 if (binding
!= base_method
.binding
) {
489 invalid_match
= "incompatible binding";
493 ObjectType object_type
= null;
494 if (parent_symbol is ObjectTypeSymbol
) {
495 object_type
= new
ObjectType ((ObjectTypeSymbol
) parent_symbol
);
496 foreach (TypeParameter type_parameter
in object_type
.type_symbol
.get_type_parameters ()) {
497 var type_arg
= new
GenericType (type_parameter
);
498 type_arg
.value_owned
= true;
499 object_type
.add_type_argument (type_arg
);
503 var actual_base_type
= base_method
.return_type
.get_actual_type (object_type
, null, this
);
504 if (!return_type
.equals (actual_base_type
)) {
505 invalid_match
= "incompatible return type";
509 Iterator
<FormalParameter
> method_params_it
= parameters
.iterator ();
511 foreach (FormalParameter base_param
in base_method
.parameters
) {
512 /* this method may not expect less arguments */
513 if (!method_params_it
.next ()) {
514 invalid_match
= "too few parameters";
518 actual_base_type
= base_param
.parameter_type
.get_actual_type (object_type
, null, this
);
519 if (!actual_base_type
.equals (method_params_it
.get ().parameter_type
)) {
520 invalid_match
= "incompatible type of parameter %d".printf (param_index
);
526 /* this method may not expect more arguments */
527 if (method_params_it
.next ()) {
528 invalid_match
= "too many parameters";
532 /* this method may throw less but not more errors than the base method */
533 foreach (DataType method_error_type
in get_error_types ()) {
535 foreach (DataType base_method_error_type
in base_method
.get_error_types ()) {
536 if (method_error_type
.compatible (base_method_error_type
)) {
543 invalid_match
= "incompatible error type `%s'".printf (method_error_type
.to_string ());
552 * Appends the specified parameter to the list of type parameters.
554 * @param p a type parameter
556 public void add_type_parameter (TypeParameter p
) {
557 type_parameters
.add (p
);
558 scope
.add (p
.name
, p
);
562 * Returns a copy of the type parameter list.
564 * @return list of type parameters
566 public Gee
.List
<TypeParameter
> get_type_parameters () {
567 return new ReadOnlyList
<TypeParameter
> (type_parameters
);
570 public int get_type_parameter_index (string name
) {
572 foreach (TypeParameter parameter
in type_parameters
) {
573 if (parameter
.name
== name
) {
582 * Adds a precondition to this method.
584 * @param precondition a boolean precondition expression
586 public void add_precondition (Expression precondition
) {
587 preconditions
.add (precondition
);
588 precondition
.parent_node
= this
;
592 * Returns a copy of the list of preconditions of this method.
594 * @return list of preconditions
596 public Gee
.List
<Expression
> get_preconditions () {
597 return new ReadOnlyList
<Expression
> (preconditions
);
601 * Adds a postcondition to this method.
603 * @param postcondition a boolean postcondition expression
605 public void add_postcondition (Expression postcondition
) {
606 postconditions
.add (postcondition
);
607 postcondition
.parent_node
= this
;
611 * Returns a copy of the list of postconditions of this method.
613 * @return list of postconditions
615 public Gee
.List
<Expression
> get_postconditions () {
616 return new ReadOnlyList
<Expression
> (postconditions
);
619 public override void replace_type (DataType old_type
, DataType new_type
) {
620 if (return_type
== old_type
) {
621 return_type
= new_type
;
624 var error_types
= get_error_types ();
625 for (int i
= 0; i
< error_types
.size
; i
++) {
626 if (error_types
[i
] == old_type
) {
627 error_types
[i
] = new_type
;
633 private void find_base_methods () {
634 if (base_methods_valid
) {
638 if (parent_symbol is Class
) {
639 if (!(this is CreationMethod
)) {
640 find_base_interface_method ((Class
) parent_symbol
);
641 if (is_virtual
|| is_abstract
|| overrides
) {
642 find_base_class_method ((Class
) parent_symbol
);
645 } else if (parent_symbol is Interface
) {
646 if (is_virtual
|| is_abstract
) {
647 _base_interface_method
= this
;
651 base_methods_valid
= true;
654 private void find_base_class_method (Class cl
) {
655 var sym
= cl
.scope
.lookup (name
);
657 var base_method
= (Method
) sym
;
658 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
659 string invalid_match
;
660 if (!compatible (base_method
, out invalid_match
)) {
662 Report
.error (source_reference
, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method
.get_full_name (), invalid_match
));
666 _base_method
= base_method
;
669 } else if (sym is Signal
) {
670 var sig
= (Signal
) sym
;
671 if (sig
.is_virtual
) {
672 var base_method
= sig
.default_handler
;
673 string invalid_match
;
674 if (!compatible (base_method
, out invalid_match
)) {
676 Report
.error (source_reference
, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method
.get_full_name (), invalid_match
));
680 _base_method
= base_method
;
685 if (cl
.base_class
!= null) {
686 find_base_class_method (cl
.base_class
);
690 private void find_base_interface_method (Class cl
) {
691 // FIXME report error if multiple possible base methods are found
692 foreach (DataType type
in cl
.get_base_types ()) {
693 if (type
.data_type is Interface
) {
694 var sym
= type
.data_type
.scope
.lookup (name
);
696 var base_method
= (Method
) sym
;
697 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
698 string invalid_match
;
699 if (!compatible (base_method
, out invalid_match
)) {
701 Report
.error (source_reference
, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method
.get_full_name (), invalid_match
));
705 _base_interface_method
= base_method
;
713 public override bool check (SemanticAnalyzer analyzer
) {
720 process_attributes ();
723 if (parent_symbol is Class
) {
724 var cl
= (Class
) parent_symbol
;
725 if (!cl
.is_abstract
) {
727 Report
.error (source_reference
, "Abstract methods may not be declared in non-abstract classes");
730 } else if (!(parent_symbol is Interface
)) {
732 Report
.error (source_reference
, "Abstract methods may not be declared outside of classes and interfaces");
735 } else if (is_virtual
) {
736 if (!(parent_symbol is Class
) && !(parent_symbol is Interface
)) {
738 Report
.error (source_reference
, "Virtual methods may not be declared outside of classes and interfaces");
742 if (parent_symbol is Class
) {
743 var cl
= (Class
) parent_symbol
;
745 Report
.error (source_reference
, "Virtual methods may not be declared in compact classes");
749 } else if (overrides
) {
750 if (!(parent_symbol is Class
)) {
752 Report
.error (source_reference
, "Methods may not be overridden outside of classes");
757 if (is_abstract
&& body
!= null) {
758 Report
.error (source_reference
, "Abstract methods cannot have bodies");
759 } else if ((is_abstract
|| is_virtual
) && external
&& !external_package
&& !parent_symbol
.external
) {
760 Report
.error (source_reference
, "Extern methods cannot be abstract or virtual");
761 } else if (external
&& body
!= null) {
762 Report
.error (source_reference
, "Extern methods cannot have bodies");
763 } else if (!is_abstract
&& !external
&& !external_package
&& body
== null) {
764 Report
.error (source_reference
, "Non-abstract, non-extern methods must have bodies");
767 if (coroutine
&& !external_package
&& !analyzer
.context
.has_package ("gio-2.0")) {
769 Report
.error (source_reference
, "gio-2.0 package required for async methods");
773 var old_source_file
= analyzer
.current_source_file
;
774 var old_symbol
= analyzer
.current_symbol
;
776 if (source_reference
!= null) {
777 analyzer
.current_source_file
= source_reference
.file
;
779 analyzer
.current_symbol
= this
;
781 return_type
.check (analyzer
);
783 var init_attr
= get_attribute ("ModuleInit");
784 if (init_attr
!= null) {
785 source_reference
.file
.context
.module_init_method
= this
;
788 if (return_type
!= null) {
789 return_type
.check (analyzer
);
792 foreach (FormalParameter param
in parameters
) {
793 param
.check (analyzer
);
796 foreach (DataType error_type
in get_error_types ()) {
797 error_type
.check (analyzer
);
800 if (result_var
!= null) {
801 result_var
.check (analyzer
);
804 foreach (Expression precondition
in preconditions
) {
805 precondition
.check (analyzer
);
808 foreach (Expression postcondition
in postconditions
) {
809 postcondition
.check (analyzer
);
813 body
.check (analyzer
);
816 analyzer
.current_source_file
= old_source_file
;
817 analyzer
.current_symbol
= old_symbol
;
819 if (analyzer
.current_struct
!= null) {
820 if (is_abstract
|| is_virtual
|| overrides
) {
821 Report
.error (source_reference
, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
824 } else if (overrides
&& base_method
== null) {
825 Report
.error (source_reference
, "%s: no suitable method found to override".printf (get_full_name ()));
828 if (!external_package
&& !overrides
&& !hides
&& get_hidden_member () != null) {
829 Report
.warning (source_reference
, "%s hides inherited method `%s'. Use the `new' keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
832 // check whether return type is at least as accessible as the method
833 if (!analyzer
.is_type_accessible (this
, return_type
)) {
835 Report
.error (source_reference
, "return type `%s` is less accessible than method `%s`".printf (return_type
.to_string (), get_full_name ()));
839 foreach (Expression precondition
in get_preconditions ()) {
840 if (precondition
.error
) {
841 // if there was an error in the precondition, skip this check
846 if (!precondition
.value_type
.compatible (analyzer
.bool_type
)) {
848 Report
.error (precondition
.source_reference
, "Precondition must be boolean");
853 foreach (Expression postcondition
in get_postconditions ()) {
854 if (postcondition
.error
) {
855 // if there was an error in the postcondition, skip this check
860 if (!postcondition
.value_type
.compatible (analyzer
.bool_type
)) {
862 Report
.error (postcondition
.source_reference
, "Postcondition must be boolean");
867 // check that all errors that can be thrown in the method body are declared
869 foreach (DataType body_error_type
in body
.get_error_types ()) {
870 bool can_propagate_error
= false;
871 foreach (DataType method_error_type
in get_error_types ()) {
872 if (body_error_type
.compatible (method_error_type
)) {
873 can_propagate_error
= true;
876 if (!can_propagate_error
&& !((ErrorType
) body_error_type
).dynamic_error
) {
877 Report
.warning (body_error_type
.source_reference
, "unhandled error `%s'".printf (body_error_type
.to_string()));
882 if (is_possible_entry_point (analyzer
)) {
883 if (analyzer
.context
.entry_point
!= null) {
885 Report
.error (source_reference
, "program already has an entry point `%s'".printf (analyzer
.context
.entry_point
.get_full_name ()));
889 analyzer
.context
.entry_point
= this
;
892 Report
.error (source_reference
, "\"main\" method cannot throw errors");
899 bool is_possible_entry_point (SemanticAnalyzer analyzer
) {
900 if (external_package
) {
904 if (analyzer
.context
.entry_point_name
== null) {
905 if (name
== null || name
!= "main") {
906 // method must be called "main"
910 // custom entry point name
911 if (get_full_name () != analyzer
.context
.entry_point_name
) {
916 if (binding
== MemberBinding
.INSTANCE
) {
917 // method must be static
921 if (return_type is VoidType
) {
922 } else if (return_type
.data_type
== analyzer
.int_type
.data_type
) {
924 // return type must be void or int
928 var params
= get_parameters ();
929 if (params
.size
== 0) {
930 // method may have no parameters
934 if (params
.size
> 1) {
935 // method must not have more than one parameter
939 Iterator
<FormalParameter
> params_it
= params
.iterator ();
941 var param
= params_it
.get ();
943 if (param
.direction
== ParameterDirection
.OUT
) {
944 // parameter must not be an out parameter
948 if (!(param
.parameter_type is ArrayType
)) {
949 // parameter must be an array
953 var array_type
= (ArrayType
) param
.parameter_type
;
954 if (array_type
.element_type
.data_type
!= analyzer
.string_type
.data_type
) {
955 // parameter must be an array of strings
962 public int get_required_arguments () {
964 foreach (var param
in parameters
) {
965 if (param
.default_expression
!= null || param
.ellipsis
) {
974 public Method
get_callback_method () {
975 assert (this
.coroutine
);
977 if (callback_method
== null) {
978 var bool_type
= new
BooleanType ((Struct
) CodeContext
.get ().root
.scope
.lookup ("bool"));
979 bool_type
.value_owned
= true;
980 callback_method
= new
Method ("callback", bool_type
, source_reference
);
981 callback_method
.access
= SymbolAccessibility
.PUBLIC
;
982 callback_method
.external
= true;
983 callback_method
.binding
= MemberBinding
.INSTANCE
;
984 callback_method
.owner
= scope
;
985 callback_method
.is_async_callback
= true;
986 callback_method
.set_cname (get_real_cname () + "_co");
988 return callback_method
;
991 public Gee
.List
<FormalParameter
> get_async_begin_parameters () {
992 assert (this
.coroutine
);
994 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
996 var params
= new ArrayList
<FormalParameter
> ();
997 foreach (var param
in parameters
) {
998 if (param
.direction
== ParameterDirection
.IN
) {
1003 var callback_type
= new
DelegateType ((Delegate
) glib_ns
.scope
.lookup ("AsyncReadyCallback"));
1004 callback_type
.nullable
= true;
1006 var callback_param
= new
FormalParameter ("_callback_", callback_type
);
1007 callback_param
.default_expression
= new
NullLiteral (source_reference
);
1008 callback_param
.cparameter_position
= -1;
1009 callback_param
.cdelegate_target_parameter_position
= -0.9;
1011 params
.add (callback_param
);
1016 public Gee
.List
<FormalParameter
> get_async_end_parameters () {
1017 assert (this
.coroutine
);
1019 var params
= new ArrayList
<FormalParameter
> ();
1021 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1022 var result_type
= new
ObjectType ((ObjectTypeSymbol
) glib_ns
.scope
.lookup ("AsyncResult"));
1024 var result_param
= new
FormalParameter ("_res_", result_type
);
1025 result_param
.cparameter_position
= 0.1;
1026 params
.add (result_param
);
1028 foreach (var param
in parameters
) {
1029 if (param
.direction
== ParameterDirection
.OUT
) {
1037 public void add_captured_variable (LocalVariable local
) {
1038 assert (this
.closure
);
1040 if (captured_variables
== null) {
1041 captured_variables
= new ArrayList
<LocalVariable
> ();
1043 captured_variables
.add (local
);
1046 public void get_captured_variables (Collection
<LocalVariable
> variables
) {
1047 if (captured_variables
!= null) {
1048 foreach (var local
in captured_variables
) {
1049 variables
.add (local
);