codegen: Use temporary variable for string concatenation
[vala-lang.git] / vala / valaarraycreationexpression.vala
blob3b52748ff9e9cea6fb42674860ca8a87e0c548a6
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 void replace_expression (Expression old_node, Expression new_node) {
117 for (int i = 0; i < sizes.size; i++) {
118 if (sizes[i] == old_node) {
119 sizes[i] = new_node;
120 return;
125 public override void replace_type (DataType old_type, DataType new_type) {
126 if (element_type == old_type) {
127 element_type = new_type;
131 private int create_sizes_from_initializer_list (CodeContext context, InitializerList il, int rank, List<Literal> sl) {
132 if (sl.size == (this.rank - rank)) {
133 // only add size if this is the first initializer list of the current dimension
134 var init = new IntegerLiteral (il.size.to_string (), il.source_reference);
135 init.check (context);
136 sl.add (init);
139 int subsize = -1;
140 foreach (Expression e in il.get_initializers ()) {
141 if (e is InitializerList) {
142 if (rank == 1) {
143 il.error = true;
144 e.error = true;
145 Report.error (e.source_reference, "Expected array element, got array initializer list");
146 return -1;
148 int size = create_sizes_from_initializer_list (context, (InitializerList) e, rank - 1, sl);
149 if (size == -1) {
150 return -1;
152 if (subsize >= 0 && subsize != size) {
153 il.error = true;
154 Report.error (il.source_reference, "Expected initializer list of size %d, got size %d".printf (subsize, size));
155 return -1;
156 } else {
157 subsize = size;
159 } else {
160 if (rank != 1) {
161 il.error = true;
162 e.error = true;
163 Report.error (e.source_reference, "Expected array initializer list, got array element");
164 return -1;
168 return il.size;
171 public override bool check (CodeContext context) {
172 if (checked) {
173 return !error;
176 checked = true;
178 List<Expression> sizes = get_sizes ();
179 var initlist = initializer_list;
181 if (element_type != null) {
182 element_type.check (context);
185 foreach (Expression e in sizes) {
186 e.check (context);
189 var calc_sizes = new ArrayList<Literal> ();
190 if (initlist != null) {
191 initlist.target_type = new ArrayType (element_type, rank, source_reference);
193 if (!initlist.check (context)) {
194 error = true;
197 var ret = create_sizes_from_initializer_list (context, initlist, rank, calc_sizes);
198 if (ret == -1) {
199 error = true;
203 if (sizes.size > 0) {
204 /* check for errors in the size list */
205 foreach (Expression e in sizes) {
206 if (e.value_type == null) {
207 /* return on previous error */
208 return false;
209 } else if (!(e.value_type is IntegerType || e.value_type is EnumValueType)) {
210 error = true;
211 Report.error (e.source_reference, "Expression of integer type expected");
214 } else {
215 if (initlist == null) {
216 error = true;
217 /* this is an internal error because it is already handeld by the parser */
218 Report.error (source_reference, "internal error: initializer list expected");
219 } else {
220 foreach (Expression size in calc_sizes) {
221 append_size (size);
226 if (error) {
227 return false;
230 /* check for wrong elements inside the initializer */
231 if (initializer_list != null && initializer_list.value_type == null) {
232 return false;
235 /* try to construct the type of the array */
236 if (element_type == null) {
237 error = true;
238 Report.error (source_reference, "Cannot determine the element type of the created array");
239 return false;
242 element_type.value_owned = true;
244 value_type = new ArrayType (element_type, rank, source_reference);
245 value_type.value_owned = true;
247 return !error;
250 public override void emit (CodeGenerator codegen) {
251 foreach (Expression e in sizes) {
252 e.emit (codegen);
255 if (initializer_list != null) {
256 initializer_list.emit (codegen);
259 codegen.visit_array_creation_expression (this);
261 codegen.visit_expression (this);