aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c14
-rw-r--r--docs/integers.md31
-rw-r--r--environment.c17
-rw-r--r--stdlib/integers.c15
-rw-r--r--stdlib/integers.h2
5 files changed, 73 insertions, 6 deletions
diff --git a/compile.c b/compile.c
index 04ec9e00..dc00d01e 100644
--- a/compile.c
+++ b/compile.c
@@ -1543,6 +1543,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
// 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) {
+ // TODO: support other integer types
arg_ast_t *args = Match(for_->iter, MethodCall)->args;
if (!args) code_err(for_->iter, "to() needs at least one argument");
@@ -1587,6 +1588,19 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
"\t", naked_body,
"}",
stop);
+ } else if (for_->iter->tag == MethodCall && streq(Match(for_->iter, MethodCall)->name, "onward") &&
+ get_type(env, Match(for_->iter, MethodCall)->self)->tag == BigIntType) {
+ // Special case for Int:onward()
+ arg_ast_t *args = Match(for_->iter, MethodCall)->args;
+ arg_t *arg_spec = new(arg_t, .name="step", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1"), .next=NULL);
+ CORD step = compile_arguments(env, for_->iter, arg_spec, args);
+ CORD value = for_->vars ? compile(body_scope, for_->vars->ast) : "i";
+ return CORD_all(
+ "for (Int_t ", value, " = ", compile(env, Match(for_->iter, MethodCall)->self), ", ",
+ "step = ", step, "; ; ", value, " = Int$plus(", value, ", step)) {\n"
+ "\t", naked_body,
+ "}",
+ stop);
}
type_t *iter_t = value_type(get_type(env, for_->iter));
diff --git a/docs/integers.md b/docs/integers.md
index b6600314..84f33414 100644
--- a/docs/integers.md
+++ b/docs/integers.md
@@ -257,6 +257,37 @@ The octal string representation of the integer.
---
+### `onward`
+
+**Description:**
+Return an iterator that counts infinitely from the starting integer (with an
+optional step size).
+
+**Signature:**
+```tomo
+func onward(first: Int, step: Int = 1 -> Text)
+```
+
+**Parameters:**
+
+- `first`: The starting integer.
+- `step`: The increment step size (default: 1).
+
+**Returns:**
+An iterator function that counts onward from the starting integer.
+
+**Example:**
+```tomo
+nums := &[:Int]
+for i in 5:onward():
+ nums:insert(i)
+ stop if i == 10
+>> nums[]
+= [5, 6, 7, 8, 9, 10]
+```
+
+---
+
### `parse`
**Description:**
diff --git a/environment.c b/environment.c
index 1427e9ec..1354999d 100644
--- a/environment.c
+++ b/environment.c
@@ -115,7 +115,6 @@ env_t *new_compilation_unit(CORD libname)
{"factorial", "Int$factorial", "func(x:Int -> Int)"},
{"format", "Int$format", "func(i:Int, digits=0 -> Text)"},
{"gcd", "Int$gcd", "func(x,y:Int -> Int)"},
- {"parse", "Int$parse", "func(text:Text -> Int?)"},
{"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes -> Text)"},
{"is_prime", "Int$is_prime", "func(x:Int,reps=50 -> Bool)"},
{"left_shifted", "Int$left_shifted", "func(x,y:Int -> Int)"},
@@ -126,13 +125,15 @@ env_t *new_compilation_unit(CORD libname)
{"negative", "Int$negative", "func(x:Int -> Int)"},
{"next_prime", "Int$next_prime", "func(x:Int -> Int)"},
{"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes -> Text)"},
+ {"onward", "Int$onward", "func(first:Int,step=1 -> func(->Int?))"},
+ {"parse", "Int$parse", "func(text:Text -> Int?)"},
{"plus", "Int$plus", "func(x,y:Int -> Int)"},
{"power", "Int$power", "func(base:Int,exponent:Int -> Int)"},
{"prev_prime", "Int$prev_prime", "func(x:Int -> Int)"},
{"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,step=none:Int -> func(->Int?))"},
+ {"to", "Int$to", "func(first:Int,last: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)"},
@@ -148,7 +149,8 @@ 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,step=none:Int64 -> func(->Int?))"},
+ {"onward", "Int64$onward", "func(first:Int64,step=Int64(1) -> func(->Int?))"},
+ {"to", "Int64$to", "func(first:Int64,last: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)"},
@@ -168,7 +170,8 @@ 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,step=none:Int32 -> func(->Int?))"},
+ {"onward", "Int32$onward", "func(first:Int32,step=Int32(1) -> func(->Int?))"},
+ {"to", "Int32$to", "func(first:Int32,last: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)"},
@@ -188,7 +191,8 @@ 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,step=none:Int16 -> func(->Int?))"},
+ {"onward", "Int16$onward", "func(first:Int16,step=Int16(1) -> func(->Int?))"},
+ {"to", "Int16$to", "func(first:Int16,last: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)"},
@@ -208,7 +212,8 @@ 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,step=none:Int8 -> func(->Int?))"},
+ {"onward", "Int8$onward", "func(first:Int8,step=Int8(1) -> func(->Int?))"},
+ {"to", "Int8$to", "func(first:Int8,last: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)"},
diff --git a/stdlib/integers.c b/stdlib/integers.c
index 858025fa..835da97b 100644
--- a/stdlib/integers.c
+++ b/stdlib/integers.c
@@ -362,6 +362,14 @@ public PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step) {
return (Closure_t){.fn=_next_int, .userdata=range};
}
+public PUREFUNC Closure_t Int$onward(Int_t first, Int_t step) {
+ IntRange_t *range = GC_MALLOC(sizeof(IntRange_t));
+ range->current = first;
+ range->last = NONE_INT;
+ range->step = step;
+ return (Closure_t){.fn=_next_int, .userdata=range};
+}
+
public Int_t Int$from_str(const char *str) {
mpz_t i;
int result;
@@ -575,6 +583,13 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t
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 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}; \
+ } \
public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text) { \
OptionalInt_t full_int = Int$parse(text); \
if (full_int.small == 0) return (Optional ## KindOfInt ## _t){.is_none=true}; \
diff --git a/stdlib/integers.h b/stdlib/integers.h
index fce243a9..7bed4551 100644
--- a/stdlib/integers.h
+++ b/stdlib/integers.h
@@ -35,6 +35,7 @@
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
Array_t type_name ## $bits(c_type x); \
Closure_t type_name ## $to(c_type first, c_type last, Optional ## type_name ## _t step); \
+ Closure_t type_name ## $onward(c_type first, c_type 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); \
@@ -102,6 +103,7 @@ 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 Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step);
+PUREFUNC Closure_t Int$onward(Int_t first, Int_t step);
OptionalInt_t Int$from_str(const char *str);
OptionalInt_t Int$parse(Text_t text);
Int_t Int$abs(Int_t x);