Release 0.7.8
[vala-lang.git] / vala / valaarraycreationexpression.vala
blob34fbd4e7a620cb08c1754ad517b9811d0d4b4b33
1 /* valaarraycreationexpression.vala
3 * Copyright (C) 2006-2009 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);
75 /**
76 * Get the sizes for all dimensions ascending from left to right.
78 public List<Expression> get_sizes () {
79 return new ReadOnlyList<Expression> (sizes);
82 public ArrayCreationExpression (DataType element_type, int rank, InitializerList? initializer_list, SourceReference source_reference) {
83 this.element_type = element_type;
84 this.rank = rank;
85 this.initializer_list = initializer_list;
86 this.source_reference = source_reference;
89 public override void accept_children (CodeVisitor visitor) {
90 if (element_type != null) {
91 element_type.accept (visitor);
94 foreach (Expression e in sizes) {
95 e.accept (visitor);
98 if (initializer_list != null) {
99 initializer_list.accept (visitor);
103 public override void accept (CodeVisitor visitor) {
104 visitor.visit_array_creation_expression (this);
106 visitor.visit_expression (this);
109 public override bool is_pure () {
110 return false;
113 public override void replace_type (DataType old_type, DataType new_type) {
114 if (element_type == old_type) {
115 element_type = new_type;
119 private int create_sizes_from_initializer_list (SemanticAnalyzer analyzer, InitializerList il, int rank, List<Literal> sl) {
120 if (sl.size == (this.rank - rank)) {
121 // only add size if this is the first initializer list of the current dimension
122 var init = new IntegerLiteral (il.size.to_string (), il.source_reference);
123 init.check (analyzer);
124 sl.add (init);
127 int subsize = -1;
128 foreach (Expression e in il.get_initializers ()) {
129 if (e is InitializerList) {
130 if (rank == 1) {
131 il.error = true;
132 e.error = true;
133 Report.error (e.source_reference, "Expected array element, got array initializer list");
134 return -1;
136 int size = create_sizes_from_initializer_list (analyzer, (InitializerList) e, rank - 1, sl);
137 if (size == -1) {
138 return -1;
140 if (subsize >= 0 && subsize != size) {
141 il.error = true;
142 Report.error (il.source_reference, "Expected initializer list of size %d, got size %d".printf (subsize, size));
143 return -1;
144 } else {
145 subsize = size;
147 } else {
148 if (rank != 1) {
149 il.error = true;
150 e.error = true;
151 Report.error (e.source_reference, "Expected array initializer list, got array element");
152 return -1;
156 return il.size;
159 public override bool check (SemanticAnalyzer analyzer) {
160 if (checked) {
161 return !error;
164 checked = true;
166 List<Expression> sizes = get_sizes ();
167 var initlist = initializer_list;
169 if (element_type != null) {
170 element_type.check (analyzer);
173 foreach (Expression e in sizes) {
174 e.check (analyzer);
177 var calc_sizes = new ArrayList<Literal> ();
178 if (initlist != null) {
179 initlist.target_type = new ArrayType (element_type, rank, source_reference);
181 initlist.check (analyzer);
183 var ret = create_sizes_from_initializer_list (analyzer, initlist, rank, calc_sizes);
184 if (ret == -1) {
185 error = true;
189 if (sizes.size > 0) {
190 /* check for errors in the size list */
191 foreach (Expression e in sizes) {
192 if (e.value_type == null) {
193 /* return on previous error */
194 return false;
195 } else if (!(e.value_type is IntegerType || e.value_type is EnumValueType)) {
196 error = true;
197 Report.error (e.source_reference, "Expression of integer type expected");
200 } else {
201 if (initlist == null) {
202 error = true;
203 /* this is an internal error because it is already handeld by the parser */
204 Report.error (source_reference, "internal error: initializer list expected");
205 } else {
206 foreach (Expression size in calc_sizes) {
207 append_size (size);
212 if (error) {
213 return false;
216 /* check for wrong elements inside the initializer */
217 if (initializer_list != null && initializer_list.value_type == null) {
218 return false;
221 /* try to construct the type of the array */
222 if (element_type == null) {
223 error = true;
224 Report.error (source_reference, "Cannot determine the element type of the created array");
225 return false;
228 element_type.value_owned = true;
230 value_type = new ArrayType (element_type, rank, source_reference);
231 value_type.value_owned = true;
233 return !error;