From f0aef41d9a8f22e54ed72ad2f44461a961429a31 Mon Sep 17 00:00:00 2001 From: Kamila Szewczyk Date: Sat, 15 Jul 2023 22:15:56 +0200 Subject: [PATCH] remove and retire remaining usages of iterator pipelines --- .../kamilalisp/atom/IteratorPipeline.java | 128 ------------------ .../kamilalisp/runtime/graph/RS.java | 20 ++- .../kamilalisp/runtime/graph/TOS.java | 35 +++-- 3 files changed, 37 insertions(+), 146 deletions(-) delete mode 100644 src/main/java/palaiologos/kamilalisp/atom/IteratorPipeline.java diff --git a/src/main/java/palaiologos/kamilalisp/atom/IteratorPipeline.java b/src/main/java/palaiologos/kamilalisp/atom/IteratorPipeline.java deleted file mode 100644 index a5f65ad5..00000000 --- a/src/main/java/palaiologos/kamilalisp/atom/IteratorPipeline.java +++ /dev/null @@ -1,128 +0,0 @@ -package palaiologos.kamilalisp.atom; - -import palaiologos.kamilalisp.error.TypeError; - -import java.math.BigInteger; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Stream; - -public class IteratorPipeline { - public static Atom evaluate(Environment env, List operations, Stream input) { - Stream result = input; - for(Atom op : operations) { - op.assertTypes(Type.LIST); - List opList = op.getList(); - if(opList.isEmpty()) { - throw new TypeError("Empty list in iterator pipeline"); - } - Atom head = opList.get(0); - List tail = opList.subList(1, opList.size()); - head.assertTypes(Type.IDENTIFIER); - switch (head.getIdentifier()) { - case "map", "¨" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to map"); - Callable f = tail.get(0).getCallable(); - result = result.map(a -> Evaluation.evaluate(env, f, List.of(a))); - } - case "filter", "⍭" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to filter"); - Callable f = tail.get(0).getCallable(); - result = result.filter(a -> Evaluation.evaluate(env, f, List.of(a)).coerceBool()); - } - case "fold", "⌿" -> { - if (tail.size() != 2) - throw new TypeError("Wrong number of arguments to reduce"); - Callable f = tail.get(0).getCallable(); - Atom initial = tail.get(1); - return result.reduce(initial, (a, b) -> Evaluation.evaluate(env, f, List.of(a, b))); - } - case "reduce", "⍀" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to reduce"); - Callable f = tail.get(0).getCallable(); - return result.reduce((a, b) -> Evaluation.evaluate(env, f, List.of(a, b))).orElse(Atom.NULL); - } - case "collect", "⍠←⌽" -> { - if (tail.size() != 0) - throw new TypeError("Wrong number of arguments to collect"); - return new Atom(result.toList()); - } - case "drop", "↓" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to drop"); - result = result.skip(tail.get(0).getInteger().intValueExact()); - } - case "take", "↑" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to take"); - result = result.limit(tail.get(0).getInteger().intValueExact()); - } - case "all", "∧?" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to all"); - Callable f = tail.get(0).getCallable(); - return new Atom(result.allMatch(a -> Evaluation.evaluate(env, f, List.of(a)).coerceBool())); - } - case "any", "∨?" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to any"); - Callable f = tail.get(0).getCallable(); - return new Atom(result.anyMatch(a -> Evaluation.evaluate(env, f, List.of(a)).coerceBool())); - } - case "none", "∅?" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to none"); - Callable f = tail.get(0).getCallable(); - return new Atom(result.noneMatch(a -> Evaluation.evaluate(env, f, List.of(a)).coerceBool())); - } - case "count", "⍴?" -> { - if (tail.size() != 0) - throw new TypeError("Wrong number of arguments to count"); - return new Atom(BigInteger.valueOf(result.count())); - } - case "take-while", "⍣↑" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to take-while"); - Callable f = tail.get(0).getCallable(); - result = result.takeWhile(a -> Evaluation.evaluate(env, f, List.of(a)).coerceBool()); - } - case "drop-while", "⍣↓" -> { - if (tail.size() != 1) - throw new TypeError("Wrong number of arguments to drop-while"); - Callable f = tail.get(0).getCallable(); - result = result.dropWhile(a -> Evaluation.evaluate(env, f, List.of(a)).coerceBool()); - } - case "unique", "⊙" -> { - if (tail.size() != 0) - throw new TypeError("Wrong number of arguments to unique"); - result = result.distinct(); - } - case "sort-asc", "⊼" -> { - if (tail.size() == 0) { - result = result.sorted(); - } else if (tail.size() == 1) { - Callable f = tail.get(0).getCallable(); - result = result.sorted((a, b) -> Evaluation.evaluate(env, f, List.of(a, b)).getInteger().intValueExact()); - } else { - throw new TypeError("Wrong number of arguments to sort-asc"); - } - } - case "sort-desc", "⊽" -> { - if (tail.size() == 0) { - result = result.sorted(Comparator.reverseOrder()); - } else if (tail.size() == 1) { - Callable f = tail.get(0).getCallable(); - result = result.sorted((a, b) -> Evaluation.evaluate(env, f, List.of(b, a)).getInteger().intValueExact()); - } else { - throw new TypeError("Wrong number of arguments to sort-desc"); - } - } - default -> throw new TypeError("Unknown iterator operation: " + head.getIdentifier()); - } - } - throw new RuntimeException("No terminal operation on iterator."); - } -} diff --git a/src/main/java/palaiologos/kamilalisp/runtime/graph/RS.java b/src/main/java/palaiologos/kamilalisp/runtime/graph/RS.java index 7d0bdc80..84429e22 100644 --- a/src/main/java/palaiologos/kamilalisp/runtime/graph/RS.java +++ b/src/main/java/palaiologos/kamilalisp/runtime/graph/RS.java @@ -1,5 +1,6 @@ package palaiologos.kamilalisp.runtime.graph; +import org.jgrapht.traverse.DepthFirstIterator; import org.jgrapht.traverse.RandomWalkVertexIterator; import palaiologos.kamilalisp.atom.*; @@ -8,17 +9,22 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -public class RS extends PrimitiveFunction implements SpecialForm { +public class RS extends PrimitiveFunction implements Lambda { @Override public Atom apply(Environment env, List args) { - assertArity(args, 3); - GraphWrapper w = Evaluation.evaluate(env, args.get(0)).getUserdata(GraphWrapper.class); + GraphWrapper w = args.get(0).getUserdata(GraphWrapper.class); Atom start = args.get(1); - List ops = args.get(2).getList(); + Callable op = args.get(2).getCallable(); + Atom init = args.size() > 3 ? args.get(3) : Atom.NULL; Iterator it = new RandomWalkVertexIterator<>(w.getGraph(), start); - Iterable iterable = () -> it; - Stream stream = StreamSupport.stream(iterable.spliterator(), false); - return IteratorPipeline.evaluate(env, ops, stream); + while (it.hasNext()) { + Atom a = it.next(); + List result = op.apply(env, List.of(a, init)).getList(); + init = result.get(0); + if (result.get(1).coerceBool()) + break; + } + return init; } @Override diff --git a/src/main/java/palaiologos/kamilalisp/runtime/graph/TOS.java b/src/main/java/palaiologos/kamilalisp/runtime/graph/TOS.java index e3529f13..658f22dc 100644 --- a/src/main/java/palaiologos/kamilalisp/runtime/graph/TOS.java +++ b/src/main/java/palaiologos/kamilalisp/runtime/graph/TOS.java @@ -1,5 +1,6 @@ package palaiologos.kamilalisp.runtime.graph; +import org.jgrapht.traverse.DepthFirstIterator; import org.jgrapht.traverse.TopologicalOrderIterator; import palaiologos.kamilalisp.atom.*; @@ -9,24 +10,36 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -public class TOS extends PrimitiveFunction implements SpecialForm { +public class TOS extends PrimitiveFunction implements Lambda { @Override public Atom apply(Environment env, List args) { if(args.size() == 3) { - GraphWrapper w = Evaluation.evaluate(env, args.get(0)).getUserdata(GraphWrapper.class); + GraphWrapper w = args.get(0).getUserdata(GraphWrapper.class); Callable comparator = Evaluation.evaluate(env, args.get(1)).getCallable(); - List ops = args.get(2).getList(); + Callable op = args.get(2).getCallable(); + Atom init = args.size() > 3 ? args.get(3) : Atom.NULL; Iterator it = new TopologicalOrderIterator<>(w.getGraph(), (o1, o2) -> Evaluation.evaluate(env, comparator, List.of(o1, o2)).getInteger().intValueExact()); - Iterable iterable = () -> it; - Stream stream = StreamSupport.stream(iterable.spliterator(), false); - return IteratorPipeline.evaluate(env, ops, stream); + while (it.hasNext()) { + Atom a = it.next(); + List result = op.apply(env, List.of(a, init)).getList(); + init = result.get(0); + if (result.get(1).coerceBool()) + break; + } + return init; } else if(args.size() == 2) { - GraphWrapper w = Evaluation.evaluate(env, args.get(0)).getUserdata(GraphWrapper.class); - List ops = args.get(2).getList(); + GraphWrapper w = args.get(0).getUserdata(GraphWrapper.class); + Callable op = args.get(1).getCallable(); + Atom init = args.size() > 2 ? args.get(3) : Atom.NULL; Iterator it = new TopologicalOrderIterator<>(w.getGraph(), Comparator.naturalOrder()); - Iterable iterable = () -> it; - Stream stream = StreamSupport.stream(iterable.spliterator(), false); - return IteratorPipeline.evaluate(env, ops, stream); + while (it.hasNext()) { + Atom a = it.next(); + List result = op.apply(env, List.of(a, init)).getList(); + init = result.get(0); + if (result.get(1).coerceBool()) + break; + } + return init; } else throw new RuntimeException("Invalid arity"); }