Skip to content
Snippets Groups Projects
QIRList.java 1.78 KiB
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);
    }
}