aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-12 13:17:53 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-12 13:17:53 -0400
commit10795782c674df12fc70ea3aeeaa2f62158b6cbd (patch)
tree4998775cf740a86de78b4b1942cc8c40543965de
parent990846debb5593f85648c82abe4d59398ecd80fb (diff)
Implement optional hashing/equality/comparisons
-rw-r--r--builtins/functions.c16
-rw-r--r--builtins/optionals.c2
-rw-r--r--builtins/optionals.h1
-rw-r--r--test/optionals.tm10
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?]