diff options
author | Johannes Weiner <hannes@cmpxchg.org> | 2010-07-17 12:02:38 +0200 |
---|---|---|
committer | Johannes Weiner <hannes@cmpxchg.org> | 2010-07-17 12:03:11 +0200 |
commit | 889225f8d7d8bc5ee5806f3b74ed6318a471deaa (patch) | |
tree | 4318afda4c22f62ceb54a39c487062d245c0362f | |
parent | 3982d0fdd6d79f2fc332efc8f43fa21c628caf06 (diff) |
sequence: implement (slice)
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
-rw-r--r-- | doc/language.txt | 2 | ||||
-rw-r--r-- | include/sheep/object_types.h | 1 | ||||
-rw-r--r-- | sheep/list.c | 37 | ||||
-rw-r--r-- | sheep/sequence.c | 18 | ||||
-rw-r--r-- | sheep/string.c | 21 |
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, }; |