Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.aya.concrete.resolve.context.ModuleContext Maven / Gradle / Ivy
// Copyright (c) 2020-2021 Yinsen (Tesla) Zhang.
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.concrete.resolve.context;
import kala.collection.Map;
import kala.collection.Seq;
import kala.collection.immutable.ImmutableSeq;
import kala.collection.mutable.DynamicSeq;
import kala.collection.mutable.MutableHashMap;
import kala.collection.mutable.MutableMap;
import org.aya.api.error.Reporter;
import org.aya.api.ref.Var;
import org.aya.concrete.resolve.error.*;
import org.aya.concrete.stmt.Stmt;
import org.aya.generic.Constants;
import org.aya.util.error.SourcePos;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.function.Function;
/**
* @author re-xyr
*/
public sealed interface ModuleContext extends Context permits NoExportContext, PhysicalModuleContext {
@Override @NotNull Context parent();
@Override default @NotNull Reporter reporter() {
return parent().reporter();
}
@Override default @NotNull Path underlyingFile() {
return parent().underlyingFile();
}
@NotNull MutableMap, Var>> definitions();
@NotNull MutableMap, MutableMap> modules();
@Override default @Nullable Var getUnqualifiedLocalMaybe(@NotNull String name, @NotNull SourcePos sourcePos) {
var result = definitions().getOrNull(name);
if (result == null) return null;
else if (result.size() == 1) return result.iterator().next().getValue();
else {
var disamb = DynamicSeq.>create();
result.forEach((k, v) -> disamb.append(k));
return reportAndThrow(new AmbiguousNameError(name, disamb.toImmutableSeq(), sourcePos));
}
}
@Override default @Nullable Var
getQualifiedLocalMaybe(@NotNull ImmutableSeq<@NotNull String> modName, @NotNull String name, @NotNull SourcePos sourcePos) {
var mod = modules().getOrNull(modName);
if (mod == null) return null;
var ref = mod.getOrNull(name);
if (ref == null) reportAndThrow(new QualifiedNameNotFoundError(modName, name, sourcePos));
return ref;
}
@Override default @Nullable MutableMap getModuleLocalMaybe(@NotNull ImmutableSeq modName) {
return modules().getOrNull(modName);
}
default void importModules(
@NotNull ImmutableSeq modName,
@NotNull Stmt.Accessibility accessibility,
@NotNull MutableMap, MutableMap> module,
@NotNull SourcePos sourcePos
) {
module.forEach((name, mod) -> importModule(accessibility, sourcePos, modName.concat(name), mod));
}
default void importModule(
@NotNull Stmt.Accessibility accessibility,
@NotNull SourcePos sourcePos,
ImmutableSeq componentName,
MutableMap mod
) {
var modules = modules();
if (modules.containsKey(componentName)) {
reportAndThrow(new DuplicateModNameError(componentName, sourcePos));
}
if (getModuleMaybe(componentName) != null) {
reporter().report(new ModShadowingWarn(componentName, sourcePos));
}
modules.set(componentName, mod);
}
default void openModule(
@NotNull ImmutableSeq modName,
@NotNull Stmt.Accessibility accessibility,
@NotNull Function using,
@NotNull Map rename,
@NotNull SourcePos sourcePos
) {
var mod = getModuleMaybe(modName);
if (mod == null) reportAndThrow(new ModNameNotFoundError(modName, sourcePos));
mod.forEach((name, ref) -> {
if (using.apply(name)) {
var newName = rename.getOrDefault(name, name);
addGlobal(modName, newName, accessibility, ref, sourcePos);
}
});
}
default void addGlobalSimple(@NotNull Stmt.Accessibility acc, @NotNull Var ref, @NotNull SourcePos sourcePos) {
addGlobal(TOP_LEVEL_MOD_NAME, ref.name(), acc, ref, sourcePos);
}
default void addGlobal(
@NotNull ImmutableSeq modName,
@NotNull String name,
@NotNull Stmt.Accessibility accessibility,
@NotNull Var ref,
@NotNull SourcePos sourcePos
) {
var definitions = definitions();
if (!definitions.containsKey(name)) {
if (getUnqualifiedMaybe(name, sourcePos) != null && !name.startsWith(Constants.ANONYMOUS_PREFIX)) {
reporter().report(new ShadowingWarn(name, sourcePos));
}
definitions.set(name, MutableHashMap.create());
} else if (definitions.get(name).containsKey(modName)) {
reportAndThrow(new DuplicateNameError(name, ref, sourcePos));
} else {
reporter().report(new AmbiguousNameWarn(name, sourcePos));
}
definitions.get(name).set(modName, ref);
if (modName.equals(TOP_LEVEL_MOD_NAME)) {
// Defined, not imported.
modules().get(TOP_LEVEL_MOD_NAME).set(name, ref);
}
}
}