summaryrefslogtreecommitdiff
path: root/vala/valasliceexpression.vala
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2009-12-19 12:02:05 +0100
committerJürg Billeter <j@bitron.ch>2009-12-19 12:02:05 +0100
commit52d84048e075bba00f59992a373e1de954fa2b60 (patch)
treeaa2ac5daf28562fd914bbea1e25c2eb7f6e0542b /vala/valasliceexpression.vala
parent1f718e4f1455b62a61b79fd701975e6c4b48522b (diff)
downloadvala-52d84048e075bba00f59992a373e1de954fa2b60.tar.gz
Initial support for array slices
Add support for slice expressions such as array[1:5] to retrieve a slice of length 4 starting at the second element of the array. Slice expressions are also supported for strings and other types that provide an appropriate slice method. Based on patch by Robin Sonefors, fixes bug 571352.
Diffstat (limited to 'vala/valasliceexpression.vala')
-rw-r--r--vala/valasliceexpression.vala177
1 files changed, 177 insertions, 0 deletions
diff --git a/vala/valasliceexpression.vala b/vala/valasliceexpression.vala
new file mode 100644
index 000000000..7713f738d
--- /dev/null
+++ b/vala/valasliceexpression.vala
@@ -0,0 +1,177 @@
+/* valasliceexpression.vala
+ *
+ * Copyright (C) 2009 Robin Sonefors
+ * Copyright (C) 2009 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Robin Sonefors <ozamosi@flukkost.nu>
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents an array slice expression e.g "a[1:5]".
+ */
+public class Vala.SliceExpression : Expression {
+ public Expression container {
+ get {
+ return _container;
+ }
+ set {
+ _container = value;
+ _container.parent_node = this;
+ }
+ }
+
+ public Expression start {
+ get {
+ return _start;
+ }
+ private set {
+ _start = value;
+ _start.parent_node = this;
+ }
+ }
+
+ public Expression stop {
+ get {
+ return _stop;
+ }
+ private set {
+ _stop = value;
+ _stop.parent_node = this;
+ }
+ }
+
+ Expression _container;
+ Expression _start;
+ Expression _stop;
+
+ public SliceExpression (Expression container, Expression start, Expression stop, SourceReference? source_reference = null) {
+ this.container = container;
+ this.start = start;
+ this.stop = stop;
+ this.source_reference = source_reference;
+ }
+
+ public override void accept (CodeVisitor visitor) {
+ visitor.visit_slice_expression (this);
+
+ visitor.visit_expression (this);
+ }
+
+ public override void accept_children (CodeVisitor visitor) {
+ container.accept (visitor);
+
+ start.accept (visitor);
+ stop.accept (visitor);
+ }
+
+ public override void replace_expression (Expression old_node, Expression new_node) {
+ if (container == old_node) {
+ container = new_node;
+ }
+ if (start == old_node) {
+ start = new_node;
+ }
+ if (stop == old_node) {
+ stop = new_node;
+ }
+ }
+
+ public override bool is_pure () {
+ return false;
+ }
+
+ public override bool check (SemanticAnalyzer analyzer) {
+ if (checked) {
+ return !error;
+ }
+
+ checked = true;
+
+ if (!container.check (analyzer)) {
+ error = true;
+ return false;
+ }
+
+ if (!start.check (analyzer)) {
+ error = true;
+ return false;
+ }
+
+ if (!stop.check (analyzer)) {
+ error = true;
+ return false;
+ }
+
+ if (container.value_type == null) {
+ error = true;
+ Report.error (container.source_reference, "Invalid container expression");
+ return false;
+ }
+
+ if (lvalue) {
+ error = true;
+ Report.error (container.source_reference, "Slice expressions cannot be used as lvalue");
+ return false;
+ }
+
+ if (container.value_type is ArrayType) {
+ value_type = container.value_type.copy ();
+ value_type.value_owned = false;
+
+ /* check if the index is of type integer */
+ if (!(start.value_type is IntegerType || start.value_type is EnumValueType)) {
+ error = true;
+ Report.error (start.source_reference, "Expression of integer type expected");
+ }
+ if (!(stop.value_type is IntegerType || stop.value_type is EnumValueType)) {
+ error = true;
+ Report.error (stop.source_reference, "Expression of integer type expected");
+ }
+ } else {
+ var slice_method = container.value_type.get_member ("slice") as Method;
+ if (slice_method != null) {
+ var slice_call = new MethodCall (new MemberAccess (container, "slice"));
+ slice_call.add_argument (start);
+ slice_call.add_argument (stop);
+ slice_call.target_type = this.target_type;
+ parent_node.replace_expression (this, slice_call);
+ return slice_call.check (analyzer);
+ }
+
+ error = true;
+ Report.error (source_reference, "The expression `%s' does not denote an array".printf (container.value_type.to_string ()));
+ }
+
+ return !error;
+ }
+
+ public override void get_defined_variables (Collection<LocalVariable> collection) {
+ container.get_defined_variables (collection);
+ start.get_defined_variables (collection);
+ stop.get_defined_variables (collection);
+ }
+
+ public override void get_used_variables (Collection<LocalVariable> collection) {
+ container.get_used_variables (collection);
+ start.get_used_variables (collection);
+ stop.get_used_variables (collection);
+ }
+}