From 068d0e8563dab7708711e0171ba1190d6037f0c9 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Wed, 10 Jul 2024 13:42:58 -0400 Subject: Add array:to() to split out functionality of array:from() --- builtins/array.c | 26 ++++++++++++++++++++------ builtins/array.h | 3 ++- compile.c | 7 +++++-- test/arrays.tm | 4 ++-- typecheck.c | 1 + 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/builtins/array.c b/builtins/array.c index 1c31be80..2d45591c 100644 --- a/builtins/array.c +++ b/builtins/array.c @@ -261,24 +261,38 @@ public array_t Array$sample(array_t arr, int64_t n, array_t weights, const TypeI return selected; } -public array_t Array$from(array_t *array, int64_t first, int64_t last) +public array_t Array$from(array_t *array, int64_t first) { if (first < 0) first = array->length + first + 1; + if (first < 1 || first > array->length) + return (array_t){.atomic=array->atomic}; + + return (array_t){ + .atomic=array->atomic, + .data=array->data + array->stride*(first-1), + .length=array->length - first + 1, + .stride=array->stride, + .data_refcount=array->data_refcount, + }; +} + +public array_t Array$to(array_t *array, int64_t last) +{ if (last < 0) last = array->length + last + 1; - if (first < 1 || first > array->length || last < first) - return (array_t){.atomic=array->atomic}; - if (last > array->length) last = array->length; + if (last == 0) + return (array_t){.atomic=array->atomic}; + return (array_t){ .atomic=array->atomic, - .data=array->data + array->stride*(first-1), - .length=last - first + 1, + .data=array->data, + .length=last, .stride=array->stride, .data_refcount=array->data_refcount, }; diff --git a/builtins/array.h b/builtins/array.h index b2884d99..56794a22 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -64,7 +64,8 @@ array_t Array$sample(array_t arr, int64_t n, array_t weights, const TypeInfo *ty void Array$clear(array_t *array); void Array$compact(array_t *arr, const TypeInfo *type); bool Array$contains(array_t array, void *item, const TypeInfo *type); -array_t Array$from(array_t *array, int64_t first, int64_t last); +array_t Array$from(array_t *array, int64_t first); +array_t Array$to(array_t *array, int64_t last); array_t Array$by(array_t *array, int64_t stride); array_t Array$reversed(array_t array); array_t Array$concat(array_t x, array_t y, const TypeInfo *type); diff --git a/compile.c b/compile.c index 9d6b1665..fe6d8454 100644 --- a/compile.c +++ b/compile.c @@ -1815,9 +1815,12 @@ CORD compile(env_t *env, ast_t *ast) return CORD_all("Array$clear(", self, ")"); } else if (streq(call->name, "from")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); - arg_t *arg_spec = new(arg_t, .name="first", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=1, .bits=64), - .next=new(arg_t, .name="last", .type=Type(IntType, .bits=64), .default_val=FakeAST(Int, .i=-1, .bits=64))); + arg_t *arg_spec = new(arg_t, .name="first", .type=Type(IntType, .bits=64)); return CORD_all("Array$from(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ")"); + } else if (streq(call->name, "to")) { + CORD self = compile_to_pointer_depth(env, call->self, 1, false); + arg_t *arg_spec = new(arg_t, .name="last", .type=Type(IntType, .bits=64)); + return CORD_all("Array$to(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ")"); } else if (streq(call->name, "by")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); arg_t *arg_spec = new(arg_t, .name="stride", .type=Type(IntType, .bits=64)); diff --git a/test/arrays.tm b/test/arrays.tm index 9eea9dd9..fb6d16ca 100644 --- a/test/arrays.tm +++ b/test/arrays.tm @@ -121,9 +121,9 @@ func main(): do: >> [i*10 for i in 5]:from(3) = [30, 40, 50] - >> [i*10 for i in 5]:from(last=3) + >> [i*10 for i in 5]:to(3) = [10, 20, 30] - >> [i*10 for i in 5]:from(last=-2) + >> [i*10 for i in 5]:to(-2) = [10, 20, 30, 40] >> [i*10 for i in 5]:from(-2) = [40, 50] diff --git a/typecheck.c b/typecheck.c index 5cc9d664..43e384f4 100644 --- a/typecheck.c +++ b/typecheck.c @@ -670,6 +670,7 @@ type_t *get_type(env_t *env, ast_t *ast) else if (streq(call->name, "sample")) return self_value_t; else if (streq(call->name, "clear")) return Type(VoidType); else if (streq(call->name, "from")) return self_value_t; + else if (streq(call->name, "to")) return self_value_t; else if (streq(call->name, "by")) return self_value_t; else if (streq(call->name, "reversed")) return self_value_t; else if (streq(call->name, "heapify")) return Type(VoidType); -- cgit v1.2.3