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
20
* JĆ¼rg Billeter <j@bitron.ch>
28
public class Vala.ArrayType : ReferenceType {
32
public DataType element_type {
33
get { return _element_type; }
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; }
47
* The length of this fixed-length array.
49
public int length { get; set; }
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;
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") {
77
return get_resize_method ();
82
private ArrayLengthField get_length_field () {
83
if (length_field == null) {
84
length_field = new ArrayLengthField (source_reference);
86
length_field.access = SymbolAccessibility.PUBLIC;
88
var root_symbol = source_reference.file.context.root;
90
// length is an int[] containing the dimensions of the array, starting at 0
91
ValueType integer = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
92
length_field.variable_type = new ArrayType (integer, 1, source_reference);
94
length_field.variable_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
101
private ArrayResizeMethod get_resize_method () {
102
if (resize_method == null) {
103
resize_method = new ArrayResizeMethod (source_reference);
105
resize_method.return_type = new VoidType ();
106
resize_method.access = SymbolAccessibility.PUBLIC;
108
resize_method.set_attribute_string ("CCode", "cname", "g_renew");
110
var root_symbol = source_reference.file.context.root;
111
var int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
113
resize_method.add_parameter (new Parameter ("length", int_type));
115
resize_method.returns_modified_pointer = true;
117
return resize_method;
120
private ArrayMoveMethod get_move_method () {
121
if (move_method == null) {
122
move_method = new ArrayMoveMethod (source_reference);
124
move_method.return_type = new VoidType ();
125
move_method.access = SymbolAccessibility.PUBLIC;
127
move_method.set_attribute_string ("CCode", "cname", "_vala_array_move");
129
var root_symbol = source_reference.file.context.root;
130
var int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
132
move_method.add_parameter (new Parameter ("src", int_type));
133
move_method.add_parameter (new Parameter ("dest", int_type));
134
move_method.add_parameter (new Parameter ("length", int_type));
139
public override DataType copy () {
140
var result = new ArrayType (element_type.copy (), rank, source_reference);
141
result.value_owned = value_owned;
142
result.nullable = nullable;
143
result.floating_reference = floating_reference;
145
result.inline_allocated = inline_allocated;
147
result.fixed_length = true;
148
result.length = length;
154
public override bool is_array () {
158
public override string to_qualified_string (Scope? scope) {
160
return "%s[%s]%s".printf (element_type.to_qualified_string (scope), string.nfill (rank - 1, ','), nullable ? "?" : "");
162
return element_type.to_qualified_string (scope);
166
public override bool compatible (DataType target_type) {
167
if (target_type.data_type != null) {
168
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")) {
169
// allow implicit conversion from string[] to GValue
173
if (target_type.data_type.is_subtype_of (CodeContext.get ().analyzer.gvariant_type.data_type)) {
174
// allow implicit conversion to GVariant
179
if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
180
/* any array type can be cast to a generic pointer */
184
/* temporarily ignore type parameters */
185
if (target_type.type_parameter != null) {
189
var target_array_type = target_type as ArrayType;
190
if (target_array_type == null) {
194
if (target_array_type.rank != rank) {
198
if (element_type is ValueType && element_type.nullable != target_array_type.element_type.nullable) {
202
if (element_type.compatible (target_array_type.element_type)
203
&& target_array_type.element_type.compatible (element_type)) {
210
public override bool is_reference_type_or_type_parameter () {
214
public override void accept_children (CodeVisitor visitor) {
215
element_type.accept (visitor);
218
public override void replace_type (DataType old_type, DataType new_type) {
219
if (element_type == old_type) {
220
element_type = new_type;
224
public override bool is_accessible (Symbol sym) {
225
return element_type.is_accessible (sym);
228
public override bool check (CodeContext context) {
229
if (invalid_syntax) {
230
Report.error (source_reference, "syntax error, no expression allowed between array brackets");
234
return element_type.check (context);
237
public override DataType get_actual_type (DataType? derived_instance_type, MemberAccess? method_access, CodeNode node_reference) {
238
if (derived_instance_type == null && method_access == null) {
242
ArrayType result = this;
244
if (element_type is GenericType || element_type.has_type_arguments ()) {
245
result = (ArrayType) result.copy ();
246
result.element_type = result.element_type.get_actual_type (derived_instance_type, method_access, node_reference);
252
public override bool is_disposable () {
254
return element_type.is_disposable ();
256
return base.is_disposable ();