aboutsummaryrefslogtreecommitdiff
path: root/stdlib/integers.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-02-21 15:51:22 -0500
committerBruce Hill <bruce@bruce-hill.com>2025-02-21 15:51:22 -0500
commitee2b02d44dae246e7e405852a4e2e726e7c8b08b (patch)
tree38668a079db9066a7ae810687fb10bc341e750e4 /stdlib/integers.c
parentebc4686d60e4044b840fc5c3167e733205935f37 (diff)
Integer range iteration over fixed width integers should iterate over
that type
Diffstat (limited to 'stdlib/integers.c')
-rw-r--r--stdlib/integers.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/stdlib/integers.c b/stdlib/integers.c
index 835da97b..c60f237d 100644
--- a/stdlib/integers.c
+++ b/stdlib/integers.c
@@ -576,19 +576,35 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t
} \
return bit_array; \
} \
+ typedef struct { \
+ Optional##KindOfInt##_t current, last; \
+ KindOfInt##_t step; \
+ } KindOfInt##Range_t; \
+ static Optional##KindOfInt##_t _next_##KindOfInt(KindOfInt##Range_t *info) \
+ { \
+ Optional##KindOfInt##_t i = info->current; \
+ if (!i.is_none) { \
+ KindOfInt##_t next; bool overflow = __builtin_add_overflow(i.i, info->step, &next); \
+ if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.i : next < info->last.i))) \
+ info->current = (Optional##KindOfInt##_t){.is_none=true}; \
+ else \
+ info->current = (Optional##KindOfInt##_t){.i=next}; \
+ } \
+ return i; \
+ } \
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}; \
+ KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
+ range->current = (Optional##KindOfInt##_t){.i=first}; \
+ range->last = (Optional##KindOfInt##_t){.i=last}; \
+ range->step = step.is_none ? (last >= first ? 1 : -1) : step.i; \
+ return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \
} \
public to_attr Closure_t KindOfInt ## $onward(c_type first, c_type step) { \
- IntRange_t *range = GC_MALLOC(sizeof(IntRange_t)); \
- range->current = KindOfInt##_to_Int(first); \
- range->last = NONE_INT; \
- range->step = KindOfInt##_to_Int(step); \
- return (Closure_t){.fn=_next_int, .userdata=range}; \
+ KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
+ range->current = (Optional##KindOfInt##_t){.i=first}; \
+ range->last = (Optional##KindOfInt##_t){.is_none=true}; \
+ range->step = step; \
+ return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \
} \
public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text) { \
OptionalInt_t full_int = Int$parse(text); \