summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2010-07-17 12:02:38 +0200
committerJohannes Weiner <hannes@cmpxchg.org>2010-07-17 12:03:11 +0200
commit889225f8d7d8bc5ee5806f3b74ed6318a471deaa (patch)
tree4318afda4c22f62ceb54a39c487062d245c0362f
parent3982d0fdd6d79f2fc332efc8f43fa21c628caf06 (diff)
sequence: implement (slice)
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
-rw-r--r--doc/language.txt2
-rw-r--r--include/sheep/object_types.h1
-rw-r--r--sheep/list.c37
-rw-r--r--sheep/sequence.c18
-rw-r--r--sheep/string.c21
5 files changed, 78 insertions, 1 deletions
diff --git a/doc/language.txt b/doc/language.txt
index 7c67921..0fe760d 100644
--- a/doc/language.txt
+++ b/doc/language.txt
@@ -89,7 +89,7 @@
(reverse sequence)
-IMPL: (slice from to sequence)
+(slice sequence from to)
(position item sequence)
diff --git a/include/sheep/object_types.h b/include/sheep/object_types.h
index c2d4a9e..b9128a1 100644
--- a/include/sheep/object_types.h
+++ b/include/sheep/object_types.h
@@ -21,6 +21,7 @@ struct sheep_sequence {
sheep_t (*concat)(struct sheep_vm *, sheep_t, unsigned int);
sheep_t (*reverse)(struct sheep_vm *, sheep_t);
sheep_t (*nth)(struct sheep_vm *, size_t, sheep_t);
+ sheep_t (*slice)(struct sheep_vm *, sheep_t, size_t, size_t);
sheep_t (*position)(struct sheep_vm *, sheep_t, sheep_t);
};
diff --git a/sheep/list.c b/sheep/list.c
index eea3026..bc9dc94 100644
--- a/sheep/list.c
+++ b/sheep/list.c
@@ -173,6 +173,42 @@ static sheep_t list_nth(struct sheep_vm *vm, size_t n, sheep_t sheep)
return sheep;
}
+static sheep_t list_slice(struct sheep_vm *vm, sheep_t sheep,
+ size_t from, size_t to)
+{
+ struct sheep_list *list, *pos;
+ sheep_t new, result = NULL;
+ size_t index = 0;
+
+ sheep_protect(vm, sheep);
+
+ new = sheep_make_cons(vm, NULL, NULL);
+ sheep_protect(vm, new);
+
+ list = sheep_list(sheep);
+ pos = sheep_list(new);
+
+ while (index < to && list->head) {
+ if (index >= from) {
+ pos->head = list->head;
+ pos->tail = sheep_make_cons(vm, NULL, NULL);
+ pos = sheep_list(pos->tail);
+ }
+ list = sheep_list(list->tail);
+ index++;
+
+ }
+ if (index == to)
+ result = new;
+ else
+ sheep_error(vm, "index %ld out of range [0, %ld)", to, index);
+
+ sheep_unprotect(vm, new);
+ sheep_unprotect(vm, sheep);
+
+ return result;
+}
+
static sheep_t list_position(struct sheep_vm *vm, sheep_t item, sheep_t sheep)
{
struct sheep_list *list;
@@ -194,6 +230,7 @@ static const struct sheep_sequence list_sequence = {
.concat = list_concat,
.reverse = list_reverse,
.nth = list_nth,
+ .slice = list_slice,
.position = list_position,
};
diff --git a/sheep/sequence.c b/sheep/sequence.c
index 2fea5dc..b4db341 100644
--- a/sheep/sequence.c
+++ b/sheep/sequence.c
@@ -64,6 +64,23 @@ static sheep_t builtin_nth(struct sheep_vm *vm, unsigned int nr_args)
return sheep_sequence(seq)->nth(vm, n, seq);
}
+/* (slice sequence from to) */
+static sheep_t builtin_slice(struct sheep_vm *vm, unsigned int nr_args)
+{
+ long from, to;
+ sheep_t seq;
+
+ if (sheep_unpack_stack(vm, nr_args, "qNN", &seq, &from, &to))
+ return NULL;
+
+ if (from < 0 || to <= from) {
+ sheep_error(vm, "invalid range [%ld, %ld)", from, to);
+ return NULL;
+ }
+
+ return sheep_sequence(seq)->slice(vm, seq, from, to);
+}
+
/* (position item sequence) */
static sheep_t builtin_position(struct sheep_vm *vm, unsigned int nr_args)
{
@@ -81,5 +98,6 @@ void sheep_sequence_builtins(struct sheep_vm *vm)
sheep_vm_function(vm, "concat", builtin_concat);
sheep_vm_function(vm, "reverse", builtin_reverse);
sheep_vm_function(vm, "nth", builtin_nth);
+ sheep_vm_function(vm, "slice", builtin_slice);
sheep_vm_function(vm, "position", builtin_position);
}
diff --git a/sheep/string.c b/sheep/string.c
index 5d61e2c..9766042 100644
--- a/sheep/string.c
+++ b/sheep/string.c
@@ -111,6 +111,26 @@ static sheep_t string_nth(struct sheep_vm *vm, size_t n, sheep_t sheep)
return __sheep_make_string(vm, new, 1);
}
+static sheep_t string_slice(struct sheep_vm *vm, sheep_t sheep,
+ size_t from, size_t to)
+{
+ struct sheep_string *string;
+ size_t length = 0;
+ char *new;
+
+ string = sheep_string(sheep);
+ if (to > string->nr_bytes) {
+ sheep_error(vm, "index %ld out of range [0, %ld)",
+ to, string->nr_bytes);
+ return NULL;
+ }
+ length = to - from;
+ new = sheep_malloc(length + 1);
+ memcpy(new, string->bytes + from, length);
+ new[length] = 0;
+ return __sheep_make_string(vm, new, length);
+}
+
static sheep_t string_position(struct sheep_vm *vm, sheep_t item, sheep_t sheep)
{
const char *str, *pos;
@@ -133,6 +153,7 @@ static const struct sheep_sequence string_sequence = {
.concat = string_concat,
.reverse = string_reverse,
.nth = string_nth,
+ .slice = string_slice,
.position = string_position,
};