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>
28 * Represents a type or namespace method.
30 public class Vala
.Method
: Member
{
31 List
<TypeParameter
> type_parameters
= new ArrayList
<TypeParameter
> ();
33 public const string DEFAULT_SENTINEL
= "NULL";
36 * The return type of this method.
38 public DataType return_type
{
39 get { return _return_type
; }
42 _return_type
.parent_node
= this
;
56 public BasicBlock entry_block
{ get; set; }
58 public BasicBlock exit_block
{ get; set; }
61 * Specifies whether this method may only be called with an instance of
64 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
67 * The name of the vfunc of this method as it is used in C code.
69 public string vfunc_name
{
71 if (_vfunc_name
== null) {
72 _vfunc_name
= this
.name
;
82 * The sentinel to use for terminating variable length argument lists.
84 public string sentinel
{
86 if (_sentinel
== null) {
87 return DEFAULT_SENTINEL
;
99 * Specifies whether this method is abstract. Abstract methods have no
100 * body, may only be specified within abstract classes, and must be
101 * overriden by derived non-abstract classes.
103 public bool is_abstract
{ get; set; }
106 * Specifies whether this method is virtual. Virtual methods may be
107 * overridden by derived classes.
109 public bool is_virtual
{ get; set; }
112 * Specifies whether this method overrides a virtual or abstract method
115 public bool overrides
{ get; set; }
118 * Specifies whether this method should be inlined.
120 public bool is_inline
{ get; set; }
123 * Specifies whether the C method returns a new instance pointer which
124 * may be different from the previous instance pointer. Only valid for
127 public bool returns_modified_pointer
{ get; set; }
130 * Specifies the virtual or abstract method this method overrides.
131 * Reference must be weak as virtual and abstract methods set
132 * base_method to themselves.
134 public Method base_method
{
136 find_base_methods ();
142 * Specifies the abstract interface method this method implements.
144 public Method base_interface_method
{
146 find_base_methods ();
147 return _base_interface_method
;
151 public bool entry_point
{ get; private set; }
154 * Specifies the generated `this' parameter for instance methods.
156 public FormalParameter this_parameter
{ get; set; }
159 * Specifies the generated `result' variable for postconditions.
161 public LocalVariable result_var
{ get; set; }
164 * Specifies the position of the instance parameter in the C function.
166 public double cinstance_parameter_position
{ get; set; }
169 * Specifies the position of the array length out parameter in the C
172 public double carray_length_parameter_position
{ get; set; }
175 * Specifies the position of the delegate target out parameter in the C
178 public double cdelegate_target_parameter_position
{ get; set; }
181 * Specifies whether the array length should be returned implicitly
182 * if the return type is an array.
184 public bool no_array_length
{ get; set; }
187 * Specifies whether the array is null terminated.
189 public bool array_null_terminated
{ get; set; }
192 * Specified a custom type for the array length parameter.
194 public string? array_length_type
{ get; set; default = null; }
197 * Specifies whether this method expects printf-style format arguments.
199 public bool printf_format
{ get; set; }
202 * Specifies whether this method expects scanf-style format arguments.
204 public bool scanf_format
{ get; set; }
207 * Specifies whether a new function without a GType parameter is
208 * available. This is only applicable to creation methods.
210 public bool has_new_function
{ get; set; default = true; }
213 * Specifies whether a construct function with a GType parameter is
214 * available. This is only applicable to creation methods.
216 public bool has_construct_function
{ get; set; default = true; }
218 public bool has_generic_type_parameter
{ get; set; }
220 public double generic_type_parameter_position
{ get; set; }
222 public weak Signal signal_reference
{ get; set; }
224 public bool closure
{ get; set; }
226 public bool coroutine
{ get; set; }
228 public bool is_async_callback
{ get; set; }
230 private List
<FormalParameter
> parameters
= new ArrayList
<FormalParameter
> ();
231 private string cname
;
232 private string _vfunc_name
;
233 private string _sentinel
;
234 private List
<Expression
> preconditions
= new ArrayList
<Expression
> ();
235 private List
<Expression
> postconditions
= new ArrayList
<Expression
> ();
236 private DataType _return_type
;
239 private weak Method _base_method
;
240 private Method _base_interface_method
;
241 private bool base_methods_valid
;
243 Method? callback_method
;
245 // only valid for closures
246 List
<LocalVariable
> captured_variables
;
249 * Creates a new method.
251 * @param name method name
252 * @param return_type method return type
253 * @param source reference to source code
254 * @return newly created method
256 public Method (string? name
, DataType return_type
, SourceReference? source_reference
= null, Comment? comment
= null) {
257 base (name
, source_reference
, comment
);
258 this
.return_type
= return_type
;
260 carray_length_parameter_position
= -3;
261 cdelegate_target_parameter_position
= -3;
265 * Appends parameter to this method.
267 * @param param a formal parameter
269 public void add_parameter (FormalParameter param
) {
270 // default C parameter position
271 param
.cparameter_position
= parameters
.size
+ 1;
272 param
.carray_length_parameter_position
= param
.cparameter_position
+ 0.1;
273 param
.cdelegate_target_parameter_position
= param
.cparameter_position
+ 0.1;
275 parameters
.add (param
);
276 if (!param
.ellipsis
) {
277 scope
.add (param
.name
, param
);
281 public List
<FormalParameter
> get_parameters () {
282 return new ReadOnlyList
<FormalParameter
> (parameters
);
286 * Remove all parameters from this method.
288 public void clear_parameters () {
289 foreach (FormalParameter param
in parameters
) {
290 if (!param
.ellipsis
) {
291 scope
.remove (param
.name
);
297 public override void accept (CodeVisitor visitor
) {
298 visitor
.visit_method (this
);
301 public override void accept_children (CodeVisitor visitor
) {
302 foreach (TypeParameter p
in get_type_parameters ()) {
306 if (return_type
!= null) {
307 return_type
.accept (visitor
);
310 foreach (FormalParameter param
in parameters
) {
311 param
.accept (visitor
);
314 foreach (DataType error_type
in get_error_types ()) {
315 error_type
.accept (visitor
);
318 if (result_var
!= null) {
319 result_var
.accept (visitor
);
322 foreach (Expression precondition
in preconditions
) {
323 precondition
.accept (visitor
);
326 foreach (Expression postcondition
in postconditions
) {
327 postcondition
.accept (visitor
);
331 body
.accept (visitor
);
336 * Returns the interface name of this method as it is used in C code.
338 * @return the name to be used in C code
340 public string get_cname () {
342 cname
= get_default_cname ();
347 public string get_finish_cname () {
349 string result
= get_cname ();
350 if (result
.has_suffix ("_async")) {
351 result
= result
.substring (0, result
.length
- "_async".length
);
358 * Returns the default interface name of this method as it is used in C
361 * @return the name to be used in C code by default
363 public virtual string get_default_cname () {
364 if (name
== "main" && parent_symbol
.name
== null) {
365 // avoid conflict with generated main function
367 } else if (name
.has_prefix ("_")) {
368 return "_%s%s".printf (parent_symbol
.get_lower_case_cprefix (), name
.offset (1));
370 return "%s%s".printf (parent_symbol
.get_lower_case_cprefix (), name
);
375 * Returns the implementation name of this data type as it is used in C
378 * @return the name to be used in C code
380 public virtual string get_real_cname () {
381 if (base_method
!= null || base_interface_method
!= null) {
382 return "%sreal_%s".printf (parent_symbol
.get_lower_case_cprefix (), name
);
388 public string get_finish_real_cname () {
390 string result
= get_real_cname ();
391 if (result
.has_suffix ("_async")) {
392 result
= result
.substring (0, result
.length
- "_async".length
);
398 public string get_finish_vfunc_name () {
400 string result
= vfunc_name
;
401 if (result
.has_suffix ("_async")) {
402 result
= result
.substring (0, result
.length
- "_async".length
);
409 * Sets the name of this method as it is used in C code.
411 * @param cname the name to be used in C code
413 public void set_cname (string cname
) {
417 private void process_ccode_attribute (Attribute a
) {
418 if (a
.has_argument ("cname")) {
419 set_cname (a
.get_string ("cname"));
421 if (a
.has_argument ("cheader_filename")) {
422 var val
= a
.get_string ("cheader_filename");
423 foreach (string filename
in val
.split (",")) {
424 add_cheader_filename (filename
);
427 if (a
.has_argument ("vfunc_name")) {
428 this
.vfunc_name
= a
.get_string ("vfunc_name");
430 if (a
.has_argument ("sentinel")) {
431 this
.sentinel
= a
.get_string ("sentinel");
433 if (a
.has_argument ("instance_pos")) {
434 cinstance_parameter_position
= a
.get_double ("instance_pos");
436 if (a
.has_argument ("array_length")) {
437 no_array_length
= !a
.get_bool ("array_length");
439 if (a
.has_argument ("array_length_type")) {
440 array_length_type
= a
.get_string ("array_length_type");
442 if (a
.has_argument ("array_null_terminated")) {
443 array_null_terminated
= a
.get_bool ("array_null_terminated");
445 if (a
.has_argument ("array_length_pos")) {
446 carray_length_parameter_position
= a
.get_double ("array_length_pos");
448 if (a
.has_argument ("delegate_target_pos")) {
449 cdelegate_target_parameter_position
= a
.get_double ("delegate_target_pos");
451 if (a
.has_argument ("has_new_function")) {
452 has_new_function
= a
.get_bool ("has_new_function");
454 if (a
.has_argument ("has_construct_function")) {
455 has_construct_function
= a
.get_bool ("has_construct_function");
457 if (a
.has_argument ("generic_type_pos")) {
458 has_generic_type_parameter
= true;
459 generic_type_parameter_position
= a
.get_double ("generic_type_pos");
464 * Process all associated attributes.
466 public void process_attributes () {
467 foreach (Attribute a
in attributes
) {
468 if (a
.name
== "CCode") {
469 process_ccode_attribute (a
);
470 } else if (a
.name
== "ReturnsModifiedPointer") {
471 returns_modified_pointer
= true;
472 } else if (a
.name
== "FloatingReference") {
473 return_type
.floating_reference
= true;
474 } else if (a
.name
== "PrintfFormat") {
475 printf_format
= true;
476 } else if (a
.name
== "ScanfFormat") {
483 * Checks whether the parameters and return type of this method are
484 * compatible with the specified method
486 * @param base_method a method
487 * @param invalid_match error string about which check failed
488 * @return true if the specified method is compatible to this method
490 public bool compatible (Method base_method
, out string? invalid_match
) {
491 if (binding
!= base_method
.binding
) {
492 invalid_match
= "incompatible binding";
496 ObjectType object_type
= null;
497 if (parent_symbol is ObjectTypeSymbol
) {
498 object_type
= new
ObjectType ((ObjectTypeSymbol
) parent_symbol
);
499 foreach (TypeParameter type_parameter
in object_type
.type_symbol
.get_type_parameters ()) {
500 var type_arg
= new
GenericType (type_parameter
);
501 type_arg
.value_owned
= true;
502 object_type
.add_type_argument (type_arg
);
506 var actual_base_type
= base_method
.return_type
.get_actual_type (object_type
, null, this
);
507 if (!return_type
.equals (actual_base_type
)) {
508 invalid_match
= "incompatible return type";
512 Iterator
<FormalParameter
> method_params_it
= parameters
.iterator ();
514 foreach (FormalParameter base_param
in base_method
.parameters
) {
515 /* this method may not expect less arguments */
516 if (!method_params_it
.next ()) {
517 invalid_match
= "too few parameters";
521 actual_base_type
= base_param
.parameter_type
.get_actual_type (object_type
, null, this
);
522 if (!actual_base_type
.equals (method_params_it
.get ().parameter_type
)) {
523 invalid_match
= "incompatible type of parameter %d".printf (param_index
);
529 /* this method may not expect more arguments */
530 if (method_params_it
.next ()) {
531 invalid_match
= "too many parameters";
535 /* this method may throw less but not more errors than the base method */
536 foreach (DataType method_error_type
in get_error_types ()) {
538 foreach (DataType base_method_error_type
in base_method
.get_error_types ()) {
539 if (method_error_type
.compatible (base_method_error_type
)) {
546 invalid_match
= "incompatible error type `%s'".printf (method_error_type
.to_string ());
550 if (base_method
.coroutine
!= this
.coroutine
) {
551 invalid_match
= "async mismatch";
559 * Appends the specified parameter to the list of type parameters.
561 * @param p a type parameter
563 public void add_type_parameter (TypeParameter p
) {
564 type_parameters
.add (p
);
565 scope
.add (p
.name
, p
);
569 * Returns a copy of the type parameter list.
571 * @return list of type parameters
573 public List
<TypeParameter
> get_type_parameters () {
574 return new ReadOnlyList
<TypeParameter
> (type_parameters
);
577 public int get_type_parameter_index (string name
) {
579 foreach (TypeParameter parameter
in type_parameters
) {
580 if (parameter
.name
== name
) {
589 * Adds a precondition to this method.
591 * @param precondition a boolean precondition expression
593 public void add_precondition (Expression precondition
) {
594 preconditions
.add (precondition
);
595 precondition
.parent_node
= this
;
599 * Returns a copy of the list of preconditions of this method.
601 * @return list of preconditions
603 public List
<Expression
> get_preconditions () {
604 return new ReadOnlyList
<Expression
> (preconditions
);
608 * Adds a postcondition to this method.
610 * @param postcondition a boolean postcondition expression
612 public void add_postcondition (Expression postcondition
) {
613 postconditions
.add (postcondition
);
614 postcondition
.parent_node
= this
;
618 * Returns a copy of the list of postconditions of this method.
620 * @return list of postconditions
622 public List
<Expression
> get_postconditions () {
623 return new ReadOnlyList
<Expression
> (postconditions
);
626 public override void replace_type (DataType old_type
, DataType new_type
) {
627 if (return_type
== old_type
) {
628 return_type
= new_type
;
631 var error_types
= get_error_types ();
632 for (int i
= 0; i
< error_types
.size
; i
++) {
633 if (error_types
[i
] == old_type
) {
634 error_types
[i
] = new_type
;
640 private void find_base_methods () {
641 if (base_methods_valid
) {
645 if (parent_symbol is Class
) {
646 if (!(this is CreationMethod
)) {
647 find_base_interface_method ((Class
) parent_symbol
);
648 if (is_virtual
|| is_abstract
|| overrides
) {
649 find_base_class_method ((Class
) parent_symbol
);
652 } else if (parent_symbol is Interface
) {
653 if (is_virtual
|| is_abstract
) {
654 _base_interface_method
= this
;
658 base_methods_valid
= true;
661 private void find_base_class_method (Class cl
) {
662 var sym
= cl
.scope
.lookup (name
);
664 var base_method
= (Method
) sym
;
665 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
666 string invalid_match
;
667 if (!compatible (base_method
, out invalid_match
)) {
669 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
));
673 _base_method
= base_method
;
676 } else if (sym is Signal
) {
677 var sig
= (Signal
) sym
;
678 if (sig
.is_virtual
) {
679 var base_method
= sig
.default_handler
;
680 string invalid_match
;
681 if (!compatible (base_method
, out invalid_match
)) {
683 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
));
687 _base_method
= base_method
;
692 if (cl
.base_class
!= null) {
693 find_base_class_method (cl
.base_class
);
697 private void find_base_interface_method (Class cl
) {
698 // FIXME report error if multiple possible base methods are found
699 foreach (DataType type
in cl
.get_base_types ()) {
700 if (type
.data_type is Interface
) {
701 var sym
= type
.data_type
.scope
.lookup (name
);
703 var base_method
= (Method
) sym
;
704 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
705 string invalid_match
;
706 if (!compatible (base_method
, out invalid_match
)) {
708 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
));
712 _base_interface_method
= base_method
;
720 public override bool check (SemanticAnalyzer analyzer
) {
727 process_attributes ();
730 if (parent_symbol is Class
) {
731 var cl
= (Class
) parent_symbol
;
732 if (!cl
.is_abstract
) {
734 Report
.error (source_reference
, "Abstract methods may not be declared in non-abstract classes");
737 } else if (!(parent_symbol is Interface
)) {
739 Report
.error (source_reference
, "Abstract methods may not be declared outside of classes and interfaces");
742 } else if (is_virtual
) {
743 if (!(parent_symbol is Class
) && !(parent_symbol is Interface
)) {
745 Report
.error (source_reference
, "Virtual methods may not be declared outside of classes and interfaces");
749 if (parent_symbol is Class
) {
750 var cl
= (Class
) parent_symbol
;
752 Report
.error (source_reference
, "Virtual methods may not be declared in compact classes");
756 } else if (overrides
) {
757 if (!(parent_symbol is Class
)) {
759 Report
.error (source_reference
, "Methods may not be overridden outside of classes");
764 if (is_abstract
&& body
!= null) {
765 Report
.error (source_reference
, "Abstract methods cannot have bodies");
766 } else if ((is_abstract
|| is_virtual
) && external
&& !external_package
&& !parent_symbol
.external
) {
767 Report
.error (source_reference
, "Extern methods cannot be abstract or virtual");
768 } else if (external
&& body
!= null) {
769 Report
.error (source_reference
, "Extern methods cannot have bodies");
770 } else if (!is_abstract
&& !external
&& !external_package
&& body
== null) {
771 Report
.error (source_reference
, "Non-abstract, non-extern methods must have bodies");
774 if (coroutine
&& !external_package
&& !analyzer
.context
.has_package ("gio-2.0")) {
776 Report
.error (source_reference
, "gio-2.0 package required for async methods");
780 var old_source_file
= analyzer
.current_source_file
;
781 var old_symbol
= analyzer
.current_symbol
;
783 if (source_reference
!= null) {
784 analyzer
.current_source_file
= source_reference
.file
;
786 analyzer
.current_symbol
= this
;
788 return_type
.check (analyzer
);
790 var init_attr
= get_attribute ("ModuleInit");
791 if (init_attr
!= null) {
792 source_reference
.file
.context
.module_init_method
= this
;
795 if (return_type
!= null) {
796 return_type
.check (analyzer
);
799 foreach (FormalParameter param
in parameters
) {
800 param
.check (analyzer
);
803 foreach (DataType error_type
in get_error_types ()) {
804 error_type
.check (analyzer
);
807 if (result_var
!= null) {
808 result_var
.check (analyzer
);
811 foreach (Expression precondition
in preconditions
) {
812 precondition
.check (analyzer
);
815 foreach (Expression postcondition
in postconditions
) {
816 postcondition
.check (analyzer
);
820 body
.check (analyzer
);
823 analyzer
.current_source_file
= old_source_file
;
824 analyzer
.current_symbol
= old_symbol
;
826 if (analyzer
.current_struct
!= null) {
827 if (is_abstract
|| is_virtual
|| overrides
) {
828 Report
.error (source_reference
, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
831 } else if (overrides
&& base_method
== null) {
832 Report
.error (source_reference
, "%s: no suitable method found to override".printf (get_full_name ()));
835 if (!external_package
&& !overrides
&& !hides
&& get_hidden_member () != null) {
836 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 ()));
839 // check whether return type is at least as accessible as the method
840 if (!analyzer
.is_type_accessible (this
, return_type
)) {
842 Report
.error (source_reference
, "return type `%s` is less accessible than method `%s`".printf (return_type
.to_string (), get_full_name ()));
846 foreach (Expression precondition
in get_preconditions ()) {
847 if (precondition
.error
) {
848 // if there was an error in the precondition, skip this check
853 if (!precondition
.value_type
.compatible (analyzer
.bool_type
)) {
855 Report
.error (precondition
.source_reference
, "Precondition must be boolean");
860 foreach (Expression postcondition
in get_postconditions ()) {
861 if (postcondition
.error
) {
862 // if there was an error in the postcondition, skip this check
867 if (!postcondition
.value_type
.compatible (analyzer
.bool_type
)) {
869 Report
.error (postcondition
.source_reference
, "Postcondition must be boolean");
874 // check that all errors that can be thrown in the method body are declared
876 foreach (DataType body_error_type
in body
.get_error_types ()) {
877 bool can_propagate_error
= false;
878 foreach (DataType method_error_type
in get_error_types ()) {
879 if (body_error_type
.compatible (method_error_type
)) {
880 can_propagate_error
= true;
883 if (!can_propagate_error
&& !((ErrorType
) body_error_type
).dynamic_error
) {
884 Report
.warning (body_error_type
.source_reference
, "unhandled error `%s'".printf (body_error_type
.to_string()));
889 if (is_possible_entry_point (analyzer
)) {
890 if (analyzer
.context
.entry_point
!= null) {
892 Report
.error (source_reference
, "program already has an entry point `%s'".printf (analyzer
.context
.entry_point
.get_full_name ()));
896 analyzer
.context
.entry_point
= this
;
899 Report
.error (source_reference
, "\"main\" method cannot throw errors");
906 bool is_possible_entry_point (SemanticAnalyzer analyzer
) {
907 if (external_package
) {
911 if (analyzer
.context
.entry_point_name
== null) {
912 if (name
== null || name
!= "main") {
913 // method must be called "main"
917 // custom entry point name
918 if (get_full_name () != analyzer
.context
.entry_point_name
) {
923 if (binding
== MemberBinding
.INSTANCE
) {
924 // method must be static
928 if (return_type is VoidType
) {
929 } else if (return_type
.data_type
== analyzer
.int_type
.data_type
) {
931 // return type must be void or int
935 var params
= get_parameters ();
936 if (params
.size
== 0) {
937 // method may have no parameters
941 if (params
.size
> 1) {
942 // method must not have more than one parameter
946 Iterator
<FormalParameter
> params_it
= params
.iterator ();
948 var param
= params_it
.get ();
950 if (param
.direction
== ParameterDirection
.OUT
) {
951 // parameter must not be an out parameter
955 if (!(param
.parameter_type is ArrayType
)) {
956 // parameter must be an array
960 var array_type
= (ArrayType
) param
.parameter_type
;
961 if (array_type
.element_type
.data_type
!= analyzer
.string_type
.data_type
) {
962 // parameter must be an array of strings
969 public int get_required_arguments () {
971 foreach (var param
in parameters
) {
972 if (param
.default_expression
!= null || param
.ellipsis
) {
981 public Method
get_callback_method () {
982 assert (this
.coroutine
);
984 if (callback_method
== null) {
985 var bool_type
= new
BooleanType ((Struct
) CodeContext
.get ().root
.scope
.lookup ("bool"));
986 bool_type
.value_owned
= true;
987 callback_method
= new
Method ("callback", bool_type
, source_reference
);
988 callback_method
.access
= SymbolAccessibility
.PUBLIC
;
989 callback_method
.external
= true;
990 callback_method
.binding
= MemberBinding
.INSTANCE
;
991 callback_method
.owner
= scope
;
992 callback_method
.is_async_callback
= true;
993 callback_method
.set_cname (get_real_cname () + "_co");
995 return callback_method
;
998 public List
<FormalParameter
> get_async_begin_parameters () {
999 assert (this
.coroutine
);
1001 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1003 var params
= new ArrayList
<FormalParameter
> ();
1004 foreach (var param
in parameters
) {
1005 if (param
.direction
== ParameterDirection
.IN
) {
1010 var callback_type
= new
DelegateType ((Delegate
) glib_ns
.scope
.lookup ("AsyncReadyCallback"));
1011 callback_type
.nullable
= true;
1013 var callback_param
= new
FormalParameter ("_callback_", callback_type
);
1014 callback_param
.default_expression
= new
NullLiteral (source_reference
);
1015 callback_param
.cparameter_position
= -1;
1016 callback_param
.cdelegate_target_parameter_position
= -0.9;
1018 params
.add (callback_param
);
1023 public List
<FormalParameter
> get_async_end_parameters () {
1024 assert (this
.coroutine
);
1026 var params
= new ArrayList
<FormalParameter
> ();
1028 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1029 var result_type
= new
ObjectType ((ObjectTypeSymbol
) glib_ns
.scope
.lookup ("AsyncResult"));
1031 var result_param
= new
FormalParameter ("_res_", result_type
);
1032 result_param
.cparameter_position
= 0.1;
1033 params
.add (result_param
);
1035 foreach (var param
in parameters
) {
1036 if (param
.direction
== ParameterDirection
.OUT
) {
1044 public void add_captured_variable (LocalVariable local
) {
1045 assert (this
.closure
);
1047 if (captured_variables
== null) {
1048 captured_variables
= new ArrayList
<LocalVariable
> ();
1050 captured_variables
.add (local
);
1053 public void get_captured_variables (Collection
<LocalVariable
> variables
) {
1054 if (captured_variables
!= null) {
1055 foreach (var local
in captured_variables
) {
1056 variables
.add (local
);