summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--eval.c90
-rw-r--r--txr.124
3 files changed, 104 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index 16085bf5..88db7899 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2012-01-25 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (dwim_loc): Handles full responsibility for assigning
+ to list and array ranges.
+ (op_modplace): Pass extra arguments to dwim_loc so it can
+ do the job for ranges. If dwim_loc returns 0, it means
+ that it did everything.
+ (op_dwim): Support list and array ranges.
+
+ * txr.1: Documented.
+
+2012-01-25 Kaz Kylheku <kaz@kylheku.com>
+
* arith.c (zerop): Misspelling in error message.
* lib.c (sub_list, replace_list, sub_vec, replace_vec):
diff --git a/eval.c b/eval.c
index e844f0a0..613359a4 100644
--- a/eval.c
+++ b/eval.c
@@ -637,7 +637,7 @@ static val op_defun(val form, val env)
return name;
}
-static val *dwim_loc(val form, val env)
+static val *dwim_loc(val form, val env, val op, val newval)
{
val obj = eval(second(form), env, form);
val args = eval_args(rest(rest(form)), env, form);
@@ -659,7 +659,23 @@ static val *dwim_loc(val form, val env)
if (rest(args))
eval_error(form, lit("[~s ...]: vector indexing needs one arg"),
obj, nao);
- return vecref_l(obj, first(args));
+ {
+ val index = first(args);
+
+ if (consp(index)) {
+ val from = eval(car(index), env, form);
+ val to = eval(cdr(index), env, form);
+
+ if (op != set_s)
+ eval_error(form, lit("[~s ~s]: slice takes only simple assignments"),
+ obj, index, nao);
+
+ replace_vec(obj, from, to, newval);
+ return 0;
+ } else {
+ return vecref_l(obj, first(args));
+ }
+ }
case CONS:
case LCONS:
if (rest(args))
@@ -668,15 +684,32 @@ static val *dwim_loc(val form, val env)
{
val index = first(args);
val cell = obj;
- if (!bignump(index) && !fixnump(index))
- eval_error(form, lit("[~s ~s]: index must be integer"),
+ if (bignump(index) || fixnump(index)) {
+ for (; gt(index, zero); index = minus(index, one))
+ cell = cdr(cell);
+ if (lt(index, zero) || !cell)
+ eval_error(form, lit("[~s ~s]: cannot assign nonexistent location"),
+ cell, first(args), nao);
+ return car_l(cell);
+ } else if (consp(index)) {
+ val from = eval(car(index), env, form);
+ val to = eval(cdr(index), env, form);
+ val newlist;
+ val tempform;
+
+ if (op != set_s)
+ eval_error(form, lit("[~s ~s]: slice takes only simple assignments"),
+ cell, index, nao);
+
+ newlist = replace_list(obj, from, to, newval);
+ tempform = list(op, second(form),
+ cons(quote_s, cons(newlist, nil)), nao);
+ eval(tempform, env, form);
+ return 0;
+ } else {
+ eval_error(form, lit("[~s ~s]: index must be integer, or pair"),
cell, index, nao);
- for (; gt(index, zero); index = minus(index, one))
- cell = cdr(cell);
- if (lt(index, zero) || !cell)
- eval_error(form, lit("[~s ~s]: cannot assign nonexistent location"),
- cell, first(args), nao);
- return car_l(cell);
+ }
}
case COBJ:
{
@@ -727,7 +760,9 @@ static val op_modplace(val form, val env)
/* TODO: dispatch these with hash table. */
val sym = car(place);
if (sym == dwim_s) {
- loc = dwim_loc(place, env);
+ loc = dwim_loc(place, env, op, newval);
+ if (loc == 0)
+ return newval;
} else if (sym == gethash_s) {
val hash = eval(second(place), env, form);
val key = eval(third(place), env, form);
@@ -908,7 +943,17 @@ static val op_dwim(val form, val env)
if (rest(args))
eval_error(form, lit("[~s ...]: vector indexing needs one arg"),
obj, nao);
- return vecref(obj, first(args));
+ {
+ val index = first(args);
+
+ if (consp(index)) {
+ val from = eval(car(index), env, form);
+ val to = eval(cdr(index), env, form);
+ return sub_vec(obj, from, to);
+ } else {
+ return vecref(obj, first(args));
+ }
+ }
case CONS:
case LCONS:
if (rest(args))
@@ -916,14 +961,21 @@ static val op_dwim(val form, val env)
obj, nao);
{
val index = first(args);
- if (!bignump(index) && !fixnump(index))
- eval_error(form, lit("[~s ~s]: index must be integer"),
+ if (!bignump(index) && !fixnump(index) && !consp(index))
+ eval_error(form, lit("[~s ~s]: index must be integer or pair"),
obj, index, nao);
- if (lt(index, zero))
- return nil;
- for (; gt(index, zero); index = minus(index, one))
- obj = cdr(obj);
- return car(obj);
+
+ if (consp(index)) {
+ val from = eval(car(index), env, form);
+ val to = eval(cdr(index), env, form);
+ return sub_list(obj, from, to);
+ } else {
+ if (lt(index, zero))
+ return nil;
+ for (; gt(index, zero); index = minus(index, one))
+ obj = cdr(obj);
+ return car(obj);
+ }
}
case COBJ:
{
diff --git a/txr.1 b/txr.1
index dc6625e5..3853fe7f 100644
--- a/txr.1
+++ b/txr.1
@@ -4372,8 +4372,10 @@ shorthand for cons.
That is to say, A .. B translates to (cons A B), and so for instance
(a b .. (c d) e .. f . g) means (a (cons b (c d)) (cons e f) . g).
-This is a syntactic sugar in certain situations in which a cons
-is used to represent a pair of numbers or other objects.
+This is a syntactic sugar useful in certain situations in which a cons is used
+to represent a pair of numbers or other objects. For instance, if L
+is a list, then [L 1 .. 3] computes a sublist of L consisting of
+elements 1 through 2 (counting from zero).
.SS The DWIM Brackets
@@ -4843,10 +4845,22 @@ refers to the first element. Indexed list access does not throw exceptions.
Negative indices yield nil, and indices beyond the end of a list
yield nil. (However assignment to a nonexistent list element throws.)
+.IP [<list> <from-index>..<to-below-index>]
+Retrieve the specified range of elements, exactly as if
+using (sub-list <list> <from-index> <to-below-index>).
+The range of elements is specified in the car and cdr fields of a cons cell,
+for which the .. (dotdot) syntactic sugar is useful.
+
.IP [<vector> <index>]
Retrieve the specified element of a vector. This is equivalent to
(vecref <vector> <index>).
+.IP [<vector> <from-index>..<to-below-index>]
+Retrieve the specified range of elements, exactly as if
+using (sub-vec <list> <from-index> <to-below-index>).
+The range of elements is specified in the car and cdr fields of a cons cell,
+for which the .. (dotdot) syntactic sugar is useful.
+
.IP [<string> <index>]
Retrieve the specified element of a string. This is equivalent to
(chr-str <string> <index>).
@@ -4858,6 +4872,12 @@ or <default-value> if there is no such entry.
The list, vector and hash table forms of dwim denote places
that can be assigned.
+The list and vector range forms can be assigned only using the set operator,
+not using the others like push and inc. Assigning to a vector range modifies
+the vector object; it is implemented using replace-vec. Assigning to a list
+range updates the form which contains the list, so the expression denoting the
+list must be an assignable place.
+
.TP
Notes: