codegen: Limit scope of locals freed on errors thrown from catch clauses
[vala-lang.git] / vala / valasliceexpression.vala
blob4680a1bff85e92c45fc783d6f37cd3ead6efca80
1 /* valasliceexpression.vala
3 * Copyright (C) 2009 Robin Sonefors
4 * Copyright (C) 2009-2010 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 check (CodeContext context) {
102 if (checked) {
103 return !error;
106 checked = true;
108 if (!container.check (context)) {
109 error = true;
110 return false;
113 if (!start.check (context)) {
114 error = true;
115 return false;
118 if (!stop.check (context)) {
119 error = true;
120 return false;
123 if (container.value_type == null) {
124 error = true;
125 Report.error (container.source_reference, "Invalid container expression");
126 return false;
129 if (lvalue) {
130 error = true;
131 Report.error (container.source_reference, "Slice expressions cannot be used as lvalue");
132 return false;
135 if (container.value_type is ArrayType) {
136 value_type = container.value_type.copy ();
137 value_type.value_owned = false;
139 /* check if the index is of type integer */
140 if (!(start.value_type is IntegerType || start.value_type is EnumValueType)) {
141 error = true;
142 Report.error (start.source_reference, "Expression of integer type expected");
144 if (!(stop.value_type is IntegerType || stop.value_type is EnumValueType)) {
145 error = true;
146 Report.error (stop.source_reference, "Expression of integer type expected");
148 } else {
149 var slice_method = container.value_type.get_member ("slice") as Method;
150 if (slice_method != null) {
151 var slice_call = new MethodCall (new MemberAccess (container, "slice"));
152 slice_call.add_argument (start);
153 slice_call.add_argument (stop);
154 slice_call.target_type = this.target_type;
155 parent_node.replace_expression (this, slice_call);
156 return slice_call.check (context);
159 error = true;
160 Report.error (source_reference, "The expression `%s' does not denote an array".printf (container.value_type.to_string ()));
163 return !error;
166 public override void emit (CodeGenerator codegen) {
167 container.emit (codegen);
169 start.emit (codegen);
170 stop.emit (codegen);
172 codegen.visit_slice_expression (this);
174 codegen.visit_expression (this);
177 public override void get_defined_variables (Collection<LocalVariable> collection) {
178 container.get_defined_variables (collection);
179 start.get_defined_variables (collection);
180 stop.get_defined_variables (collection);
183 public override void get_used_variables (Collection<LocalVariable> collection) {
184 container.get_used_variables (collection);
185 start.get_used_variables (collection);
186 stop.get_used_variables (collection);