1 /* valadelegatetype.vala
3 * Copyright (C) 2007-2012 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
26 * The type of an instance of a delegate.
28 public class Vala
.DelegateType
: CallableType
{
29 public weak Delegate delegate_symbol
{ get; set; }
31 public bool is_called_once
{ get; set; }
33 public DelegateType (Delegate delegate_symbol
) {
34 this
.delegate_symbol
= delegate_symbol
;
35 this
.is_called_once
= (delegate_symbol
.get_attribute_string ("CCode", "scope") == "async");
38 public override bool is_invokable () {
42 public override DataType?
get_return_type () {
43 return delegate_symbol
.return_type
;
46 public override List
<Parameter
>?
get_parameters () {
47 return delegate_symbol
.get_parameters ();
50 public override string to_qualified_string (Scope? scope
) {
51 // logic temporarily duplicated from DataType class
53 Symbol global_symbol
= delegate_symbol
;
54 while (global_symbol
.parent_symbol
!= null && global_symbol
.parent_symbol
.name
!= null) {
55 global_symbol
= global_symbol
.parent_symbol
;
59 Scope parent_scope
= scope
;
60 while (sym
== null && parent_scope
!= null) {
61 sym
= parent_scope
.lookup (global_symbol
.name
);
62 parent_scope
= parent_scope
.parent_scope
;
67 if (sym
!= null && global_symbol
!= sym
) {
68 s
= "global::" + delegate_symbol
.get_full_name ();;
70 s
= delegate_symbol
.get_full_name ();
73 var type_args
= get_type_arguments ();
74 if (type_args
.size
> 0) {
77 foreach (DataType type_arg
in type_args
) {
83 if (!type_arg
.value_owned
) {
86 s
+= type_arg
.to_qualified_string (scope
);
96 public override DataType
copy () {
97 var result
= new
DelegateType (delegate_symbol
);
98 result
.source_reference
= source_reference
;
99 result
.value_owned
= value_owned
;
100 result
.nullable
= nullable
;
102 foreach (DataType arg
in get_type_arguments ()) {
103 result
.add_type_argument (arg
.copy ());
106 result
.is_called_once
= is_called_once
;
111 public override bool is_accessible (Symbol sym
) {
112 return delegate_symbol
.is_accessible (sym
);
115 public override bool check (CodeContext context
) {
116 if (is_called_once
&& !value_owned
) {
117 Report
.warning (source_reference
, "delegates with scope=\"async\" must be owned");
120 if (!delegate_symbol
.check (context
)) {
124 var n_type_params
= delegate_symbol
.get_type_parameters ().size
;
125 var n_type_args
= get_type_arguments ().size
;
126 if (n_type_args
> 0 && n_type_args
< n_type_params
) {
127 Report
.error (source_reference
, "too few type arguments");
129 } else if (n_type_args
> 0 && n_type_args
> n_type_params
) {
130 Report
.error (source_reference
, "too many type arguments");
134 foreach (DataType type
in get_type_arguments ()) {
135 if (!type
.check (context
)) {
143 public override bool compatible (DataType target_type
) {
144 var dt_target
= target_type as DelegateType
;
145 if (dt_target
== null) {
150 if (delegate_symbol
== dt_target
.delegate_symbol
) {
154 // target-delegate is allowed to ensure stricter return type (stronger postcondition)
155 if (!get_return_type ().stricter (dt_target
.get_return_type ().get_actual_type (dt_target
, null, this
))) {
159 var parameters
= get_parameters ();
160 Iterator
<Parameter
> params_it
= parameters
.iterator ();
162 if (dt_target
.delegate_symbol
.parent_symbol is Signal
&& dt_target
.delegate_symbol
.sender_type
!= null && parameters
.size
== dt_target
.get_parameters ().size
+ 1) {
163 // target-delegate has sender parameter
166 // target-delegate is allowed to accept arguments of looser types (weaker precondition)
167 var p
= params_it
.get ();
168 if (!dt_target
.delegate_symbol
.sender_type
.stricter (p
.variable_type
)) {
173 foreach (Parameter param
in dt_target
.get_parameters ()) {
174 /* target-delegate is allowed to accept less arguments */
175 if (!params_it
.next ()) {
179 // target-delegate is allowed to accept arguments of looser types (weaker precondition)
180 var p
= params_it
.get ();
181 if (!param
.variable_type
.get_actual_type (this
, null, this
).stricter (p
.variable_type
)) {
186 /* target-delegate may not expect more arguments */
187 if (params_it
.next ()) {
191 // target-delegate may throw less but not more errors than the delegate
192 foreach (DataType error_type
in get_error_types ()) {
194 foreach (DataType delegate_error_type
in dt_target
.get_error_types ()) {
195 if (error_type
.compatible (delegate_error_type
)) {
209 public override bool is_disposable () {
210 return delegate_symbol
.has_target
&& value_owned
&& !is_called_once
;