diff --git a/docs/scarpet/language/LoopsAndHigherOrderFunctions.md b/docs/scarpet/language/LoopsAndHigherOrderFunctions.md index 41a1c5aa..34409e6d 100644 --- a/docs/scarpet/language/LoopsAndHigherOrderFunctions.md +++ b/docs/scarpet/language/LoopsAndHigherOrderFunctions.md @@ -49,13 +49,14 @@ for(range(1000000,1100000),check_prime(_)) => 7216 From which we can learn that there is 7216 primes between 1M and 1.1M -### `while(cond, limit, expr)` +### `while(cond, expr)`, `while(cond, limit, expr)` -Evaluates expression `expr` repeatedly until condition `cond` becomes false, but not more than `limit` times. +Evaluates expression `expr` repeatedly until condition `cond` becomes false, but not more than `limit` times (if limit is specified). Returns the result of the last `expr` evaluation, or `null` if nothing was successful. Both `expr` and `cond` will received a bound variable `_` indicating current iteration, so its a number.
+while(a<100,a=_*_) => 100 // loop stopped at condition
 while(a<100,10,a=_*_)  => 81 // loop exhausted via limit
 while(a<100,20,a=_*_)  => 100 // loop stopped at condition, but a has already been assigned
 while(_*_<100,20,a=_*_)  => 81 // loop stopped at condition, before a was assigned a value
diff --git a/src/main/java/carpet/script/language/Loops.java b/src/main/java/carpet/script/language/Loops.java
index 5d6ac58f..552325df 100644
--- a/src/main/java/carpet/script/language/Loops.java
+++ b/src/main/java/carpet/script/language/Loops.java
@@ -49,8 +49,42 @@ public class Loops
         });
 
         // lazy
-        expression.addLazyFunction("while", 3, (c, t, lv) ->
+        expression.addLazyFunction("while", -1, (c, t, lv) ->
         {
+            if (lv.size() == 2) { // lets do nasty way so performance is not affected (might be super unnecessary, but hey)
+                LazyValue condition = lv.get(0);
+                LazyValue expr = lv.get(1);
+                long i = 0;
+                Value lastOne = Value.NULL;
+                //scoping
+                LazyValue defaultVal = c.getVariable("_");
+                c.setVariable("_", (cc, tt) -> new NumericValue(0).bindTo("_"));
+                while (condition.evalValue(c, Context.BOOLEAN).getBoolean())
+                {
+                    try
+                    {
+                        lastOne = expr.evalValue(c, t);
+                    }
+                    catch (BreakStatement | ContinueStatement stmt)
+                    {
+                        if (stmt.retval != null)
+                        {
+                            lastOne = stmt.retval;
+                        }
+                        if (stmt instanceof BreakStatement)
+                        {
+                            break;
+                        }
+                    }
+                    i++;
+                    long seriously = i;
+                    c.setVariable("_", (cc, tt) -> new NumericValue(seriously).bindTo("_"));
+                }
+                //revering scope
+                c.setVariable("_", defaultVal);
+                Value lastValueNoKidding = lastOne;
+                return (cc, tt) -> lastValueNoKidding;
+            }
             long limit = NumericValue.asNumber(lv.get(1).evalValue(c)).getLong();
             LazyValue condition = lv.get(0);
             LazyValue expr = lv.get(2);