vala: Report error for error-domains without any code
[vala-gnome.git] / vala / valaarraytype.vala
blob626c60c89954b40e965c9e7c4f3c125a55ea5b05
1 /* valaarraytype.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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * An array type.
28 public class Vala.ArrayType : ReferenceType {
29 /**
30 * The element type.
32 public DataType element_type {
33 get { return _element_type; }
34 set {
35 _element_type = value;
36 _element_type.parent_node = this;
40 public bool invalid_syntax { get; set; }
42 public bool inline_allocated { get; set; }
44 public bool fixed_length { get; set; }
46 /**
47 * The length of this fixed-length array.
49 public Expression? length {
50 get { return _length; }
51 set {
52 _length = value;
53 if (_length != null) {
54 _length.parent_node = this;
59 /**
60 * The rank of this array.
62 public int rank { get; set; }
64 private DataType _element_type;
65 private Expression _length;
67 private ArrayLengthField length_field;
68 private ArrayResizeMethod resize_method;
69 private ArrayMoveMethod move_method;
70 private ArrayCopyMethod copy_method;
72 public ArrayType (DataType element_type, int rank, SourceReference? source_reference) {
73 this.element_type = element_type;
74 this.rank = rank;
75 this.source_reference = source_reference;
78 public override Symbol? get_member (string member_name) {
79 if (member_name == "length") {
80 return get_length_field ();
81 } else if (member_name == "move") {
82 return get_move_method ();
83 } else if (member_name == "resize") {
84 if (rank > 1) {
85 return null;
87 return get_resize_method ();
88 } else if (member_name == "copy") {
89 return get_copy_method ();
91 return null;
94 private ArrayLengthField get_length_field () {
95 if (length_field == null) {
96 length_field = new ArrayLengthField (source_reference);
98 length_field.access = SymbolAccessibility.PUBLIC;
100 var root_symbol = source_reference.file.context.root;
101 if (rank > 1) {
102 // length is an int[] containing the dimensions of the array, starting at 0
103 ValueType integer = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
104 length_field.variable_type = new ArrayType (integer, 1, source_reference);
105 } else {
106 length_field.variable_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
110 return length_field;
113 private ArrayResizeMethod get_resize_method () {
114 if (resize_method == null) {
115 resize_method = new ArrayResizeMethod (source_reference);
117 resize_method.return_type = new VoidType ();
118 resize_method.access = SymbolAccessibility.PUBLIC;
120 resize_method.set_attribute_string ("CCode", "cname", "g_renew");
122 var root_symbol = source_reference.file.context.root;
123 var int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
125 resize_method.add_parameter (new Parameter ("length", int_type));
127 resize_method.returns_modified_pointer = true;
129 return resize_method;
132 private ArrayMoveMethod get_move_method () {
133 if (move_method == null) {
134 move_method = new ArrayMoveMethod (source_reference);
136 move_method.return_type = new VoidType ();
137 move_method.access = SymbolAccessibility.PUBLIC;
139 move_method.set_attribute_string ("CCode", "cname", "_vala_array_move");
141 var root_symbol = source_reference.file.context.root;
142 var int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
144 move_method.add_parameter (new Parameter ("src", int_type));
145 move_method.add_parameter (new Parameter ("dest", int_type));
146 move_method.add_parameter (new Parameter ("length", int_type));
148 return move_method;
151 private ArrayCopyMethod get_copy_method () {
152 if (copy_method == null) {
153 copy_method = new ArrayCopyMethod (source_reference);
155 copy_method.return_type = this.copy ();
156 copy_method.return_type.value_owned = true;
157 copy_method.access = SymbolAccessibility.PUBLIC;
159 copy_method.set_attribute_string ("CCode", "cname", "_vala_array_copy");
161 return copy_method;
164 public override DataType copy () {
165 var result = new ArrayType (element_type.copy (), rank, source_reference);
166 result.value_owned = value_owned;
167 result.nullable = nullable;
168 result.floating_reference = floating_reference;
170 result.inline_allocated = inline_allocated;
171 if (fixed_length) {
172 result.fixed_length = true;
173 result.length = length;
176 return result;
179 public override bool is_array () {
180 return true;
183 public override string to_qualified_string (Scope? scope) {
184 var elem_str = element_type.to_qualified_string (scope);
185 if (element_type.is_weak () && !(parent_node is Constant)) {
186 elem_str = "(unowned %s)".printf (elem_str);
189 if (!fixed_length) {
190 return "%s[%s]%s".printf (elem_str, string.nfill (rank - 1, ','), nullable ? "?" : "");
191 } else {
192 return elem_str;
196 public override bool compatible (DataType target_type) {
197 if (CodeContext.get ().profile == Profile.GOBJECT && target_type.data_type != null) {
198 if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvalue_type.data_type) && element_type.data_type == CodeContext.get ().root.scope.lookup ("string")) {
199 // allow implicit conversion from string[] to GValue
200 return true;
203 if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvariant_type.data_type)) {
204 // allow implicit conversion to GVariant
205 return true;
209 if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
210 /* any array type can be cast to a generic pointer */
211 return true;
214 /* temporarily ignore type parameters */
215 if (target_type is GenericType) {
216 return true;
219 var target_array_type = target_type as ArrayType;
220 if (target_array_type == null) {
221 return false;
224 if (target_array_type.rank != rank) {
225 return false;
228 if (element_type is ValueType && element_type.nullable != target_array_type.element_type.nullable) {
229 return false;
232 if (element_type.compatible (target_array_type.element_type)
233 && target_array_type.element_type.compatible (element_type)) {
234 return true;
237 return false;
240 public override bool is_reference_type_or_type_parameter () {
241 return true;
244 public override void accept_children (CodeVisitor visitor) {
245 element_type.accept (visitor);
248 public override void replace_type (DataType old_type, DataType new_type) {
249 if (element_type == old_type) {
250 element_type = new_type;
254 public override bool is_accessible (Symbol sym) {
255 return element_type.is_accessible (sym);
258 public override bool check (CodeContext context) {
259 if (invalid_syntax) {
260 Report.error (source_reference, "syntax error, no expression allowed between array brackets");
261 error = true;
262 return false;
265 if (fixed_length && length != null) {
266 length.check (context);
268 if (length.value_type == null || !(length.value_type is IntegerType) || !length.is_constant ()) {
269 Report.error (length.source_reference, "Expression of constant integer type expected");
270 return false;
274 return element_type.check (context);
277 public override DataType get_actual_type (DataType? derived_instance_type, List<DataType>? method_type_arguments, CodeNode node_reference) {
278 ArrayType result = (ArrayType) this.copy ();
280 if (derived_instance_type == null && method_type_arguments == null) {
281 return result;
284 if (element_type is GenericType || element_type.has_type_arguments ()) {
285 result.element_type = result.element_type.get_actual_type (derived_instance_type, method_type_arguments, node_reference);
288 return result;
291 public override DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
292 var array_type = value_type as ArrayType;
293 if (array_type != null) {
294 return element_type.infer_type_argument (type_param, array_type.element_type);
297 return null;
300 public override bool is_disposable () {
301 if (fixed_length) {
302 return element_type.is_disposable ();
303 } else {
304 return base.is_disposable ();