aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-05 12:41:13 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-05 12:41:13 -0400
commit34d98f067eff63d9f10031f6b2b42103d2e3db51 (patch)
tree44d97dcf23a2b2ae347b24d87fd6ea8fa414becd
parente91b53f07018608f2eba7d11748708b97b2cb4e9 (diff)
For big or arbitrarily big integers not known to be constant, do full
Int$plus(a,b) logic so it's definitely correct and doesn't error.
-rw-r--r--compile.c29
-rw-r--r--test/reductions.tm4
2 files changed, 22 insertions, 11 deletions
diff --git a/compile.c b/compile.c
index e18a400c..f5a27ae9 100644
--- a/compile.c
+++ b/compile.c
@@ -1092,18 +1092,30 @@ CORD compile_statement(env_t *env, ast_t *ast)
n = mpz_get_str(NULL, 10, i);
else
goto big_n;
- } else {
- big_n:
- n = CORD_all("Int_to_Int64(", compile(env, for_->iter), ", false)");
+
+
+ if (for_->empty && mpz_cmp_si(i, 0) == 0) {
+ return compile_statement(env, for_->empty);
+ } else {
+ return CORD_all(
+ "for (int64_t i = 1; i <= ", n, "; ++i) {\n",
+ for_->vars ? CORD_all("\tInt_t ", compile(body_scope, for_->vars->ast), " = I_small(i);\n") : CORD_EMPTY,
+ "\t", naked_body,
+ "}\n",
+ stop, "\n");
+ }
}
+ big_n:
+ n = compile(env, for_->iter);
+ CORD i = for_->vars ? compile(body_scope, for_->vars->ast) : "i";
+ CORD n_var = for_->vars ? CORD_all("max", i) : "n";
if (for_->empty) {
return CORD_all(
"{\n"
- "int64_t n = ", n, ";\n"
- "if (n > 0) {\n"
- "for (int64_t i = 1; i <= n; ++i) {\n",
- for_->vars ? CORD_all("\tInt_t ", compile(body_scope, for_->vars->ast), " = I(i);\n") : CORD_EMPTY,
+ "Int_t ", n_var, " = ", compile(env, for_->iter), ";\n"
+ "if (!I_is_zero(", n_var, ")) {\n"
+ "for (Int_t ", i, " = I(1); Int$compare_value(", i, ", ", n_var, ") <= 0; ", i, " = Int$plus(", i, ", I(1))) {\n",
"\t", naked_body,
"}\n"
"} else ", compile_statement(env, for_->empty),
@@ -1111,8 +1123,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
"}\n");
} else {
return CORD_all(
- "for (int64_t i = 1, n = ", n, "; i <= n; ++i) {\n",
- for_->vars ? CORD_all("\tInt_t ", compile(body_scope, for_->vars->ast), " = I(i);\n") : CORD_EMPTY,
+ "for (Int_t ", i, " = I(1), ", n_var, " = ", n, "; Int$compare_value(", i, ", ", n_var, ") <= 0; ", i, " = Int$plus(", i, ", I(1))) {\n",
"\t", naked_body,
"}\n",
stop, "\n");
diff --git a/test/reductions.tm b/test/reductions.tm
index 72db3d1b..47f1612a 100644
--- a/test/reductions.tm
+++ b/test/reductions.tm
@@ -18,8 +18,8 @@ func main():
= Foo(x=0, y=-999)
!! (or) and (and) have early out behavior:
- >> (or) i == 3 for i in 99999999999999999
+ >> (or) i == 3 for i in 9999999999999999999999999999
= yes
- >> (and) i < 10 for i in 99999999999999999
+ >> (and) i < 10 for i in 9999999999999999999999999999
= no