All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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