summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-03-07 19:45:01 -0800
committerKaz Kylheku <kaz@kylheku.com>2024-03-07 19:45:01 -0800
commitfe1d0cb216b54a511ab9e3dc4f41b3ce09075997 (patch)
tree88c81759b5ba2efee3307509d4750523a5769283 /lib.c
parentb5d92c7b65b7c8efd3c62da070b52326989dfe0b (diff)
downloadtxr-fe1d0cb216b54a511ab9e3dc4f41b3ce09075997.tar.gz
txr-fe1d0cb216b54a511ab9e3dc4f41b3ce09075997.tar.bz2
txr-fe1d0cb216b54a511ab9e3dc4f41b3ce09075997.zip
New function: rangeref.
Because ranges can be iterated like sequences, and are identified as vector-like, they have to support indexing. However, ranges already have semantics as a function: with a sequence argument, they slice it. Let's put the semantics into a function called rangeref, so it can be coherently documented. * eval.c (eval_init): Register rangeref intrinsic. * lib.c (generic_funcall): Range as a function works in terms of rangeref. (ref): Handle RNG case via rangeref. (rangeref): New function. * lib.h (rangeref): Declared. * tests/012/seq.tl: New tests.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/lib.c b/lib.c
index 7875c7d2..97a36e3e 100644
--- a/lib.c
+++ b/lib.c
@@ -8537,7 +8537,7 @@ INLINE val do_generic_funcall(val fun, varg args_in)
case 0:
callerror(fun, lit("missing required arguments"));
case 1:
- return sub(args->arg[0], fun->rn.from, fun->rn.to);
+ return rangeref(fun, args->arg[0]);
default:
callerror(fun, lit("too many arguments"));
}
@@ -13288,6 +13288,8 @@ val ref(val seq, val ind)
return vecref(seq, ind);
case BUF:
return buf_get_uchar(seq, ind);
+ case RNG:
+ return rangeref(seq, ind);
default:
type_mismatch(lit("ref: ~s is not a sequence"), seq, nao);
}
@@ -14039,6 +14041,37 @@ val in_range_star(val range, val num)
}
}
+val rangeref(val range, val ind)
+{
+ val self = lit("rangeref");
+
+ if (integerp(ind))
+ {
+ val fr = range->rn.from;
+ val to = range->rn.to;
+ val eind = ind;
+
+ if (to != t && to != colon_k) {
+ val len = minus(to, fr);
+
+ if (minusp(eind))
+ eind = plus(eind, len);
+
+ if (minusp(eind) || ge(eind, len))
+ goto err;
+ } else if (minusp(eind)) {
+ goto err;
+ }
+
+ return plus(fr, eind);
+ err:
+ uw_throwf(error_s, lit("~a: ~s is out of range for ~s"),
+ self, ind, range, nao);
+ }
+
+ return sub(ind, range->rn.from, range->rn.to);
+}
+
#if CONFIG_LOCALE_TOLERANCE
static void locale_init(void)