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

org.aya.resolve.ResolveInfo Maven / Gradle / Ivy

There is a newer version: 0.36.0
Show 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;

import kala.collection.mutable.MutableMap;
import org.aya.generic.stmt.TyckOrder;
import org.aya.primitive.PrimFactory;
import org.aya.primitive.ShapeFactory;
import org.aya.resolve.context.Context;
import org.aya.resolve.context.ModuleContext;
import org.aya.resolve.salt.AyaBinOpSet;
import org.aya.syntax.concrete.stmt.BindBlock;
import org.aya.syntax.concrete.stmt.ModuleName;
import org.aya.syntax.concrete.stmt.Stmt;
import org.aya.syntax.concrete.stmt.UseHide;
import org.aya.syntax.core.def.AnyDef;
import org.aya.syntax.core.def.TyckAnyDef;
import org.aya.syntax.ref.AnyVar;
import org.aya.syntax.ref.CompiledVar;
import org.aya.syntax.ref.DefVar;
import org.aya.tyck.ExprTycker;
import org.aya.tyck.TyckState;
import org.aya.util.binop.OpDecl;
import org.aya.util.error.SourcePos;
import org.aya.util.reporter.Reporter;
import org.aya.util.terck.MutableGraph;
import org.jetbrains.annotations.Debug;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @param thisModule   context of the underlying module
 * @param primFactory  globally shared prim definition data
 * @param shapeFactory shapes local to this module
 * @param opSet        operators local to this module
 * @param opRename     open/import renames with operators
 * @param depGraph     local to this module
 * @param imports      importing information, it only contains the modules that is explicitly imported, 
 *                     should not be confused with the {@code import} in {@link ModuleContext#importModuleContext}
 * @param reExports    re-exporting module, it is {@link ModuleName.Qualified} rather than {@link String}
 *                     cause we can re-export a module inside another module without import it.
 */
@Debug.Renderer(text = "thisModule.modulePath().toString()")
public record ResolveInfo(
  @NotNull ModuleContext thisModule,
  @NotNull PrimFactory primFactory,
  @NotNull ShapeFactory shapeFactory,
  @NotNull AyaBinOpSet opSet,
  @NotNull MutableMap opRename,
  @NotNull MutableMap imports,
  @NotNull MutableMap reExports,
  @NotNull MutableGraph depGraph
) {
  public ResolveInfo(
    @NotNull ModuleContext thisModule,
    @NotNull PrimFactory primFactory,
    @NotNull ShapeFactory shapeFactory
  ) {
    this(thisModule, primFactory, shapeFactory, new AyaBinOpSet(thisModule.reporter()));
  }
  public ResolveInfo(
    @NotNull ModuleContext thisModule,
    @NotNull PrimFactory primFactory,
    @NotNull ShapeFactory shapeFactory,
    @NotNull AyaBinOpSet opSet
  ) {
    this(thisModule, primFactory, shapeFactory, opSet,
      MutableMap.create(), MutableMap.create(), MutableMap.create(), MutableGraph.create());
  }
  public ExprTycker newTycker() { return newTycker(opSet.reporter); }
  public ExprTycker newTycker(@NotNull Reporter reporter) { return new ExprTycker(makeTyckState(), reporter); }
  public @NotNull TyckState makeTyckState() { return new TyckState(shapeFactory, primFactory); }

  public record ImportInfo(@NotNull ResolveInfo resolveInfo, boolean reExport) { }
  public record OpRenameInfo(
    @NotNull Context bindCtx, @NotNull RenamedOpDecl renamed,
    @NotNull BindBlock bind, boolean reExport
  ) { }

  public @Nullable OpDecl resolveOpDecl(AnyVar var) {
    return switch (var) {
      case CompiledVar jit -> resolveOpDecl(jit.core());
      case DefVar ref -> resolveOpDecl(new TyckAnyDef<>(ref));
      default -> null;
    };
  }
  public @NotNull OpDecl resolveOpDecl(AnyDef defVar) {
    var renameInfo = opRename.getOrNull(defVar);
    return renameInfo != null ? renameInfo.renamed() : defVar;
  }

  /**
   * @param reExport if this operator is renamed in this module, then true,
   *                 or if publicly renamed by upstream, then false.
   * @see #open(ResolveInfo, SourcePos, Stmt.Accessibility)
   */
  public void renameOp(
    @NotNull Context bindCtx, @NotNull AnyDef defVar,
    @NotNull RenamedOpDecl renamed, @NotNull BindBlock bind, boolean reExport
  ) {
    // TODO: what if already exists?
    opRename.put(defVar, new OpRenameInfo(bindCtx, renamed, bind, reExport));
  }

  public void open(@NotNull ResolveInfo other, @NotNull SourcePos sourcePos, @NotNull Stmt.Accessibility acc) {
    // open defined operator and their bindings
    opSet.importBind(other.opSet, sourcePos);
    // open discovered shapes as well
    shapeFactory.importAll(other.shapeFactory);
    // open renamed operators and their bindings
    other.opRename.forEach((defVar, tuple) -> {
      // if it is `public open`, make renamed operators transitively accessible by storing
      // them in my `opRename` bc "my importers" cannot access `other.opRename`.
      // see: https://github.com/aya-prover/aya-dev/issues/519
      renameOp(thisModule, defVar, tuple.renamed, tuple.bind, acc != Stmt.Accessibility.Public);
    });
  }

  public @NotNull Reporter reporter() {
    return this.opSet.reporter;
  }

  @Debug.Renderer(text = "opInfo.name()")
  public record RenamedOpDecl(@NotNull OpInfo opInfo) implements OpDecl { }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy