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

org.aya.resolve.visitor.PatternResolver Maven / Gradle / Ivy

The newest version!
// 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.resolve.visitor;

import org.aya.generic.stmt.TyckUnit;
import org.aya.resolve.context.Context;
import org.aya.resolve.error.NameProblem;
import org.aya.syntax.compile.JitCon;
import org.aya.syntax.concrete.Pattern;
import org.aya.syntax.concrete.stmt.ModuleName;
import org.aya.syntax.concrete.stmt.decl.DataCon;
import org.aya.syntax.core.def.ConDefLike;
import org.aya.syntax.ref.AnyDefVar;
import org.aya.syntax.ref.AnyVar;
import org.aya.syntax.ref.CompiledVar;
import org.aya.syntax.ref.DefVar;
import org.aya.util.error.Panic;
import org.aya.util.error.PosedUnaryOperator;
import org.aya.util.error.SourcePos;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.function.Consumer;

public class PatternResolver implements PosedUnaryOperator {
  // DIRTY!!
  private @NotNull Context context;
  private final @NotNull Consumer parentAdd;

  public PatternResolver(@NotNull Context context, @NotNull Consumer parentAdd) {
    this.context = context;
    this.parentAdd = parentAdd;
  }

  public @NotNull Context context() { return context; }
  public @NotNull Pattern apply(@NotNull SourcePos pos, @NotNull Pattern pat) { return post(pos, pat.descent(this)); }

  public @NotNull Pattern post(@NotNull SourcePos pos, @NotNull Pattern pat) {
    return switch (pat) {
      case Pattern.Bind bind -> {
        // Check whether this {bind} is a Con
        var conMaybe = context.iterate(ctx -> isCon(ctx.getUnqualifiedLocalMaybe(bind.bind().name(), pos)));
        if (conMaybe != null) {
          // It wants to be a con!
          addReference(conMaybe);
          yield new Pattern.Con(pos, ConDefLike.from(conMaybe));
        }

        // It is not a constructor, it is a bind
        context = context.bind(bind.bind());
        yield bind;
      }
      case Pattern.QualifiedRef qref -> {
        var qid = qref.qualifiedID();
        if (!(qid.component() instanceof ModuleName.Qualified mod))
          throw new Panic("QualifiedRef#qualifiedID should be qualified");
        var conMaybe = context.iterate(ctx -> isCon(ctx.getQualifiedLocalMaybe(mod, qid.name(), pos)));
        if (conMaybe != null) {
          addReference(conMaybe);
          yield new Pattern.Con(pos, ConDefLike.from(conMaybe));
        }

        // !! No Such Thing !!
        yield context.reportAndThrow(new NameProblem.QualifiedNameNotFoundError(qid.component(), qid.name(), pos));
      }
      case Pattern.As as -> {
        context = context.bind(as.as());
        yield as;
      }
      default -> pat;
    };
  }

  private void addReference(@NotNull AnyDefVar defVar) {
    if (defVar instanceof DefVar fr) parentAdd.accept(fr.concrete);
  }

  private static @Nullable AnyDefVar isCon(@Nullable AnyVar myMaybe) {
    return switch (myMaybe) {
      case DefVar def when def.concrete instanceof DataCon -> def;
      case CompiledVar var when var.core() instanceof JitCon -> var;
      case null, default -> null;
    };
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy