diff --git a/docs/scarpet/language/Containers.md b/docs/scarpet/language/Containers.md index 1f4759d9..8b07497c 100644 --- a/docs/scarpet/language/Containers.md +++ b/docs/scarpet/language/Containers.md @@ -215,6 +215,8 @@ map(range(10),_*_) => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] reduce(range(10),_a+_, 0) => 45 range(5,10) => [5, 6, 7, 8, 9] range(20, 10, -2) => [20, 18, 16, 14, 12] +range(-0.3, 0.3, 0.1) => [-0.3, -0.2, -0.1, 0, 0.1, 0.2] +range(0.3, -0.3, -0.1) => [0.3, 0.2, 0.1, -0, -0.1, -0.2] ## Map operations diff --git a/src/main/java/carpet/script/language/DataStructures.java b/src/main/java/carpet/script/language/DataStructures.java index c61f5d42..10c21c94 100644 --- a/src/main/java/carpet/script/language/DataStructures.java +++ b/src/main/java/carpet/script/language/DataStructures.java @@ -135,23 +135,25 @@ public class DataStructures { expression.addFunction("range", (lv) -> { - long from = 0; - long to = 0; - long step = 1; + NumericValue from = Value.ZERO; + NumericValue to; + NumericValue step = Value.ONE; int argsize = lv.size(); if (argsize == 0 || argsize > 3) throw new InternalExpressionException("'range' accepts from 1 to 3 arguments, not "+argsize); - to = NumericValue.asNumber(lv.get(0)).getLong(); + to = NumericValue.asNumber(lv.get(0)); if (lv.size() > 1) { from = to; - to = NumericValue.asNumber(lv.get(1)).getLong(); + to = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) { - step = NumericValue.asNumber(lv.get(2)).getLong(); + step = NumericValue.asNumber(lv.get(2)); } } - return LazyListValue.range(from, to, step); + return (from.isInteger() && to.isInteger() && step.isInteger()) + ? LazyListValue.rangeLong(from.getLong(), to.getLong(), step.getLong()) + : LazyListValue.rangeDouble(from.getDouble(), to.getDouble(), step.getDouble()); }); expression.addLazyFunction("m", -1, (c, t, llv) -> diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index 2edd637d..5c68a75a 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -11,7 +11,7 @@ import java.util.Locale; public abstract class LazyListValue extends AbstractListValue implements Iterator { - public static LazyListValue range(long from, long to, long step) + public static LazyListValue rangeDouble(double from, double to, double step) { return new LazyListValue() { @@ -23,10 +23,10 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato this.limit = to; this.stepp = step; } - private long start; - private long current; - private long limit; - private long stepp; + private final double start; + private double current; + private final double limit; + private final double stepp; @Override public Value next() { @@ -50,7 +50,50 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public String getString() { - return String.format(Locale.ROOT, "[%d, %d, ..., %d)",start, start+stepp, limit); + return String.format(Locale.ROOT, "[%s, %s, ..., %s)",NumericValue.of(start).getString(), NumericValue.of(start+stepp).getString(), NumericValue.of( limit).getString()); + } + }; + } + public static LazyListValue rangeLong(long from, long to, long step) + { + return new LazyListValue() + { + { + if (step == 0) + throw new InternalExpressionException("Range will never end with a zero step"); + this.start = from; + this.current = this.start; + this.limit = to; + this.stepp = step; + } + private final long start; + private long current; + private final long limit; + private final long stepp; + @Override + public Value next() + { + Value val = new NumericValue(current); + current += stepp; + return val; + } + + @Override + public void reset() + { + current = start; + } + + @Override + public boolean hasNext() + { + return stepp > 0?(current < limit):(current > limit); + } + + @Override + public String getString() + { + return String.format(Locale.ROOT, "[%s, %s, ..., %s)",NumericValue.of(start).getString(), NumericValue.of(start+stepp).getString(), NumericValue.of( limit).getString()); } }; } diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index 26b6ec56..00a506f4 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -308,4 +308,9 @@ public class NumericValue extends Value if (longValue != null) return new NumericValue(-longValue); return new NumericValue(-value); } + + public boolean isInteger() + { + return longValue!= null || getDouble() == (double)getLong(); + } } diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index 91e3e893..679a9263 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -13,10 +13,12 @@ import java.util.regex.PatternSyntaxException; public abstract class Value implements Comparable, Cloneable { - public static Value FALSE = new NumericValue(0); - public static Value TRUE = new NumericValue(1); - public static Value ZERO = FALSE; - public static Value NULL = new NullValue(); + public static NumericValue FALSE = new NumericValue(0); + public static NumericValue TRUE = new NumericValue(1); + public static NumericValue ZERO = FALSE; + public static NumericValue ONE = TRUE; + + public static NullValue NULL = new NullValue(); public String boundVariable;