1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-27 18:49:54 +00:00

Add array/join and tuple/join

Utilities for combining indexed types more efficiently. `array/join`
also solves some interface issues with array/concat
This commit is contained in:
Calvin Rose 2024-08-10 15:16:28 -05:00
parent ce36c4c0d6
commit ab70524d85
5 changed files with 96 additions and 0 deletions

View File

@ -271,6 +271,7 @@ test_files = [
'test/suite-struct.janet', 'test/suite-struct.janet',
'test/suite-symcache.janet', 'test/suite-symcache.janet',
'test/suite-table.janet', 'test/suite-table.janet',
'test/suite-tuple.janet',
'test/suite-unknown.janet', 'test/suite-unknown.janet',
'test/suite-value.janet', 'test/suite-value.janet',
'test/suite-vm.janet' 'test/suite-vm.janet'

View File

@ -275,6 +275,31 @@ JANET_CORE_FN(cfun_array_concat,
return janet_wrap_array(array); return janet_wrap_array(array);
} }
JANET_CORE_FN(cfun_array_join,
"(array/join arr & parts)",
"Join a variable number of arrays and tuples into the first argument, "
"which must be an array. "
"Return the modified array `arr`.") {
int32_t i;
janet_arity(argc, 1, -1);
JanetArray *array = janet_getarray(argv, 0);
for (i = 1; i < argc; i++) {
int32_t j, len = 0;
const Janet *vals = NULL;
if (!janet_indexed_view(argv[i], &vals, &len)) {
janet_panicf("expected indexed type for argument %d, got %v", i, argv[i]);
}
if (array->data == vals) {
int32_t newcount = array->count + len;
janet_array_ensure(array, newcount, 2);
janet_indexed_view(argv[i], &vals, &len);
}
for (j = 0; j < len; j++)
janet_array_push(array, vals[j]);
}
return janet_wrap_array(array);
}
JANET_CORE_FN(cfun_array_insert, JANET_CORE_FN(cfun_array_insert,
"(array/insert arr at & xs)", "(array/insert arr at & xs)",
"Insert all `xs` into array `arr` at index `at`. `at` should be an integer between " "Insert all `xs` into array `arr` at index `at`. `at` should be an integer between "
@ -385,6 +410,7 @@ void janet_lib_array(JanetTable *env) {
JANET_CORE_REG("array/remove", cfun_array_remove), JANET_CORE_REG("array/remove", cfun_array_remove),
JANET_CORE_REG("array/trim", cfun_array_trim), JANET_CORE_REG("array/trim", cfun_array_trim),
JANET_CORE_REG("array/clear", cfun_array_clear), JANET_CORE_REG("array/clear", cfun_array_clear),
JANET_CORE_REG("array/join", cfun_array_join),
JANET_REG_END JANET_REG_END
}; };
janet_core_cfuns_ext(env, NULL, array_cfuns); janet_core_cfuns_ext(env, NULL, array_cfuns);

View File

@ -116,6 +116,34 @@ JANET_CORE_FN(cfun_tuple_setmap,
return argv[0]; return argv[0];
} }
JANET_CORE_FN(cfun_tuple_join,
"(tuple/join & parts)",
"Create a tuple by joining together other tuples and arrays.") {
janet_arity(argc, 0, -1);
int32_t total_len = 0;
for (int32_t i = 0; i < argc; i++) {
int32_t len = 0;
const Janet *vals = NULL;
if (!janet_indexed_view(argv[i], &vals, &len)) {
janet_panicf("expected indexed type for argument %d, got %v", i, argv[i]);
}
if (INT32_MAX - total_len < len) {
janet_panic("tuple too large");
}
total_len += len;
}
Janet *tup = janet_tuple_begin(total_len);
Janet *tup_cursor = tup;
for (int32_t i = 0; i < argc; i++) {
int32_t len = 0;
const Janet *vals = NULL;
janet_indexed_view(argv[i], &vals, &len);
memcpy(tup_cursor, vals, len * sizeof(Janet));
tup_cursor += len;
}
return janet_wrap_tuple(janet_tuple_end(tup));
}
/* Load the tuple module */ /* Load the tuple module */
void janet_lib_tuple(JanetTable *env) { void janet_lib_tuple(JanetTable *env) {
JanetRegExt tuple_cfuns[] = { JanetRegExt tuple_cfuns[] = {
@ -124,6 +152,7 @@ void janet_lib_tuple(JanetTable *env) {
JANET_CORE_REG("tuple/type", cfun_tuple_type), JANET_CORE_REG("tuple/type", cfun_tuple_type),
JANET_CORE_REG("tuple/sourcemap", cfun_tuple_sourcemap), JANET_CORE_REG("tuple/sourcemap", cfun_tuple_sourcemap),
JANET_CORE_REG("tuple/setmap", cfun_tuple_setmap), JANET_CORE_REG("tuple/setmap", cfun_tuple_setmap),
JANET_CORE_REG("tuple/join", cfun_tuple_join),
JANET_REG_END JANET_REG_END
}; };
janet_core_cfuns_ext(env, NULL, tuple_cfuns); janet_core_cfuns_ext(env, NULL, tuple_cfuns);

View File

@ -76,6 +76,16 @@
(array/trim a) (array/trim a)
(array/ensure @[1 1] 6 2) (array/ensure @[1 1] 6 2)
# array/join
(assert (deep= @[1 2 3] (array/join @[] [1] [2] [3])) "array/join 1")
(assert (deep= @[] (array/join @[])) "array/join 2")
(assert (deep= @[1 :a :b :c] (array/join @[1] @[:a :b] [] [:c])) "array/join 3")
(assert (deep= @[:x :y :z "abc123" "def456"] (array/join @[:x :y :z] ["abc123" "def456"])) "array/join 4")
(assert-error "array/join error 1" (array/join))
(assert-error "array/join error 2" (array/join []))
(assert-error "array/join error 3" (array/join [] "abc123"))
(assert-error "array/join error 4" (array/join @[] "abc123"))
(assert-error "array/join error 5" (array/join @[] "abc123"))
(end-suite) (end-suite)

30
test/suite-tuple.janet Normal file
View File

@ -0,0 +1,30 @@
# Copyright (c) 2023 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
(import ./helper :prefix "" :exit true)
(start-suite)
(assert (= [1 2 3] (tuple/join [1] [2] [3])) "tuple/join 1")
(assert (= [] (tuple/join)) "tuple/join 2")
(assert (= [:a :b :c] (tuple/join @[:a :b] [] [:c])) "tuple/join 3")
(assert (= ["abc123" "def456"] (tuple/join ["abc123" "def456"])) "tuple/join 4")
(end-suite)