valac: Always use the given "pkg-config" and respect PKG_CONFIG envar
[vala-gnome.git] / vala / valaarraycreationexpression.vala
bloba43315788a116b31a6bedf44010a8f62d12e28a0
1 /* valaarraycreationexpression.vala
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
20 * Author:
21 * Raffaele Sandrini <raffaele@sandrini.ch>
22 * Jürg Billeter <j@bitron.ch>
25 using GLib;
27 /**
28 * Represents an array creation expression e.g. {{{ new int[] {1,2,3} }}}.
30 public class Vala.ArrayCreationExpression : Expression {
31 /**
32 * The type of the elements of the array.
34 public DataType element_type {
35 get { return _element_type; }
36 set {
37 _element_type = value;
38 _element_type.parent_node = this;
42 /**
43 * The rank of the array.
45 public int rank { get; set; }
47 /**
48 * The size for each dimension ascending from left to right.
50 private List<Expression> sizes = new ArrayList<Expression> ();
52 /**
53 * The root array initializer list.
55 public InitializerList? initializer_list {
56 get { return _initializer_list; }
57 set {
58 _initializer_list = value;
59 if (_initializer_list != null) {
60 _initializer_list.parent_node = this;
65 private DataType _element_type;
66 private InitializerList? _initializer_list;
68 /**
69 * Add a size expression.
71 public void append_size (Expression size) {
72 sizes.add (size);
73 if (size != null) {
74 size.parent_node = this;
78 /**
79 * Get the sizes for all dimensions ascending from left to right.
81 public List<Expression> get_sizes () {
82 return sizes;
85 public ArrayCreationExpression (DataType element_type, int rank, InitializerList? initializer_list, SourceReference source_reference) {
86 this.element_type = element_type;
87 this.rank = rank;
88 this.initializer_list = initializer_list;
89 this.source_reference = source_reference;
92 public override void accept_children (CodeVisitor visitor) {
93 if (element_type != null) {
94 element_type.accept (visitor);
97 foreach (Expression e in sizes) {
98 e.accept (visitor);
101 if (initializer_list != null) {
102 initializer_list.accept (visitor);
106 public override void accept (CodeVisitor visitor) {
107 visitor.visit_array_creation_expression (this);
109 visitor.visit_expression (this);
112 public override bool is_pure () {
113 return false;
116 public override bool is_accessible (Symbol sym) {
117 foreach (Expression e in sizes) {
118 if (!e.is_accessible (sym)) {
119 return false;
123 if (initializer_list != null) {
124 return initializer_list.is_accessible (sym);
127 return true;
130 public override void replace_expression (Expression old_node, Expression new_node) {
131 for (int i = 0; i < sizes.size; i++) {
132 if (sizes[i] == old_node) {
133 sizes[i] = new_node;
134 return;
139 public override void replace_type (DataType old_type, DataType new_type) {
140 if (element_type == old_type) {
141 element_type = new_type;
145 private int create_sizes_from_initializer_list (CodeContext context, InitializerList il, int rank, List<Literal> sl) {
146 if (sl.size == (this.rank - rank)) {
147 // only add size if this is the first initializer list of the current dimension
148 var init = new IntegerLiteral (il.size.to_string (), il.source_reference);
149 init.check (context);
150 sl.add (init);
153 int subsize = -1;
154 foreach (Expression e in il.get_initializers ()) {
155 if (e is InitializerList) {
156 if (rank == 1) {
157 il.error = true;
158 e.error = true;
159 Report.error (e.source_reference, "Expected array element, got array initializer list");
160 return -1;
162 int size = create_sizes_from_initializer_list (context, (InitializerList) e, rank - 1, sl);
163 if (size == -1) {
164 return -1;
166 if (subsize >= 0 && subsize != size) {
167 il.error = true;
168 Report.error (il.source_reference, "Expected initializer list of size %d, got size %d".printf (subsize, size));
169 return -1;
170 } else {
171 subsize = size;
173 } else {
174 if (rank != 1) {
175 il.error = true;
176 e.error = true;
177 Report.error (e.source_reference, "Expected array initializer list, got array element");
178 return -1;
182 return il.size;
185 public override bool check (CodeContext context) {
186 if (checked) {
187 return !error;
190 checked = true;
192 List<Expression> sizes = get_sizes ();
193 var initlist = initializer_list;
195 if (element_type != null) {
196 element_type.check (context);
199 foreach (Expression e in sizes) {
200 e.check (context);
203 var calc_sizes = new ArrayList<Literal> ();
204 if (initlist != null) {
205 initlist.target_type = new ArrayType (element_type, rank, source_reference);
207 if (!initlist.check (context)) {
208 error = true;
211 var ret = create_sizes_from_initializer_list (context, initlist, rank, calc_sizes);
212 if (ret == -1) {
213 error = true;
217 if (sizes.size > 0) {
218 /* check for errors in the size list */
219 foreach (Expression e in sizes) {
220 if (e.value_type == null) {
221 /* return on previous error */
222 return false;
223 } else if (!(e.value_type is IntegerType || e.value_type is EnumValueType)) {
224 error = true;
225 Report.error (e.source_reference, "Expression of integer type expected");
228 } else {
229 if (initlist == null) {
230 error = true;
231 /* this is an internal error because it is already handeld by the parser */
232 Report.error (source_reference, "internal error: initializer list expected");
233 } else {
234 foreach (Expression size in calc_sizes) {
235 append_size (size);
240 if (error) {
241 return false;
244 /* check for wrong elements inside the initializer */
245 if (initializer_list != null && initializer_list.value_type == null) {
246 return false;
249 /* try to construct the type of the array */
250 if (element_type == null) {
251 error = true;
252 Report.error (source_reference, "Cannot determine the element type of the created array");
253 return false;
256 value_type = new ArrayType (element_type, rank, source_reference);
257 value_type.value_owned = true;
259 return !error;
262 public override void emit (CodeGenerator codegen) {
263 foreach (Expression e in sizes) {
264 e.emit (codegen);
267 if (initializer_list != null) {
268 initializer_list.emit (codegen);
271 codegen.visit_array_creation_expression (this);
273 codegen.visit_expression (this);
276 public override void get_used_variables (Collection<Variable> collection) {
277 foreach (Expression e in sizes) {
278 e.get_used_variables (collection);
281 if (initializer_list != null) {
282 initializer_list.get_used_variables (collection);