diff --git a/releasenotes.md b/releasenotes.md index 1ab796c41..6b1ee6506 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -18,6 +18,7 @@ - Support linking .o files in compilation command. #1417 - Slicing constant strings at compile time works. - Allow the "self" parameter to be $/# for macro methods. +- Support compile time slicing of untyped lists. ### Fixes - Issue where a lambda wasn't correctly registered as external. #1408 diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 69899a0aa..b2b4449e4 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3314,6 +3314,12 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, Che expr_rewrite_const_string(expr, data); return true; } + case CONST_UNTYPED_LIST: + assert(!type_is_arraylike(subscripted->type)); + vec_erase_front(subscripted->const_expr.untyped_list, range->start_index); + vec_resize(subscripted->const_expr.untyped_list, range->len_index); + expr_replace(expr, subscripted); + return true; default: break; } diff --git a/src/utils/lib.h b/src/utils/lib.h index 76d26545b..b120c2f58 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -277,6 +277,21 @@ static inline void vec_pop(void *vec) header[-1].size--; } +static inline void vec_erase_front(void *vec, unsigned to_erase) +{ + if (!to_erase) return; + assert(vec); + unsigned size = vec_size(vec); + assert(size >= to_erase); + void **vecptr = (void**)vec; + for (int i = to_erase; i < size; i++) + { + vecptr[i - to_erase] = vecptr[i]; + } + VHeader_ *header = vec; + header[-1].size -= to_erase; +} + static inline void vec_erase_at(void *vec, unsigned i) { assert(vec); diff --git a/test/unit/regression/ct_slice.c3 b/test/unit/regression/ct_slice.c3 index 334ca73c8..bd154bb0e 100644 --- a/test/unit/regression/ct_slice.c3 +++ b/test/unit/regression/ct_slice.c3 @@ -13,4 +13,17 @@ fn void! slice_string() assert($d == "bc"); assert(d == "bc"); assert($a[..] == "abcd"); +} + +fn void slice_untyped() +{ + var $v = { 1, "hello", 3 }; + int[1] v = $v[0:1]; + assert(v == int[1] { 1 }); + int[1] v2 = $v[2:1]; + assert(v2 == int[1] { 3 }); + String[1] v3 = $v[1:1]; + assert(v3 == String[1] { "hello" }); + int[] v4 = $v[0:1]; + assert(v4 == int[] { 1 }); } \ No newline at end of file