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
: 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 return_block
{ get; set; }
60 public BasicBlock exit_block
{ get; set; }
63 * Specifies whether this method may only be called with an instance of
66 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
69 * The name of the vfunc of this method as it is used in C code.
71 public string vfunc_name
{
73 if (_vfunc_name
== null) {
74 _vfunc_name
= this
.name
;
84 * The sentinel to use for terminating variable length argument lists.
86 public string sentinel
{
88 if (_sentinel
== null) {
89 return DEFAULT_SENTINEL
;
101 * Specifies whether this method is abstract. Abstract methods have no
102 * body, may only be specified within abstract classes, and must be
103 * overriden by derived non-abstract classes.
105 public bool is_abstract
{ get; set; }
108 * Specifies whether this method is virtual. Virtual methods may be
109 * overridden by derived classes.
111 public bool is_virtual
{ get; set; }
114 * Specifies whether this method overrides a virtual or abstract method
117 public bool overrides
{ get; set; }
120 * Specifies whether this method should be inlined.
122 public bool is_inline
{ get; set; }
124 public bool returns_floating_reference
{ get; set; }
127 * Specifies whether the C method returns a new instance pointer which
128 * may be different from the previous instance pointer. Only valid for
131 public bool returns_modified_pointer
{ get; set; }
134 * Specifies the virtual or abstract method this method overrides.
135 * Reference must be weak as virtual and abstract methods set
136 * base_method to themselves.
138 public Method base_method
{
140 find_base_methods ();
146 * Specifies the abstract interface method this method implements.
148 public Method base_interface_method
{
150 find_base_methods ();
151 return _base_interface_method
;
155 public bool entry_point
{ get; private set; }
158 * Specifies the generated `this` parameter for instance methods.
160 public FormalParameter this_parameter
{ get; set; }
163 * Specifies the generated `result` variable for postconditions.
165 public LocalVariable result_var
{ get; set; }
168 * Specifies the position of the instance parameter in the C function.
170 public double cinstance_parameter_position
{ get; set; }
173 * Specifies the position of the array length out parameter in the C
176 public double carray_length_parameter_position
{ get; set; }
179 * Specifies the position of the delegate target out parameter in the C
182 public double cdelegate_target_parameter_position
{ get; set; }
185 * Specifies whether the array length should be returned implicitly
186 * if the return type is an array.
188 public bool no_array_length
{ get; set; }
191 * Specifies whether the array is null terminated.
193 public bool array_null_terminated
{ get; set; }
196 * Specified a custom type for the array length parameter.
198 public string? array_length_type
{ get; set; default = null; }
201 * Specifies whether this method expects printf-style format arguments.
203 public bool printf_format
{ get; set; }
206 * Specifies whether this method expects scanf-style format arguments.
208 public bool scanf_format
{ get; set; }
211 * Specifies whether a new function without a GType parameter is
212 * available. This is only applicable to creation methods.
214 public bool has_new_function
{ get; set; default = true; }
217 * Specifies whether a construct function with a GType parameter is
218 * available. This is only applicable to creation methods.
220 public bool has_construct_function
{ get; set; default = true; }
222 public bool has_generic_type_parameter
{ get; set; }
224 public double generic_type_parameter_position
{ get; set; }
226 public bool simple_generics
{ get; set; }
228 public weak Signal signal_reference
{ get; set; }
230 public bool closure
{ get; set; }
232 public bool coroutine
{ get; set; }
234 public bool is_async_callback
{ get; set; }
236 private List
<FormalParameter
> parameters
= new ArrayList
<FormalParameter
> ();
237 private string cname
;
238 private string finish_name
;
239 private string _vfunc_name
;
240 private string _sentinel
;
241 private List
<Expression
> preconditions
= new ArrayList
<Expression
> ();
242 private List
<Expression
> postconditions
= new ArrayList
<Expression
> ();
243 private DataType _return_type
;
246 private weak Method _base_method
;
247 private Method _base_interface_method
;
248 private bool base_methods_valid
;
250 Method? callback_method
;
252 // only valid for closures
253 List
<LocalVariable
> captured_variables
;
256 * Creates a new method.
258 * @param name method name
259 * @param return_type method return type
260 * @param source reference to source code
261 * @return newly created method
263 public Method (string? name
, DataType return_type
, SourceReference? source_reference
= null, Comment? comment
= null) {
264 base (name
, source_reference
, comment
);
265 this
.return_type
= return_type
;
267 carray_length_parameter_position
= -3;
268 cdelegate_target_parameter_position
= -3;
272 * Appends parameter to this method.
274 * @param param a formal parameter
276 public void add_parameter (FormalParameter param
) {
277 // default C parameter position
278 param
.cparameter_position
= parameters
.size
+ 1;
279 param
.carray_length_parameter_position
= param
.cparameter_position
+ 0.1;
280 param
.cdelegate_target_parameter_position
= param
.cparameter_position
+ 0.1;
281 param
.cdestroy_notify_parameter_position
= param
.cparameter_position
+ 0.1;
283 parameters
.add (param
);
284 if (!param
.ellipsis
) {
285 scope
.add (param
.name
, param
);
289 public List
<FormalParameter
> get_parameters () {
294 * Remove all parameters from this method.
296 public void clear_parameters () {
297 foreach (FormalParameter param
in parameters
) {
298 if (!param
.ellipsis
) {
299 scope
.remove (param
.name
);
305 public override void accept (CodeVisitor visitor
) {
306 visitor
.visit_method (this
);
309 public override void accept_children (CodeVisitor visitor
) {
310 foreach (TypeParameter p
in get_type_parameters ()) {
314 if (return_type
!= null) {
315 return_type
.accept (visitor
);
318 foreach (FormalParameter param
in parameters
) {
319 param
.accept (visitor
);
322 foreach (DataType error_type
in get_error_types ()) {
323 error_type
.accept (visitor
);
326 if (result_var
!= null) {
327 result_var
.accept (visitor
);
330 foreach (Expression precondition
in preconditions
) {
331 precondition
.accept (visitor
);
334 foreach (Expression postcondition
in postconditions
) {
335 postcondition
.accept (visitor
);
339 body
.accept (visitor
);
344 * Returns the interface name of this method as it is used in C code.
346 * @return the name to be used in C code
348 public string get_cname () {
350 cname
= get_default_cname ();
355 public string get_finish_cname () {
357 if (finish_name
== null) {
358 finish_name
= get_default_finish_cname ();
363 public void set_finish_cname (string name
) {
368 * Returns the default interface name of this method as it is used in C
371 * @return the name to be used in C code by default
373 public virtual string get_default_cname () {
374 if (name
== "main" && parent_symbol
.name
== null) {
375 // avoid conflict with generated main function
377 } else if (name
.has_prefix ("_")) {
378 return "_%s%s".printf (parent_symbol
.get_lower_case_cprefix (), name
.offset (1));
380 return "%s%s".printf (parent_symbol
.get_lower_case_cprefix (), name
);
385 * Returns the implementation name of this data type as it is used in C
388 * @return the name to be used in C code
390 public virtual string get_real_cname () {
391 if (base_method
!= null || base_interface_method
!= null) {
392 return "%sreal_%s".printf (parent_symbol
.get_lower_case_cprefix (), name
);
398 protected string get_finish_name_for_basename (string basename
) {
399 string result
= basename
;
400 if (result
.has_suffix ("_async")) {
401 result
= result
.substring (0, result
.length
- "_async".length
);
407 public string get_finish_real_cname () {
409 return get_finish_name_for_basename (get_real_cname ());
412 public string get_finish_vfunc_name () {
414 return get_finish_name_for_basename (vfunc_name
);
417 public string get_default_finish_cname () {
418 return get_finish_name_for_basename (get_cname ());
422 * Sets the name of this method as it is used in C code.
424 * @param cname the name to be used in C code
426 public void set_cname (string cname
) {
430 private void process_ccode_attribute (Attribute a
) {
431 if (a
.has_argument ("cname")) {
432 set_cname (a
.get_string ("cname"));
434 if (a
.has_argument ("cheader_filename")) {
435 var val
= a
.get_string ("cheader_filename");
436 foreach (string filename
in val
.split (",")) {
437 add_cheader_filename (filename
);
440 if (a
.has_argument ("vfunc_name")) {
441 this
.vfunc_name
= a
.get_string ("vfunc_name");
443 if (a
.has_argument ("finish_name")) {
444 this
.finish_name
= a
.get_string ("finish_name");
446 if (a
.has_argument ("sentinel")) {
447 this
.sentinel
= a
.get_string ("sentinel");
449 if (a
.has_argument ("instance_pos")) {
450 cinstance_parameter_position
= a
.get_double ("instance_pos");
452 if (a
.has_argument ("array_length")) {
453 no_array_length
= !a
.get_bool ("array_length");
455 if (a
.has_argument ("array_length_type")) {
456 array_length_type
= a
.get_string ("array_length_type");
458 if (a
.has_argument ("array_null_terminated")) {
459 array_null_terminated
= a
.get_bool ("array_null_terminated");
461 if (a
.has_argument ("array_length_pos")) {
462 carray_length_parameter_position
= a
.get_double ("array_length_pos");
464 if (a
.has_argument ("delegate_target_pos")) {
465 cdelegate_target_parameter_position
= a
.get_double ("delegate_target_pos");
467 if (a
.has_argument ("has_new_function")) {
468 has_new_function
= a
.get_bool ("has_new_function");
470 if (a
.has_argument ("has_construct_function")) {
471 has_construct_function
= a
.get_bool ("has_construct_function");
473 if (a
.has_argument ("generic_type_pos")) {
474 has_generic_type_parameter
= true;
475 generic_type_parameter_position
= a
.get_double ("generic_type_pos");
477 if (a
.has_argument ("simple_generics")) {
478 simple_generics
= a
.get_bool ("simple_generics");
480 if (a
.has_argument ("returns_floating_reference")) {
481 returns_floating_reference
= a
.get_bool ("returns_floating_reference");
486 * Process all associated attributes.
488 public void process_attributes () {
489 foreach (Attribute a
in attributes
) {
490 if (a
.name
== "CCode") {
491 process_ccode_attribute (a
);
492 } else if (a
.name
== "ReturnsModifiedPointer") {
493 returns_modified_pointer
= true;
494 } else if (a
.name
== "FloatingReference") {
495 return_type
.floating_reference
= true;
496 } else if (a
.name
== "PrintfFormat") {
497 printf_format
= true;
498 } else if (a
.name
== "ScanfFormat") {
500 } else if (a
.name
== "NoArrayLength") {
501 Report
.warning (source_reference
, "NoArrayLength attribute is deprecated, use [CCode (array_length = false)] instead.");
502 no_array_length
= true;
503 } else if (a
.name
== "Deprecated") {
504 process_deprecated_attribute (a
);
510 * Checks whether the parameters and return type of this method are
511 * compatible with the specified method
513 * @param base_method a method
514 * @param invalid_match error string about which check failed
515 * @return true if the specified method is compatible to this method
517 public bool compatible (Method base_method
, out string? invalid_match
) {
518 if (binding
!= base_method
.binding
) {
519 invalid_match
= "incompatible binding";
523 ObjectType object_type
= null;
524 if (parent_symbol is ObjectTypeSymbol
) {
525 object_type
= new
ObjectType ((ObjectTypeSymbol
) parent_symbol
);
526 foreach (TypeParameter type_parameter
in object_type
.type_symbol
.get_type_parameters ()) {
527 var type_arg
= new
GenericType (type_parameter
);
528 type_arg
.value_owned
= true;
529 object_type
.add_type_argument (type_arg
);
533 var actual_base_type
= base_method
.return_type
.get_actual_type (object_type
, null, this
);
534 if (!return_type
.equals (actual_base_type
)) {
535 invalid_match
= "incompatible return type";
539 Iterator
<FormalParameter
> method_params_it
= parameters
.iterator ();
541 foreach (FormalParameter base_param
in base_method
.parameters
) {
542 /* this method may not expect less arguments */
543 if (!method_params_it
.next ()) {
544 invalid_match
= "too few parameters";
548 actual_base_type
= base_param
.parameter_type
.get_actual_type (object_type
, null, this
);
549 if (!actual_base_type
.equals (method_params_it
.get ().parameter_type
)) {
550 invalid_match
= "incompatible type of parameter %d".printf (param_index
);
556 /* this method may not expect more arguments */
557 if (method_params_it
.next ()) {
558 invalid_match
= "too many parameters";
562 /* this method may throw less but not more errors than the base method */
563 foreach (DataType method_error_type
in get_error_types ()) {
565 foreach (DataType base_method_error_type
in base_method
.get_error_types ()) {
566 if (method_error_type
.compatible (base_method_error_type
)) {
573 invalid_match
= "incompatible error type `%s'".printf (method_error_type
.to_string ());
577 if (base_method
.coroutine
!= this
.coroutine
) {
578 invalid_match
= "async mismatch";
586 * Appends the specified parameter to the list of type parameters.
588 * @param p a type parameter
590 public void add_type_parameter (TypeParameter p
) {
591 type_parameters
.add (p
);
592 scope
.add (p
.name
, p
);
596 * Returns a copy of the type parameter list.
598 * @return list of type parameters
600 public List
<TypeParameter
> get_type_parameters () {
601 return type_parameters
;
604 public int get_type_parameter_index (string name
) {
606 foreach (TypeParameter parameter
in type_parameters
) {
607 if (parameter
.name
== name
) {
616 * Adds a precondition to this method.
618 * @param precondition a boolean precondition expression
620 public void add_precondition (Expression precondition
) {
621 preconditions
.add (precondition
);
622 precondition
.parent_node
= this
;
626 * Returns a copy of the list of preconditions of this method.
628 * @return list of preconditions
630 public List
<Expression
> get_preconditions () {
631 return preconditions
;
635 * Adds a postcondition to this method.
637 * @param postcondition a boolean postcondition expression
639 public void add_postcondition (Expression postcondition
) {
640 postconditions
.add (postcondition
);
641 postcondition
.parent_node
= this
;
645 * Returns a copy of the list of postconditions of this method.
647 * @return list of postconditions
649 public List
<Expression
> get_postconditions () {
650 return postconditions
;
653 public override void replace_type (DataType old_type
, DataType new_type
) {
654 if (return_type
== old_type
) {
655 return_type
= new_type
;
658 var error_types
= get_error_types ();
659 for (int i
= 0; i
< error_types
.size
; i
++) {
660 if (error_types
[i
] == old_type
) {
661 error_types
[i
] = new_type
;
667 private void find_base_methods () {
668 if (base_methods_valid
) {
672 if (parent_symbol is Class
) {
673 if (!(this is CreationMethod
)) {
674 find_base_interface_method ((Class
) parent_symbol
);
675 if (is_virtual
|| is_abstract
|| overrides
) {
676 find_base_class_method ((Class
) parent_symbol
);
679 } else if (parent_symbol is Interface
) {
680 if (is_virtual
|| is_abstract
) {
681 _base_interface_method
= this
;
685 base_methods_valid
= true;
688 private void find_base_class_method (Class cl
) {
689 var sym
= cl
.scope
.lookup (name
);
691 var base_method
= (Method
) sym
;
692 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
693 string invalid_match
;
694 if (!compatible (base_method
, out invalid_match
)) {
696 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
));
700 _base_method
= base_method
;
703 } else if (sym is Signal
) {
704 var sig
= (Signal
) sym
;
705 if (sig
.is_virtual
) {
706 var base_method
= sig
.default_handler
;
707 string invalid_match
;
708 if (!compatible (base_method
, out invalid_match
)) {
710 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
));
714 _base_method
= base_method
;
719 if (cl
.base_class
!= null) {
720 find_base_class_method (cl
.base_class
);
724 private void find_base_interface_method (Class cl
) {
725 // FIXME report error if multiple possible base methods are found
726 foreach (DataType type
in cl
.get_base_types ()) {
727 if (type
.data_type is Interface
) {
728 var sym
= type
.data_type
.scope
.lookup (name
);
730 var base_method
= (Method
) sym
;
731 if (base_method
.is_abstract
|| base_method
.is_virtual
) {
732 string invalid_match
;
733 if (!compatible (base_method
, out invalid_match
)) {
735 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
));
739 _base_interface_method
= base_method
;
747 public override bool check (SemanticAnalyzer analyzer
) {
754 process_attributes ();
757 if (parent_symbol is Class
) {
758 var cl
= (Class
) parent_symbol
;
759 if (!cl
.is_abstract
) {
761 Report
.error (source_reference
, "Abstract methods may not be declared in non-abstract classes");
764 } else if (!(parent_symbol is Interface
)) {
766 Report
.error (source_reference
, "Abstract methods may not be declared outside of classes and interfaces");
769 } else if (is_virtual
) {
770 if (!(parent_symbol is Class
) && !(parent_symbol is Interface
)) {
772 Report
.error (source_reference
, "Virtual methods may not be declared outside of classes and interfaces");
776 if (parent_symbol is Class
) {
777 var cl
= (Class
) parent_symbol
;
779 Report
.error (source_reference
, "Virtual methods may not be declared in compact classes");
783 } else if (overrides
) {
784 if (!(parent_symbol is Class
)) {
786 Report
.error (source_reference
, "Methods may not be overridden outside of classes");
789 } else if (access
== SymbolAccessibility
.PROTECTED
) {
790 if (!(parent_symbol is Class
) && !(parent_symbol is Interface
)) {
792 Report
.error (source_reference
, "Protected methods may not be declared outside of classes and interfaces");
797 if (is_abstract
&& body
!= null) {
798 Report
.error (source_reference
, "Abstract methods cannot have bodies");
799 } else if ((is_abstract
|| is_virtual
) && external
&& !external_package
&& !parent_symbol
.external
) {
800 Report
.error (source_reference
, "Extern methods cannot be abstract or virtual");
801 } else if (external
&& body
!= null) {
802 Report
.error (source_reference
, "Extern methods cannot have bodies");
803 } else if (!is_abstract
&& !external
&& !external_package
&& body
== null) {
804 Report
.error (source_reference
, "Non-abstract, non-extern methods must have bodies");
807 if (coroutine
&& !external_package
&& !analyzer
.context
.has_package ("gio-2.0")) {
809 Report
.error (source_reference
, "gio-2.0 package required for async methods");
813 var old_source_file
= analyzer
.current_source_file
;
814 var old_symbol
= analyzer
.current_symbol
;
816 if (source_reference
!= null) {
817 analyzer
.current_source_file
= source_reference
.file
;
819 analyzer
.current_symbol
= this
;
821 return_type
.check (analyzer
);
823 var init_attr
= get_attribute ("ModuleInit");
824 if (init_attr
!= null) {
825 source_reference
.file
.context
.module_init_method
= this
;
828 if (return_type
!= null) {
829 return_type
.check (analyzer
);
832 if (parameters
.size
== 1 && parameters
[0].ellipsis
&& body
!= null) {
833 // accept just `...' for external methods for convenience
835 Report
.error (parameters
[0].source_reference
, "Named parameter required before `...'");
838 foreach (FormalParameter param
in parameters
) {
839 param
.check (analyzer
);
840 if (coroutine
&& param
.direction
== ParameterDirection
.REF
) {
842 Report
.error (param
.source_reference
, "Reference parameters are not supported for async methods");
846 foreach (DataType error_type
in get_error_types ()) {
847 error_type
.check (analyzer
);
850 if (result_var
!= null) {
851 result_var
.check (analyzer
);
854 foreach (Expression precondition
in preconditions
) {
855 precondition
.check (analyzer
);
858 foreach (Expression postcondition
in postconditions
) {
859 postcondition
.check (analyzer
);
863 body
.check (analyzer
);
866 analyzer
.current_source_file
= old_source_file
;
867 analyzer
.current_symbol
= old_symbol
;
869 if (analyzer
.current_struct
!= null) {
870 if (is_abstract
|| is_virtual
|| overrides
) {
871 Report
.error (source_reference
, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
874 } else if (overrides
&& base_method
== null) {
875 Report
.error (source_reference
, "%s: no suitable method found to override".printf (get_full_name ()));
878 if (!external_package
&& !overrides
&& !hides
&& get_hidden_member () != null) {
879 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 ()));
882 // check whether return type is at least as accessible as the method
883 if (!analyzer
.is_type_accessible (this
, return_type
)) {
885 Report
.error (source_reference
, "return type `%s` is less accessible than method `%s`".printf (return_type
.to_string (), get_full_name ()));
889 foreach (Expression precondition
in get_preconditions ()) {
890 if (precondition
.error
) {
891 // if there was an error in the precondition, skip this check
896 if (!precondition
.value_type
.compatible (analyzer
.bool_type
)) {
898 Report
.error (precondition
.source_reference
, "Precondition must be boolean");
903 foreach (Expression postcondition
in get_postconditions ()) {
904 if (postcondition
.error
) {
905 // if there was an error in the postcondition, skip this check
910 if (!postcondition
.value_type
.compatible (analyzer
.bool_type
)) {
912 Report
.error (postcondition
.source_reference
, "Postcondition must be boolean");
917 // check that all errors that can be thrown in the method body are declared
919 foreach (DataType body_error_type
in body
.get_error_types ()) {
920 bool can_propagate_error
= false;
921 foreach (DataType method_error_type
in get_error_types ()) {
922 if (body_error_type
.compatible (method_error_type
)) {
923 can_propagate_error
= true;
926 bool is_dynamic_error
= body_error_type is ErrorType
&& ((ErrorType
) body_error_type
).dynamic_error
;
927 if (!can_propagate_error
&& !is_dynamic_error
) {
928 Report
.warning (body_error_type
.source_reference
, "unhandled error `%s'".printf (body_error_type
.to_string()));
933 if (is_possible_entry_point (analyzer
)) {
934 if (analyzer
.context
.entry_point
!= null) {
936 Report
.error (source_reference
, "program already has an entry point `%s'".printf (analyzer
.context
.entry_point
.get_full_name ()));
940 analyzer
.context
.entry_point
= this
;
943 Report
.error (source_reference
, "\"main\" method cannot throw errors");
950 bool is_possible_entry_point (SemanticAnalyzer analyzer
) {
951 if (external_package
) {
955 if (analyzer
.context
.entry_point_name
== null) {
956 if (name
== null || name
!= "main") {
957 // method must be called "main"
961 // custom entry point name
962 if (get_full_name () != analyzer
.context
.entry_point_name
) {
967 if (binding
== MemberBinding
.INSTANCE
) {
968 // method must be static
972 if (return_type is VoidType
) {
973 } else if (return_type
.data_type
== analyzer
.int_type
.data_type
) {
975 // return type must be void or int
979 var params
= get_parameters ();
980 if (params
.size
== 0) {
981 // method may have no parameters
985 if (params
.size
> 1) {
986 // method must not have more than one parameter
990 Iterator
<FormalParameter
> params_it
= params
.iterator ();
992 var param
= params_it
.get ();
994 if (param
.direction
== ParameterDirection
.OUT
) {
995 // parameter must not be an out parameter
999 if (!(param
.parameter_type is ArrayType
)) {
1000 // parameter must be an array
1004 var array_type
= (ArrayType
) param
.parameter_type
;
1005 if (array_type
.element_type
.data_type
!= analyzer
.string_type
.data_type
) {
1006 // parameter must be an array of strings
1013 public int get_required_arguments () {
1015 foreach (var param
in parameters
) {
1016 if (param
.default_expression
!= null || param
.ellipsis
) {
1017 // optional argument
1025 public Method
get_callback_method () {
1026 assert (this
.coroutine
);
1028 if (callback_method
== null) {
1029 var bool_type
= new
BooleanType ((Struct
) CodeContext
.get ().root
.scope
.lookup ("bool"));
1030 bool_type
.value_owned
= true;
1031 callback_method
= new
Method ("callback", bool_type
, source_reference
);
1032 callback_method
.access
= SymbolAccessibility
.PUBLIC
;
1033 callback_method
.external
= true;
1034 callback_method
.binding
= MemberBinding
.INSTANCE
;
1035 callback_method
.owner
= scope
;
1036 callback_method
.is_async_callback
= true;
1037 callback_method
.set_cname (get_real_cname () + "_co");
1039 return callback_method
;
1042 public List
<FormalParameter
> get_async_begin_parameters () {
1043 assert (this
.coroutine
);
1045 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1047 var params
= new ArrayList
<FormalParameter
> ();
1048 foreach (var param
in parameters
) {
1049 if (param
.direction
== ParameterDirection
.IN
) {
1054 var callback_type
= new
DelegateType ((Delegate
) glib_ns
.scope
.lookup ("AsyncReadyCallback"));
1055 callback_type
.nullable
= true;
1056 callback_type
.is_called_once
= true;
1058 var callback_param
= new
FormalParameter ("_callback_", callback_type
);
1059 callback_param
.default_expression
= new
NullLiteral (source_reference
);
1060 callback_param
.cparameter_position
= -1;
1061 callback_param
.cdelegate_target_parameter_position
= -0.9;
1063 params
.add (callback_param
);
1068 public List
<FormalParameter
> get_async_end_parameters () {
1069 assert (this
.coroutine
);
1071 var params
= new ArrayList
<FormalParameter
> ();
1073 var glib_ns
= CodeContext
.get ().root
.scope
.lookup ("GLib");
1074 var result_type
= new
ObjectType ((ObjectTypeSymbol
) glib_ns
.scope
.lookup ("AsyncResult"));
1076 var result_param
= new
FormalParameter ("_res_", result_type
);
1077 result_param
.cparameter_position
= 0.1;
1078 params
.add (result_param
);
1080 foreach (var param
in parameters
) {
1081 if (param
.direction
== ParameterDirection
.OUT
) {
1089 public void add_captured_variable (LocalVariable local
) {
1090 assert (this
.closure
);
1092 if (captured_variables
== null) {
1093 captured_variables
= new ArrayList
<LocalVariable
> ();
1095 captured_variables
.add (local
);
1098 public void get_captured_variables (Collection
<LocalVariable
> variables
) {
1099 if (captured_variables
!= null) {
1100 foreach (var local
in captured_variables
) {
1101 variables
.add (local
);
1106 public override void get_defined_variables (Collection
<LocalVariable
> collection
) {
1107 // capturing variables is only supported if they are initialized
1108 // therefore assume that captured variables are initialized
1110 get_captured_variables (collection
);