mirror of
https://github.com/enso-org/enso.git
synced 2024-11-27 06:32:30 +03:00
Avoiding dependency on EnsoContext from Module and ModuleScope (#7277)
Less dependencies on `EnsoContext` - `Module` shall exist without it. `Module` is a result of a `Compiler` and shall be created before its execution - e.g. requiring `EnsoContext` (with all its runtime information) is a bit too _demanding_. # Important Notes The only reason why `Module` wanted `EnsoContext` was to create its (associated) `Type`. `Type`'s constructor needed a parent type and the code was asking for `Any` from the context. That's unnecessary at creation time - we can just use some constant (like `null`) and turning it into `Any` during execution. Benchmarks show that there is no slowdown doing so.
This commit is contained in:
parent
aaa235fbad
commit
3d2c0c0154
@ -173,15 +173,11 @@ public final class Module implements TruffleObject {
|
||||
* belong to a package.
|
||||
*/
|
||||
private Module(
|
||||
QualifiedName name,
|
||||
Package<TruffleFile> pkg,
|
||||
boolean synthetic,
|
||||
Rope literalSource,
|
||||
EnsoContext context) {
|
||||
QualifiedName name, Package<TruffleFile> pkg, boolean synthetic, Rope literalSource) {
|
||||
this.sources =
|
||||
literalSource == null ? ModuleSources.NONE : ModuleSources.NONE.newWith(literalSource);
|
||||
this.name = name;
|
||||
this.scope = new ModuleScope(this, context);
|
||||
this.scope = new ModuleScope(this);
|
||||
this.pkg = pkg;
|
||||
this.compilationStage = synthetic ? CompilationStage.INITIAL : CompilationStage.AFTER_CODEGEN;
|
||||
this.cache = new ModuleCache(this);
|
||||
@ -198,8 +194,8 @@ public final class Module implements TruffleObject {
|
||||
* belong to a package.
|
||||
* @return the module with empty scope.
|
||||
*/
|
||||
public static Module empty(QualifiedName name, Package<TruffleFile> pkg, EnsoContext context) {
|
||||
return new Module(name, pkg, false, null, context);
|
||||
public static Module empty(QualifiedName name, Package<TruffleFile> pkg) {
|
||||
return new Module(name, pkg, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,9 +207,8 @@ public final class Module implements TruffleObject {
|
||||
* @param source source of the module declaring exports of the desired modules
|
||||
* @return the synthetic module
|
||||
*/
|
||||
public static Module synthetic(
|
||||
QualifiedName name, Package<TruffleFile> pkg, Rope source, EnsoContext context) {
|
||||
return new Module(name, pkg, true, source, context);
|
||||
public static Module synthetic(QualifiedName name, Package<TruffleFile> pkg, Rope source) {
|
||||
return new Module(name, pkg, true, source);
|
||||
}
|
||||
|
||||
/** Clears any literal source set for this module. */
|
||||
@ -333,7 +328,7 @@ public final class Module implements TruffleObject {
|
||||
* @return the scope defined by this module
|
||||
*/
|
||||
public ModuleScope compileScope(EnsoContext context) {
|
||||
ensureScopeExists(context);
|
||||
ensureScopeExists();
|
||||
if (!compilationStage.isAtLeast(CompilationStage.AFTER_CODEGEN)) {
|
||||
try {
|
||||
compile(context);
|
||||
@ -344,9 +339,9 @@ public final class Module implements TruffleObject {
|
||||
}
|
||||
|
||||
/** Create scope if it does not exist. */
|
||||
public void ensureScopeExists(EnsoContext context) {
|
||||
public void ensureScopeExists() {
|
||||
if (scope == null) {
|
||||
scope = new ModuleScope(this, context);
|
||||
scope = new ModuleScope(this);
|
||||
compilationStage = CompilationStage.INITIAL;
|
||||
}
|
||||
}
|
||||
@ -404,7 +399,7 @@ public final class Module implements TruffleObject {
|
||||
}
|
||||
|
||||
private void compile(EnsoContext context) throws IOException {
|
||||
ensureScopeExists(context);
|
||||
ensureScopeExists();
|
||||
Source source = getSource();
|
||||
if (source == null) return;
|
||||
scope.reset();
|
||||
|
@ -124,7 +124,7 @@ public final class Builtins {
|
||||
*/
|
||||
public Builtins(EnsoContext context) {
|
||||
EnsoLanguage language = context.getLanguage();
|
||||
module = Module.empty(QualifiedName.fromString(MODULE_NAME), null, null);
|
||||
module = Module.empty(QualifiedName.fromString(MODULE_NAME), null);
|
||||
scope = module.compileScope(context);
|
||||
|
||||
builtins = initializeBuiltinTypes(loadedBuiltinConstructors, language, scope);
|
||||
|
@ -118,6 +118,13 @@ public final class Type implements TruffleObject {
|
||||
}
|
||||
|
||||
public Type getSupertype() {
|
||||
if (supertype == null) {
|
||||
if (builtin) {
|
||||
return null;
|
||||
}
|
||||
var ctx = EnsoContext.get(null);
|
||||
return ctx.getBuiltins().any();
|
||||
}
|
||||
return supertype;
|
||||
}
|
||||
|
||||
@ -204,13 +211,13 @@ public final class Type implements TruffleObject {
|
||||
if (isNothing(lib) || !hasMetaParents()) {
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
assert supertype != null;
|
||||
return new Array(supertype);
|
||||
assert getSupertype() != null;
|
||||
return new Array(getSupertype());
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean hasMetaParents() {
|
||||
return supertype != null && supertype != this;
|
||||
return getSupertype() != null && getSupertype() != this;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
|
@ -10,7 +10,6 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.Module;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
@ -32,9 +31,8 @@ public final class ModuleScope implements TruffleObject {
|
||||
* Creates a new object of this class.
|
||||
*
|
||||
* @param module the module related to the newly created scope.
|
||||
* @param context the current langauge context
|
||||
*/
|
||||
public ModuleScope(Module module, EnsoContext context) {
|
||||
public ModuleScope(Module module) {
|
||||
this.polyglotSymbols = new HashMap<>();
|
||||
this.types = new HashMap<>();
|
||||
this.methods = new HashMap<>();
|
||||
@ -42,12 +40,7 @@ public final class ModuleScope implements TruffleObject {
|
||||
this.imports = new HashSet<>();
|
||||
this.exports = new HashSet<>();
|
||||
this.module = module;
|
||||
this.associatedType =
|
||||
Type.createSingleton(
|
||||
module.getName().item(),
|
||||
this,
|
||||
context == null ? null : context.getBuiltins().any(),
|
||||
false);
|
||||
this.associatedType = Type.createSingleton(module.getName().item(), this, null, false);
|
||||
}
|
||||
|
||||
public ModuleScope(
|
||||
|
@ -136,7 +136,7 @@ public final class TopLevelScope implements TruffleObject {
|
||||
private static Module createModule(TopLevelScope scope, Object[] arguments, EnsoContext context)
|
||||
throws ArityException, UnsupportedTypeException {
|
||||
String moduleName = Types.extractArguments(arguments, String.class);
|
||||
return Module.empty(QualifiedName.simpleName(moduleName), null, context);
|
||||
return Module.empty(QualifiedName.simpleName(moduleName), null);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
|
@ -552,7 +552,7 @@ class Compiler(
|
||||
"Parsing module [{0}].",
|
||||
module.getName
|
||||
)
|
||||
module.ensureScopeExists(context)
|
||||
module.ensureScopeExists()
|
||||
module.getScope.reset()
|
||||
|
||||
if (irCachingEnabled && !module.isInteractive) {
|
||||
@ -585,7 +585,7 @@ class Compiler(
|
||||
"Loading module [{0}] from source.",
|
||||
module.getName
|
||||
)
|
||||
module.ensureScopeExists(context)
|
||||
module.ensureScopeExists()
|
||||
module.getScope.reset()
|
||||
|
||||
val moduleContext = ModuleContext(
|
||||
|
@ -348,8 +348,7 @@ object PackageRepository {
|
||||
Module.synthetic(
|
||||
qName,
|
||||
pkg,
|
||||
Rope(source),
|
||||
context
|
||||
Rope(source)
|
||||
),
|
||||
modulesWithSources.map(_._1)
|
||||
)
|
||||
|
@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -153,6 +154,30 @@ public class MetaObjectTest extends TestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorsAreWeird() {
|
||||
var g = ValuesGenerator.create(ctx, ValuesGenerator.Language.ENSO);
|
||||
for (var v : g.errors()) {
|
||||
Value vMeta = v.getMetaObject();
|
||||
var isError = vMeta.equals(g.typeError());
|
||||
var isPanic = vMeta.equals(g.typePanic());
|
||||
|
||||
assertTrue("either error or panic: " + v, isError || isPanic);
|
||||
assertNotEquals("never both: " + v, isError, isPanic);
|
||||
|
||||
if (isError) {
|
||||
assertFalse("No meta parents for errors: " + vMeta, vMeta.hasMetaParents());
|
||||
} else {
|
||||
assertTrue("There are meta parents for panics: " + vMeta, vMeta.hasMetaParents());
|
||||
var arr = vMeta.getMetaParents();
|
||||
for (long i = 0; i < arr.getArraySize(); i++) {
|
||||
var p = arr.getArrayElement(i);
|
||||
assertEquals(g.typeAny(), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAllTypesSatisfy(Check check) throws Exception {
|
||||
var g = generator();
|
||||
var expecting = new LinkedHashSet<Value>();
|
||||
|
@ -202,7 +202,7 @@ trait CompilerRunner {
|
||||
isGeneratingDocs: Boolean = false
|
||||
): ModuleContext = {
|
||||
ModuleContext(
|
||||
module = Module.empty(moduleName, null, null),
|
||||
module = Module.empty(moduleName, null),
|
||||
freshNameSupply = freshNameSupply,
|
||||
passConfiguration = passConfiguration,
|
||||
compilerConfig = compilerConfig,
|
||||
@ -226,7 +226,7 @@ trait CompilerRunner {
|
||||
passConfiguration: Option[PassConfiguration] = None,
|
||||
compilerConfig: CompilerConfig = defaultConfig
|
||||
): InlineContext = {
|
||||
val mod = Module.empty(QualifiedName.simpleName("Test_Module"), null, null)
|
||||
val mod = Module.empty(QualifiedName.simpleName("Test_Module"), null)
|
||||
mod.unsafeSetIr(
|
||||
IR.Module(List(), List(), List(), None)
|
||||
.updateMetadata(
|
||||
|
Loading…
Reference in New Issue
Block a user