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
21 * Robin Sonefors <ozamosi@flukkost.nu>
22 * Jürg Billeter <j@bitron.ch>
28 * Represents an array slice expression e.g "a[1:5]".
30 public class Vala
.SliceExpression
: Expression
{
31 public Expression container
{
37 _container
.parent_node
= this
;
41 public Expression start
{
47 _start
.parent_node
= this
;
51 public Expression stop
{
57 _stop
.parent_node
= this
;
61 Expression _container
;
65 public SliceExpression (Expression container
, Expression start
, Expression stop
, SourceReference? source_reference
= null) {
66 this
.container
= container
;
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
) {
89 if (start
== old_node
) {
92 if (stop
== old_node
) {
97 public override bool is_pure () {
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
) {
112 if (!container
.check (context
)) {
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
)) {
127 if (!stop
.check (context
)) {
132 if (container
.value_type
== null) {
134 Report
.error (container
.source_reference
, "Invalid container expression");
140 Report
.error (container
.source_reference
, "Slice expressions cannot be used as lvalue");
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
)) {
151 Report
.error (start
.source_reference
, "Expression of integer type expected");
153 if (!(stop
.value_type is IntegerType
|| stop
.value_type is EnumValueType
)) {
155 Report
.error (stop
.source_reference
, "Expression of integer type expected");
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
);
169 Report
.error (source_reference
, "The expression `%s' does not denote an array".printf (container
.value_type
.to_string ()));
175 public override void emit (CodeGenerator codegen
) {
176 container
.emit (codegen
);
178 start
.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
);