From 5fc7577b5a3bc2c445522dfd5b287e1c6eddc3e9 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 31 Aug 2025 23:33:22 -0400 Subject: Switch to using optional return values for list indexing. --- src/stdlib/lists.h | 47 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) (limited to 'src/stdlib') diff --git a/src/stdlib/lists.h b/src/stdlib/lists.h index 1ba46222..74314aa6 100644 --- a/src/stdlib/lists.h +++ b/src/stdlib/lists.h @@ -10,26 +10,19 @@ #include "util.h" // Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1 -#define List_get(item_type, arr_expr, index_expr, start, end) \ - *({ \ - const List_t list = arr_expr; \ +#define List_get(list_expr, index_expr, item_type, var, optional_expr, none_expr) \ + ({ \ + const List_t list = list_expr; \ int64_t index = index_expr; \ - int64_t off = index + (index < 0) * (list.length + 1) - 1; \ - if (unlikely(off < 0 || off >= list.length)) \ - fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", \ - (int64_t)list.length, ")\n"); \ - (item_type *)(list.data + list.stride * off); \ + int64_t offset = index + (index < 0) * (list.length + 1) - 1; \ + unlikely(offset < 0 || offset >= list.length) ? none_expr : ({ \ + item_type var = *(item_type *)(list.data + list.stride * offset); \ + optional_expr; \ + }); \ }) -#define List_get_unchecked(type, x, i) \ +#define List_lvalue(item_type, list_expr, index_expr, start, end) \ *({ \ - const List_t list = x; \ - int64_t index = i; \ - int64_t off = index + (index < 0) * (list.length + 1) - 1; \ - (type *)(list.data + list.stride * off); \ - }) -#define List_lvalue(item_type, arr_expr, index_expr, start, end) \ - *({ \ - List_t *list = arr_expr; \ + List_t *list = list_expr; \ int64_t index = index_expr; \ int64_t off = index + (index < 0) * (list->length + 1) - 1; \ if (unlikely(off < 0 || off >= list->length)) \ @@ -38,15 +31,7 @@ if (list->data_refcount > 0) List$compact(list, sizeof(item_type)); \ (item_type *)(list->data + list->stride * off); \ }) -#define List_lvalue_unchecked(item_type, arr_expr, index_expr) \ - *({ \ - List_t *list = arr_expr; \ - int64_t index = index_expr; \ - int64_t off = index + (index < 0) * (list->length + 1) - 1; \ - if (list->data_refcount > 0) List$compact(list, sizeof(item_type)); \ - (item_type *)(list->data + list->stride * off); \ - }) -#define List_set(item_type, list, index, value, start, end) List_lvalue(item_type, arr_expr, index, start, end) = value +#define List_set(item_type, list, index, value, start, end) List_lvalue(item_type, list_expr, index, start, end) = value #define is_atomic(x) \ _Generic(x, \ bool: true, \ @@ -103,9 +88,9 @@ void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeIn #define List$remove_item_value(list, item_expr, max, type) \ List$remove_item(list, (__typeof(item_expr)[1]){item_expr}, max, type) -#define List$pop(arr_expr, index_expr, item_type, nonnone_var, nonnone_expr, none_expr) \ +#define List$pop(list_expr, index_expr, item_type, nonnone_var, nonnone_expr, none_expr) \ ({ \ - List_t *list = arr_expr; \ + List_t *list = list_expr; \ Int_t index = index_expr; \ int64_t index64 = Int64$from_int(index, false); \ int64_t off = index64 + (index64 < 0) * (list->length + 1) - 1; \ @@ -131,9 +116,9 @@ List_t List$shuffled(List_t list, OptionalClosure_t random_int64, int64_t padded void *List$random(List_t list, OptionalClosure_t random_int64); #define List$random_value(list, random_int64, t) \ ({ \ - List_t _arr = list; \ - if (_arr.length == 0) fail("Cannot get a random value from an empty list!"); \ - *(t *)List$random(_arr, random_int64); \ + List_t _list_expr = list; \ + if (_list_expr.length == 0) fail("Cannot get a random value from an empty list!"); \ + *(t *)List$random(_list_expr, random_int64); \ }) List_t List$sample(List_t list, Int_t n, List_t weights, Closure_t random_num, int64_t padded_item_size); Table_t List$counts(List_t list, const TypeInfo_t *type); -- cgit v1.2.3 From 0a7062e2d711b5ac7fb71e873f293a8f0d0e8bc6 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 1 Sep 2025 12:43:08 -0400 Subject: Improved error messages --- src/stdlib/lists.h | 10 ++++++++++ src/stdlib/tables.h | 12 ++++++++++++ 2 files changed, 22 insertions(+) (limited to 'src/stdlib') diff --git a/src/stdlib/lists.h b/src/stdlib/lists.h index 74314aa6..1386b2fa 100644 --- a/src/stdlib/lists.h +++ b/src/stdlib/lists.h @@ -10,6 +10,16 @@ #include "util.h" // Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1 +#define List_get_checked(list_expr, index_expr, item_type, start, end) \ + ({ \ + const List_t list = list_expr; \ + int64_t index = index_expr; \ + int64_t off = index + (index < 0) * (list.length + 1) - 1; \ + if (unlikely(off < 0 || off >= list.length)) \ + fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", \ + (int64_t)list.length, ")\n"); \ + *(item_type *)(list.data + list.stride * off); \ + }) #define List_get(list_expr, index_expr, item_type, var, optional_expr, none_expr) \ ({ \ const List_t list = list_expr; \ diff --git a/src/stdlib/tables.h b/src/stdlib/tables.h index 208bf6b2..129aa5ec 100644 --- a/src/stdlib/tables.h +++ b/src/stdlib/tables.h @@ -49,6 +49,18 @@ void *Table$get(Table_t t, const void *key, const TypeInfo_t *type); val_t *nonnull_var = Table$get(t, &k, info_expr); \ nonnull_var ? nonnull_expr : null_expr; \ }) +#define Table$get_checked(table_expr, key_t, val_t, key_expr, start, end, info_expr) \ + ({ \ + const Table_t t = table_expr; \ + const key_t key = key_expr; \ + const TypeInfo_t *info = info_expr; \ + val_t *value = Table$get(t, &key, info); \ + if (unlikely(value == NULL)) \ + fail_source(__SOURCE_FILE__, start, end, \ + "This key was not found in the table: ", generic_as_text(&key, false, info->TableInfo.key), \ + "\n"); \ + *value; \ + }) #define Table$get_or_setdefault(table_expr, key_t, val_t, key_expr, default_expr, info_expr) \ ({ \ Table_t *t = table_expr; \ -- cgit v1.2.3 From 639d5ddfca562e5b3645955551be244b5e8ca9c6 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 1 Sep 2025 12:51:19 -0400 Subject: Make text indexing optional --- src/stdlib/text.c | 5 ++++- src/stdlib/text.h | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/stdlib') diff --git a/src/stdlib/text.c b/src/stdlib/text.c index ed4023a4..f4533be5 100644 --- a/src/stdlib/text.c +++ b/src/stdlib/text.c @@ -725,7 +725,10 @@ Text_t Text$reversed(Text_t text) { } public -PUREFUNC Text_t Text$cluster(Text_t text, Int_t index) { return Text$slice(text, index, index); } +PUREFUNC OptionalText_t Text$cluster(Text_t text, Int_t index) { + Text_t slice = Text$slice(text, index, index); + return slice.length <= 0 ? NONE_TEXT : slice; +} static Text_t Text$from_components(List_t graphemes, Table_t unique_clusters) { size_t blob_size = (sizeof(int32_t[unique_clusters.entries.length]) + sizeof(uint8_t[graphemes.length])); diff --git a/src/stdlib/text.h b/src/stdlib/text.h index 5fa95675..c08e5267 100644 --- a/src/stdlib/text.h +++ b/src/stdlib/text.h @@ -41,7 +41,17 @@ Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int); Text_t Text$from(Text_t text, Int_t first); Text_t Text$to(Text_t text, Int_t last); Text_t Text$reversed(Text_t text); -Text_t Text$cluster(Text_t text, Int_t index_int); +OptionalText_t Text$cluster(Text_t text, Int_t index_int); +#define Text$cluster_checked(text_expr, index_expr, start, end) \ + ({ \ + const Text_t text = text_expr; \ + Int_t index = index_expr; \ + OptionalText_t cluster = Text$cluster(text, index); \ + if (unlikely(cluster.length < 0)) \ + fail_source(__SOURCE_FILE__, start, end, "Invalid text index: ", index, " (text has length ", \ + (int64_t)text.length, ")\n"); \ + cluster; \ + }) OptionalText_t Text$from_str(const char *str); OptionalText_t Text$from_strn(const char *str, size_t len); PUREFUNC uint64_t Text$hash(const void *text, const TypeInfo_t *); -- cgit v1.2.3