diff --git a/src/qir/ast/data/QIRList.java b/src/qir/ast/data/QIRList.java index a2349ca964426ceca7a1400d0b3f83b97da5fea3..90c6d9ccdf4ceb368d9d1960f4a93c8fcf5f5cc2 100644 --- a/src/qir/ast/data/QIRList.java +++ b/src/qir/ast/data/QIRList.java @@ -1,5 +1,11 @@ package qir.ast.data; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Predicate; + import com.oracle.truffle.api.source.SourceSection; import qir.ast.QIRNode; @@ -13,6 +19,43 @@ public abstract class QIRList extends QIRNode { super(source); } + private final QIRList iterate(final Predicate<QIRNode> p, final BiConsumer<Deque<QIRNode>, QIRNode> c) { + if (this instanceof QIRLnil) + return this; + + final Deque<QIRNode> tmp = new ArrayDeque<>(); + QIRList result = QIRLnil.getInstance(); + + for (QIRNode e = this; e instanceof QIRLcons && p.test(e); e = ((QIRLcons) e).getTail()) + c.accept(tmp, ((QIRLcons) e).getValue()); + for (QIRNode e : tmp) + result = new QIRLcons(null, e, result); + return result; + } + + private final QIRList iterateAll(final BiConsumer<Deque<QIRNode>, QIRNode> c) { + return iterate(e -> true, c); + } + + public final QIRList map(final Function<QIRNode, QIRNode> f) { + return iterateAll((stack, e) -> stack.push(f.apply(e))); + } + + public final QIRList filter(final Function<QIRNode, Boolean> f) { + return iterateAll((stack, e) -> { + if (f.apply(e)) + stack.push(e); + }); + } + + // TODO: That is ugly. + private long tmpLimit; + + public final QIRList limit(final long limit) { + tmpLimit = limit; + return iterate(e -> tmpLimit-- > 0, (stack, e) -> stack.add(e)); + } + @Override public <T> T accept(final IQIRVisitor<T> visitor) { return visitor.visit(this); diff --git a/src/qir/ast/operator/QIRFilter.java b/src/qir/ast/operator/QIRFilter.java index 85b5f651cbe7bbd0fbf6a902c4d8d015fa91c9ed..99716aa97864028f450caeae6d3c56ebcd473225 100644 --- a/src/qir/ast/operator/QIRFilter.java +++ b/src/qir/ast/operator/QIRFilter.java @@ -1,17 +1,12 @@ package qir.ast.operator; -import java.util.ArrayDeque; -import java.util.Deque; - import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.source.SourceSection; import qir.ast.QIRApply; import qir.ast.QIRNode; -import qir.ast.data.QIRLcons; import qir.ast.data.QIRList; -import qir.ast.data.QIRLnil; import qir.driver.IQIRVisitor; import qir.util.QIRAny; import qir.util.QIRException; @@ -67,21 +62,13 @@ public final class QIRFilter extends QIROperator { } catch (UnexpectedResultException e) { throw new QIRException("Expected list as input in QIRFilter"); } - final Deque<QIRNode> tmp = new ArrayDeque<>(); - QIRList result = QIRLnil.getInstance(); - - if (input instanceof QIRLnil) - return input; - for (QIRNode e = input; e instanceof QIRLcons; e = ((QIRLcons) e).getTail()) + return input.filter(e -> { try { - if (new QIRApply(null, f, ((QIRLcons) e).getValue()).executeBoolean(frame).isTrue()) - tmp.push(((QIRLcons) e).getValue()); - } catch (UnexpectedResultException e1) { + return new QIRApply(null, f, e).executeBoolean(frame).isTrue(); + } catch (UnexpectedResultException e2) { throw new QIRException("Expected boolean as result of configuration application in QIRFilter"); } - while (!tmp.isEmpty()) - result = new QIRLcons(null, tmp.pop(), result); - return result; + }); } @Override diff --git a/src/qir/ast/operator/QIRLimit.java b/src/qir/ast/operator/QIRLimit.java index 87c86bca03105871668b7f63251f7e2fa580949d..abc4430274d323deec2c3080b39823435fd26bab 100644 --- a/src/qir/ast/operator/QIRLimit.java +++ b/src/qir/ast/operator/QIRLimit.java @@ -1,15 +1,11 @@ package qir.ast.operator; -import java.util.ArrayDeque; -import java.util.Deque; - import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.source.SourceSection; import qir.ast.QIRNode; -import qir.ast.data.QIRLcons; -import qir.ast.data.QIRLnil; +import qir.ast.data.QIRList; import qir.driver.IQIRVisitor; import qir.util.QIRAny; import qir.util.QIRException; @@ -63,18 +59,9 @@ public final class QIRLimit extends QIROperator { } catch (UnexpectedResultException e) { throw new QIRException("Expected number as configuration in QIRLimit"); } - final long tmp = longLimit; try { - QIRNode src = child.executeList(frame); - final Deque<QIRNode> nodes = new ArrayDeque<>(); - while (src instanceof QIRLcons && tmp > 0) { - nodes.add(((QIRLcons) src).getValue()); - src = ((QIRLcons) src).getTail(); - } - QIRNode res = QIRLnil.getInstance(); - for (QIRNode node : nodes) - res = new QIRLcons(null, node, res); - return res; + QIRList src = child.executeList(frame); + return src.limit(longLimit); } catch (UnexpectedResultException e) { throw new QIRException("Expected list as input in QIRLimit"); } diff --git a/src/qir/ast/operator/QIRProject.java b/src/qir/ast/operator/QIRProject.java index 0edbd88163eef638c7de928e18c5e02ebbf4153e..d9e913f86ba7522ffaa822b2a49d93c8f3de1ee0 100644 --- a/src/qir/ast/operator/QIRProject.java +++ b/src/qir/ast/operator/QIRProject.java @@ -1,17 +1,12 @@ package qir.ast.operator; -import java.util.ArrayDeque; -import java.util.Deque; - import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.source.SourceSection; import qir.ast.QIRApply; import qir.ast.QIRNode; -import qir.ast.data.QIRLcons; import qir.ast.data.QIRList; -import qir.ast.data.QIRLnil; import qir.driver.IQIRVisitor; import qir.util.QIRAny; import qir.util.QIRException; @@ -67,16 +62,7 @@ public final class QIRProject extends QIROperator { } catch (UnexpectedResultException e) { throw new QIRException("Expected list as input for QIRProject"); } - final Deque<QIRNode> tmp = new ArrayDeque<>(); - QIRList result = QIRLnil.getInstance(); - - if (input instanceof QIRLnil) - return input; - for (QIRNode e = input; e instanceof QIRLcons; e = ((QIRLcons) e).getTail()) - tmp.push(new QIRApply(null, f, ((QIRLcons) e).getValue()).executeGeneric(frame)); - while (!tmp.isEmpty()) - result = new QIRLcons(null, tmp.pop(), result); - return result; + return input.map(e -> new QIRApply(null, f, e).executeGeneric(frame)); } @Override