summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--lib.c33
-rw-r--r--txr.18
3 files changed, 45 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index cdb86cde..005969c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2012-02-22 Kaz Kylheku <kaz@kylheku.com>
+ * lib.c (sub_list, replace_list, lazy_sub_str, sub_str,
+ replace_str, sub_vec, replace_vec): Implementing floating zero
+ behavior. This is necessary so that the important case index .. (+
+ index 1) for selecting one element as a subrange works even if index is
+ negative.
+
+ * txr.1: Floating zero behavior for ranges documented.
+
+2012-02-22 Kaz Kylheku <kaz@kylheku.com>
+
* eval.c (dwim_loc): del operator's return value is the
deleted range of values. Missing del cases added for single
index cases.
diff --git a/lib.c b/lib.c
index db4b145e..657bbb66 100644
--- a/lib.c
+++ b/lib.c
@@ -443,8 +443,11 @@ val sub_list(val list, val from, val to)
from = zero;
else if (from == t)
from = nil;
- else if (lt(from, zero))
+ else if (lt(from, zero)) {
from = plus(from, len = length(list));
+ if (zerop(to))
+ to = nil;
+ }
if (to == t)
to = nil;
@@ -494,8 +497,11 @@ val replace_list(val list, val items, val from, val to)
from = zero;
else if (from == t)
from = nil;
- else if (lt(from, zero))
+ else if (lt(from, zero)) {
from = plus(from, len ? len : (len = length(list)));
+ if (zerop(to))
+ to = len;
+ }
if (to == t)
to = nil;
@@ -1483,6 +1489,9 @@ static val lazy_sub_str(val lstr, val from, val to)
if (lt(from, zero)) {
from = plus(from, len = length_str(lstr));
from = max2(zero, from);
+
+ if (zerop(to))
+ to = t;
}
if (ge(from, len_pfx)) {
@@ -1534,8 +1543,11 @@ val sub_str(val str_in, val from, val to)
from = zero;
else if (from == t)
return null_string;
- else if (lt(from, zero))
+ else if (lt(from, zero)) {
from = plus(from, len);
+ if (zerop(to))
+ to = len;
+ }
if (to == nil || to == t)
to = len;
@@ -1572,8 +1584,11 @@ val replace_str(val str_in, val items, val from, val to)
from = zero;
else if (from == t)
from = len;
- else if (lt(from, zero))
+ else if (lt(from, zero)) {
from = plus(from, len);
+ if (zerop(to))
+ to = len;
+ }
if (to == nil || to == t)
to = len;
@@ -2939,8 +2954,11 @@ val sub_vec(val vec_in, val from, val to)
from = zero;
else if (from == t)
from = len;
- else if (lt(from, zero))
+ else if (lt(from, zero)) {
from = plus(from, len);
+ if (zerop(to))
+ to = len;
+ }
if (to == nil || to == t)
to = len;
@@ -2979,8 +2997,11 @@ val replace_vec(val vec_in, val items, val from, val to)
from = zero;
else if (from == t)
from = len;
- else if (lt(from, zero))
+ else if (lt(from, zero)) {
from = plus(from, len);
+ if (zerop(to))
+ to = len;
+ }
if (to == nil || to == t)
to = len;
diff --git a/txr.1 b/txr.1
index ca8dacbd..29323040 100644
--- a/txr.1
+++ b/txr.1
@@ -5101,6 +5101,14 @@ Either end of the range can also be specified as nil. If the start is specified
as nil, it means zero. If the end is specified as nil, it means one element
past the end. Thus nil .. nil spans all of the elements.
+The value zero has a "floating" behavior when used as the end of a range.
+If the start of the range is a negative value, and the end of the
+range is zero, the zero is interpreted as being the position past the
+end of the sequence, rather than the first element. For instance the range
+-1..0 means the same thing as -1..t or -1..nil. Zero at the start of a range
+always means the first element, so that 0..-1 refers to all the elements except
+for the last one.
+
.TP
Notes: