org.aya.resolve.context.Candidate 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.resolve.context;
import kala.collection.CollectionView;
import kala.collection.SeqView;
import kala.collection.immutable.ImmutableMap;
import kala.collection.immutable.ImmutableSeq;
import kala.collection.mutable.MutableMap;
import org.aya.syntax.concrete.stmt.ModuleName;
import org.aya.util.error.Panic;
import org.jetbrains.annotations.NotNull;
/**
* Candidate represents a list of candidate of symbol resolving
*/
public sealed interface Candidate {
/**
* Merge two candidate.
*
* @implSpec If conflict happens, {@param candy} will overwrite {@code this},
* the user should check all possible conflicts before merge.
*/
@NotNull Candidate merge(@NotNull Candidate candy);
boolean isAmbiguous();
boolean isEmpty();
@NotNull ImmutableSeq from();
boolean contains(@NotNull ModuleName modName);
static @NotNull Candidate of(@NotNull ModuleName fromModule, @NotNull T symbol) {
return switch (fromModule) {
case ModuleName.Qualified qualified -> Imported.of(qualified, symbol);
case ModuleName.ThisRef _ -> new Defined<>(symbol);
};
}
/**
* Returns the only symbol in this candidate, should check {@link #isEmpty()} and {@link #isAmbiguous()} first.
*
* @return the only symbol in this candidate, exception if this candidate {@link #isEmpty()} or {@link #isAmbiguous()}
*/
T get();
CollectionView getAll();
/**
* A candidate list that only store one symbol, furthermore, it implies the symbol is defined in this module.
*/
record Defined(T symbol) implements Candidate {
@Override public @NotNull Candidate merge(@NotNull Candidate symbol) {
return symbol instanceof Candidate.Defined defined ? defined : this;
}
@Override public boolean isAmbiguous() { return false; }
@Override public boolean isEmpty() { return false; }
@Override public T get() { return symbol; }
@Override
public CollectionView getAll() {
return SeqView.of(symbol);
}
@Override public @NotNull ImmutableSeq from() { return ImmutableSeq.of(ModuleName.This); }
@Override public boolean contains(@NotNull ModuleName modName) { return modName == ModuleName.This; }
}
/**
* Default candidate, it represents a candidate list that is imported from other module
*
* @param symbols key: the module that the symbol comes from
* value: the symbol
*/
record Imported(@NotNull ImmutableMap symbols) implements Candidate {
public static @NotNull Candidate empty() {
return new Imported<>(ImmutableMap.empty());
}
public static @NotNull Candidate of(@NotNull ModuleName.Qualified from, @NotNull T symbol) {
return new Imported<>(ImmutableMap.of(from, symbol));
}
@Override public boolean isAmbiguous() {
return symbols.valuesView().distinct().sizeGreaterThan(1);
}
@Override public boolean isEmpty() { return symbols.isEmpty(); }
@Override public T get() {
var view = symbols.valuesView().distinct();
if (view.sizeGreaterThan(1)) Panic.unreachable();
//noinspection OptionalGetWithoutIsPresent
return symbols.valuesView().stream().findFirst().get();
}
@Override
public CollectionView getAll() {
return symbols.valuesView();
}
@Override
public @NotNull ImmutableSeq from() {
return ImmutableSeq.from(symbols.keysView());
}
@Override public boolean contains(@NotNull ModuleName modName) {
return modName instanceof ModuleName.Qualified qmod && symbols.containsKey(qmod);
}
@Override public @NotNull Candidate merge(@NotNull Candidate candy) {
return switch (candy) {
case Candidate.Defined v -> v;
case Candidate.Imported imported -> {
var symbols = MutableMap.create();
symbols.putAll(this.symbols);
symbols.putAll(imported.symbols);
yield new Imported<>(ImmutableMap.from(symbols));
}
};
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy