diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-09-12 13:17:53 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-09-12 13:17:53 -0400 |
| commit | 10795782c674df12fc70ea3aeeaa2f62158b6cbd (patch) | |
| tree | 4998775cf740a86de78b4b1942cc8c40543965de | |
| parent | 990846debb5593f85648c82abe4d59398ecd80fb (diff) | |
Implement optional hashing/equality/comparisons
| -rw-r--r-- | builtins/functions.c | 16 | ||||
| -rw-r--r-- | builtins/optionals.c | 2 | ||||
| -rw-r--r-- | builtins/optionals.h | 1 | ||||
| -rw-r--r-- | test/optionals.tm | 10 |
4 files changed, 23 insertions, 6 deletions
diff --git a/builtins/functions.c b/builtins/functions.c index 3c01f678..a2b17807 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -115,9 +115,7 @@ PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo *type) case ArrayInfo: return Array$hash(obj, type); case ChannelInfo: return Channel$hash((Channel_t**)obj, type); case TableInfo: return Table$hash(obj, type); - case OptionalInfo: { - errx(1, "Optional hash not implemented"); - } + case OptionalInfo: return is_null(obj, type->OptionalInfo.type) ? 0 : generic_hash(obj, type->OptionalInfo.type); case EmptyStructInfo: return 0; case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info if (!type->CustomInfo.hash) @@ -141,7 +139,11 @@ PUREFUNC public int32_t generic_compare(const void *x, const void *y, const Type case ChannelInfo: return Channel$compare((Channel_t**)x, (Channel_t**)y, type); case TableInfo: return Table$compare(x, y, type); case OptionalInfo: { - errx(1, "Optional compare not implemented"); + bool x_is_null = is_null(x, type->OptionalInfo.type); + bool y_is_null = is_null(y, type->OptionalInfo.type); + if (x_is_null && y_is_null) return 0; + else if (x_is_null != y_is_null) return (int32_t)y_is_null - (int32_t)x_is_null; + else return generic_compare(x, y, type->OptionalInfo.type); } case EmptyStructInfo: return 0; case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info @@ -166,7 +168,11 @@ PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo case TableInfo: return Table$equal(x, y, type); case EmptyStructInfo: return true; case OptionalInfo: { - errx(1, "Optional equal not implemented"); + bool x_is_null = is_null(x, type->OptionalInfo.type); + bool y_is_null = is_null(y, type->OptionalInfo.type); + if (x_is_null && y_is_null) return true; + else if (x_is_null != y_is_null) return false; + else return generic_equal(x, y, type->OptionalInfo.type); } case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info if (!type->CustomInfo.equal) diff --git a/builtins/optionals.c b/builtins/optionals.c index 8a1aaf99..8b890c97 100644 --- a/builtins/optionals.c +++ b/builtins/optionals.c @@ -14,7 +14,7 @@ public const Table_t NULL_TABLE = {.entries.length=-1}; public const Closure_t NULL_CLOSURE = {.fn=NULL}; public const Text_t NULL_TEXT = {.length=-1}; -static inline bool is_null(const void *obj, const TypeInfo *non_optional_type) +public PUREFUNC bool is_null(const void *obj, const TypeInfo *non_optional_type) { if (non_optional_type == &Int$info) return ((Int_t*)obj)->small == 0; diff --git a/builtins/optionals.h b/builtins/optionals.h index 10599473..5f0a407f 100644 --- a/builtins/optionals.h +++ b/builtins/optionals.h @@ -18,6 +18,7 @@ extern const Int_t NULL_INT; extern const Closure_t NULL_CLOSURE; extern const Text_t NULL_TEXT; +PUREFUNC bool is_null(const void *obj, const TypeInfo *non_optional_type); Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo *type); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/test/optionals.tm b/test/optionals.tm index 5c18d58d..a3f33d6c 100644 --- a/test/optionals.tm +++ b/test/optionals.tm @@ -274,3 +274,13 @@ func main(): >> maybe_int(yes)! = 123 : Int + + # Test comparisons, hashing, equality: + >> (!Int == 5?) + = no + >> (5? == 5?) + = yes + >> {!Int, !Int} + = {!Int} + >> [5?, !Int, !Int, 6?]:sorted() + = [!Int, !Int, 5?, 6?] |
