From 95100469b6c7f301bb14bcda5dbc16b93c9ce0dc Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 2 Apr 2024 13:13:33 -0400 Subject: Add array:sorted() --- builtins/array.c | 7 +++++++ builtins/array.h | 1 + compile.c | 6 +++--- test/arrays.tm | 7 +++++++ typecheck.c | 1 + 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/builtins/array.c b/builtins/array.c index 84b65ae7..4eea25fb 100644 --- a/builtins/array.c +++ b/builtins/array.c @@ -151,6 +151,13 @@ public void Array$sort(array_t *arr, closure_t comparison, const TypeInfo *type) qsort_r(arr->data, arr->length, item_size, comparison.fn, comparison.userdata); } +public array_t Array$sorted(array_t arr, closure_t comparison, const TypeInfo *type) +{ + arr.data_refcount = 3; + Array$sort(&arr, comparison, type); + return arr; +} + public void Array$shuffle(array_t *arr, const TypeInfo *type) { int64_t item_size = get_item_size(type); diff --git a/builtins/array.h b/builtins/array.h index 7b432194..c6722e6d 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -57,6 +57,7 @@ void Array$insert(array_t *arr, const void *item, int64_t index, const TypeInfo void Array$insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type); void Array$remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type); void Array$sort(array_t *arr, closure_t comparison, const TypeInfo *type); +array_t Array$sorted(array_t arr, closure_t comparison, const TypeInfo *type); void Array$shuffle(array_t *arr, const TypeInfo *type); void *Array$random(array_t arr); void Array$clear(array_t *array); diff --git a/compile.c b/compile.c index c4983254..ff6a868d 100644 --- a/compile.c +++ b/compile.c @@ -1485,8 +1485,8 @@ CORD compile(env_t *env, ast_t *ast) CORD self = compile_to_pointer_depth(env, call->self, 1, false); (void)compile_arguments(env, ast, NULL, call->args); return CORD_all("Array$shuffle(", self, ", ", compile_type_info(env, self_value_t), ")"); - } else if (streq(call->name, "sort")) { - CORD self = compile_to_pointer_depth(env, call->self, 1, false); + } else if (streq(call->name, "sort") || streq(call->name, "sorted")) { + CORD self = compile_to_pointer_depth(env, call->self, streq(call->name, "sort") ? 1 : 0, false); CORD comparison; if (call->args) { type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true, .is_readonly=true); @@ -1497,7 +1497,7 @@ CORD compile(env_t *env, ast_t *ast) } else { comparison = CORD_all("(closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "}"); } - return CORD_all("Array$sort(", self, ", ", comparison, ", ", compile_type_info(env, self_value_t), ")"); + return CORD_all("Array$", call->name, "(", self, ", ", comparison, ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "clear")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); (void)compile_arguments(env, ast, NULL, call->args); diff --git a/test/arrays.tm b/test/arrays.tm index d4dd2119..60bdc69a 100644 --- a/test/arrays.tm +++ b/test/arrays.tm @@ -76,9 +76,16 @@ if yes if yes >> nums := [10, -20, 30] + // Sorted function doesn't mutate original: + >> nums:sorted() + = [-20, 10, 30] + >> nums + = [10, -20, 30] + // Sort function does mutate in place: >> nums:sort() >> nums = [-20, 10, 30] + // Custom sort functions: >> nums:sort(func(x:&%Int,y:&%Int) x:abs() <> y:abs()) >> nums = [10, -20, 30] diff --git a/typecheck.c b/typecheck.c index f876851e..93b105b2 100644 --- a/typecheck.c +++ b/typecheck.c @@ -505,6 +505,7 @@ type_t *get_type(env_t *env, ast_t *ast) else if (streq(call->name, "insert_all")) return Type(VoidType); else if (streq(call->name, "remove")) return Type(VoidType); else if (streq(call->name, "sort")) return Type(VoidType); + else if (streq(call->name, "sorted")) return self_value_t; else if (streq(call->name, "shuffle")) return Type(VoidType); else if (streq(call->name, "random")) return Type(PointerType, .pointed=Match(self_value_t, ArrayType)->item_type, .is_optional=true, .is_readonly=true); -- cgit v1.2.3