klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 12e79d94e0fee73b63217e42ec2993c8296b2339
parent 6e222811e7e4659a250446be56499d0446015d75
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun, 27 Nov 2011 19:43:13 -0300

Added vector-copy!, vector-copy-partial, and vector-copy-partial! to the ground environment. Added all corresponding tests.

Diffstat:
MTODO | 9++++++---
Msrc/kgvectors.c | 169++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/tests/vectors.k | 43+++++++++++++++++++++++++++++++++++++++++++
3 files changed, 213 insertions(+), 8 deletions(-)

diff --git a/TODO b/TODO @@ -16,8 +16,14 @@ functions in kghelpers ** check if all inline functions need to be inline * fix: +** fix some inconsistencies between the man page and the interpreter + behaviour. +** fix/test the tty detection in the interpreter ** current-jiffy (r7rs) ** jiffies-per-second (r7rs) +* documentation +** update the manual with the current features +** add a section to the manual with the interpreter usaged * operatives: ** $when (r7rs) ** $unless (r7rs) @@ -34,9 +40,6 @@ ** vector-map (r7rs) ** bytevector-map (r7rs) ** string-map (r7rs) -** vector-copy! (r7rs) -** vector-copy-partial (r7rs) -** vector-copy-partial! (r7rs) ** read-line (r7rs) ** number->string (r7rs) ** string->number (r7rs) diff --git a/src/kgvectors.c b/src/kgvectors.c @@ -253,6 +253,156 @@ void vector_to_bytevector(klisp_State *K) kapply_cc(K, res); } +/* 13.2.9? vector-copy! */ +void vector_copyB(klisp_State *K) +{ + TValue *xparams = K->next_xparams; + TValue ptree = K->next_value; + TValue denv = K->next_env; + klisp_assert(ttisenvironment(K->next_env)); + UNUSED(xparams); + UNUSED(denv); + bind_2tp(K, ptree, "vector", ttisvector, vector1, + "vector", ttisvector, vector2); + + if (kvector_immutablep(vector2)) { + klispE_throw_simple(K, "immutable destination vector"); + return; + } else if (kvector_size(vector1) > kvector_size(vector2)) { + klispE_throw_simple(K, "destination vector is too small"); + return; + } + + if (!tv_equal(vector1, vector2) && + !tv_equal(vector1, K->empty_vector)) { + memcpy(kvector_buf(vector2), + kvector_buf(vector1), + kvector_size(vector1) * sizeof(TValue)); + } + kapply_cc(K, KINERT); +} + +/* ?.? vector-copy-partial */ +/* TEMP: at least for now this always returns mutable vectors */ +void vector_copy_partial(klisp_State *K) +{ + TValue *xparams = K->next_xparams; + TValue ptree = K->next_value; + TValue denv = K->next_env; + klisp_assert(ttisenvironment(K->next_env)); + UNUSED(xparams); + UNUSED(denv); + bind_3tp(K, ptree, "vector", ttisvector, vector, + "exact integer", keintegerp, tv_start, + "exact integer", keintegerp, tv_end); + + if (!ttisfixint(tv_start) || ivalue(tv_start) < 0 || + ivalue(tv_start) > kvector_size(vector)) { + /* TODO show index */ + klispE_throw_simple(K, "start index out of bounds"); + return; + } + + int32_t start = ivalue(tv_start); + + if (!ttisfixint(tv_end) || ivalue(tv_end) < 0 || + ivalue(tv_end) > kvector_size(vector)) { + klispE_throw_simple(K, "end index out of bounds"); + return; + } + + int32_t end = ivalue(tv_end); + + if (start > end) { + /* TODO show indexes */ + klispE_throw_simple(K, "end index is smaller than start index"); + return; + } + + int32_t size = end - start; + TValue new_vector; + /* the if isn't strictly necessary but it's clearer this way */ + if (size == 0) { + new_vector = K->empty_vector; + } else { + new_vector = kvector_new_bs_g(K, true, kvector_buf(vector) + + start, size); + } + kapply_cc(K, new_vector); +} + +/* ?.? vector-copy-partial! */ +void vector_copy_partialB(klisp_State *K) +{ + TValue *xparams = K->next_xparams; + TValue ptree = K->next_value; + TValue denv = K->next_env; + klisp_assert(ttisenvironment(K->next_env)); + UNUSED(xparams); + UNUSED(denv); + bind_al3tp(K, ptree, "vector", ttisvector, vector1, + "exact integer", keintegerp, tv_start, + "exact integer", keintegerp, tv_end, + rest); + + /* XXX: this will send wrong error msgs (bad number of arg) */ + bind_2tp(K, rest, + "vector", ttisvector, vector2, + "exact integer", keintegerp, tv_start2); + + if (!ttisfixint(tv_start) || ivalue(tv_start) < 0 || + ivalue(tv_start) > kvector_size(vector1)) { + /* TODO show index */ + klispE_throw_simple(K, "start index out of bounds"); + return; + } + + int32_t start = ivalue(tv_start); + + if (!ttisfixint(tv_end) || ivalue(tv_end) < 0 || + ivalue(tv_end) > kvector_size(vector1)) { + klispE_throw_simple(K, "end index out of bounds"); + return; + } + + int32_t end = ivalue(tv_end); + + if (start > end) { + /* TODO show indexes */ + klispE_throw_simple(K, "end index is smaller than start index"); + return; + } + + int32_t size = end - start; + + if (kvector_immutablep(vector2)) { + klispE_throw_simple(K, "immutable destination vector"); + return; + } + + if (!ttisfixint(tv_start2) || ivalue(tv_start2) < 0 || + ivalue(tv_start2) > kvector_size(vector2)) { + klispE_throw_simple(K, "to index out of bounds"); + return; + } + + int32_t start2 = ivalue(tv_start2); + int64_t end2 = (int64_t) start2 + size; + + if ((end2 > INT32_MAX) || + (((int32_t) end2) > kvector_size(vector2))) { + klispE_throw_simple(K, "not enough space in destination"); + return; + } + + if (size > 0) { + memcpy(kvector_buf(vector2) + start2, + kvector_buf(vector1) + start, + size * sizeof(TValue)); + } + kapply_cc(K, KINERT); +} + /* ?.? vector-fill! */ void vector_fillB(klisp_State *K) { @@ -326,23 +476,32 @@ void kinit_vectors_ground_env(klisp_State *K) add_applicative(K, ground_env, "vector->list", vector_to_list, 0); add_applicative(K, ground_env, "list->vector", list_to_vector, 0); - /* ??.1.?? vector-copy */ + /* ?.? vector-copy */ add_applicative(K, ground_env, "vector-copy", vector_copy, 0); - /* 13.?? vector->bytevector, bytevector->vector */ + /* ?.? vector->bytevector, bytevector->vector */ add_applicative(K, ground_env, "vector->bytevector", vector_to_bytevector, 0); add_applicative(K, ground_env, "bytevector->vector", bytevector_to_vector, 0); - /* vector->string, string->vector */ + /* ?.? vector->string, string->vector */ /* in kgstrings.c */ - /* TODO: vector-copy! vector-copy-partial vector-copy-partial! */ + /* ?.? vector-copy! */ + add_applicative(K, ground_env, "vector-copy!", vector_copyB, 0); + + /* ?.? vector-copy-partial */ + add_applicative(K, ground_env, "vector-copy-partial", + vector_copy_partial, 0); + /* ?.? vector-copy-partial! */ + add_applicative(K, ground_env, "vector-copy-partial!", + vector_copy_partialB, 0); + /* ?.? vector-fill! */ add_applicative(K, ground_env, "vector-fill!", vector_fillB, 0); - /* ??.1.?? vector->immutable-vector */ + /* ?.? vector->immutable-vector */ add_applicative(K, ground_env, "vector->immutable-vector", vector_to_immutable_vector, 0); } diff --git a/src/tests/vectors.k b/src/tests/vectors.k @@ -123,11 +123,54 @@ ($check-predicate (mutable-bytevector? (vector->bytevector (vector 0 1)))) + ;; errors ($check-error (vector->bytevector (vector -1))) ($check-error (vector->bytevector (vector 256))) ($check-error (vector->bytevector (vector (integer->char 41)))) +;; XXX vector-copy! +;; additional property: returns #inert +;; additional property: destination must be mutable +;; +($let ((v (make-vector 5 0))) + ($check equal? (vector-copy! (vector 1 2 3 4 5) v) #inert) + ($check equal? v (vector 1 2 3 4 5)) + ($check-no-error (vector-copy! (vector->immutable-vector (vector 9 9)) v)) + ($check equal? v (vector 9 9 3 4 5)) + ($check-error (vector-copy! (vector 1 2 3 4 5 6) v)) + ($check-error + (vector-copy! + (vector 1) + (vector->immutable-vector (vector 1))))) + +;; (R7RS 3rd draft, ) vector-copy-partial + +($check equal? (vector-copy-partial (vector 1 2 3) 0 0) (vector)) +($check equal? (vector-copy-partial (vector 1 2 3) 0 2) (vector 1 2)) +($check equal? (vector-copy-partial (vector 1 2 3) 2 3) (vector 3)) +($check equal? (vector-copy-partial (vector 1 2 3) 3 3) (vector)) +($check-error (vector-copy-partial (vector 1 2 3) 2 4)) +($check-error (vector-copy-partial (vector 1 2 3) -1 0)) + +;; R7RS 3rd draft, vector-copy-partial! +;; additional property: returns #inert +;; additional property: destination must be mutable +;; +($let* + ((v (make-vector 5 9)) + (w (vector->immutable-vector v))) + ($check equal? (vector-copy-partial! (vector 1 2) 0 2 v 0) #inert) + ($check equal? v (vector 1 2 9 9 9)) + ($check equal? (vector-copy-partial! (vector 5 6) 1 2 v 4) #inert) + ($check equal? v (vector 1 2 9 9 6)) + ($check-error (vector-copy-partial! (vector 1 2) 0 2 v -1)) + ($check-error (vector-copy-partial! (vector 1 2) 0 2 v 4)) + ($check-error (vector-copy-partial! (vector 1 2) 2 3 v 0)) + ($check-error (vector-copy-partial! (vector 1 2) -1 0 v 0)) + ($check-error (vector-copy-partial! (vector 1 2) 0 2 w 0))) + + ;; XXX vector-fill! ($check-predicate (inert? (vector-fill! (vector 1 2) 0))) ($check equal? ($let ((v (vector 1 2 3)))