From 022ad3cae98e31758f9a6f9c4a8b2cbb86ab384c Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 4 Sep 2023 10:56:39 +0200 Subject: [PATCH] set and interval iteration --- .../java/leekscript/common/IntervalType.java | 22 ++++++++ src/main/java/leekscript/common/SetType.java | 4 -- src/main/java/leekscript/common/Type.java | 2 +- src/main/java/leekscript/runner/AI.java | 11 ++-- .../runner/values/IntervalLeekValue.java | 32 +++++++++++ .../runner/values/SetLeekValue.java | 54 ++++++++++++++----- src/test/java/test/TestInterval.java | 3 ++ src/test/java/test/TestSet.java | 2 + 8 files changed, 106 insertions(+), 24 deletions(-) create mode 100644 src/main/java/leekscript/common/IntervalType.java diff --git a/src/main/java/leekscript/common/IntervalType.java b/src/main/java/leekscript/common/IntervalType.java new file mode 100644 index 00000000..316abc36 --- /dev/null +++ b/src/main/java/leekscript/common/IntervalType.java @@ -0,0 +1,22 @@ +package leekscript.common; + +public class IntervalType extends Type { + + + public IntervalType() { + super("interval", "t", "IntervalLeekValue", "IntervalLeekValue", "new IntervalLeekValue()"); + } + + @Override + public Type element() { + return Type.INT; + } + + public boolean canBeIterable() { + return true; + } + + public boolean isIterable() { + return true; + } +} diff --git a/src/main/java/leekscript/common/SetType.java b/src/main/java/leekscript/common/SetType.java index 59ed31b9..cc94c211 100644 --- a/src/main/java/leekscript/common/SetType.java +++ b/src/main/java/leekscript/common/SetType.java @@ -26,10 +26,6 @@ public Type element() { return type; } - public boolean isSet() { - return true; - } - public boolean canBeIterable() { return true; } diff --git a/src/main/java/leekscript/common/Type.java b/src/main/java/leekscript/common/Type.java index 5cf2e64e..5a24690d 100644 --- a/src/main/java/leekscript/common/Type.java +++ b/src/main/java/leekscript/common/Type.java @@ -34,7 +34,7 @@ public class Type { // public static final Type LEGACY_ARRAY = new LegacyArrayType(); public static final Type ARRAY = array(Type.ANY); public static final Type SET = set(Type.ANY); - public static final Type INTERVAL = new Type("interval", "t", "IntervalLeekValue", "IntervalLeekValue", "new IntervalLeekValue()"); + public static final Type INTERVAL = new IntervalType(); public static final Type ARRAY_INT = array(Type.INT); public static final Type ARRAY_REAL = array(Type.REAL); public static final Type ARRAY_STRING = array(Type.STRING); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 0225b327..9ac28eca 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1500,11 +1500,11 @@ public Object toJSON(Object v, HashSet visited) throws LeekRunException } public boolean isPrimitive(Object value) { - return !(value instanceof ArrayLeekValue || value instanceof MapLeekValue || value instanceof LegacyArrayLeekValue || value instanceof IntervalLeekValue || value instanceof ObjectLeekValue || value instanceof NativeObjectLeekValue); + return !(value instanceof ArrayLeekValue || value instanceof MapLeekValue || value instanceof LegacyArrayLeekValue || value instanceof SetLeekValue || value instanceof IntervalLeekValue || value instanceof ObjectLeekValue || value instanceof NativeObjectLeekValue); } public boolean isIterable(Object value) throws LeekRunException { - boolean ok = value instanceof LegacyArrayLeekValue || value instanceof ArrayLeekValue || value instanceof MapLeekValue || value instanceof IntervalLeekValue; + boolean ok = value instanceof LegacyArrayLeekValue || value instanceof ArrayLeekValue || value instanceof MapLeekValue || value instanceof SetLeekValue || value instanceof IntervalLeekValue; if (!ok && version >= 2) { addSystemLog(AILog.ERROR, Error.NOT_ITERABLE, new Object[] { value }); } @@ -1518,9 +1518,10 @@ public Iterator> iterator(Object value) { return ((ArrayLeekValue) value).genericIterator(); } else if (value instanceof MapLeekValue) { return ((MapLeekValue) value).entrySet().iterator(); - } else if (value instanceof IntervalLeekValue) { - // TODO - return null; + } else if (value instanceof SetLeekValue set) { + return set.genericIterator(); + } else if (value instanceof IntervalLeekValue interval) { + return interval.iterator(); } return null; } diff --git a/src/main/java/leekscript/runner/values/IntervalLeekValue.java b/src/main/java/leekscript/runner/values/IntervalLeekValue.java index 6bd050bf..dbf3f594 100644 --- a/src/main/java/leekscript/runner/values/IntervalLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntervalLeekValue.java @@ -1,6 +1,9 @@ package leekscript.runner.values; +import java.util.AbstractMap; +import java.util.Iterator; import java.util.Set; +import java.util.Map.Entry; import leekscript.AILog; import leekscript.common.Error; @@ -9,6 +12,31 @@ public class IntervalLeekValue { + public static class IntervalIterator implements Iterator> { + + private IntervalLeekValue interval; + private long i = 0; + private long x; + + public IntervalIterator(IntervalLeekValue interval) { + this.interval = interval; + this.x = (long) interval.from; + } + + @Override + public boolean hasNext() { + return x < interval.to; + } + + @Override + public Entry next() { + var e = new AbstractMap.SimpleEntry(i, x); + i++; + x++; + return e; + } + } + private final AI ai; public final int id; @@ -191,4 +219,8 @@ public ArrayLeekValue range(AI ai, Object start, Object end, double step) throws return array; } + + public Iterator> iterator() { + return new IntervalIterator(this); + } } diff --git a/src/main/java/leekscript/runner/values/SetLeekValue.java b/src/main/java/leekscript/runner/values/SetLeekValue.java index 8882dda0..0be8a739 100644 --- a/src/main/java/leekscript/runner/values/SetLeekValue.java +++ b/src/main/java/leekscript/runner/values/SetLeekValue.java @@ -1,24 +1,46 @@ package leekscript.runner.values; +import java.util.AbstractMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.Set; import leekscript.runner.AI; import leekscript.runner.LeekRunException; -public class SetLeekValue { +public class SetLeekValue extends HashSet { + + public static class SetIterator implements Iterator> { + + private Iterator it; + private long i = 0; + + public SetIterator(SetLeekValue set) { + this.it = set.iterator(); + } + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public Entry next() { + var e = new AbstractMap.SimpleEntry(i, it.next()); + i++; + return e; + } + } private final AI ai; public final int id; - private final HashSet set; - public SetLeekValue(AI ai, Object[] values) throws LeekRunException { this.ai = ai; this.id = ai.getNextObjectID(); - this.set = new HashSet(); for (Object value : values) { - this.set.add(value); + this.add(value); } } @@ -48,7 +70,7 @@ public String toString(AI ai, Set visited) throws LeekRunException { boolean first = true; - for (Object value : set) { + for (var value : this) { if (first) { first = false; } else { @@ -69,17 +91,17 @@ public String toString(AI ai, Set visited) throws LeekRunException { } public Object setPut(AI ai, Object value) throws LeekRunException { - set.add(value); + add(value); return value; } public Object setRemove(AI ai, Object value) throws LeekRunException { - set.remove(value); + remove(value); return value; } public SetLeekValue setClear(AI ai) throws LeekRunException { - set.clear(); + clear(); return this; } @@ -88,19 +110,23 @@ public boolean setContains(AI ai, Object value) throws LeekRunException { } public boolean operatorIn(Object value) throws LeekRunException { - return set.contains(value); + return contains(value); } public long setSize(AI ai) throws LeekRunException { - return set.size(); + return size(); } public boolean setIsEmpty(AI ai) throws LeekRunException { - return set.isEmpty(); + return isEmpty(); } public boolean setIsSubsetOf(AI ai, SetLeekValue set) throws LeekRunException { - ai.ops(this.set.size() * 2); - return set.set.containsAll(this.set); + ai.ops(this.size() * 2); + return set.containsAll(this); + } + + public Iterator> genericIterator() { + return new SetIterator(this); } } diff --git a/src/test/java/test/TestInterval.java b/src/test/java/test/TestInterval.java index cd0ec9c2..ec4bdd54 100644 --- a/src/test/java/test/TestInterval.java +++ b/src/test/java/test/TestInterval.java @@ -153,5 +153,8 @@ public void run() throws Exception { code_v4_("return [1..4][:-1:];").equals("[1.0, 2.0, 3.0]"); code_v4_("return [1..4][2::];").equals("[3.0, 4.0]"); code_v4_("return [1..4][:2:];").equals("[1.0, 2.0]"); + + section("Interval iteration"); + code_v4_("var i = [0..6] var x = 0 for (var y in i) x += y return x").equals("15"); } } diff --git a/src/test/java/test/TestSet.java b/src/test/java/test/TestSet.java index 9b18c59e..c72ad877 100644 --- a/src/test/java/test/TestSet.java +++ b/src/test/java/test/TestSet.java @@ -75,5 +75,7 @@ public void run() throws Exception { code_v4_("Set i = <>; Set j = <1, 2>; return setIsSubsetOf(j, i)").equals("false"); code_v4_("Set i = <>; Set j = <>; return setIsSubsetOf(i, j)").equals("true"); + section("Set iteration"); + code_v4_("var s = <1, 2, 3, 4, 5> var x = 0 for (var y in s) x += y return x").equals("15"); } }