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; import qir.driver.IQIRVisitor; /** * {@link QIRList} is the generic representation of a list in QIR. */ public abstract class QIRList extends QIRNode { public QIRList(final SourceSection source) { 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); } }