diff options
| author | Mistivia <i@mistivia.com> | 2025-06-22 16:17:20 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-06-22 16:17:20 +0800 |
| commit | 5c0eddbed7f838daac17e0b9d9c2a23f17da4660 (patch) | |
| tree | 583026ff5f0614d6e6672e6bbb7879c24c701236 /src/builtins.c | |
| parent | b19a0b2ea246be5610812bf7dd4088e0c4a70952 (diff) | |
min, max
Diffstat (limited to 'src/builtins.c')
| -rw-r--r-- | src/builtins.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/builtins.c b/src/builtins.c index 198f80d..fbf5855 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2,6 +2,88 @@ #include "interp.h" #include "sexp.h" #include <algds/str.h> +#include <stdint.h> +#include <float.h> + +SExpRef builtin_min(Interp *interp, SExpRef args) { + if (LENGTH(args) < 1) return new_error(interp, "min: wrong arg number.\n"); + bool hasReal = false; + FOREACH(iter, args) { + SExpRef x = CAR(iter); + if (VALTYPE(x) == kRealSExp) hasReal = true; + if (VALTYPE(x) != kRealSExp && VALTYPE(x) != kIntegerSExp) { + return new_error(interp, "min: wrong type.\n"); + } + } + if (hasReal) { + double min = DBL_MAX; + FOREACH(iter, args) { + SExpRef x = CAR(iter); + if (VALTYPE(x) == kIntegerSExp) { + if (REF(x)->integer < min) { + min = REF(x)->integer; + } + } + if (VALTYPE(x) == kRealSExp) { + if (REF(x)->real < min) { + min = REF(x)->real; + } + } + } + return new_integer(interp, min); + } else { + int64_t min = INT64_MAX; + FOREACH(iter, args) { + SExpRef x = CAR(iter); + if (VALTYPE(x) == kIntegerSExp) { + if (REF(x)->integer < min) { + min = REF(x)->integer; + } + } + } + return new_integer(interp, min); + } +} + +SExpRef builtin_max(Interp *interp, SExpRef args) { + if (LENGTH(args) < 1) return new_error(interp, "min: wrong arg number.\n"); + bool hasReal = false; + FOREACH(iter, args) { + SExpRef x = CAR(iter); + if (VALTYPE(x) == kRealSExp) hasReal = true; + if (VALTYPE(x) != kRealSExp && VALTYPE(x) != kIntegerSExp) { + return new_error(interp, "min: wrong type.\n"); + } + } + if (hasReal) { + double max = -DBL_MAX; + FOREACH(iter, args) { + SExpRef x = CAR(iter); + if (VALTYPE(x) == kIntegerSExp) { + if (REF(x)->integer > max) { + max = REF(x)->integer; + } + } + if (VALTYPE(x) == kRealSExp) { + if (REF(x)->real > max) { + max = REF(x)->real; + } + } + } + return new_real(interp, max); + } else { + int64_t max = INT64_MIN; + FOREACH(iter, args) { + SExpRef x = CAR(iter); + if (VALTYPE(x) == kIntegerSExp) { + if (REF(x)->integer > max) { + max = REF(x)->integer; + } + } + } + return new_integer(interp, max); + } +} static bool equal_impl(Interp *interp, SExpRef x, SExpRef y) { if (VALTYPE(x) != VALTYPE(y)) return false; |
