aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/README.md1
-rw-r--r--stdlib/datatypes.h4
-rw-r--r--stdlib/integers.c45
-rw-r--r--stdlib/integers.h14
-rw-r--r--stdlib/ranges.c74
-rw-r--r--stdlib/ranges.h10
-rw-r--r--stdlib/tomo.h1
7 files changed, 43 insertions, 106 deletions
diff --git a/stdlib/README.md b/stdlib/README.md
index 9916c064..c3814114 100644
--- a/stdlib/README.md
+++ b/stdlib/README.md
@@ -29,7 +29,6 @@ some common functionality.
- Paths: [header](stdlib/paths.h), [implementation](stdlib/paths.c)
- Patterns: [header](stdlib/patterns.h), [implementation](stdlib/patterns.c)
- Pointers: [header](stdlib/pointers.h), [implementation](stdlib/pointers.c)
-- Ranges: [header](stdlib/ranges.h), [implementation](stdlib/ranges.c)
- Shell: [header](stdlib/shell.h), [implementation](stdlib/shell.c)
- Tables: [header](stdlib/tables.h), [implementation](stdlib/tables.c)
- Text: [header](stdlib/text.h), [implementation](stdlib/text.c)
diff --git a/stdlib/datatypes.h b/stdlib/datatypes.h
index 0254060b..af37446a 100644
--- a/stdlib/datatypes.h
+++ b/stdlib/datatypes.h
@@ -62,10 +62,6 @@ typedef struct {
void *fn, *userdata;
} Closure_t;
-typedef struct Range_s {
- Int_t first, last, step;
-} Range_t;
-
enum text_type { TEXT_ASCII, TEXT_GRAPHEMES, TEXT_CONCAT };
typedef struct Text_s {
diff --git a/stdlib/integers.c b/stdlib/integers.c
index e5344370..858025fa 100644
--- a/stdlib/integers.c
+++ b/stdlib/integers.c
@@ -32,6 +32,11 @@ public Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t*) {
return text;
}
+static bool Int$is_none(const void *i, const TypeInfo_t*)
+{
+ return ((Int_t*)i)->small == 0;
+}
+
public PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y) {
if (likely(x.small & y.small & 1))
return (x.small > y.small) - (x.small < y.small);
@@ -330,8 +335,31 @@ public OptionalInt_t Int$sqrt(Int_t i)
return Int$from_mpz(result);
}
-public PUREFUNC Range_t Int$to(Int_t from, Int_t to) {
- return (Range_t){from, to, Int$compare_value(to, from) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1}};
+typedef struct {
+ OptionalInt_t current, last;
+ Int_t step;
+} IntRange_t;
+
+static OptionalInt_t _next_int(IntRange_t *info)
+{
+ OptionalInt_t i = info->current;
+ if (!Int$is_none(&i, &Int$info)) {
+ Int_t next = Int$plus(i, info->step);
+ if (!Int$is_none(&info->last, &Int$info) && Int$compare_value(next, info->last) == Int$compare_value(info->step, I(0)))
+ next = NONE_INT;
+ info->current = next;
+ }
+ return i;
+}
+
+public PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step) {
+ IntRange_t *range = GC_MALLOC(sizeof(IntRange_t));
+ range->current = first;
+ range->last = last;
+ range->step = Int$is_none(&step, &Int$info) ?
+ Int$compare_value(last, first) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1}
+ : step;
+ return (Closure_t){.fn=_next_int, .userdata=range};
}
public Int_t Int$from_str(const char *str) {
@@ -415,11 +443,6 @@ public Int_t Int$factorial(Int_t n)
return Int$from_mpz(ret);
}
-static bool Int$is_none(const void *i, const TypeInfo_t*)
-{
- return ((Int_t*)i)->small == 0;
-}
-
static void Int$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t*)
{
Int_t i = *(Int_t*)obj;
@@ -545,8 +568,12 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t
} \
return bit_array; \
} \
- public to_attr Range_t KindOfInt ## $to(c_type from, c_type to) { \
- return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? I_small(1): I_small(-1)}; \
+ public to_attr Closure_t KindOfInt ## $to(c_type first, c_type last, Optional ## KindOfInt ## _t step) { \
+ IntRange_t *range = GC_MALLOC(sizeof(IntRange_t)); \
+ range->current = KindOfInt##_to_Int(first); \
+ range->last = KindOfInt##_to_Int(last); \
+ range->step = step.is_none ? (last >= first ? I_small(1) : I_small(-1)) : KindOfInt##_to_Int(step.i); \
+ return (Closure_t){.fn=_next_int, .userdata=range}; \
} \
public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text) { \
OptionalInt_t full_int = Int$parse(text); \
diff --git a/stdlib/integers.h b/stdlib/integers.h
index 033a6873..fce243a9 100644
--- a/stdlib/integers.h
+++ b/stdlib/integers.h
@@ -22,7 +22,7 @@
#define I16(x) ((int16_t)x)
#define I8(x) ((int8_t)x)
-#define DEFINE_INT_TYPE(c_type, type_name, to_attr) \
+#define DEFINE_INT_TYPE(c_type, type_name) \
typedef struct { \
c_type i; \
bool is_none:1; \
@@ -34,7 +34,7 @@
Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
Array_t type_name ## $bits(c_type x); \
- to_attr Range_t type_name ## $to(c_type from, c_type to); \
+ Closure_t type_name ## $to(c_type first, c_type last, Optional ## type_name ## _t step); \
PUREFUNC Optional ## type_name ## _t type_name ## $parse(Text_t text); \
MACROLIKE PUREFUNC c_type type_name ## $clamped(c_type x, c_type min, c_type max) { \
return x < min ? min : (x > max ? max : x); \
@@ -68,10 +68,10 @@
return (c_type)((u##c_type)x >> y); \
}
-DEFINE_INT_TYPE(int64_t, Int64, __attribute__(()))
-DEFINE_INT_TYPE(int32_t, Int32, CONSTFUNC)
-DEFINE_INT_TYPE(int16_t, Int16, CONSTFUNC)
-DEFINE_INT_TYPE(int8_t, Int8, CONSTFUNC)
+DEFINE_INT_TYPE(int64_t, Int64)
+DEFINE_INT_TYPE(int32_t, Int32)
+DEFINE_INT_TYPE(int16_t, Int16)
+DEFINE_INT_TYPE(int8_t, Int8)
#undef DEFINE_INT_TYPE
#define NONE_INT64 ((OptionalInt64_t){.is_none=true})
@@ -101,7 +101,7 @@ PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y);
Text_t Int$format(Int_t i, Int_t digits);
Text_t Int$hex(Int_t i, Int_t digits, bool uppercase, bool prefix);
Text_t Int$octal(Int_t i, Int_t digits, bool prefix);
-PUREFUNC Range_t Int$to(Int_t from, Int_t to);
+PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step);
OptionalInt_t Int$from_str(const char *str);
OptionalInt_t Int$parse(Text_t text);
Int_t Int$abs(Int_t x);
diff --git a/stdlib/ranges.c b/stdlib/ranges.c
deleted file mode 100644
index dfb878ea..00000000
--- a/stdlib/ranges.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// Functions that operate on numeric ranges
-
-#include <ctype.h>
-#include <err.h>
-#include <gc.h>
-#include <math.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/param.h>
-
-#include "integers.h"
-#include "text.h"
-#include "types.h"
-#include "util.h"
-
-
-PUREFUNC static int32_t Range$compare(const void *vx, const void *vy, const TypeInfo_t *)
-{
- if (vx == vy) return 0;
- Range_t *x = (Range_t*)vx, *y = (Range_t*)vy;
- int32_t diff = Int$compare(&x->first, &y->first, &Int$info);
- if (diff != 0) return diff;
- diff = Int$compare(&x->last, &y->last, &Int$info);
- if (diff != 0) return diff;
- return Int$compare(&x->step, &y->step, &Int$info);
-}
-
-PUREFUNC static bool Range$equal(const void *vx, const void *vy, const TypeInfo_t*)
-{
- if (vx == vy) return true;
- Range_t *x = (Range_t*)vx, *y = (Range_t*)vy;
- return Int$equal(&x->first, &y->first, &Int$info) && Int$equal(&x->last, &y->last, &Int$info) && Int$equal(&x->step, &y->step, &Int$info);
-}
-
-static Text_t Range$as_text(const void *obj, bool use_color, const TypeInfo_t *)
-{
- if (!obj) return Text("Range");
-
- Range_t *r = (Range_t*)obj;
- Text_t first = Int$as_text(&r->first, use_color, &Int$info);
- Text_t last = Int$as_text(&r->last, use_color, &Int$info);
- Text_t step = Int$as_text(&r->step, use_color, &Int$info);
- return Text$format(use_color ? "\x1b[0;1mRange\x1b[m(first=%k, last=%k, step=%k)"
- : "Range(first=%k, last=%k, step=%k)", &first, &last, &step);
-}
-
-PUREFUNC public Range_t Range$reversed(Range_t r)
-{
- return (Range_t){r.last, r.first, Int$negative(r.step)};
-}
-
-PUREFUNC public Range_t Range$by(Range_t r, Int_t step)
-{
- return (Range_t){r.first, r.last, Int$times(step, r.step)};
-}
-
-static bool Range$is_none(const void *obj, const TypeInfo_t*)
-{
- return ((Range_t*)obj)->step.small == 0x1;
-}
-
-public const TypeInfo_t Range$info = {
- .size=sizeof(Range_t),
- .align=__alignof(Range_t),
- .metamethods={
- .as_text=Range$as_text,
- .compare=Range$compare,
- .equal=Range$equal,
- .is_none=Range$is_none,
- },
-};
-
-// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/stdlib/ranges.h b/stdlib/ranges.h
deleted file mode 100644
index 1656bdaa..00000000
--- a/stdlib/ranges.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-// Ranges represent numeric ranges
-
-PUREFUNC Range_t Range$reversed(Range_t r);
-PUREFUNC Range_t Range$by(Range_t r, Int_t step);
-
-extern const TypeInfo_t Range$info;
-
-// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
diff --git a/stdlib/tomo.h b/stdlib/tomo.h
index 7ed25412..d3887af4 100644
--- a/stdlib/tomo.h
+++ b/stdlib/tomo.h
@@ -24,7 +24,6 @@
#include "paths.h"
#include "patterns.h"
#include "pointers.h"
-#include "ranges.h"
#include "rng.h"
#include "shell.h"
#include "siphash.h"