Add string.replace method, patch by Ali Sabil
[vala-lang.git] / vala / valadatatype.vala
blobc0d1878256184072ed8a62d655fa23e1c9c43119
1 /* valadatatype.vala
3 * Copyright (C) 2006-2008 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.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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <raffaele@sandrini.ch>
24 using GLib;
25 using Gee;
27 /**
28 * A reference to a data type. This is used to specify static types of
29 * expressions.
31 public abstract class Vala.DataType : CodeNode {
32 /**
33 * Specifies that the expression or variable owns the value.
35 public bool value_owned { get; set; }
37 /**
38 * Specifies that the expression may be null.
40 public bool nullable { get; set; }
42 /**
43 * Specifies that this type is a generic type argument.
45 public bool is_type_argument { get; set; }
47 /**
48 * The referred data type.
50 public weak TypeSymbol data_type { get; set; }
52 /**
53 * The referred generic type parameter.
55 public TypeParameter type_parameter { get; set; }
57 /**
58 * Specifies that the expression transfers a floating reference.
60 public bool floating_reference { get; set; }
62 /**
63 * Specifies that the type supports dynamic lookup.
65 public bool is_dynamic { get; set; }
67 private Gee.List<DataType> type_argument_list;
68 private static Gee.List<DataType> _empty_type_list;
70 /**
71 * Appends the specified type as generic type argument.
73 * @param arg a type reference
75 public void add_type_argument (DataType arg) {
76 if (type_argument_list == null) {
77 type_argument_list = new ArrayList<DataType> ();
79 type_argument_list.add (arg);
80 arg.parent_node = this;
83 /**
84 * Returns a copy of the list of generic type arguments.
86 * @return type argument list
88 public Gee.List<DataType> get_type_arguments () {
89 if (type_argument_list != null) {
90 return type_argument_list;
92 if (_empty_type_list == null) {
93 _empty_type_list = new ReadOnlyList<DataType> (new ArrayList<DataType> ());
95 return _empty_type_list;
98 /**
99 * Removes all generic type arguments.
101 public void remove_all_type_arguments () {
102 type_argument_list = null;
105 public override void accept (CodeVisitor visitor) {
106 if (type_argument_list != null && type_argument_list.size > 0) {
107 foreach (DataType type_arg in type_argument_list) {
108 type_arg.accept (visitor);
112 visitor.visit_data_type (this);
116 * Returns the name and qualifiers of this type as it is used in C code.
118 * @return the type string to be used in C code
120 public virtual string? get_cname () {
121 // raise error
122 Report.error (source_reference, "unresolved type reference");
123 return null;
127 * Returns the name and qualifiers of this type as it is used in C code
128 * in a const declaration.
130 * @return the type string to be used in C code const declarations
132 public string get_const_cname () {
133 string ptr;
134 TypeSymbol t;
135 // FIXME: workaround to make constant arrays possible
136 if (this is ArrayType) {
137 t = ((ArrayType) this).element_type.data_type;
138 } else {
139 t = data_type;
141 if (!t.is_reference_type ()) {
142 ptr = "";
143 } else {
144 ptr = "*";
147 return "const %s%s".printf (t.get_cname (), ptr);
151 * Returns the C name of this data type in lower case. Words are
152 * separated by underscores.
154 * @param infix a string to be placed between namespace and data type
155 * name or null
156 * @return the lower case name to be used in C code
158 public virtual string? get_lower_case_cname (string? infix = null) {
159 return data_type.get_lower_case_cname (infix);
162 public override string to_string () {
163 return to_qualified_string (null);
166 public virtual string to_qualified_string (Scope? scope = null) {
167 string s;
169 if (data_type != null) {
170 Symbol global_symbol = data_type;
171 while (global_symbol.parent_symbol.name != null) {
172 global_symbol = global_symbol.parent_symbol;
175 Symbol sym = null;
176 Scope parent_scope = scope;
177 while (sym == null && parent_scope != null) {
178 sym = parent_scope.lookup (global_symbol.name);
179 parent_scope = parent_scope.parent_scope;
182 if (sym != null && global_symbol != sym) {
183 s = "global::" + data_type.get_full_name ();;
184 } else {
185 s = data_type.get_full_name ();
187 } else if (type_parameter != null) {
188 s = type_parameter.name;
189 } else {
190 s = "null";
193 var type_args = get_type_arguments ();
194 if (type_args.size > 0) {
195 s += "<";
196 bool first = true;
197 foreach (DataType type_arg in type_args) {
198 if (!first) {
199 s += ",";
200 } else {
201 first = false;
203 if (!type_arg.value_owned) {
204 s += "weak ";
206 s += type_arg.to_qualified_string (scope);
208 s += ">";
210 if (nullable) {
211 s += "?";
214 return s;
218 * Creates a shallow copy of this type reference.
220 * @return copy of this type reference
222 public abstract DataType copy ();
225 * Checks two type references for equality. May only be used with
226 * resolved type references.
228 * @param type2 a type reference
229 * @return true if this type reference is equal to type2, false
230 * otherwise
232 public virtual bool equals (DataType type2) {
233 if (type2.value_owned != value_owned) {
234 return false;
236 if (type2.nullable != nullable) {
237 return false;
239 if (type2.data_type != data_type) {
240 return false;
242 if (type2.type_parameter != null || type_parameter != null) {
243 if (type2.type_parameter == null || type_parameter == null) {
244 return false;
246 if (!type2.type_parameter.equals (type_parameter)) {
247 return false;
250 if (type2.floating_reference != floating_reference) {
251 return false;
254 return true;
258 * Checks whether this type reference is at least as strict as the
259 * specified type reference type2.
261 * @param type2 a type reference
262 * @return true if this type reference is stricter or equal
264 public virtual bool stricter (DataType type2) {
265 if (type2.value_owned != value_owned) {
266 return false;
269 if (!type2.nullable && nullable) {
270 return false;
273 /* temporarily ignore type parameters */
274 if (type_parameter != null || type2.type_parameter != null) {
275 return true;
278 if (type2.data_type != data_type) {
279 // FIXME: allow this type reference to refer to a
280 // subtype of the type type2 is referring to
281 return false;
284 if (type2.floating_reference != floating_reference) {
285 return false;
288 return true;
291 public override void replace_type (DataType old_type, DataType new_type) {
292 if (type_argument_list != null) {
293 for (int i = 0; i < type_argument_list.size; i++) {
294 if (type_argument_list[i] == old_type) {
295 type_argument_list[i] = new_type;
296 return;
302 public virtual bool compatible (DataType target_type) {
303 if (target_type is DelegateType && this is DelegateType) {
304 return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol;
307 if (target_type is PointerType) {
308 /* any reference or array type or pointer type can be cast to a generic pointer */
309 if (type_parameter != null ||
310 (data_type != null && (
311 data_type.is_reference_type () ||
312 this is DelegateType))) {
313 return true;
316 return false;
319 /* temporarily ignore type parameters */
320 if (target_type.type_parameter != null) {
321 return true;
324 if (this is ArrayType != target_type is ArrayType) {
325 return false;
328 if (data_type is Enum && target_type.data_type is Struct && ((Struct) target_type.data_type).is_integer_type ()) {
329 return true;
332 if (data_type == target_type.data_type) {
333 return true;
336 if (data_type is Struct && target_type.data_type is Struct) {
337 var expr_struct = (Struct) data_type;
338 var expect_struct = (Struct) target_type.data_type;
340 /* integer types may be implicitly cast to floating point types */
341 if (expr_struct.is_integer_type () && expect_struct.is_floating_type ()) {
342 return true;
345 if ((expr_struct.is_integer_type () && expect_struct.is_integer_type ()) ||
346 (expr_struct.is_floating_type () && expect_struct.is_floating_type ())) {
347 if (expr_struct.get_rank () <= expect_struct.get_rank ()) {
348 return true;
353 if (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type)) {
354 return true;
357 return false;
361 * Returns whether instances of this type are invokable.
363 * @return true if invokable, false otherwise
365 public virtual bool is_invokable () {
366 return false;
370 * Returns the return type of this invokable.
372 * @return return type
374 public virtual DataType? get_return_type () {
375 return null;
379 * Returns copy of the list of invocation parameters.
381 * @return parameter list
383 public virtual Gee.List<FormalParameter>? get_parameters () {
384 return null;
387 public virtual bool is_reference_type_or_type_parameter () {
388 return (data_type != null &&
389 data_type.is_reference_type ()) ||
390 type_parameter != null;
393 public virtual bool is_array () {
394 return false;
398 * Returns a list of symbols that define this type.
400 * @return symbol list
402 public virtual Gee.List<Symbol> get_symbols () {
403 var symbols = new ArrayList<Symbol> ();
404 if (data_type != null) {
405 symbols.add (data_type);
407 return symbols;
410 public virtual Symbol? get_member (string member_name) {
411 if (data_type != null) {
412 return SemanticAnalyzer.symbol_lookup_inherited (data_type, member_name);
414 return null;
417 public virtual Symbol? get_pointer_member (string member_name) {
418 return null;
422 * Checks whether this data type references a real struct. A real struct
423 * is a struct which is not a simple (fundamental) type.
425 public virtual bool is_real_struct_type () {
426 var s = data_type as Struct;
427 if (s != null && !s.is_simple_type ()) {
428 return true;
430 return false;
433 public virtual string? get_type_id () {
434 if (data_type != null) {
435 return data_type.get_type_id ();
436 } else {
437 return null;
442 * Returns type signature as used for GVariant and D-Bus.
444 public virtual string? get_type_signature () {
445 if (data_type != null) {
446 string sig = data_type.get_type_signature ();
448 var type_args = get_type_arguments ();
449 if (type_args.size > 0) {
450 assert (sig.str ("%s") != null);
452 string element_sig = "";
453 foreach (DataType type_arg in type_args) {
454 var s = type_arg.get_type_signature ();
455 if (s != null) {
456 element_sig += s;
460 sig = sig.printf (element_sig);
463 return sig;
464 } else {
465 return null;
470 * Returns whether the value needs to be disposed, i.e. whether
471 * allocated memory or other resources need to be released when
472 * the value is no longer needed.
474 public virtual bool is_disposable () {
475 if (!value_owned) {
476 return false;
479 if (is_reference_type_or_type_parameter ()) {
480 return true;
482 return false;