codegen: Fix floating reference regression with Variants
[vala-gnome.git] / vala / valasliceexpression.vala
blob6621b41d81f1a53433709c411a2846eddeea453d
1 /* valasliceexpression.vala
3 * Copyright (C) 2009 Robin Sonefors
4 * Copyright (C) 2009-2013 Jürg Billeter
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 * Robin Sonefors <ozamosi@flukkost.nu>
22 * Jürg Billeter <j@bitron.ch>
25 using GLib;
27 /**
28 * Represents an array slice expression e.g "a[1:5]".
30 public class Vala.SliceExpression : Expression {
31 public Expression container {
32 get {
33 return _container;
35 set {
36 _container = value;
37 _container.parent_node = this;
41 public Expression start {
42 get {
43 return _start;
45 private set {
46 _start = value;
47 _start.parent_node = this;
51 public Expression stop {
52 get {
53 return _stop;
55 private set {
56 _stop = value;
57 _stop.parent_node = this;
61 Expression _container;
62 Expression _start;
63 Expression _stop;
65 public SliceExpression (Expression container, Expression start, Expression stop, SourceReference? source_reference = null) {
66 this.container = container;
67 this.start = start;
68 this.stop = stop;
69 this.source_reference = source_reference;
72 public override void accept (CodeVisitor visitor) {
73 visitor.visit_slice_expression (this);
75 visitor.visit_expression (this);
78 public override void accept_children (CodeVisitor visitor) {
79 container.accept (visitor);
81 start.accept (visitor);
82 stop.accept (visitor);
85 public override void replace_expression (Expression old_node, Expression new_node) {
86 if (container == old_node) {
87 container = new_node;
89 if (start == old_node) {
90 start = new_node;
92 if (stop == old_node) {
93 stop = new_node;
97 public override bool is_pure () {
98 return false;
101 public override bool is_accessible (Symbol sym) {
102 return container.is_accessible (sym) && start.is_accessible (sym) && stop.is_accessible (sym);
105 public override bool check (CodeContext context) {
106 if (checked) {
107 return !error;
110 checked = true;
112 if (!container.check (context)) {
113 error = true;
114 return false;
117 if (container.value_type is ArrayType) {
118 start.target_type = context.analyzer.int_type.copy ();
119 stop.target_type = context.analyzer.int_type.copy ();
122 if (!start.check (context)) {
123 error = true;
124 return false;
127 if (!stop.check (context)) {
128 error = true;
129 return false;
132 if (container.value_type == null) {
133 error = true;
134 Report.error (container.source_reference, "Invalid container expression");
135 return false;
138 if (lvalue) {
139 error = true;
140 Report.error (container.source_reference, "Slice expressions cannot be used as lvalue");
141 return false;
144 if (container.value_type is ArrayType) {
145 value_type = container.value_type.copy ();
146 value_type.value_owned = false;
148 /* check if the index is of type integer */
149 if (!(start.value_type is IntegerType || start.value_type is EnumValueType)) {
150 error = true;
151 Report.error (start.source_reference, "Expression of integer type expected");
153 if (!(stop.value_type is IntegerType || stop.value_type is EnumValueType)) {
154 error = true;
155 Report.error (stop.source_reference, "Expression of integer type expected");
157 } else {
158 var slice_method = container.value_type.get_member ("slice") as Method;
159 if (slice_method != null) {
160 var slice_call = new MethodCall (new MemberAccess (container, "slice"));
161 slice_call.add_argument (start);
162 slice_call.add_argument (stop);
163 slice_call.target_type = this.target_type;
164 parent_node.replace_expression (this, slice_call);
165 return slice_call.check (context);
168 error = true;
169 Report.error (source_reference, "The expression `%s' does not denote an array".printf (container.value_type.to_string ()));
172 return !error;
175 public override void emit (CodeGenerator codegen) {
176 container.emit (codegen);
178 start.emit (codegen);
179 stop.emit (codegen);
181 codegen.visit_slice_expression (this);
183 codegen.visit_expression (this);
186 public override void get_defined_variables (Collection<Variable> collection) {
187 container.get_defined_variables (collection);
188 start.get_defined_variables (collection);
189 stop.get_defined_variables (collection);
192 public override void get_used_variables (Collection<Variable> collection) {
193 container.get_used_variables (collection);
194 start.get_used_variables (collection);
195 stop.get_used_variables (collection);