3 * Copyright (C) 2006-2010 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
: Subroutine
, Callable
{
31 List
<TypeParameter
> type_parameters
;
34 * The return type of this method.
36 public DataType return_type
{
37 get { return _return_type
; }
40 _return_type
.parent_node
= this
;
44 public override bool has_result
{
45 get { return !(return_type is VoidType
); }
49 * Specifies whether this method may only be called with an instance of
52 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
55 * Specifies whether this method is abstract. Abstract methods have no
56 * body, may only be specified within abstract classes, and must be
57 * overriden by derived non-abstract classes.
59 public bool is_abstract
{ get; set; }
62 * Specifies whether this method is virtual. Virtual methods may be
63 * overridden by derived classes.
65 public bool is_virtual
{ get; set; }
68 * Specifies whether this method overrides a virtual or abstract method
71 public bool overrides
{ get; set; }
74 * Specifies whether this method should be inlined.
76 public bool is_inline
{ get; set; }
78 public bool returns_floating_reference
{
80 return get_attribute_bool ("CCode", "returns_floating_reference");
83 set_attribute_bool ("CCode", "returns_floating_reference", value
);
88 * Specifies whether the C method returns a new instance pointer which
89 * may be different from the previous instance pointer. Only valid for
92 public bool returns_modified_pointer
{
94 return get_attribute ("ReturnsModifiedPointer") != null;
97 set_attribute ("ReturnsModifiedPointer", value
);
102 * Specifies the virtual or abstract method this method overrides.
103 * Reference must be weak as virtual and abstract methods set
104 * base_method to themselves.
106 public Method base_method
{
108 find_base_methods ();
114 * Specifies the abstract interface method this method implements.
116 public Method base_interface_method
{
118 find_base_methods ();
119 return _base_interface_method
;
124 * Specifies the explicit interface containing the method this method implements.
126 public DataType base_interface_type
{
127 get { return _base_interface_type
; }
129 _base_interface_type
= value
;
130 _base_interface_type
.parent_node
= this
;
134 public bool entry_point
{ get; private set; }
137 * Specifies the generated `this` parameter for instance methods.
139 public Parameter this_parameter
{ get; set; }
142 * Specifies whether this method expects printf-style format arguments.
144 public bool printf_format
{
146 return get_attribute ("PrintfFormat") != null;
149 set_attribute ("PrintfFormat", value
);
154 * Specifies whether this method expects scanf-style format arguments.
156 public bool scanf_format
{
158 return get_attribute ("ScanfFormat") != null;
161 set_attribute ("ScanfFormat", value
);
166 * Specifies whether a construct function with a GType parameter is
167 * available. This is only applicable to creation methods.
169 public bool has_construct_function
{
171 return get_attribute_bool ("CCode", "has_construct_function", true);
174 set_attribute_bool ("CCode", "has_construct_function", value
);
178 public weak Signal signal_reference
{ get; set; }
180 public bool closure
{ get; set; }
182 public bool coroutine
{ get; set; }
184 public bool is_async_callback
{ get; set; }
186 public int yield_count
{ get; set; }
188 private List
<Parameter
> parameters
= new ArrayList
<Parameter
> ();
189 private List
<Expression
> preconditions
;
190 private List
<Expression
> postconditions
;
191 private DataType _return_type
;
193 private weak Method _base_method
;
194 private weak Method _base_interface_method
;
195 private DataType _base_interface_type
;
196 private bool base_methods_valid
;
198 Method? callback_method
;
201 // only valid for closures
202 List
<LocalVariable
> captured_variables
;
204 static List
<Expression
> _empty_expression_list
;
205 static List
<TypeParameter
> _empty_type_parameter_list
;
208 * Creates a new method.
210 * @param name method name
211 * @param return_type method return type
212 * @param source_reference reference to source code
213 * @return newly created method
215 public Method (string? name
, DataType return_type
, SourceReference? source_reference
= null, Comment? comment
= null) {
216 base (name
, source_reference
, comment
);
217 this
.return_type
= return_type
;
221 * Appends parameter to this method.
223 * @param param a formal parameter
225 public void add_parameter (Parameter param
) {
226 // default C parameter position
227 parameters
.add (param
);
228 scope
.add (param
.name
, param
);
231 public List
<Parameter
> get_parameters () {
236 * Remove all parameters from this method.
238 public void clear_parameters () {
239 foreach (Parameter param
in parameters
) {
240 if (!param
.ellipsis
) {
241 scope
.remove (param
.name
);
247 public bool is_variadic () {
248 foreach (Parameter param
in parameters
) {
249 if (param
.ellipsis
) {
256 public override void accept (CodeVisitor visitor
) {
257 visitor
.visit_method (this
);
260 public override void accept_children (CodeVisitor visitor
) {
261 foreach (TypeParameter p
in get_type_parameters ()) {
265 if (base_interface_type
!= null) {
266 base_interface_type
.accept (visitor
);
269 if (return_type
!= null) {
270 return_type
.accept (visitor
);
273 foreach (Parameter param
in parameters
) {
274 param
.accept (visitor
);
277 foreach (DataType error_type
in get_error_types ()) {
278 error_type
.accept (visitor
);
281 if (result_var
!= null) {
282 result_var
.accept (visitor
);
285 if (preconditions
!= null) {
286 foreach (Expression precondition
in preconditions
) {
287 precondition
.accept (visitor
);
291 if (postconditions
!= null) {
292 foreach (Expression postcondition
in postconditions
) {
293 postcondition
.accept (visitor
);
298 body
.accept (visitor
);
303 * Checks whether the parameters and return type of this method are
304 * compatible with the specified method
306 * @param base_method a method
307 * @param invalid_match error string about which check failed
308 * @return true if the specified method is compatible to this method
310 public bool compatible (Method base_method
, out string? invalid_match
) {
311 // method is always compatible to itself
312 if (this
== base_method
) {
313 invalid_match
= null;
317 if (binding
!= base_method
.binding
) {
318 invalid_match
= "incompatible binding";
322 ObjectType object_type
= null;
323 if (parent_symbol is ObjectTypeSymbol
) {
324 object_type
= new
ObjectType ((ObjectTypeSymbol
) parent_symbol
);
325 foreach (TypeParameter type_parameter
in object_type
.type_symbol
.get_type_parameters ()) {
326 var type_arg
= new
GenericType (type_parameter
);
327 type_arg
.value_owned
= true;
328 object_type
.add_type_argument (type_arg
);
332 if (this
.get_type_parameters ().size
< base_method
.get_type_parameters ().size
) {
333 invalid_match
= "too few type parameters";
335 } else if (this
.get_type_parameters ().size
> base_method
.get_type_parameters ().size
) {
336 invalid_match
= "too many type parameters";
340 List
<DataType
> method_type_args
= null;
341 if (this
.get_type_parameters ().size
> 0) {
342 method_type_args
= new ArrayList
<DataType
> ();
343 foreach (TypeParameter type_parameter
in this
.get_type_parameters ()) {
344 var type_arg
= new
GenericType (type_parameter
);
345 type_arg
.value_owned
= true;
346 method_type_args
.add (type_arg
);
350 var actual_base_type
= base_method
.return_type
.get_actual_type (object_type
, method_type_args
, this
);
351 if (!return_type
.equals (actual_base_type
)) {
352 invalid_match
= "Base method expected return type `%s', but `%s' was provided".printf (actual_base_type
.to_qualified_string (), return_type
.to_qualified_string ());
356 Iterator
<Parameter
> method_params_it
= parameters
.iterator ();
358 foreach (Parameter base_param
in base_method
.parameters
) {
359 /* this method may not expect less arguments */
360 if (!method_params_it
.next ()) {
361 invalid_match
= "too few parameters";
365 var param
= method_params_it
.get ();
366 if (base_param
.ellipsis
!= param
.ellipsis
) {
367 invalid_match
= "ellipsis parameter mismatch";
370 if (!base_param
.ellipsis
) {
371 if (base_param
.direction
!= param
.direction
) {
372 invalid_match
= "incompatible direction of parameter %d".printf (param_index
);
376 actual_base_type
= base_param
.variable_type
.get_actual_type (object_type
, method_type_args
, this
);
377 if (!actual_base_type
.equals (param
.variable_type
)) {
378 invalid_match
= "incompatible type of parameter %d".printf (param_index
);
385 /* this method may not expect more arguments */
386 if (method_params_it
.next ()) {
387 invalid_match
= "too many parameters";
391 /* this method may throw less but not more errors than the base method */
392 foreach (DataType method_error_type
in get_error_types ()) {
394 foreach (DataType base_method_error_type
in base_method
.get_error_types ()) {
395 if (method_error_type
.compatible (base_method_error_type
)) {
402 invalid_match
= "incompatible error type `%s'".printf (method_error_type
.to_string ());
406 if (base_method
.coroutine
!= this
.coroutine
) {
407 invalid_match
= "async mismatch";
411 invalid_match
= null;
416 * Appends the specified parameter to the list of type parameters.
418 * @param p a type parameter
420 public void add_type_parameter (TypeParameter p
) {
421 if (type_parameters
== null) {
422 type_parameters
= new ArrayList
<TypeParameter
> ();
424 type_parameters
.add (p
);
425 scope
.add (p
.name
, p
);
429 * Returns a copy of the type parameter list.
431 * @return list of type parameters
433 public List
<TypeParameter
> get_type_parameters () {
434 if (type_parameters
!= null) {
435 return type_parameters
;
437 if (_empty_type_parameter_list
== null) {
438 _empty_type_parameter_list
= new ArrayList
<TypeParameter
> ();
440 return _empty_type_parameter_list
;
443 public int get_type_parameter_index (string name
) {
444 if (type_parameters
== null) {
449 foreach (TypeParameter parameter
in type_parameters
) {
450 if (parameter
.name
== name
) {
459 * Adds a precondition to this method.
461 * @param precondition a boolean precondition expression
463 public void add_precondition (Expression precondition
) {
464 if (preconditions
== null) {
465 preconditions
= new ArrayList
<Expression
> ();
467 preconditions
.add (precondition
);
468 precondition
.parent_node
= this
;
472 * Returns a copy of the list of preconditions of this method.
474 * @return list of preconditions
476 public List
<Expression
> get_preconditions () {
477 if (preconditions
!= null) {
478 return preconditions
;
480 if (_empty_expression_list
== null) {
481 _empty_expression_list
= new ArrayList
<Expression
> ();
483 return _empty_expression_list
;
487 * Adds a postcondition to this method.
489 * @param postcondition a boolean postcondition expression
491 public void add_postcondition (Expression postcondition
) {
492 if (postconditions
== null) {
493 postconditions
= new ArrayList
<Expression
> ();
495 postconditions
.add (postcondition
);
496 postcondition
.parent_node
= this
;
500 * Returns a copy of the list of postconditions of this method.
502 * @return list of postconditions
504 public List
<Expression
> get_postconditions () {
505 if (postconditions
!= null) {
506 return postconditions
;
508 if (_empty_expression_list
== null) {
509 _empty_expression_list
= new ArrayList
<Expression
> ();
511 return _empty_expression_list
;
514 public override void replace_type (DataType old_type
, DataType new_type
) {
515 if (base_interface_type
== old_type
) {
516 base_interface_type
= new_type
;
519 if (return_type
== old_type
) {
520 return_type
= new_type
;
523 var error_types
= get_error_types ();
524 for (int i
= 0; i
< error_types
.size
; i
++) {
525 if (error_types
[i
] == old_type
) {
526 error_types
[i
] = new_type
;
532 private void find_base_methods () {
533 if (base_methods_valid
) {
537 if (parent_symbol is Class
) {
538 if (!(this is CreationMethod
)) {
539 find_base_interface_method ((Class
) parent_symbol
);
540 if (is_virtual
|| is_abstract
|| overrides
) {
541 find_base_class_method ((Class
) parent_symbol
);
544 } else if (parent_symbol is Interface
) {
545 if (is_virtual
|| is_abstract
) {
546 _base_interface_method
= this
;
550 base_methods_valid
= true;
553 private void find_base_class_method (Class cl
) {
554 var sym
= cl
.scope
.lookup (name
);
556 var sig
= (Signal
) sym
;
557 sym
= sig
.default_handler
;
560 var base_method
= (Method
) sym
;
561 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
562 string invalid_match
;
563 if (!compatible (base_method
, out invalid_match
)) {
565 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
));
569 _base_method
= base_method
;
574 if (cl
.base_class
!= null) {
575 find_base_class_method (cl
.base_class
);
579 private void find_base_interface_method (Class cl
) {
580 foreach (DataType type
in cl
.get_base_types ()) {
581 if (type
.data_type is Interface
) {
582 if (base_interface_type
!= null && base_interface_type
.data_type
!= type
.data_type
) {
586 var sym
= type
.data_type
.scope
.lookup (name
);
588 var sig
= (Signal
) sym
;
589 sym
= sig
.default_handler
;
592 var base_method
= (Method
) sym
;
593 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
594 if (base_interface_type
== null) {
595 // check for existing explicit implementation
596 var has_explicit_implementation
= false;
597 foreach (var m
in cl
.get_methods ()) {
598 if (m
.base_interface_type
!= null && base_method
== m
.base_interface_method
) {
599 has_explicit_implementation
= true;
603 if (has_explicit_implementation
) {
608 string invalid_match
= null;
609 if (!compatible (base_method
, out invalid_match
)) {
611 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
));
615 _base_interface_method
= base_method
;
622 if (base_interface_type
!= null) {
623 Report
.error (source_reference
, "%s: no suitable interface method found to implement".printf (get_full_name ()));
627 public override bool check (CodeContext context
) {
634 if (get_attribute ("DestroysInstance") != null) {
635 this_parameter
.variable_type
.value_owned
= true;
637 if (get_attribute ("NoThrow") != null) {
638 get_error_types ().clear ();
642 if (parent_symbol is Class
) {
643 var cl
= (Class
) parent_symbol
;
644 if (!cl
.is_abstract
) {
646 Report
.error (source_reference
, "Abstract methods may not be declared in non-abstract classes");
649 } else if (!(parent_symbol is Interface
)) {
651 Report
.error (source_reference
, "Abstract methods may not be declared outside of classes and interfaces");
654 } else if (is_virtual
) {
655 if (!(parent_symbol is Class
) && !(parent_symbol is Interface
)) {
657 Report
.error (source_reference
, "Virtual methods may not be declared outside of classes and interfaces");
661 if (parent_symbol is Class
) {
662 var cl
= (Class
) parent_symbol
;
663 if (cl
.is_compact
&& cl
!= context
.analyzer
.gsource_type
) {
664 Report
.error (source_reference
, "Virtual methods may not be declared in compact classes");
668 } else if (overrides
) {
669 if (!(parent_symbol is Class
)) {
671 Report
.error (source_reference
, "Methods may not be overridden outside of classes");
674 } else if (access
== SymbolAccessibility
.PROTECTED
) {
675 if (!(parent_symbol is Class
) && !(parent_symbol is Interface
)) {
677 Report
.error (source_reference
, "Protected methods may not be declared outside of classes and interfaces");
682 if (is_abstract
&& body
!= null) {
683 Report
.error (source_reference
, "Abstract methods cannot have bodies");
684 } else if ((is_abstract
|| is_virtual
) && external
&& !external_package
&& !parent_symbol
.external
) {
685 Report
.error (source_reference
, "Extern methods cannot be abstract or virtual");
686 } else if (external
&& body
!= null) {
687 Report
.error (source_reference
, "Extern methods cannot have bodies");
688 } else if (!is_abstract
&& !external
&& source_type
== SourceFileType
.SOURCE
&& body
== null) {
689 Report
.error (source_reference
, "Non-abstract, non-extern methods must have bodies");
692 if (coroutine
&& !external_package
&& !context
.has_package ("gio-2.0")) {
694 Report
.error (source_reference
, "gio-2.0 package required for async methods");
698 var old_source_file
= context
.analyzer
.current_source_file
;
699 var old_symbol
= context
.analyzer
.current_symbol
;
701 if (source_reference
!= null) {
702 context
.analyzer
.current_source_file
= source_reference
.file
;
704 context
.analyzer
.current_symbol
= this
;
706 return_type
.check (context
);
708 var init_attr
= get_attribute ("ModuleInit");
709 if (init_attr
!= null) {
710 source_reference
.file
.context
.module_init_method
= this
;
713 if (return_type
!= null) {
714 return_type
.check (context
);
717 if (parameters
.size
== 1 && parameters
[0].ellipsis
&& body
!= null && binding
!= MemberBinding
.INSTANCE
) {
718 // accept just `...' for external methods and instance methods
720 Report
.error (parameters
[0].source_reference
, "Named parameter required before `...'");
724 // TODO: begin and end parameters must be checked separately for coroutines
725 var optional_param
= false;
726 foreach (Parameter param
in parameters
) {
727 param
.check (context
);
728 if (coroutine
&& param
.direction
== ParameterDirection
.REF
) {
730 Report
.error (param
.source_reference
, "Reference parameters are not supported for async methods");
732 if (optional_param
&& param
.initializer
== null && !param
.ellipsis
) {
733 Report
.warning (param
.source_reference
, "parameter without default follows parameter with default");
734 } else if (param
.initializer
!= null) {
735 optional_param
= true;
740 foreach (DataType error_type
in get_error_types ()) {
741 error_type
.check (context
);
743 // check whether error type is at least as accessible as the method
744 if (!context
.analyzer
.is_type_accessible (this
, error_type
)) {
746 Report
.error (source_reference
, "error type `%s` is less accessible than method `%s`".printf (error_type
.to_string (), get_full_name ()));
751 if (result_var
!= null) {
752 result_var
.check (context
);
755 if (preconditions
!= null) {
756 foreach (Expression precondition
in preconditions
) {
757 precondition
.check (context
);
761 if (postconditions
!= null) {
762 foreach (Expression postcondition
in postconditions
) {
763 postcondition
.check (context
);
768 body
.check (context
);
771 if (context
.analyzer
.current_struct
!= null) {
772 if (is_abstract
|| is_virtual
|| overrides
) {
774 Report
.error (source_reference
, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
777 } else if (overrides
&& base_method
== null) {
778 Report
.error (source_reference
, "%s: no suitable method found to override".printf (get_full_name ()));
779 } else if ((is_abstract
|| is_virtual
|| overrides
) && access
== SymbolAccessibility
.PRIVATE
) {
781 Report
.error (source_reference
, "Private member `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
785 if (base_interface_type
!= null && base_interface_method
!= null && parent_symbol is Class
) {
786 var cl
= (Class
) parent_symbol
;
787 foreach (var m
in cl
.get_methods ()) {
788 if (m
!= this
&& m
.base_interface_method
== base_interface_method
) {
792 Report
.error (source_reference
, "`%s' already contains an implementation for `%s'".printf (cl
.get_full_name (), base_interface_method
.get_full_name ()));
793 Report
.notice (m
.source_reference
, "previous implementation of `%s' was here".printf (base_interface_method
.get_full_name ()));
799 context
.analyzer
.current_source_file
= old_source_file
;
800 context
.analyzer
.current_symbol
= old_symbol
;
802 if (!external_package
&& !overrides
&& !hides
&& get_hidden_member () != null) {
803 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 ()));
806 // check whether return type is at least as accessible as the method
807 if (!context
.analyzer
.is_type_accessible (this
, return_type
)) {
809 Report
.error (source_reference
, "return type `%s` is less accessible than method `%s`".printf (return_type
.to_string (), get_full_name ()));
813 foreach (Expression precondition
in get_preconditions ()) {
814 if (precondition
.error
) {
815 // if there was an error in the precondition, skip this check
820 if (!precondition
.value_type
.compatible (context
.analyzer
.bool_type
)) {
822 Report
.error (precondition
.source_reference
, "Precondition must be boolean");
827 foreach (Expression postcondition
in get_postconditions ()) {
828 if (postcondition
.error
) {
829 // if there was an error in the postcondition, skip this check
834 if (!postcondition
.value_type
.compatible (context
.analyzer
.bool_type
)) {
836 Report
.error (postcondition
.source_reference
, "Postcondition must be boolean");
841 // check that all errors that can be thrown in the method body are declared
843 foreach (DataType body_error_type
in body
.get_error_types ()) {
844 bool can_propagate_error
= false;
845 foreach (DataType method_error_type
in get_error_types ()) {
846 if (body_error_type
.compatible (method_error_type
)) {
847 can_propagate_error
= true;
850 bool is_dynamic_error
= body_error_type is ErrorType
&& ((ErrorType
) body_error_type
).dynamic_error
;
851 if (!can_propagate_error
&& !is_dynamic_error
) {
852 Report
.warning (body_error_type
.source_reference
, "unhandled error `%s'".printf (body_error_type
.to_string()));
857 if (is_possible_entry_point (context
)) {
858 if (context
.entry_point
!= null) {
860 Report
.error (source_reference
, "program already has an entry point `%s'".printf (context
.entry_point
.get_full_name ()));
864 context
.entry_point
= this
;
867 Report
.error (source_reference
, "\"main\" method cannot throw errors");
871 Report
.error (source_reference
, "\"main\" method cannot be inline");
875 Report
.error (source_reference
, "\"main\" method cannot be async");
879 if (get_attribute ("GtkCallback") != null) {
886 bool is_possible_entry_point (CodeContext context
) {
887 if (external_package
) {
891 if (context
.entry_point_name
== null) {
892 if (name
== null || name
!= "main") {
893 // method must be called "main"
897 // custom entry point name
898 if (get_full_name () != context
.entry_point_name
) {
903 if (binding
== MemberBinding
.INSTANCE
) {
904 // method must be static
908 if (return_type is VoidType
) {
909 } else if (return_type
.data_type
== context
.analyzer
.int_type
.data_type
) {
911 // return type must be void or int
915 var params
= get_parameters ();
916 if (params
.size
== 0) {
917 // method may have no parameters
921 if (params
.size
> 1) {
922 // method must not have more than one parameter
926 Iterator
<Parameter
> params_it
= params
.iterator ();
928 var param
= params_it
.get ();
930 if (param
.direction
== ParameterDirection
.OUT
) {
931 // parameter must not be an out parameter
935 if (!(param
.variable_type is ArrayType
)) {
936 // parameter must be an array
940 var array_type
= (ArrayType
) param
.variable_type
;
941 if (array_type
.element_type
.data_type
!= context
.analyzer
.string_type
.data_type
) {
942 // parameter must be an array of strings
949 public int get_required_arguments () {
951 foreach (var param
in parameters
) {
952 if (param
.initializer
!= null || param
.ellipsis
) {
961 public Method
get_end_method () {
962 assert (this
.coroutine
);
964 if (end_method
== null) {
965 end_method
= new
Method ("end", return_type
, source_reference
);
966 end_method
.access
= SymbolAccessibility
.PUBLIC
;
967 end_method
.external
= true;
968 end_method
.owner
= scope
;
969 foreach (var param
in get_async_end_parameters ()) {
970 end_method
.add_parameter (param
.copy ());
972 foreach (var param
in get_type_parameters ()) {
973 end_method
.add_type_parameter (param
);
979 public Method
get_callback_method () {
980 assert (this
.coroutine
);
982 if (callback_method
== null) {
983 var bool_type
= new
BooleanType ((Struct
) CodeContext
.get ().root
.scope
.lookup ("bool"));
984 bool_type
.value_owned
= true;
985 callback_method
= new
Method ("callback", bool_type
, source_reference
);
986 callback_method
.access
= SymbolAccessibility
.PUBLIC
;
987 callback_method
.external
= true;
988 callback_method
.binding
= MemberBinding
.INSTANCE
;
989 callback_method
.owner
= scope
;
990 callback_method
.is_async_callback
= true;
992 return callback_method
;
995 public List
<Parameter
> get_async_begin_parameters () {
996 assert (this
.coroutine
);
998 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1000 var params
= new ArrayList
<Parameter
> ();
1001 Parameter ellipsis
= null;
1002 foreach (var param
in parameters
) {
1003 if (param
.ellipsis
) {
1005 } else if (param
.direction
== ParameterDirection
.IN
) {
1010 var callback_type
= new
DelegateType ((Delegate
) glib_ns
.scope
.lookup ("AsyncReadyCallback"));
1011 callback_type
.nullable
= true;
1012 callback_type
.value_owned
= true;
1013 callback_type
.is_called_once
= true;
1015 var callback_param
= new
Parameter ("_callback_", callback_type
);
1016 callback_param
.initializer
= new
NullLiteral (source_reference
);
1017 callback_param
.initializer
.target_type
= callback_type
.copy ();
1018 callback_param
.set_attribute_double ("CCode", "pos", -1);
1019 callback_param
.set_attribute_double ("CCode", "delegate_target_pos", -0.9);
1021 params
.add (callback_param
);
1023 if (ellipsis
!= null) {
1024 params
.add (ellipsis
);
1030 public List
<Parameter
> get_async_end_parameters () {
1031 assert (this
.coroutine
);
1033 var params
= new ArrayList
<Parameter
> ();
1035 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1036 var result_type
= new
ObjectType ((ObjectTypeSymbol
) glib_ns
.scope
.lookup ("AsyncResult"));
1038 var result_param
= new
Parameter ("_res_", result_type
);
1039 result_param
.set_attribute_double ("CCode", "pos", 0.1);
1040 params
.add (result_param
);
1042 foreach (var param
in parameters
) {
1043 if (param
.direction
== ParameterDirection
.OUT
) {
1051 public void add_captured_variable (LocalVariable local
) {
1052 assert (this
.closure
);
1054 if (captured_variables
== null) {
1055 captured_variables
= new ArrayList
<LocalVariable
> ();
1057 captured_variables
.add (local
);
1060 public void get_captured_variables (Collection
<LocalVariable
> variables
) {
1061 if (captured_variables
!= null) {
1062 foreach (var local
in captured_variables
) {
1063 variables
.add (local
);
1068 public override void get_defined_variables (Collection
<Variable
> collection
) {
1069 // capturing variables is only supported if they are initialized
1070 // therefore assume that captured variables are initialized
1072 get_captured_variables ((Collection
<LocalVariable
>) collection
);
1076 public int get_format_arg_index () {
1077 for (int i
= 0; i
< parameters
.size
; i
++) {
1078 if (parameters
[i
].format_arg
) {