
org.aya.util.tyck.MCT Maven / Gradle / Ivy
// Copyright (c) 2020-2022 Tesla (Yinsen) Zhang.
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.util.tyck;
import kala.collection.SeqView;
import kala.collection.immutable.ImmutableSeq;
import kala.collection.mutable.MutableDeque;
import kala.collection.mutable.MutableList;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Multi-case trees.
*
* @author ice1000
*/
public sealed interface MCT {
static @NotNull ImmutableSeq> extract(
PatClass pats, @NotNull ImmutableSeq> subPatsSeq) {
return pats.contents().map(subPatsSeq::get);
}
/**
* Helper method to avoid stack being too deep and fuel being consumed for distinct patterns.
*
* @param subPatsSeq should be of the same length, and should not be empty.
* @param classifier turn a set of sub-patterns into an MCT.
* @return pattern classes
*/
static @NotNull MCT classify(
@NotNull SeqView telescope,
@NotNull ImmutableSeq> subPatsSeq,
@NotNull BiFunction, ImmutableSeq>, MCT> classifier
) {
while (telescope.isNotEmpty()) {
var res = classifier.apply(telescope, subPatsSeq);
if (res != null) return res;
else {
telescope = telescope.drop(1);
subPatsSeq = subPatsSeq.map(SubPats::drop);
}
}
// Done
return new Leaf<>(subPatsSeq.map(SubPats::ix));
}
default @NotNull ImmutableSeq> toSeq() {
var buffer = MutableList.>create();
forEach(buffer::append);
return buffer.toImmutableSeq();
}
default void forEach(@NotNull Consumer> f) {
var queue = MutableDeque.>create();
queue.enqueue(this);
while (queue.isNotEmpty()) switch (queue.dequeue()) {
case PatClass leaf -> f.accept(leaf);
case Node node -> node.children.forEach(queue::enqueue);
}
}
@NotNull MCT map(@NotNull Function, PatClass> f);
@NotNull MCT flatMap(@NotNull Function, MCT> f);
sealed interface PatClass extends MCT {
@NotNull ImmutableSeq contents();
@NotNull MCT propagate(@NotNull MCT mct);
@Override default @NotNull PatClass map(@NotNull Function, PatClass> f) {
return f.apply(this);
}
@Override default @NotNull MCT flatMap(@NotNull Function, MCT> f) {
return f.apply(this);
}
}
record Leaf(@NotNull ImmutableSeq contents) implements PatClass {
@Override public @NotNull MCT propagate(@NotNull MCT mct) {
return mct;
}
}
record Error(
@NotNull ImmutableSeq contents,
@NotNull Err errorMessage
) implements PatClass {
@Override public @NotNull MCT propagate(@NotNull MCT mct) {
return mct.map(newClz -> new Error<>(newClz.contents(), errorMessage));
}
}
record Node(@NotNull Term type, @NotNull ImmutableSeq> children) implements MCT {
@Override public @NotNull Node map(@NotNull Function, PatClass> f) {
return new Node<>(type, children.map(child -> child.map(f)));
}
@Override public @NotNull Node flatMap(@NotNull Function, MCT> f) {
return new Node<>(type, children.map(child -> child.flatMap(f)));
}
}
record SubPats(@NotNull SeqView pats, int ix) {
@Contract(pure = true) public @NotNull Pat head() {
return pats.first();
}
@Contract(pure = true) public @NotNull SubPats drop() {
return new SubPats<>(pats.drop(1), ix);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy