summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-06-30 21:42:48 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-06-30 21:42:48 -0700
commit349c01fff273ffcaf5d46873121a067eb82f7997 (patch)
treec4d69d70054d73a923512f1dfe9231c8f3ce9196
parentd7ea45f4c26ff460d062f24f3fbb33c018874dcf (diff)
downloadtxr-349c01fff273ffcaf5d46873121a067eb82f7997.tar.gz
txr-349c01fff273ffcaf5d46873121a067eb82f7997.tar.bz2
txr-349c01fff273ffcaf5d46873121a067eb82f7997.zip
Callable integers become assignable places.
* lib.c (dwim_set): Handle seq argument being an integer or range. * tests/012/callable.tl: A few tests. * txr.1: Documented.
-rw-r--r--lib.c96
-rw-r--r--tests/012/callable.tl8
-rw-r--r--txr.128
3 files changed, 101 insertions, 31 deletions
diff --git a/lib.c b/lib.c
index 086041a0..44f5005f 100644
--- a/lib.c
+++ b/lib.c
@@ -13134,42 +13134,78 @@ val replace(val seq, val items, val from, val to)
val dwim_set(val place_p, val seq, varg vargs)
{
val self = lit("index/range assignment");
+ type_t st = type(seq);
- switch (type(seq)) {
- case COBJ:
- if (type(seq) == COBJ) {
- if (seq->co.cls == hash_cls) {
- args_normalize_least(vargs, 3);
-
- switch (vargs->fill) {
- case 2:
- (void) sethash(seq, vargs->arg[0], vargs->arg[1]);
- break;
- case 3:
- if (vargs->list)
- goto excargs;
- (void) sethash(seq, vargs->arg[0], vargs->arg[2]);
- break;
- default:
- goto fewargs;
+ switch (st) {
+ case NUM:
+ case BGNUM:
+ case RNG:
+ {
+ args_normalize_least(vargs, 3);
+ switch (vargs->fill) {
+ case 2:
+ {
+ val arg = vargs->arg[0];
+ val newval = vargs->arg[1];
+ switch (type(arg)) {
+ case NUM:
+ case BGNUM:
+ case RNG:
+ goto notplace;
+ default:
+ if (st == RNG) {
+ range_bind (x, y, seq);
+ if (!place_p && listp(arg))
+ goto notplace;
+ return replace(arg, newval, x, y);
+ } else {
+ (void) refset(arg, seq, newval);
+ return seq;
+ }
+ }
}
+ case 1:
+ case 0:
+ goto fewargs;
+ default:
+ goto excargs;
+ }
+ }
+ case COBJ:
+ if (seq->co.cls == hash_cls) {
+ args_normalize_least(vargs, 3);
- return seq;
+ switch (vargs->fill) {
+ case 2:
+ (void) sethash(seq, vargs->arg[0], vargs->arg[1]);
+ break;
+ case 3:
+ if (vargs->list)
+ goto excargs;
+ (void) sethash(seq, vargs->arg[0], vargs->arg[2]);
+ break;
+ case 1:
+ case 0:
+ goto fewargs;
+ default:
+ goto excargs;
}
- if (obj_struct_p(seq)) {
- {
- val lambda_set_meth = get_special_slot(seq, lambda_set_m);
- if (lambda_set_meth) {
- (void) funcall(method_args(seq, lambda_set_s, vargs));
- return seq;
- }
+
+ return seq;
+ }
+ if (obj_struct_p(seq)) {
+ {
+ val lambda_set_meth = get_special_slot(seq, lambda_set_m);
+ if (lambda_set_meth) {
+ (void) funcall(method_args(seq, lambda_set_s, vargs));
+ return seq;
}
- if (get_special_slot(seq, car_m))
- goto list;
- type_mismatch(lit("~a: object ~s lacks "
- "~s or ~s method"),
- self, seq, lambda_set_s, car_s, nao);
}
+ if (get_special_slot(seq, car_m))
+ goto list;
+ type_mismatch(lit("~a: object ~s lacks "
+ "~s or ~s method"),
+ self, seq, lambda_set_s, car_s, nao);
}
/* fallthrough */
default:
diff --git a/tests/012/callable.tl b/tests/012/callable.tl
index 0f0e9327..9e88b955 100644
--- a/tests/012/callable.tl
+++ b/tests/012/callable.tl
@@ -21,3 +21,11 @@
(test (mapcar [callf list* 2 0 1 3..:] '((A B C X) (D E F Y) (G H I Z)))
((C A B X) (F D E Y) (I G H Z)))
+
+(mtest
+ (set [1 1] 2) :error
+ (set [1 1..2] 2) :error
+ (set [1..2 1] 2) :error
+ (set [1..2 1..2] 2) :error
+ (let ((abc "abc")) (set [1..2 abc] "42") abc) "a42c"
+ (let ((abc "abc")) (set [1 abc] #\d) abc) "adc")
diff --git a/txr.1 b/txr.1
index c88e06a3..f2f4f975 100644
--- a/txr.1
+++ b/txr.1
@@ -14291,10 +14291,14 @@ defined by \*(TX programs.
.mets (gethash < hash < key <> [ alt ])
.mets (hash-userdata << hash )
.mets (dwim < obj-place < index <> [ alt ])
+.mets (dwim < integer < obj-place ) ;; integers are callable
+.mets (dwim < range < obj-place ) ;; ranges are callable
.mets (sub-list < obj >> [ from <> [ to ]])
.mets (sub-vec < obj >> [ from <> [ to ]])
.mets (sub-str < str >> [ from <> [ to ]])
.mets >> [ obj-place < index <> [ alt ]] ;; equivalent to dwim
+.mets >> [ integer < obj-place ]
+.mets >> [ range < obj-place ]
.mets (symbol-value << symbol-valued-form )
.mets (symbol-function << function-name-valued-form )
.mets (symbol-macro << symbol-valued-form )
@@ -15966,9 +15970,11 @@ retrieve a global macro expander using the function
.coNP Operator @ dwim
.synb
.mets (dwim << argument *)
-.mets <> '[' argument *']'
.mets (set (dwim < obj-place < index <> [ alt ]) << new-value )
+.mets (set (dwim >> { integer | << range } << obj-place ) << new-value )
+.mets <> '[' argument *']'
.mets (set >> '[' obj-place < index <> [ alt ]']' << new-value )
+.mets (set >> '[{' integer | << range } << obj-place']' << new-value )
.syne
.desc
The
@@ -16296,14 +16302,34 @@ These, in turn, rely on the specialized functions.
.code carray-sub
and
.codn carray-replace .
+
.meIP >> [ buf << index ]
Indexing is supported for objects of type
.codn buf .
This provides a way to access and store the individual bytes
of a buffer.
+
+.meIP >> [ integer << sequence ]
+If the left argument is an integer, it denotes selection of an
+element from
+.metn sequence .
+The
+.meta integer
+value acts as the index into a vector-like or list-like sequence,
+or a key into a hash table.
+
+.meIP >> [ range << sequence ]
+If the left argument is an range, it denotes selection of a
+subrange of
+.metn sequence .
.RE
.PP
+Note that the various above forms are not actually special cases of
+.code dwim
+but the consequence of the objects appearing as the first argument being
+callable as functions, and their respective semantics.
+
.TP* "Range Indexing:"
Vector and list range indexing is based from zero, meaning
that the first element is numbered zero, the second one