1 /* valatypereference.vala
3 * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
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 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>
21 * Raffaele Sandrini <rasa@gmx.ch>
27 * A reference to a data type. This is used to specify static types of
30 public class Vala
.TypeReference
: CodeNode
{
32 * Specifies that the expression transfers ownership of its value.
34 public bool transfers_ownership
{ get; set; }
37 * Specifies that the expression assumes ownership if used as an lvalue
40 public bool takes_ownership
{ get; set; }
43 * Specifies that the expression is a reference used in out parameters.
45 public bool is_out
{ get; set; }
48 * Specifies that the expression is guaranteed not to be null.
50 public bool non_null
{ get; set; }
53 * Specifies that the expression is known to be null.
55 public bool is_null
{ get; set; }
58 * The referred data type.
60 public weak DataType data_type
{ get; set; }
63 * The referred generic type parameter.
65 public TypeParameter type_parameter
{ get; set; }
68 * Specifies that the expression transfers a floating reference.
70 public bool floating_reference
{ get; set; }
73 * The name of the namespace containing the referred data type. May only
74 * be used with unresolved type references.
76 public string namespace_name
{ get; set; }
79 * The name of the referred data type. May only be used with unresolved
82 public string type_name
{ get; set; }
85 * Specifies the rank of the array this reference is possibly referring to. "0" indicates no array.
86 * WARNING: This property may only be set by the parser and only be read by the symbol resolver.
88 public int array_rank
{ get; set; }
91 * Specifies the level of the pointer if this is a pointer-type. "0" indicates no pointer-type.
92 * WARNING: This property may only be set by the parser and only be read by the symbol resolver.
94 public int pointer_level
{ get; set; }
97 * Specifies that the expression is a reference used in ref parameters.
99 public bool is_ref
{ get; set; }
102 * The weak modifier has been specified. May only be used with
103 * unresolved type references.
105 public bool is_weak
{ get; set; }
107 private List
<TypeReference
> type_argument_list
;
109 public TypeReference () {
113 * Creates a new type reference.
115 * @param ns optional namespace name
116 * @param type_name type symbol name
117 * @param source reference to source code
118 * @return newly created type reference
120 public TypeReference
.from_name (string ns
, string! type
, SourceReference source
= null) {
123 source_reference
= source
;
127 * Creates a new type reference from a code expression.
129 * @param expr member access expression
130 * @param source reference to source code
131 * @return newly created type reference
133 public static TypeReference
new_from_expression (Expression
! expr
) {
135 string type_name
= null;
136 if (expr is MemberAccess
) {
137 TypeReference type_ref
= null;
139 MemberAccess ma
= (MemberAccess
) expr
;
140 if (ma
.inner
!= null) {
141 if (ma
.inner is MemberAccess
) {
142 var simple
= (MemberAccess
) ma
.inner
;
143 type_ref
= new TypeReference
.from_name (simple
.member_name
, ma
.member_name
, ma
.source_reference
);
146 type_ref
= new TypeReference
.from_name (null, ma
.member_name
, ma
.source_reference
);
149 if (type_ref
!= null) {
150 var type_args
= ma
.get_type_arguments ();
151 foreach (TypeReference arg
in type_args
) {
152 type_ref
.add_type_argument (arg
);
159 Report
.error (expr
.source_reference
, "Type reference must be simple name or member access expression");
164 * Appends the specified type as generic type argument.
166 * @param arg a type reference
168 public void add_type_argument (TypeReference
! arg
) {
169 type_argument_list
.append (arg
);
173 * Returns a copy of the list of generic type arguments.
175 * @return type argument list
177 public List
<weak TypeReference
> get_type_arguments () {
178 return type_argument_list
.copy ();
182 * Removes all generic type arguments.
184 public void remove_all_type_arguments () {
185 type_argument_list
= null;
188 public override void accept (CodeVisitor
! visitor
) {
189 foreach (TypeReference type_arg
in type_argument_list
) {
190 type_arg
.accept (visitor
);
193 visitor
.visit_type_reference (this
);
197 * Returns the name and qualifiers of this type as it is used in C code.
199 * @return the type string to be used in C code
201 public string get_cname (bool var_type
= false, bool const_type
= false) {
202 if (data_type
== null && type_parameter
== null) {
212 if (type_parameter
!= null || (!data_type
.is_reference_type () && !is_ref
&& !is_out
)) {
214 } else if ((data_type
.is_reference_type () && !is_ref
&& !is_out
) || (!data_type
.is_reference_type () && (is_ref
|| is_out
))) {
219 if (data_type
!= null) {
220 return data_type
.get_cname (const_type
).concat (ptr
, arr
, null);
221 } else if (type_parameter
!= null) {
222 return "gpointer".concat (ptr
, arr
, null);
225 Report
.error (source_reference
, "unresolved type reference");
231 * Returns the name and qualifiers of this type as it is used in C code
232 * in a const declaration.
234 * @return the type string to be used in C code const declarations
236 public string get_const_cname () {
239 /* FIXME: dirty hack to make constant arrays possible */
240 if (data_type is Array
) {
241 t
= ((Array
) data_type
).element_type
;
245 if (!t
.is_reference_type ()) {
251 return "const %s%s".printf (t
.get_cname (), ptr
);
255 * Returns a user-readable name of the type corresponding to this type
258 * @return display name
260 public string! to_string () {
261 if (data_type
!= null) {
262 return data_type
.symbol
.get_full_name ();
263 } else if (type_parameter
!= null) {
264 return type_parameter
.name
;
271 * Creates a shallow copy of this type reference.
273 * @return copy of this type reference
275 public TypeReference
! copy () {
276 var result
= new
TypeReference ();
277 result
.source_reference
= source_reference
;
278 result
.transfers_ownership
= transfers_ownership
;
279 result
.takes_ownership
= takes_ownership
;
280 result
.is_out
= is_out
;
281 result
.non_null
= non_null
;
282 result
.data_type
= data_type
;
283 result
.type_parameter
= type_parameter
;
284 result
.floating_reference
= floating_reference
;
285 result
.namespace_name
= namespace_name
;
286 result
.type_name
= type_name
;
287 result
.array_rank
= array_rank
;
288 result
.pointer_level
= pointer_level
;
289 result
.is_ref
= is_ref
;
290 result
.is_weak
= is_weak
;
292 foreach (TypeReference arg
in type_argument_list
) {
293 result
.type_argument_list
.append (arg
.copy ());
300 * Checks two type references for equality. May only be used with
301 * resolved type references.
303 * @param type2 a type reference
304 * @return true if this type reference is equal to type2, false
307 public bool equals (TypeReference
! type2
) {
308 if (type2
.transfers_ownership
!= transfers_ownership
) {
311 if (type2
.takes_ownership
!= takes_ownership
) {
314 if (type2
.is_ref
!= is_ref
) {
317 if (type2
.is_out
!= is_out
) {
320 if (type2
.non_null
!= non_null
) {
323 if (type2
.data_type
!= data_type
) {
326 if (type2
.type_parameter
!= null || type_parameter
!= null) {
327 if (type2
.type_parameter
== null || type_parameter
== null) {
330 if (!type2
.type_parameter
.equals (type_parameter
)) {
334 if (type2
.floating_reference
!= floating_reference
) {
342 * Checks whether this type reference is at least as strict as the
343 * specified type reference type2.
345 * @param type2 a type reference
346 * @return true if this type reference is stricter or equal
348 public bool stricter (TypeReference
! type2
) {
349 if (type2
.transfers_ownership
!= transfers_ownership
) {
352 if (type2
.takes_ownership
!= takes_ownership
) {
355 if (type2
.is_ref
!= is_ref
) {
358 if (type2
.is_out
!= is_out
) {
362 if (type2
.non_null
&& !non_null
) {
366 if (type2
.data_type
!= data_type
) {
367 // FIXME: allow this type reference to refer to a
368 // subtype of the type type2 is referring to
371 if (type2
.type_parameter
!= type_parameter
) {
374 if (type2
.floating_reference
!= floating_reference
) {