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

org.aya.tyck.pat.YouTrack Maven / Gradle / Ivy

// Copyright (c) 2020-2024 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.tyck.pat;

import kala.collection.Seq;
import kala.collection.immutable.ImmutableSeq;
import kala.collection.mutable.MutableLinkedSet;
import kala.collection.mutable.MutableList;
import kala.collection.mutable.MutableSet;
import org.aya.syntax.core.pat.Pat;
import org.aya.syntax.core.term.FreeTerm;
import org.aya.syntax.core.term.Param;
import org.aya.syntax.core.term.Term;
import org.aya.syntax.ref.LocalCtx;
import org.aya.tyck.ExprTycker;
import org.aya.tyck.error.ClausesProblem;
import org.aya.tyck.error.UnifyInfo;
import org.aya.util.error.SourcePos;
import org.aya.util.error.WithPos;
import org.aya.util.tyck.pat.PatClass;
import org.jetbrains.annotations.NotNull;

/**
 * YouTrack checks confluence.
 *
 * @see PatClassifier#classify
 */
public record YouTrack(
  @NotNull ImmutableSeq telescope,
  @NotNull ExprTycker tycker, @NotNull SourcePos pos
) {
  private record Info(int ix, @NotNull WithPos matching) { }
  private void unifyClauses(
    Term result, Info lhsInfo, Info rhsInfo,
    MutableSet doms
  ) {
    var ctx = tycker.localCtx();
    var unifyResult = PatUnify.unifyPat(
      lhsInfo.matching.data().patterns().view(),
      rhsInfo.matching.data().patterns().view(), ctx,
      MutableList.create(), MutableList.create());
    var unify = unifyResult.unify();
    domination(ctx, unify.rhsSubst(), lhsInfo.ix, rhsInfo.ix, rhsInfo.matching, doms);
    domination(ctx, unify.lhsSubst(), rhsInfo.ix, lhsInfo.ix, lhsInfo.matching, doms);
    var lhsTerm = lhsInfo.matching.data().body().instantiateTele(unify.lhsSubst().view());
    var rhsTerm = rhsInfo.matching.data().body().instantiateTele(unify.rhsSubst().view());
    // // TODO: Currently all holes at this point are in an ErrorTerm
    // if (lhsTerm instanceof ErrorTerm error && error.description() instanceof MetaCall hole) {
    //   hole.ref().conditions.append(Tuple.of(lhsSubst, rhsTerm));
    // }
    // if (rhsTerm instanceof ErrorTerm error && error.description() instanceof MetaCall hole) {
    //   hole.ref().conditions.append(Tuple.of(rhsSubst, lhsTerm));
    // }
    result = tycker.whnf(result.instantiateTele(unifyResult.args().view()));
    tycker.unifyTermReported(lhsTerm, rhsTerm, result, pos, comparison ->
      new ClausesProblem.Confluence(pos, rhsInfo.ix + 1, lhsInfo.ix + 1,
        comparison, new UnifyInfo(tycker.state), rhsInfo.matching.sourcePos(), lhsInfo.matching.sourcePos()));
  }

  private void domination(
    LocalCtx ctx, Seq subst,
    int lhsIx, int rhsIx, WithPos matching,
    MutableSet doms
  ) {
    if (subst.allMatch(dom -> dom instanceof FreeTerm(var ref) && ctx.contains(ref)))
      doms.add(new ClausesProblem.Domination(lhsIx + 1, rhsIx + 1, matching.sourcePos()));
  }

  public void check(
    @NotNull ClauseTycker.TyckResult clauses, @NotNull Term type,
    @NotNull ImmutableSeq>> mct
  ) {
    var doms = MutableLinkedSet.create();
    mct.forEach(results -> {
      var contents = results.cls()
        .flatMapToObj(i -> Pat.Preclause.lift(clauses.clauses().get(i))
          .map(matching -> new Info(i, matching)));
      for (int i = 1, size = contents.size(); i < size; i++) {
        var ix = i;
        tycker.subscoped(() -> {
          unifyClauses(type, contents.get(ix - 1), contents.get(ix), doms);
          return null;
        });
      }
    });
    doms.forEach(tycker::fail);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy