From 5fc88e79561ed5d717493714d148e3d1e5c87950 Mon Sep 17 00:00:00 2001 From: jacopodl Date: Thu, 25 Jan 2024 14:57:57 +0100 Subject: [PATCH] feat: add min/max methods to List and Tuple objects --- argon/vm/datatype/list.cpp | 40 ++++++++++++++++++++++++++++++ argon/vm/datatype/support/common.h | 27 ++++++++++++++++++++ argon/vm/datatype/tuple.cpp | 36 +++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/argon/vm/datatype/list.cpp b/argon/vm/datatype/list.cpp index 4ca323a5..d3ba8262 100644 --- a/argon/vm/datatype/list.cpp +++ b/argon/vm/datatype/list.cpp @@ -6,6 +6,8 @@ #include +#include + #include #include #include @@ -114,6 +116,42 @@ ARGON_METHOD(list_insert, insert, return ok ? (ArObject *) IncRef(self) : nullptr; } +ARGON_METHOD(list_max, max, + "Returns the item with the highest value.\n" + "\n" + "- Returns: Highest value.\n" + "\n" + "# SEE\n" + "- min\n", + nullptr, false, false) { + auto *self = (List *) _self; + ArObject *max = nullptr; + + std::shared_lock _(self->rwlock); + + support::MaxMin(self->objects, &max, self->length, false); + + return max; +} + +ARGON_METHOD(list_min, min, + "Returns the item with the lowest value.\n" + "\n" + "- Returns: Lowest value.\n" + "\n" + "# SEE\n" + "- max\n", + nullptr, false, false) { + auto *self = (List *) _self; + ArObject *min = nullptr; + + std::shared_lock _(self->rwlock); + + support::MaxMin(self->objects, &min, self->length, true); + + return min; +} + ARGON_METHOD(list_pop, pop, "Remove and returns the item at the end of the list.\n" "\n" @@ -193,6 +231,8 @@ const FunctionDef list_methods[] = { list_extend, list_find, list_insert, + list_max, + list_min, list_pop, list_remove, list_reverse, diff --git a/argon/vm/datatype/support/common.h b/argon/vm/datatype/support/common.h index d712ac3c..f4003538 100644 --- a/argon/vm/datatype/support/common.h +++ b/argon/vm/datatype/support/common.h @@ -6,6 +6,7 @@ #define ARGON_VM_DATATYPE_SUPPORT_COMMON_H_ #include +#include #include #include @@ -134,6 +135,32 @@ namespace argon::vm::datatype::support { return (ArObject *) ret; } + + inline bool MaxMin(ArObject **list, ArObject **out, ArSize length, bool min) { + auto mode = min ? CompareMode::LE : CompareMode::GR; + *out = nullptr; + + if (length == 0) { + ErrorFormat(kValueError[0], "%s on empty sequence", min ? "min" : "max"); + + return false; + } + + ArObject *ret = *list; + + for (ArSize i = 1; i < length; i++) { + auto *res = Compare(ret, list[i], mode); + if (res == nullptr) + return false; + + if (res == (ArObject *) False) + ret = list[i]; + } + + *out = IncRef(ret); + + return true; + } } #endif // !ARGON_VM_DATATYPE_SUPPORT_COMMON_H_ diff --git a/argon/vm/datatype/tuple.cpp b/argon/vm/datatype/tuple.cpp index 4f7a6627..68e69f43 100644 --- a/argon/vm/datatype/tuple.cpp +++ b/argon/vm/datatype/tuple.cpp @@ -4,6 +4,8 @@ #include +#include + #include #include #include @@ -47,10 +49,44 @@ ARGON_METHOD(tuple_find, find, return (ArObject *) IntNew(-1); } +ARGON_METHOD(tuple_max, max, + "Returns the item with the highest value.\n" + "\n" + "- Returns: Highest value.\n" + "\n" + "# SEE\n" + "- min\n", + nullptr, false, false) { + auto *self = (Tuple *) _self; + ArObject *max = nullptr; + + support::MaxMin(self->objects, &max, self->length, false); + + return max; +} + +ARGON_METHOD(tuple_min, min, + "Returns the item with the lowest value.\n" + "\n" + "- Returns: Lowest value.\n" + "\n" + "# SEE\n" + "- max\n", + nullptr, false, false) { + auto *self = (Tuple *) _self; + ArObject *min = nullptr; + + support::MaxMin(self->objects, &min, self->length, true); + + return min; +} + const FunctionDef tuple_methods[] = { tuple_tuple, tuple_find, + tuple_max, + tuple_min, ARGON_METHOD_SENTINEL };