From 5be955904682300153af0abdfd6b711b9da2ac8f Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Thu, 13 Feb 2025 15:03:22 -0500 Subject: [PATCH] Deprecate Range datatype in favor of using iterator methods --- Makefile | 2 +- compile.c | 70 ++++++++++++++++++++++++++++++------------- docs/README.md | 1 - docs/integers.md | 23 +++++++++----- docs/ranges.md | 65 ---------------------------------------- environment.c | 34 ++++----------------- environment.h | 1 - stdlib/README.md | 1 - stdlib/datatypes.h | 4 --- stdlib/integers.c | 45 ++++++++++++++++++++++------ stdlib/integers.h | 14 ++++----- stdlib/ranges.c | 74 ---------------------------------------------- stdlib/ranges.h | 10 ------- stdlib/tomo.h | 1 - test/ranges.tm | 31 ------------------- 15 files changed, 115 insertions(+), 261 deletions(-) delete mode 100644 docs/ranges.md delete mode 100644 stdlib/ranges.c delete mode 100644 stdlib/ranges.h delete mode 100644 test/ranges.tm diff --git a/Makefile b/Makefile index a0194a9..a41312e 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ CFLAGS_PLACEHOLDER="$$(echo -e '\033[2m\033[m')" LDLIBS=-lgc -lcord -lm -lunistring -lgmp -ldl BUILTIN_OBJS=stdlib/siphash.o stdlib/arrays.o stdlib/bools.o stdlib/bytes.o stdlib/nums.o stdlib/integers.o \ stdlib/pointers.o stdlib/memory.o stdlib/text.o stdlib/threads.o stdlib/c_strings.o stdlib/tables.o \ - stdlib/types.o stdlib/util.o stdlib/files.o stdlib/ranges.o stdlib/shell.o stdlib/paths.o stdlib/rng.o \ + stdlib/types.o stdlib/util.o stdlib/files.o stdlib/shell.o stdlib/paths.o stdlib/rng.o \ stdlib/optionals.o stdlib/patterns.o stdlib/metamethods.o stdlib/functiontype.o stdlib/stdlib.o \ stdlib/structs.o stdlib/enums.o stdlib/moments.o stdlib/mutexeddata.o TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm)) diff --git a/compile.c b/compile.c index 154a9e0..04ec9e0 100644 --- a/compile.c +++ b/compile.c @@ -500,7 +500,6 @@ PUREFUNC CORD compile_unsigned_type(type_t *t) CORD compile_type(type_t *t) { if (t == THREAD_TYPE) return "Thread_t"; - else if (t == RANGE_TYPE) return "Range_t"; else if (t == RNG_TYPE) return "RNG_t"; else if (t == MATCH_TYPE) return "Match_t"; @@ -1541,26 +1540,58 @@ static CORD _compile_statement(env_t *env, ast_t *ast) naked_body = CORD_all(naked_body, "\n", loop_ctx.skip_label, ": continue;"); CORD stop = loop_ctx.stop_label ? CORD_all("\n", loop_ctx.stop_label, ":;") : CORD_EMPTY; + // Special case for improving performance for numeric iteration: + if (for_->iter->tag == MethodCall && streq(Match(for_->iter, MethodCall)->name, "to") && + get_type(env, Match(for_->iter, MethodCall)->self)->tag == BigIntType) { + arg_ast_t *args = Match(for_->iter, MethodCall)->args; + if (!args) code_err(for_->iter, "to() needs at least one argument"); + + CORD last = CORD_EMPTY, step = CORD_EMPTY, optional_step = CORD_EMPTY; + if (!args->name || streq(args->name, "last")) { + last = compile_to_type(env, args->value, INT_TYPE); + if (args->next) { + if (args->next->name && !streq(args->next->name, "step")) + code_err(args->next->value, "Invalid argument name: %s", args->next->name); + if (get_type(env, args->next->value)->tag == OptionalType) + optional_step = compile_to_type(env, args->next->value, Type(OptionalType, .type=INT_TYPE)); + else + step = compile_to_type(env, args->next->value, INT_TYPE); + } + } else if (streq(args->name, "step")) { + if (get_type(env, args->value)->tag == OptionalType) + optional_step = compile_to_type(env, args->value, Type(OptionalType, .type=INT_TYPE)); + else + step = compile_to_type(env, args->value, INT_TYPE); + if (args->next) { + if (args->next->name && !streq(args->next->name, "last")) + code_err(args->next->value, "Invalid argument name: %s", args->next->name); + last = compile_to_type(env, args->next->value, INT_TYPE); + } + } + + if (!last) + code_err(for_->iter, "No `last` argument was given"); + + if (step && optional_step) + step = CORD_all("({ OptionalInt_t maybe_step = ", optional_step, "; maybe_step->small == 0 ? (Int$compare_value(last, first) >= 0 ? I_small(1) : I_small(-1)) : (Int_t)maybe_step; })"); + else if (!step) + step = "Int$compare_value(last, first) >= 0 ? I_small(1) : I_small(-1)"; + + CORD value = for_->vars ? compile(body_scope, for_->vars->ast) : "i"; + return CORD_all( + "for (Int_t first = ", compile(env, Match(for_->iter, MethodCall)->self), ", ", + value, " = first, " + "last = ", last, ", " + "step = ", step, "; " + "Int$compare_value(", value, ", last) != Int$compare_value(step, I_small(0)); ", value, " = Int$plus(", value, ", step)) {\n" + "\t", naked_body, + "}", + stop); + } + type_t *iter_t = value_type(get_type(env, for_->iter)); type_t *iter_value_t = value_type(iter_t); - if (iter_value_t == RANGE_TYPE) { - CORD range = compile_to_pointer_depth(env, for_->iter, 0, false); - CORD value = for_->vars ? compile(body_scope, for_->vars->ast) : "i"; - if (for_->empty) - code_err(ast, "Ranges are never empty, they always contain at least their starting element"); - return CORD_all( - "{\n" - "const Range_t range = ", range, ";\n" - "if (range.step.small == 0) fail(\"This range has a 'step' of zero and will loop infinitely!\");\n" - "bool negative = (Int$compare_value(range.step, I(0)) < 0);\n" - "for (Int_t ", value, " = range.first; ({ int32_t cmp = Int$compare_value(", value, ", range.last); negative ? cmp >= 0 : cmp <= 0;}) ; ", value, " = Int$plus(", value, ", range.step)) {\n" - "\t", naked_body, - "\n}", - stop, - "\n}"); - } - switch (iter_value_t->tag) { case ArrayType: { type_t *item_t = Match(iter_value_t, ArrayType)->item_type; @@ -3848,7 +3879,7 @@ CORD compile(env_t *env, ast_t *ast) case StructType: { for (arg_t *field = Match(value_t, StructType)->fields; field; field = field->next) { if (streq(field->name, f->field)) { - const char *prefix = (value_t == RANGE_TYPE || value_t == MATCH_TYPE) ? "" : "$"; + const char *prefix = (value_t == MATCH_TYPE) ? "" : "$"; if (fielded_t->tag == PointerType) { CORD fielded = compile_to_pointer_depth(env, f->fielded, 1, false); return CORD_asprintf("(%r)->%s%s", fielded, prefix, f->field); @@ -4086,7 +4117,6 @@ void compile_namespace(env_t *env, const char *ns_name, ast_t *block) CORD compile_type_info(env_t *env, type_t *t) { if (t == THREAD_TYPE) return "&Thread$info"; - else if (t == RANGE_TYPE) return "&Range$info"; else if (t == MATCH_TYPE) return "&Match$info"; else if (t == RNG_TYPE) return "&RNG$info"; diff --git a/docs/README.md b/docs/README.md index e525396..01e261f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,7 +24,6 @@ Information about Tomo's built-in types can be found here: - [Moment](moments.md) - [Enums](enums.md) - [Floating point numbers](nums.md) -- [Integer Ranges](ranges.md) - [Integers](integers.md) - [Languages](langs.md) - [Mutexed Data](mutexed.md) diff --git a/docs/integers.md b/docs/integers.md index b69ed2b..b660031 100644 --- a/docs/integers.md +++ b/docs/integers.md @@ -297,25 +297,34 @@ of the representable range or if the entire text can't be parsed as an integer, ### `to` **Description:** -Creates an inclusive range of integers between the specified start and end values. +Returns an iterator function that iterates over the range of numbers specified. +Iteration is assumed to be nonempty and **Signature:** ```tomo -func to(from: Int, to: Int -> Range) +func to(first: Int, last: Int, step : Int? = none:Int -> func(->Int?)) ``` **Parameters:** -- `from`: The starting value of the range. -- `to`: The ending value of the range. +- `first`: The starting value of the range. +- `last`: The ending value of the range. +- `step`: An optional step size to use. If unspecified or `none`, the step will be inferred to be `+1` if `last >= first`, otherwise `-1`. **Returns:** -A range object representing all integers from `from` to `to` (inclusive). +An iterator function that returns each integer in the given range (inclusive). **Example:** ```tomo ->> 1:to(5) -= Range(first=1, last=5, step=1) +>> 2:to(5) += func(->Int?) +>> [x for x in 2:to(5)] += [2, 3, 4, 5] +>> [x for x in 5:to(2)] += [5, 4, 3, 2] + +>> [x for x in 2:to(5, step=2)] += [2, 4] ``` --- diff --git a/docs/ranges.md b/docs/ranges.md deleted file mode 100644 index 799b0eb..0000000 --- a/docs/ranges.md +++ /dev/null @@ -1,65 +0,0 @@ -# Ranges - -Ranges are Tomo's way to do iteration over numeric ranges. Ranges are typically -created using the `Int.to()` method like so: `5:to(10)`. Ranges are -*inclusive*. - -```tomo ->> [i for i in 3:to(5)] -= [3, 4, 5] -``` - ---- - -## Range Methods - -### `reversed` - -**Description:** -Returns a reversed copy of the range. - -**Signature:** -```tomo -func reversed(range: Range -> Range) -``` - -**Parameters:** - -- `range`: The range to be reversed. - -**Returns:** -A new `Range` with the order of elements reversed. - -**Example:** -```tomo ->> 1:to(5):reversed() -= Range(first=5, last=1, step=-1) -``` - ---- - -### `by` - -**Description:** -Creates a new range with a specified step value. - -**Signature:** -```tomo -func by(range: Range, step: Int -> Range) -``` - -**Parameters:** - -- `range`: The original range. -- `step`: The step value to be used in the new range. - -**Returns:** -A new `Range` that increments by the specified step value. - -**Example:** -```tomo ->> 1:to(5):by(2) -= Range(first=1, last=5, step=2) -``` - ---- diff --git a/environment.c b/environment.c index 5f3fe76..1427e9e 100644 --- a/environment.c +++ b/environment.c @@ -13,7 +13,6 @@ type_t *TEXT_TYPE = NULL; type_t *MATCH_TYPE = NULL; -type_t *RANGE_TYPE = NULL; type_t *RNG_TYPE = NULL; public type_t *THREAD_TYPE = NULL; @@ -67,15 +66,6 @@ env_t *new_compilation_unit(CORD libname) const char *name, *code, *type_str; } ns_entry_t; - { - env_t *range_env = namespace_env(env, "Range"); - RANGE_TYPE = Type( - StructType, .name="Range", .env=range_env, - .fields=new(arg_t, .name="first", .type=INT_TYPE, - .next=new(arg_t, .name="last", .type=INT_TYPE, - .next=new(arg_t, .name="step", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1"))))); - } - { env_t *match_env = namespace_env(env, "Match"); MATCH_TYPE = Type( @@ -142,7 +132,7 @@ env_t *new_compilation_unit(CORD libname) {"right_shifted", "Int$right_shifted", "func(x,y:Int -> Int)"}, {"sqrt", "Int$sqrt", "func(x:Int -> Int?)"}, {"times", "Int$times", "func(x,y:Int -> Int)"}, - {"to", "Int$to", "func(from:Int,to:Int -> Range)"}, + {"to", "Int$to", "func(from:Int,to:Int,step=none:Int -> func(->Int?))"}, )}, {"Int64", Type(IntType, .bits=TYPE_IBITS64), "Int64_t", "Int64$info", TypedArray(ns_entry_t, {"abs", "labs", "func(i:Int64 -> Int64)"}, @@ -158,7 +148,7 @@ env_t *new_compilation_unit(CORD libname) {"modulo", "Int64$modulo", "func(x,y:Int64 -> Int64)"}, {"modulo1", "Int64$modulo1", "func(x,y:Int64 -> Int64)"}, {"octal", "Int64$octal", "func(i:Int64, digits=0, prefix=yes -> Text)"}, - {"to", "Int64$to", "func(from:Int64,to:Int64 -> Range)"}, + {"to", "Int64$to", "func(from:Int64,to:Int64,step=none:Int64 -> func(->Int?))"}, {"unsigned_left_shifted", "Int64$unsigned_left_shifted", "func(x:Int64,y:Int64 -> Int64)"}, {"unsigned_right_shifted", "Int64$unsigned_right_shifted", "func(x:Int64,y:Int64 -> Int64)"}, {"wrapping_minus", "Int64$wrapping_minus", "func(x:Int64,y:Int64 -> Int64)"}, @@ -178,7 +168,7 @@ env_t *new_compilation_unit(CORD libname) {"modulo", "Int32$modulo", "func(x,y:Int32 -> Int32)"}, {"modulo1", "Int32$modulo1", "func(x,y:Int32 -> Int32)"}, {"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes -> Text)"}, - {"to", "Int32$to", "func(from:Int32,to:Int32 -> Range)"}, + {"to", "Int32$to", "func(from:Int32,to:Int32,step=none:Int32 -> func(->Int?))"}, {"unsigned_left_shifted", "Int32$unsigned_left_shifted", "func(x:Int32,y:Int32 -> Int32)"}, {"unsigned_right_shifted", "Int32$unsigned_right_shifted", "func(x:Int32,y:Int32 -> Int32)"}, {"wrapping_minus", "Int32$wrapping_minus", "func(x:Int32,y:Int32 -> Int32)"}, @@ -198,7 +188,7 @@ env_t *new_compilation_unit(CORD libname) {"modulo", "Int16$modulo", "func(x,y:Int16 -> Int16)"}, {"modulo1", "Int16$modulo1", "func(x,y:Int16 -> Int16)"}, {"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes -> Text)"}, - {"to", "Int16$to", "func(from:Int16,to:Int16 -> Range)"}, + {"to", "Int16$to", "func(from:Int16,to:Int16,step=none:Int16 -> func(->Int?))"}, {"unsigned_left_shifted", "Int16$unsigned_left_shifted", "func(x:Int16,y:Int16 -> Int16)"}, {"unsigned_right_shifted", "Int16$unsigned_right_shifted", "func(x:Int16,y:Int16 -> Int16)"}, {"wrapping_minus", "Int16$wrapping_minus", "func(x:Int16,y:Int16 -> Int16)"}, @@ -218,7 +208,7 @@ env_t *new_compilation_unit(CORD libname) {"modulo", "Int8$modulo", "func(x,y:Int8 -> Int8)"}, {"modulo1", "Int8$modulo1", "func(x,y:Int8 -> Int8)"}, {"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes -> Text)"}, - {"to", "Int8$to", "func(from:Int8,to:Int8 -> Range)"}, + {"to", "Int8$to", "func(from:Int8,to:Int8,step=none:Int8 -> func(->Int?))"}, {"unsigned_left_shifted", "Int8$unsigned_left_shifted", "func(x:Int8,y:Int8 -> Int8)"}, {"unsigned_right_shifted", "Int8$unsigned_right_shifted", "func(x:Int8,y:Int8 -> Int8)"}, {"wrapping_minus", "Int8$wrapping_minus", "func(x:Int8,y:Int8 -> Int8)"}, @@ -285,10 +275,6 @@ env_t *new_compilation_unit(CORD libname) #undef F_opt #undef F #undef C - {"Range", RANGE_TYPE, "Range_t", "Range", TypedArray(ns_entry_t, - {"reversed", "Range$reversed", "func(range:Range -> Range)"}, - {"by", "Range$by", "func(range:Range, step:Int -> Range)"}, - )}, {"Match", MATCH_TYPE, "Match_t", "Match", TypedArray(ns_entry_t, // No methods )}, @@ -547,16 +533,6 @@ env_t *for_scope(env_t *env, ast_t *ast) type_t *iter_t = value_type(get_type(env, for_->iter)); env_t *scope = fresh_scope(env); - if (iter_t == RANGE_TYPE) { - if (for_->vars) { - if (for_->vars->next) - code_err(for_->vars->next->ast, "This is too many variables for this loop"); - const char *var = Match(for_->vars->ast, Var)->name; - set_binding(scope, var, INT_TYPE, CORD_cat("_$", var)); - } - return scope; - } - switch (iter_t->tag) { case ArrayType: { type_t *item_t = Match(iter_t, ArrayType)->item_type; diff --git a/environment.h b/environment.h index 8f4eb1c..287bb2b 100644 --- a/environment.h +++ b/environment.h @@ -71,7 +71,6 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name); #define code_err(ast, ...) compiler_err((ast)->file, (ast)->start, (ast)->end, __VA_ARGS__) extern type_t *TEXT_TYPE; extern type_t *MATCH_TYPE; -extern type_t *RANGE_TYPE; extern type_t *RNG_TYPE; extern type_t *THREAD_TYPE; diff --git a/stdlib/README.md b/stdlib/README.md index 9916c06..c381411 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 0254060..af37446 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 e534437..858025f 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 033a687..fce243a 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 dfb878e..0000000 --- a/stdlib/ranges.c +++ /dev/null @@ -1,74 +0,0 @@ -// Functions that operate on numeric ranges - -#include -#include -#include -#include -#include -#include -#include -#include - -#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 1656bda..0000000 --- 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 7ed2541..d3887af 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" diff --git a/test/ranges.tm b/test/ranges.tm deleted file mode 100644 index 0ff67c1..0000000 --- a/test/ranges.tm +++ /dev/null @@ -1,31 +0,0 @@ - -func main(): - >> r := 5:to(10):by(2) - = Range(first=5, last=10, step=2) - >> r.first - = 5 - >> r.last - = 10 - >> r.step - = 2 - - >> Range(1, 5) == 1:to(5) - = yes - - >> 1:to(5) == 5:to(1):reversed() - = yes - - >> Range(1, 5) == Range(5, 10) - = no - - >> [i for i in 3:to(5)] - = [3, 4, 5] - - >> [i for i in 3:to(10):by(2)] - = [3, 5, 7, 9] - - >> [i for i in 3:to(10):reversed():by(2)] - = [10, 8, 6, 4] - - >> [i for i in (2:to(10):by(2)):by(2)] - = [2, 6, 10]