klisp

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

commit 6fdc0dabcbb73819675aca0aa530dfd9f03382a5
parent 70ee93008be662eac3194822241d60e9bebd4c18
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Mon, 28 Nov 2011 18:32:53 -0300

Added string-map, vector-map, and bytevector-map to the ground environment. Added the corresponding tests. Refactored the conversion routines from and to list from all array types.

Diffstat:
MTODO | 3+++
Msrc/kgbytevectors.c | 47++++++++++-------------------------------------
Msrc/kgcombiners.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/kghelpers.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kghelpers.h | 13+++++++++++++
Msrc/kgstrings.c | 51+++++++++++----------------------------------------
Msrc/kgvectors.c | 37++++++++++---------------------------
Msrc/kpair.h | 3+++
Msrc/tests/combiners.k | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 415 insertions(+), 129 deletions(-)

diff --git a/TODO b/TODO @@ -15,6 +15,9 @@ ** eliminate char * arguments where not needed (like list check/copy functions in kghelpers ** check if all inline functions need to be inline +** standarize either int32_t (now used in lists) or uint32_t (now used + in strings, vectors and bytevectors) for sizes (and maybe use a + typedef like lua) * fix: ** fix/test the tty detection in the interpreter ** current-jiffy (r7rs) diff --git a/src/kgbytevectors.c b/src/kgbytevectors.c @@ -28,30 +28,6 @@ /* ?.? immutable-bytevector?, mutable-bytevector? */ /* use ftypep */ -/* Helper for bytevector and list->bytevector */ -/* GC: Assumes ls is rooted */ -TValue list_to_bytevector_h(klisp_State *K, char *name, TValue ls) -{ - /* don't allow cycles */ - int32_t pairs; - check_typed_list(K, ku8p, false, ls, &pairs, NULL); - - TValue new_bb; - /* the if isn't strictly necessary but it's clearer this way */ - if (pairs == 0) { - return K->empty_bytevector; - } else { - new_bb = kbytevector_new_s(K, pairs); - uint8_t *buf = kbytevector_buf(new_bb); - TValue tail = ls; - while(pairs--) { - *buf++ = ivalue(kcar(tail)); - tail = kcdr(tail); - } - return new_bb; - } -} - /* ?.? bytevector */ void bytevector(klisp_State *K) { @@ -62,7 +38,10 @@ void bytevector(klisp_State *K) UNUSED(xparams); UNUSED(denv); - TValue new_bb = list_to_bytevector_h(K, "bytevector", ptree); + /* don't allow cycles */ + int32_t pairs; + check_typed_list(K, ku8p, false, ptree, &pairs, NULL); + TValue new_bb = list_to_bytevector_h(K, ptree, pairs); kapply_cc(K, new_bb); } @@ -77,18 +56,9 @@ void bytevector_to_list(klisp_State *K) UNUSED(denv); bind_1tp(K, ptree, "bytevector", ttisbytevector, bb); - int32_t pairs = kbytevector_size(bb); - uint8_t *buf = kbytevector_buf(bb); - TValue tail = kget_dummy1(K); - - while(pairs--) { - TValue new_pair = kcons(K, i2tv(*buf), KNIL); - buf++; - kset_cdr(tail, new_pair); - tail = new_pair; - } - kapply_cc(K, kcutoff_dummy1(K)); + TValue res = bytevector_to_list_h(K, bb, NULL); + kapply_cc(K, res); } /* ?.? list->bytevector */ @@ -104,7 +74,10 @@ void list_to_bytevector(klisp_State *K) /* check later in list_to_bytevector_h */ bind_1p(K, ptree, ls); - TValue new_bb = list_to_bytevector_h(K, "list->bytevector", ls); + /* don't allow cycles */ + int32_t pairs; + check_typed_list(K, ku8p, false, ls, &pairs, NULL); + TValue new_bb = list_to_bytevector_h(K, ls, pairs); kapply_cc(K, new_bb); } diff --git a/src/kgcombiners.c b/src/kgcombiners.c @@ -25,11 +25,14 @@ /* continuations */ void do_vau(klisp_State *K); + +void do_map(klisp_State *K); void do_map_ret(klisp_State *K); void do_map_encycle(klisp_State *K); -void do_map(klisp_State *K); void do_map_cycle(klisp_State *K); +void do_array_map_ret(klisp_State *K); + /* 4.10.1 operative? */ /* uses typep */ @@ -449,6 +452,36 @@ void map(klisp_State *K) ** an open issue (see comment in map). */ +/* NOTE: the type error on the result of app are only checked after + all values are collected. This could be changed if necessary, by + having map continuations take an additional typecheck param */ +/* Helpers for array_map */ + +/* copy the resulting list to a new vector */ +void do_array_map_ret(klisp_State *K) +{ + TValue *xparams = K->next_xparams; + TValue obj = K->next_value; + klisp_assert(ttisnil(K->next_env)); + /* + ** xparams[0]: (dummy . complete-ls) + ** xparams[1]: list->array + ** xparams[2]: length + */ + UNUSED(obj); + + TValue ls = kcdr(xparams[0]); + TValue (*list_to_array)(klisp_State *K, TValue array, int32_t size) = + pvalue(xparams[1]); + int32_t length = ivalue(xparams[2]); + + /* This will also avoid some problems with continuations + captured from within the dynamic extent to map + and later mutation of the result */ + TValue copy = list_to_array(K, ls, length); + kapply_cc(K, copy); +} + /* 5.9.? string-map */ /* 5.9.? vector-map */ /* 5.9.? bytevector-map */ @@ -460,51 +493,71 @@ void array_map(klisp_State *K) klisp_assert(ttisenvironment(K->next_env)); /* - ** xparams[0]: array->list fn - ** xparams[1]: list->array fn - ** xparams[2]: type name + ** xparams[0]: list->array fn + ** xparams[1]: array->list fn (with type check and size ret) */ - UNUSED(xparams); + TValue list_to_array_tv = xparams[0]; + TValue (*array_to_list)(klisp_State *K, TValue array, int32_t *size) = + pvalue(xparams[1]); -/* TODO */ bind_al1tp(K, ptree, "applicative", ttisapplicative, app, lss); + /* check that lss is a non empty list, and copy it */ if (ttisnil(lss)) { - klispE_throw_simple(K, "no lists"); + klispE_throw_simple(K, "no arguments after applicative"); return; } - /* get the metrics of the ptree of each call to app and - of the result list */ int32_t app_pairs, app_apairs, app_cpairs; - int32_t res_pairs, res_apairs, res_cpairs; - - map_for_each_get_metrics(K, lss, &app_apairs, &app_cpairs, - &res_apairs, &res_cpairs); - app_pairs = app_apairs + app_cpairs; - res_pairs = res_apairs + res_cpairs; + /* the copied list should be protected from gc, and will host + the lists resulting from the conversion */ + lss = check_copy_list(K, lss, true, &app_pairs, &app_cpairs); + app_apairs = app_pairs - app_cpairs; + krooted_tvs_push(K, lss); + /* check that all elements have the correct type and same size, + and convert them to lists */ + int32_t res_pairs; + TValue head = kcar(lss); + TValue tail = kcdr(lss); + TValue ls = array_to_list(K, head, &res_pairs); + kset_car(lss, ls); /* save the first */ + /* all array will produce acyclic lists */ + + for(int32_t i = 1 /* jump over first */; i < app_pairs; ++i) { + head = kcar(tail); + int32_t pairs; + ls = array_to_list(K, head, &pairs); + /* in klisp all arrays should have the same length */ + if (pairs != res_pairs) { + klispE_throw_simple(K, "arguments of different length"); + return; + } + kset_car(tail, ls); + tail = kcdr(tail); + } + /* create the list of parameters to app */ lss = map_for_each_transpose(K, lss, app_apairs, app_cpairs, - res_apairs, res_cpairs); + res_pairs, 0); /* cycle pairs is always 0 */ /* ASK John: the semantics when this is mixed with continuations, isn't all that great..., but what are the expectations considering there is no prescribed order? */ + krooted_tvs_pop(K); krooted_tvs_push(K, lss); - /* This will be the list to be returned, but it will be copied - before to play a little nicer with continuations */ + /* This will be the list to be returned, but it will be transformed + to an array before returning (making it also play a little nicer + with continuations) */ TValue dummy = kcons(K, KINERT, KNIL); krooted_tvs_push(K, dummy); - TValue ret_cont = (res_cpairs == 0)? - kmake_continuation(K, kget_cc(K), do_map_ret, 1, dummy) - : kmake_continuation(K, kget_cc(K), do_map_cycle, 4, - app, dummy, i2tv(res_cpairs), denv); - + TValue ret_cont = + kmake_continuation(K, kget_cc(K), do_array_map_ret, 3, dummy, + list_to_array_tv, i2tv(res_pairs)); krooted_tvs_push(K, ret_cont); /* schedule the mapping of the elements of the acyclic part. @@ -512,7 +565,7 @@ void array_map(klisp_State *K) the inert value passed to the first continuation */ TValue new_cont = kmake_continuation(K, ret_cont, do_map, 6, app, lss, dummy, - i2tv(res_apairs), denv, KTRUE); + i2tv(res_pairs), denv, KTRUE); krooted_tvs_pop(K); krooted_tvs_pop(K); @@ -552,6 +605,13 @@ void kinit_combiners_ground_env(klisp_State *K) add_applicative(K, ground_env, "apply", apply, 0); /* 5.9.1 map */ add_applicative(K, ground_env, "map", map, 0); + /* 5.9.? string-map, vector-map, bytevector-map */ + add_applicative(K, ground_env, "string-map", array_map, 2, + p2tv(list_to_string_h), p2tv(string_to_list_h)); + add_applicative(K, ground_env, "vector-map", array_map, 2, + p2tv(list_to_vector_h), p2tv(vector_to_list_h)); + add_applicative(K, ground_env, "bytevector-map", array_map, 2, + p2tv(list_to_bytevector_h), p2tv(bytevector_to_list_h)); /* 6.2.1 combiner? */ add_applicative(K, ground_env, "combiner?", ftypep, 2, symbol, p2tv(kcombinerp)); @@ -562,9 +622,12 @@ void kinit_combiners_cont_names(klisp_State *K) { Table *t = tv2table(K->cont_name_table); + add_cont_name(K, t, do_vau, "$vau-bind!-eval"); + add_cont_name(K, t, do_map, "map-acyclic-part"); add_cont_name(K, t, do_map_encycle, "map-encycle!"); add_cont_name(K, t, do_map_ret, "map-ret"); add_cont_name(K, t, do_map_cycle, "map-cyclic-part"); - add_cont_name(K, t, do_vau, "$vau-bind!-eval"); + + add_cont_name(K, t, do_array_map_ret, "array-map-ret"); } diff --git a/src/kghelpers.c b/src/kghelpers.c @@ -534,6 +534,146 @@ TValue check_copy_env_list(klisp_State *K, TValue obj) return kcutoff_dummy3(K); } +/* Helpers for string, list->string, and string-map, + bytevector, list->bytevector, bytevector-map, + vector, list->vector, and vector-map */ +/* GC: Assume ls is rooted */ +/* ls should a list of length 'length' of the correct type + (chars for string, u8 for bytevector, any for vector) */ +/* these type checks each element */ + +TValue list_to_string_h(klisp_State *K, TValue ls, int32_t length) +{ + TValue new_str; + /* the if isn't strictly necessary but it's clearer this way */ + if (length == 0) { + return K->empty_string; + } else { + new_str = kstring_new_s(K, length); + char *buf = kstring_buf(new_str); + while(length-- > 0) { + TValue head = kcar(ls); + if (!ttischar(head)) { + klispE_throw_simple_with_irritants(K, "Bad type (expected " + "char)", 1, head); + return KINERT; + } + *buf++ = chvalue(head); + ls = kcdr(ls); + } + return new_str; + } +} + +TValue list_to_vector_h(klisp_State *K, TValue ls, int32_t length) +{ + + if (length == 0) { + return K->empty_vector; + } else { + TValue new_vec = kvector_new_sf(K, length, KINERT); + TValue *buf = kvector_buf(new_vec); + while(length-- > 0) { + *buf++ = kcar(ls); + ls = kcdr(ls); + } + return new_vec; + } +} + +TValue list_to_bytevector_h(klisp_State *K, TValue ls, int32_t length) +{ + TValue new_bb; + /* the if isn't strictly necessary but it's clearer this way */ + if (length == 0) { + return K->empty_bytevector; + } else { + new_bb = kbytevector_new_s(K, length); + uint8_t *buf = kbytevector_buf(new_bb); + while(length-- > 0) { + TValue head = kcar(ls); + if (!ttisu8(head)) { + klispE_throw_simple_with_irritants(K, "Bad type (expected " + "u8)", 1, head); + return KINERT; + } + *buf++ = ivalue(head); + ls = kcdr(ls); + } + return new_bb; + } +} + +/* Helpers for string->list, string-map, string-foreach, + bytevector->list, bytevector-map, bytevector-foreach, + vector->list, vector-map, and vector-foreach */ +/* GC: Assume array is rooted */ +TValue string_to_list_h(klisp_State *K, TValue obj, int32_t *length) +{ + if (!ttisstring(obj)) { + klispE_throw_simple_with_irritants(K, "Bad type (expected string)", + 1, obj); + return KINERT; + } + + int32_t pairs = kstring_size(obj); + if (length != NULL) *length = pairs; + + char *buf = kstring_buf(obj) + pairs - 1; + TValue tail = KNIL; + krooted_vars_push(K, &tail); + while(pairs-- > 0) { + tail = kcons(K, ch2tv(*buf), tail); + --buf; + } + krooted_vars_pop(K); + return tail; +} + +TValue vector_to_list_h(klisp_State *K, TValue obj, int32_t *length) +{ + if (!ttisvector(obj)) { + klispE_throw_simple_with_irritants(K, "Bad type (expected vector)", + 1, obj); + return KINERT; + } + + int32_t pairs = kvector_size(obj); + if (length != NULL) *length = pairs; + + TValue *buf = kvector_buf(obj) + pairs - 1; + TValue tail = KNIL; + krooted_vars_push(K, &tail); + while(pairs-- > 0) { + tail = kcons(K, *buf, tail); + --buf; + } + krooted_vars_pop(K); + return tail; +} + +TValue bytevector_to_list_h(klisp_State *K, TValue obj, int32_t *length) +{ + if (!ttisbytevector(obj)) { + klispE_throw_simple_with_irritants(K, "Bad type (expected bytevector)", + 1, obj); + return KINERT; + } + + int32_t pairs = kbytevector_size(obj); + if (length != NULL) *length = pairs; + + uint8_t *buf = kbytevector_buf(obj) + pairs - 1; + TValue tail = KNIL; + krooted_vars_push(K, &tail); + while(pairs-- > 0) { + tail = kcons(K, i2tv(*buf), tail); + --buf; + } + krooted_vars_pop(K); + return tail; +} + /* Some helpers for working with fixints (signed 32 bits) */ int64_t kgcd32_64(int32_t a_, int32_t b_) { diff --git a/src/kghelpers.h b/src/kghelpers.h @@ -360,6 +360,19 @@ TValue check_copy_list(klisp_State *K, TValue obj, bool force_copy, /* GC: assume obj is rooted, uses dummy3 */ TValue check_copy_env_list(klisp_State *K, TValue obj); +/* The assimetry in error checking in the following functions + is a product of the contexts in which they are used, see the + .c for an enumeration of such contexts */ +/* list->? conversion functions, only type errors of elems checked */ +TValue list_to_string_h(klisp_State *K, TValue ls, int32_t length); +TValue list_to_vector_h(klisp_State *K, TValue ls, int32_t length); +TValue list_to_bytevector_h(klisp_State *K, TValue ls, int32_t length); + +/* ?->list conversion functions, type checked */ +TValue string_to_list_h(klisp_State *K, TValue obj, int32_t *length); +TValue vector_to_list_h(klisp_State *K, TValue obj, int32_t *length); +TValue bytevector_to_list_h(klisp_State *K, TValue obj, int32_t *length); + /* ** Generic function for type predicates ** It can only be used by types that have a unique tag diff --git a/src/kgstrings.c b/src/kgstrings.c @@ -138,30 +138,6 @@ void string_setB(klisp_State *K) kapply_cc(K, KINERT); } -/* Helper for string and list->string */ -/* GC: Assumes ls is rooted */ -TValue list_to_string_h(klisp_State *K, char *name, TValue ls) -{ - /* don't allow cycles */ - int32_t pairs; - check_typed_list(K, kcharp, false, ls, &pairs, NULL); - - TValue new_str; - /* the if isn't strictly necessary but it's clearer this way */ - if (pairs == 0) { - return K->empty_string; - } else { - new_str = kstring_new_s(K, pairs); - char *buf = kstring_buf(new_str); - TValue tail = ls; - while(pairs--) { - *buf++ = chvalue(kcar(tail)); - tail = kcdr(tail); - } - return new_str; - } -} - /* 13.2.1? string */ void string(klisp_State *K) { @@ -172,7 +148,10 @@ void string(klisp_State *K) UNUSED(xparams); UNUSED(denv); - TValue new_str = list_to_string_h(K, "string", ptree); + /* don't allow cycles */ + int32_t pairs; + check_typed_list(K, kcharp, false, ptree, &pairs, NULL); + TValue new_str = list_to_string_h(K, ptree, pairs); kapply_cc(K, new_str); } @@ -427,18 +406,8 @@ void string_to_list(klisp_State *K) UNUSED(denv); bind_1tp(K, ptree, "string", ttisstring, str); - int32_t pairs = kstring_size(str); - char *buf = kstring_buf(str); - - TValue tail = kget_dummy1(K); - - while(pairs--) { - TValue new_pair = kcons(K, ch2tv(*buf), KNIL); - buf++; - kset_cdr(tail, new_pair); - tail = new_pair; - } - kapply_cc(K, kcutoff_dummy1(K)); + TValue res = string_to_list_h(K, str, NULL); + kapply_cc(K, res); } void list_to_string(klisp_State *K) @@ -450,10 +419,12 @@ void list_to_string(klisp_State *K) UNUSED(xparams); UNUSED(denv); - /* check later in list_to_string_h */ + /* check later */ bind_1p(K, ptree, ls); - - TValue new_str = list_to_string_h(K, "list->string", ls); + /* don't allow cycles */ + int32_t pairs; + check_typed_list(K, kcharp, false, ls, &pairs, NULL); + TValue new_str = list_to_string_h(K, ls, pairs); kapply_cc(K, new_str); } diff --git a/src/kgvectors.c b/src/kgvectors.c @@ -132,31 +132,16 @@ void vector_copy(klisp_State *K) kapply_cc(K, new_vector); } -static TValue list_to_vector_h(klisp_State *K, const char *name, TValue ls) -{ - /* don't allow cycles */ - int32_t pairs; - check_list(K, false, ls, &pairs, NULL); - - if (pairs == 0) { - return K->empty_vector; - } else { - TValue res = kvector_new_sf(K, pairs, KINERT); - for (int i = 0; i < pairs; i++) { - kvector_buf(res)[i] = kcar(ls); - ls = kcdr(ls); - } - return res; - } -} - /* (R7RS 3rd draft 6.3.6) vector */ void vector(klisp_State *K) { klisp_assert(ttisenvironment(K->next_env)); TValue ptree = K->next_value; - TValue res = list_to_vector_h(K, "vector", ptree); + /* don't allow cycles */ + int32_t pairs; + check_list(K, false, ptree, &pairs, NULL); + TValue res = list_to_vector_h(K, ptree, pairs); kapply_cc(K, res); } @@ -167,7 +152,10 @@ void list_to_vector(klisp_State *K) TValue ptree = K->next_value; bind_1p(K, ptree, ls); - TValue res = list_to_vector_h(K, "list->vector", ls); + /* don't allow cycles */ + int32_t pairs; + check_list(K, false, ls, &pairs, NULL); + TValue res = list_to_vector_h(K, ls, pairs); kapply_cc(K, res); } @@ -179,13 +167,8 @@ void vector_to_list(klisp_State *K) TValue ptree = K->next_value; bind_1tp(K, ptree, "vector", ttisvector, v); - TValue tail = KNIL; - krooted_vars_push(K, &tail); - size_t i = kvector_size(v); - while (i-- > 0) - tail = kcons(K, kvector_buf(v)[i], tail); - krooted_vars_pop(K); - kapply_cc(K, tail); + TValue res = vector_to_list_h(K, v, NULL); + kapply_cc(K, res); } /* 13.? bytevector->vector, vector->bytevector */ diff --git a/src/kpair.h b/src/kpair.h @@ -102,6 +102,9 @@ TValue klist_g(klisp_State *K, bool m, int32_t n, ...); #define klist(K_, n_, ...) (klist_g(K_, true, n_, __VA_ARGS__)) #define kimm_list(K_, n_, ...) (klist_g(K_, false, n_, __VA_ARGS__)) +/* TODO/REFACTOR: delete these functions, instead use + a pushed var */ + inline TValue kget_dummy1(klisp_State *K) { klisp_assert(ttispair(K->dummy_pair1) && ttisnil(kcdr(K->dummy_pair1))); diff --git a/src/tests/combiners.k b/src/tests/combiners.k @@ -223,6 +223,91 @@ . #0#)) (list #f #f #f #f)) +;; string-map +($check-predicate (applicative? string-map)) +($check equal? (string-map char-downcase "") "") +($check equal? (string-map char-upcase "abc") "ABC") +($let ((char-max ($lambda chars + (integer->char + (apply max + (map char->integer chars)))))) + ($check equal? (string-map char-max "abc" "ABC" "xyz" "XYZ") + "xyz") + ($check equal? (string-map char-max "abc" "ABC" . #0=("xyz" "XYZ". #0#)) + "xyz")) + +($let ((p (cons () ()))) + ($check eq? + ($sequence (string-map (wrap ($vau #ignore env + (set-car! p env) + #\a)) + "a") + (car p)) + (get-current-environment))) + +($let ((p (cons 0 ()))) + ($check eq? + ($sequence (string-map ($lambda (x) + (set-car! p (+ (car p) (char->integer x))) + #\a) + "abcd") + (car p)) + (apply + (map char->integer (string->list "abcd"))))) + +;; vector-map +($check-predicate (applicative? vector-map)) +($check equal? (vector-map inert? (vector #inert #ignore #inert)) + (vector #t #f #t)) +($check equal? (vector-map inert? (vector)) (vector)) +($check equal? (vector-map max (vector 1 2) . + #0=((vector 3 4) (vector 5 6). #0#)) + (vector 5 6)) + +($let ((p (cons () ()))) + ($check eq? + ($sequence (vector-map (wrap ($vau #ignore env + (set-car! p env))) + (vector 1)) + (car p)) + (get-current-environment))) + +($let ((p (cons 0 ()))) + ($check eq? + ($sequence (vector-map ($lambda (x) + (set-car! p (+ (car p) x))) + (vector 1 2 3 4)) + (car p)) + 10)) + +;; bytevector-map +($check-predicate (applicative? bytevector-map)) +($check equal? (bytevector-map + (bytevector)) (bytevector)) +($check equal? (bytevector-map ($lambda (x) (+ x 1)) (bytevector 1 2 3)) + (bytevector 2 3 4)) +($check equal? (bytevector-map max (bytevector 1 2) (bytevector 3 4) + (bytevector 5 6)) + (bytevector 5 6)) +($check equal? (bytevector-map max (bytevector 1 2) . #0=((bytevector 3 4) + (bytevector 5 6) . #0#)) + (bytevector 5 6)) + +($let ((p (cons () ()))) + ($check eq? + ($sequence (bytevector-map (wrap ($vau #ignore env + (set-car! p env) + 1)) + (bytevector 1)) + (car p)) + (get-current-environment))) + +($let ((p (cons 0 ()))) + ($check eq? + ($sequence (bytevector-map ($lambda (x) + (set-car! p (+ (car p) x)) + 1) + (bytevector 1 2 3 4)) + (car p)) + 10)) ;;; ;;; Error Checking and Robustness @@ -318,3 +403,55 @@ ($check-error (map list (list 1 2) #inert)) ($check-error (map cons (list 1 2))) + +;; string-map +($check-error (string-map)) +($check-error (string-map char-upcase)) ; the list can't be empty +($check-error (string-map ($lambda ls #\a) "abc" "ab")) +($check-error (string-map ($lambda ls #\a) "abc" . #0=("ab" . #0#))) + +($check-error (string-map char->number "abc")) +($check-error (string-map char>=? "abc" "def")) + +($check-error (string-map char-upcase #\a)) +($check-error (string-map char-upcase (list #\a))) +($check-error (string-map #inert "abc")) +($check-error (string-map (unwrap char-upcase) "abc")) +($check-error (string-map char-upcase "abc" "def")) +($check-error (string-map char-upcase . #0=("abc". #0#))) + +;; vector-map +($check-error (vector-map)) +($check-error (vector-map char-upcase)) ; the list can't be empty +($check-error (vector-map + (vector 1 2 3) (vector 1 2))) +($check-error (vector-map + (vector 1 2 3) . #0=((vector 1 2) . #0#))) + +($check-error (vector-map char-upcase #\a)) +($check-error (vector-map char-upcase (list #\a))) +($check-error (vector-map + (bytevector 1))) +($check-error (vector-map #inert (vector))) +($check-error (vector-map (unwrap +) (vector 1 2 3))) +($check-error (vector-map ($lambda (x) (+ x 1)) + (vector 1 2) (vector 1 2))) +($check-error (vector-map ($lambda (x) (+ x 1)) . + #0=((vector 1 2) . #0#))) + +;; bytevector-map +($check-error (bytevector-map)) +($check-error (bytevector-map +)) ; the list can't be empty +($check-error (bytevector-map + (bytevector 1 2) (bytevector 1 2 3))) +($check-error (bytevector-map + (bytevector 1 2) . + #0=((bytevector 1 2 3) . #0#))) + +($check-error (bytevector-map number->char (bytevector 41 42 43))) +($check-error (bytevector-map + (bytevector 100 200) (bytevector 300 400))) + +($check-error (bytevector-map + 1)) +($check-error (bytevector-map + (list 1))) +($check-error (bytevector-map + (vector 1))) +($check-error (bytevector-map #inert (bytevector 1 2 3))) +($check-error (bytevector-map (unwrap char-upcase) (bytevector 1 2 3))) +($check-error (bytevector-map ($lambda (x) (+ x 1)) + (bytevector 1 2 3) (bytevector 1 2 3))) +($check-error (bytevector-map ($lambda (x) (+ x 1)) . + #0=((bytevector 1 2 3) . #0#)))