Fix `this' access in default signal handlers
[vala-lang.git] / vala / valaarraytype.vala
blob710a17b6b720ffec6805bcada1b63c3efdd67aeb
1 /* valaarraytype.vala
3 * Copyright (C) 2007-2009 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 int length { get; set; }
51 /**
52 * The rank of this array.
54 public int rank { get; set; }
56 private DataType _element_type;
58 private ArrayLengthField length_field;
59 private ArrayResizeMethod resize_method;
60 private ArrayMoveMethod move_method;
62 public ArrayType (DataType element_type, int rank, SourceReference? source_reference) {
63 this.element_type = element_type;
64 this.rank = rank;
65 this.source_reference = source_reference;
68 public override Symbol? get_member (string member_name) {
69 if (member_name == "length") {
70 return get_length_field ();
71 } else if (member_name == "move") {
72 return get_move_method ();
73 } else if (member_name == "resize") {
74 return get_resize_method ();
76 return null;
79 private ArrayLengthField get_length_field () {
80 if (length_field == null) {
81 length_field = new ArrayLengthField (source_reference);
83 length_field.access = SymbolAccessibility.PUBLIC;
85 var root_symbol = source_reference.file.context.root;
86 if (rank > 1) {
87 // length is an int[] containing the dimensions of the array, starting at 0
88 ValueType integer = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
89 length_field.field_type = new ArrayType (integer, 1, source_reference);
90 } else {
91 length_field.field_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
95 return length_field;
98 private ArrayResizeMethod get_resize_method () {
99 if (resize_method == null) {
100 resize_method = new ArrayResizeMethod (source_reference);
102 resize_method.return_type = new VoidType ();
103 resize_method.access = SymbolAccessibility.PUBLIC;
105 resize_method.set_cname ("g_renew");
107 var root_symbol = source_reference.file.context.root;
108 var int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
110 resize_method.add_parameter (new FormalParameter ("length", int_type));
112 resize_method.returns_modified_pointer = true;
114 return resize_method;
117 private ArrayMoveMethod get_move_method () {
118 if (move_method == null) {
119 move_method = new ArrayMoveMethod (source_reference);
121 move_method.return_type = new VoidType ();
122 move_method.access = SymbolAccessibility.PUBLIC;
124 move_method.set_cname ("_vala_array_move");
126 var root_symbol = source_reference.file.context.root;
127 var int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
129 move_method.add_parameter (new FormalParameter ("src", int_type));
130 move_method.add_parameter (new FormalParameter ("dest", int_type));
131 move_method.add_parameter (new FormalParameter ("length", int_type));
133 return move_method;
136 public override DataType copy () {
137 var result = new ArrayType (element_type.copy (), rank, source_reference);
138 result.value_owned = value_owned;
139 result.nullable = nullable;
140 result.floating_reference = floating_reference;
142 result.inline_allocated = inline_allocated;
143 if (fixed_length) {
144 result.fixed_length = true;
145 result.length = length;
148 return result;
151 public override string? get_cname () {
152 if (inline_allocated) {
153 return element_type.get_cname ();
154 } else {
155 return element_type.get_cname () + "*";
159 public override string get_cdeclarator_suffix () {
160 if (fixed_length) {
161 return "[%d]".printf (length);
162 } else if (inline_allocated) {
163 return "[]";
164 } else {
165 return "";
169 public override bool is_array () {
170 return true;
173 public override string to_qualified_string (Scope? scope) {
174 return "%s[%s]%s".printf (element_type.to_qualified_string (scope), string.nfill (rank - 1, ','), nullable ? "?" : "");
177 public override bool compatible (DataType target_type) {
178 if (target_type.get_type_id () == "G_TYPE_VALUE" && element_type.data_type == CodeContext.get ().root.scope.lookup ("string")) {
179 // allow implicit conversion from string[] to GValue
180 return true;
183 if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
184 /* any array type can be cast to a generic pointer */
185 return true;
188 /* temporarily ignore type parameters */
189 if (target_type.type_parameter != null) {
190 return true;
193 var target_array_type = target_type as ArrayType;
194 if (target_array_type == null) {
195 return false;
198 if (element_type.compatible (target_array_type.element_type)
199 && target_array_type.element_type.compatible (element_type)) {
200 return true;
203 return false;
206 public override bool is_reference_type_or_type_parameter () {
207 return true;
210 public override string? get_type_signature () {
211 string element_type_signature = element_type.get_type_signature ();
213 if (element_type_signature == null) {
214 return null;
217 return string.nfill (rank, 'a') + element_type_signature;
220 public override void accept_children (CodeVisitor visitor) {
221 element_type.accept (visitor);
224 public override void replace_type (DataType old_type, DataType new_type) {
225 if (element_type == old_type) {
226 element_type = new_type;
230 public override Gee.List<Symbol> get_symbols () {
231 return element_type.get_symbols ();
234 public override bool check (SemanticAnalyzer analyzer) {
235 if (invalid_syntax) {
236 Report.error (source_reference, "syntax error, no expression allowed between array brackets");
237 error = true;
238 return false;
240 return element_type.check (analyzer);
243 public override string? get_type_id () {
244 if (element_type.data_type == CodeContext.get ().root.scope.lookup ("string")) {
245 return "G_TYPE_STRV";
246 } else {
247 return null;