mirror of
https://github.com/enso-org/enso.git
synced 2024-09-11 13:15:52 +03:00
Extract mutable builder from ModuleScope
(#9914)
Refactored mutable parts of `ModuleScope` into builder to make it easier to reduce unnecessary locks. # Important Notes Elements of ModuleScope (types, imports etc) are used while _building_ of it may still be in progress. In order to make static typing happy, every `ModuleScope.Builder` can be exposed as (unmodifiable) `ModuleScope`.
This commit is contained in:
parent
698f4b5640
commit
1bc14252df
@ -209,7 +209,7 @@ type Unresolved_Symbol
|
||||
- new_name: The new name for the unresolved symbol.
|
||||
rename : Text -> Any
|
||||
rename self new_name =
|
||||
create_unresolved_symbol new_name self.scope
|
||||
create_unresolved_symbol new_name self.value
|
||||
|
||||
## ADVANCED
|
||||
GROUP Metadata
|
||||
@ -219,14 +219,6 @@ type Unresolved_Symbol
|
||||
name : Text
|
||||
name self = get_unresolved_symbol_name self.value
|
||||
|
||||
## ADVANCED
|
||||
GROUP Metadata
|
||||
ICON metadata
|
||||
|
||||
Returns the definition scope of an unresolved symbol.
|
||||
scope : Any
|
||||
scope self = get_unresolved_symbol_scope self.value
|
||||
|
||||
## ADVANCED
|
||||
GROUP Metadata
|
||||
ICON metadata
|
||||
@ -348,9 +340,9 @@ get_polyglot_language value = @Builtin_Method "Meta.get_polyglot_language"
|
||||
|
||||
Arguments:
|
||||
- name: The name of the unresolved symbol.
|
||||
- scope: The scope in which the symbol name is unresolved.
|
||||
- symbol: The unresolved symbol from which to get the scope.
|
||||
create_unresolved_symbol : Text -> Any -> Unresolved_Symbol
|
||||
create_unresolved_symbol name scope = @Builtin_Method "Meta.create_unresolved_symbol"
|
||||
create_unresolved_symbol name symbol = @Builtin_Method "Meta.create_unresolved_symbol"
|
||||
|
||||
## PRIVATE
|
||||
|
||||
@ -361,15 +353,6 @@ create_unresolved_symbol name scope = @Builtin_Method "Meta.create_unresolved_sy
|
||||
get_unresolved_symbol_name : Unresolved_Symbol -> Text
|
||||
get_unresolved_symbol_name symbol = @Builtin_Method "Meta.get_unresolved_symbol_name"
|
||||
|
||||
## PRIVATE
|
||||
|
||||
Obtains the scope in which the provided unresolved symbol was created.
|
||||
|
||||
Arguments:
|
||||
- symbol: The unresolved symbol from which to get the scope.
|
||||
get_unresolved_symbol_scope : Unresolved_Symbol -> Any
|
||||
get_unresolved_symbol_scope symbol = @Builtin_Method "Meta.get_unresolved_symbol_scope"
|
||||
|
||||
## PRIVATE
|
||||
|
||||
Get the fields of an atom constructor.
|
||||
|
@ -69,7 +69,8 @@ class ModuleManagementTest
|
||||
|""".stripMargin)
|
||||
|
||||
mainModule.reparse()
|
||||
val mainFun2 = mainModule.getMethod(assocCons, "main").get
|
||||
val assocCons2 = mainModule.getAssociatedType
|
||||
val mainFun2 = mainModule.getMethod(assocCons2, "main").get
|
||||
mainFun2.execute().asLong() shouldEqual 4567L
|
||||
}
|
||||
|
||||
@ -88,13 +89,15 @@ class ModuleManagementTest
|
||||
mainModule.setSource("""
|
||||
|main = 456
|
||||
|""".stripMargin)
|
||||
val mainFun2 = mainModule.getMethod(assocCons, "main").get
|
||||
val assocCons2 = mainModule.getAssociatedType
|
||||
val mainFun2 = mainModule.getMethod(assocCons2, "main").get
|
||||
mainFun2.execute().asLong() shouldEqual 456L
|
||||
|
||||
mainModule.setSource("""
|
||||
|main = 789
|
||||
|""".stripMargin)
|
||||
val mainFun3 = mainModule.getMethod(assocCons, "main").get
|
||||
val assocCons3 = mainModule.getAssociatedType
|
||||
val mainFun3 = mainModule.getMethod(assocCons3, "main").get
|
||||
mainFun3.execute().asLong() shouldEqual 789L
|
||||
|
||||
ctx.writeMain("""
|
||||
@ -102,7 +105,8 @@ class ModuleManagementTest
|
||||
|""".stripMargin)
|
||||
|
||||
mainModule.setSourceFile(ctx.pkg.mainFile.getAbsolutePath)
|
||||
val mainFun4 = mainModule.getMethod(assocCons, "main").get
|
||||
val assocCons4 = mainModule.getAssociatedType
|
||||
val mainFun4 = mainModule.getMethod(assocCons4, "main").get
|
||||
mainFun4.execute().asLong() shouldEqual 987L
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ class InlineContextUtils {
|
||||
* Creates a main method, generates some local variables, and fills their identifiers in the given
|
||||
* set.
|
||||
*
|
||||
* @param localVarsCnt How many local variables should be initialized in the main method
|
||||
* @param localVarNames local variables that should be initialized in the main method
|
||||
* @return Body of the main method
|
||||
*/
|
||||
static InlineSource createMainMethodWithLocalVars(Context ctx, Set<String> localVarNames)
|
||||
|
@ -70,11 +70,12 @@ public interface CompilerContext extends CompilerStub {
|
||||
|
||||
// Truffle related
|
||||
|
||||
void truffleRunCodegen(Module module, CompilerConfig config) throws IOException;
|
||||
void truffleRunCodegen(Module module, ModuleScopeBuilder scopeBuilder, CompilerConfig config)
|
||||
throws IOException;
|
||||
|
||||
// module related
|
||||
|
||||
void runStubsGenerator(Module module);
|
||||
void runStubsGenerator(Module module, ModuleScopeBuilder scopeBuilder);
|
||||
|
||||
boolean typeContainsValues(String name);
|
||||
|
||||
@ -147,5 +148,11 @@ public interface CompilerContext extends CompilerStub {
|
||||
public abstract org.enso.compiler.core.ir.Module getIr();
|
||||
|
||||
public abstract boolean isPrivate();
|
||||
|
||||
public abstract ModuleScopeBuilder getScopeBuilder();
|
||||
|
||||
public abstract ModuleScopeBuilder newScopeBuilder();
|
||||
}
|
||||
|
||||
public abstract static class ModuleScopeBuilder {}
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ class Compiler(
|
||||
|
||||
runErrorHandling(requiredModules)
|
||||
|
||||
requiredModules.foreach { module =>
|
||||
val requiredModulesWithScope = requiredModules.map { module =>
|
||||
if (
|
||||
!context
|
||||
.getCompilationStage(module)
|
||||
@ -368,16 +368,21 @@ class Compiler(
|
||||
CompilationStage.AFTER_RUNTIME_STUBS
|
||||
)
|
||||
) {
|
||||
context.runStubsGenerator(module)
|
||||
val moduleScopeBuilder = module.getScopeBuilder()
|
||||
context.runStubsGenerator(module, moduleScopeBuilder)
|
||||
context.updateModule(
|
||||
module,
|
||||
{ u =>
|
||||
u.compilationStage(CompilationStage.AFTER_RUNTIME_STUBS)
|
||||
}
|
||||
)
|
||||
(module, moduleScopeBuilder)
|
||||
} else {
|
||||
(module, module.getScopeBuilder)
|
||||
}
|
||||
}
|
||||
requiredModules.foreach { module =>
|
||||
|
||||
requiredModulesWithScope.foreach { case (module, moduleScopeBuilder) =>
|
||||
if (
|
||||
!context
|
||||
.getCompilationStage(module)
|
||||
@ -393,7 +398,7 @@ class Compiler(
|
||||
context.getModuleName(module)
|
||||
)
|
||||
|
||||
context.truffleRunCodegen(module, config)
|
||||
context.truffleRunCodegen(module, moduleScopeBuilder, config)
|
||||
}
|
||||
context.updateModule(
|
||||
module,
|
||||
|
@ -120,10 +120,10 @@ public final class ExecutionService {
|
||||
Module module, String typeName, String methodName)
|
||||
throws TypeNotFoundException, MethodNotFoundException {
|
||||
ModuleScope scope = module.compileScope(context);
|
||||
Type type =
|
||||
scope
|
||||
.getType(typeName)
|
||||
.orElseThrow(() -> new TypeNotFoundException(module.getName().toString(), typeName));
|
||||
Type type = scope.getType(typeName, false);
|
||||
if (type == null) {
|
||||
throw new TypeNotFoundException(module.getName().toString(), typeName);
|
||||
}
|
||||
Function function = scope.lookupMethodDefinition(type, methodName);
|
||||
if (function == null) {
|
||||
throw new MethodNotFoundException(module.getName().toString(), type, methodName);
|
||||
|
@ -63,70 +63,66 @@ class UpsertVisualizationJob(
|
||||
ctx.locking.withContextLock(
|
||||
config.executionContextId,
|
||||
this.getClass,
|
||||
() =>
|
||||
ctx.locking.withWriteCompilationLock(
|
||||
this.getClass,
|
||||
() => {
|
||||
val maybeCallable =
|
||||
UpsertVisualizationJob.evaluateVisualizationExpression(
|
||||
config.visualizationModule,
|
||||
config.expression
|
||||
() => {
|
||||
val maybeCallable =
|
||||
UpsertVisualizationJob.evaluateVisualizationExpression(
|
||||
config.visualizationModule,
|
||||
config.expression
|
||||
)
|
||||
|
||||
maybeCallable match {
|
||||
case Left(ModuleNotFound(moduleName)) =>
|
||||
ctx.endpoint.sendToClient(
|
||||
Api.Response(Api.ModuleNotFound(moduleName))
|
||||
)
|
||||
None
|
||||
|
||||
case Left(EvaluationFailed(message, result)) =>
|
||||
replyWithExpressionFailedError(
|
||||
config.executionContextId,
|
||||
visualizationId,
|
||||
expressionId,
|
||||
message,
|
||||
result
|
||||
)
|
||||
None
|
||||
|
||||
case Right(EvaluationResult(module, callable, arguments)) =>
|
||||
val visualization =
|
||||
UpsertVisualizationJob.updateAttachedVisualization(
|
||||
visualizationId,
|
||||
expressionId,
|
||||
module,
|
||||
config,
|
||||
callable,
|
||||
arguments
|
||||
)
|
||||
|
||||
maybeCallable match {
|
||||
case Left(ModuleNotFound(moduleName)) =>
|
||||
ctx.endpoint.sendToClient(
|
||||
Api.Response(Api.ModuleNotFound(moduleName))
|
||||
)
|
||||
None
|
||||
|
||||
case Left(EvaluationFailed(message, result)) =>
|
||||
replyWithExpressionFailedError(
|
||||
val stack =
|
||||
ctx.contextManager.getStack(config.executionContextId)
|
||||
val runtimeCache = stack.headOption
|
||||
.flatMap(frame => Option(frame.cache))
|
||||
val cachedValue = runtimeCache
|
||||
.flatMap(c => Option(c.get(expressionId)))
|
||||
UpsertVisualizationJob.requireVisualizationSynchronization(
|
||||
stack,
|
||||
expressionId
|
||||
)
|
||||
cachedValue match {
|
||||
case Some(value) =>
|
||||
ProgramExecutionSupport.executeAndSendVisualizationUpdate(
|
||||
config.executionContextId,
|
||||
visualizationId,
|
||||
runtimeCache.getOrElse(new RuntimeCache),
|
||||
stack.headOption.get.syncState,
|
||||
visualization,
|
||||
expressionId,
|
||||
message,
|
||||
result
|
||||
value
|
||||
)
|
||||
None
|
||||
|
||||
case Right(EvaluationResult(module, callable, arguments)) =>
|
||||
val visualization =
|
||||
UpsertVisualizationJob.updateAttachedVisualization(
|
||||
visualizationId,
|
||||
expressionId,
|
||||
module,
|
||||
config,
|
||||
callable,
|
||||
arguments
|
||||
)
|
||||
val stack =
|
||||
ctx.contextManager.getStack(config.executionContextId)
|
||||
val runtimeCache = stack.headOption
|
||||
.flatMap(frame => Option(frame.cache))
|
||||
val cachedValue = runtimeCache
|
||||
.flatMap(c => Option(c.get(expressionId)))
|
||||
UpsertVisualizationJob.requireVisualizationSynchronization(
|
||||
stack,
|
||||
expressionId
|
||||
)
|
||||
cachedValue match {
|
||||
case Some(value) =>
|
||||
ProgramExecutionSupport.executeAndSendVisualizationUpdate(
|
||||
config.executionContextId,
|
||||
runtimeCache.getOrElse(new RuntimeCache),
|
||||
stack.headOption.get.syncState,
|
||||
visualization,
|
||||
expressionId,
|
||||
value
|
||||
)
|
||||
None
|
||||
case None =>
|
||||
Some(Executable(config.executionContextId, stack))
|
||||
}
|
||||
case None =>
|
||||
Some(Executable(config.executionContextId, stack))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -284,7 +280,6 @@ object UpsertVisualizationJob {
|
||||
): Either[EvaluationFailure, AnyRef] = {
|
||||
Either
|
||||
.catchNonFatal {
|
||||
ctx.locking.assertWriteCompilationLock()
|
||||
ctx.executionService.evaluateExpression(module, argumentExpression)
|
||||
}
|
||||
.leftFlatMap {
|
||||
@ -355,7 +350,6 @@ object UpsertVisualizationJob {
|
||||
.catchNonFatal {
|
||||
expression match {
|
||||
case Api.VisualizationExpression.Text(_, expression, _) =>
|
||||
ctx.locking.assertWriteCompilationLock()
|
||||
ctx.executionService.evaluateExpression(
|
||||
expressionModule,
|
||||
expression
|
||||
@ -504,7 +498,10 @@ object UpsertVisualizationJob {
|
||||
callback,
|
||||
arguments
|
||||
)
|
||||
invalidateCaches(visualization)
|
||||
ctx.locking.withWriteCompilationLock(
|
||||
this.getClass,
|
||||
() => invalidateCaches(visualization)
|
||||
)
|
||||
ctx.contextManager.upsertVisualization(
|
||||
visualizationConfig.executionContextId,
|
||||
visualization
|
||||
|
@ -52,7 +52,7 @@ public interface IR {
|
||||
* @return the external identifier for this IR node
|
||||
*/
|
||||
default Option<@ExternalID UUID> getExternalId() {
|
||||
return location().flatMap(l -> l.id().map(id -> id));
|
||||
return location().flatMap(l -> l.id());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,7 +138,8 @@ object CallArgument {
|
||||
|""".toSingleLine
|
||||
|
||||
/** @inheritdoc */
|
||||
override def children: List[IR] = name.toList :+ value
|
||||
override def children: List[IR] =
|
||||
name.map(List(_, value)).getOrElse(List(value))
|
||||
|
||||
/** @inheritdoc */
|
||||
override def showCode(indent: Int): String = {
|
||||
|
@ -265,7 +265,10 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
|
||||
var m = org.enso.interpreter.runtime.Module.fromCompilerModule(mod);
|
||||
var toTruffle =
|
||||
new IrToTruffle(
|
||||
context, request.getSource(), m.getScope(), redirectConfigWithStrictErrors);
|
||||
context,
|
||||
request.getSource(),
|
||||
m.getScopeBuilder(),
|
||||
redirectConfigWithStrictErrors);
|
||||
exprNode = toTruffle.runInline(ir, sco, "<inline_source>");
|
||||
} else {
|
||||
exprNode = null;
|
||||
|
@ -4,7 +4,6 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import org.enso.compiler.phase.ImportResolverAlgorithm;
|
||||
import org.enso.editions.LibraryName;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
@ -74,10 +73,8 @@ final class InvokeMethodImportResolver
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Type> definedEntities(UnresolvedSymbol name) {
|
||||
var associatedType = module.getScope().getType(name.getName());
|
||||
var allRelativeTypes = module.getScope().getTypes().values();
|
||||
return Stream.concat(associatedType.stream(), allRelativeTypes.stream()).toList();
|
||||
protected List<Type> definedEntities(UnresolvedSymbol symbol) {
|
||||
return module.getScope().getAllTypes(symbol.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,7 +29,6 @@ import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.data.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
import org.enso.interpreter.runtime.state.State;
|
||||
import org.enso.pkg.Package;
|
||||
|
||||
@ -276,33 +275,22 @@ public abstract class InvokeFunctionNode extends BaseNode {
|
||||
|
||||
private Package<TruffleFile> getThisProject() {
|
||||
if (getRootNode() instanceof EnsoRootNode thisRootNode) {
|
||||
var modScope = thisRootNode.getModuleScope();
|
||||
if (modScope != null) {
|
||||
return modScope.getModule().getPackage();
|
||||
}
|
||||
return thisRootNode.getModuleScope().getModule().getPackage();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Package<TruffleFile> getFunctionProject(Function function) {
|
||||
var modScope = getModuleScopeForFunction(function);
|
||||
if (modScope != null) {
|
||||
return modScope.getModule().getPackage();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ModuleScope getModuleScopeForFunction(Function function) {
|
||||
var cons = AtomConstructor.accessorFor(function);
|
||||
if (cons != null) {
|
||||
return cons.getDefinitionScope();
|
||||
return cons.getDefinitionScope().getModule().getPackage();
|
||||
}
|
||||
cons = MethodRootNode.constructorFor(function);
|
||||
if (cons != null) {
|
||||
return cons.getDefinitionScope();
|
||||
return cons.getDefinitionScope().getModule().getPackage();
|
||||
}
|
||||
if (function.getCallTarget().getRootNode() instanceof EnsoRootNode ensoRootNode) {
|
||||
return ensoRootNode.getModuleScope();
|
||||
return ensoRootNode.getModuleScope().getModule().getPackage();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -18,10 +18,11 @@ public abstract class Builtin {
|
||||
this(name, Arrays.asList(params));
|
||||
}
|
||||
|
||||
private AtomConstructor build(EnsoLanguage language, ModuleScope scope, Type type) {
|
||||
var res = new AtomConstructor(name, scope, type, true);
|
||||
private AtomConstructor build(EnsoLanguage language, ModuleScope.Builder scope, Type type) {
|
||||
var res = new AtomConstructor(name, scope.getModule(), type, true);
|
||||
res.initializeFields(
|
||||
language,
|
||||
scope,
|
||||
IntStream.range(0, params.size())
|
||||
.mapToObj(
|
||||
i ->
|
||||
@ -50,7 +51,9 @@ public abstract class Builtin {
|
||||
}
|
||||
|
||||
public final void initialize(
|
||||
EnsoLanguage language, ModuleScope scope, Map<Class<? extends Builtin>, Builtin> builtins) {
|
||||
EnsoLanguage language,
|
||||
ModuleScope.Builder scope,
|
||||
Map<Class<? extends Builtin>, Builtin> builtins) {
|
||||
if (type == null) {
|
||||
Type supertype = null;
|
||||
if (getSuperType() != null) {
|
||||
|
@ -1,11 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.meta;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedConversion;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
|
||||
@BuiltinMethod(
|
||||
@ -13,10 +18,33 @@ import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
name = "create_unresolved_symbol",
|
||||
description = "Creates a new unresolved symbol node",
|
||||
autoRegister = false)
|
||||
public class CreateUnresolvedSymbolNode extends Node {
|
||||
public abstract class CreateUnresolvedSymbolNode extends Node {
|
||||
private @Child ExpectStringNode expectStringNode = ExpectStringNode.build();
|
||||
|
||||
Object execute(Object name, ModuleScope scope) {
|
||||
static CreateUnresolvedSymbolNode build() {
|
||||
return CreateUnresolvedSymbolNodeGen.create();
|
||||
}
|
||||
|
||||
abstract Object execute(Object name, Object symbol);
|
||||
|
||||
@Specialization
|
||||
Object doSymbol(Object name, UnresolvedSymbol symbol) {
|
||||
return executeWithScope(name, symbol.getScope());
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doConversion(Object name, UnresolvedConversion symbol) {
|
||||
return executeWithScope(name, symbol.getScope());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
ModuleScope doFallback(Object name, Object symbol) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
throw new PanicException(
|
||||
builtins.error().makeTypeError("Unresolved_Symbol", symbol, "symbol"), this);
|
||||
}
|
||||
|
||||
private Object executeWithScope(Object name, ModuleScope scope) {
|
||||
String result = expectStringNode.execute(name);
|
||||
if (result.equals(Constants.Names.FROM_MEMBER)) {
|
||||
return UnresolvedConversion.build(scope);
|
||||
|
@ -127,7 +127,7 @@ public final class EqualsNode extends Node {
|
||||
|
||||
private static boolean isDefinedIn(ModuleScope scope, Function fn) {
|
||||
if (fn.getCallTarget().getRootNode() instanceof EnsoRootNode ensoRoot) {
|
||||
return ensoRoot.getModuleScope() == scope;
|
||||
return ensoRoot.getModuleScope().getModule() == scope.getModule();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ public class FindTypeByFqnNode extends Node {
|
||||
var moduleName = fullName.getParent().get();
|
||||
var maybeModule = ctx.getTopScope().getModule(moduleName.toString());
|
||||
if (maybeModule.isPresent()) {
|
||||
var foundType = maybeModule.get().getScope().getType(fullName.item());
|
||||
if (foundType.isPresent()) {
|
||||
return foundType.get();
|
||||
var foundType = maybeModule.get().getScope().getType(fullName.item(), false);
|
||||
if (foundType != null) {
|
||||
return foundType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.meta;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedConversion;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Meta",
|
||||
name = "get_unresolved_symbol_scope",
|
||||
description = "Gets the scope of an unresolved symbol",
|
||||
autoRegister = false)
|
||||
public abstract class GetUnresolvedSymbolScopeNode extends Node {
|
||||
static GetUnresolvedSymbolScopeNode build() {
|
||||
return GetUnresolvedSymbolScopeNodeGen.create();
|
||||
}
|
||||
|
||||
abstract ModuleScope execute(Object symbol);
|
||||
|
||||
@Specialization
|
||||
ModuleScope doSymbol(UnresolvedSymbol symbol) {
|
||||
return symbol.getScope();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
ModuleScope doConversion(UnresolvedConversion symbol) {
|
||||
return symbol.getScope();
|
||||
}
|
||||
|
||||
@Fallback
|
||||
ModuleScope doFallback(Object symbol) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
throw new PanicException(
|
||||
builtins.error().makeTypeError("Unresolved_Symbol", symbol, "symbol"), this);
|
||||
}
|
||||
}
|
@ -86,7 +86,7 @@ public abstract class EvalNode extends BaseNode {
|
||||
var sco = newInlineContext.localScope().getOrElse(LocalScope::root);
|
||||
var mod = newInlineContext.getModule();
|
||||
var m = org.enso.interpreter.runtime.Module.fromCompilerModule(mod);
|
||||
var toTruffle = new IrToTruffle(context, src, m.getScope(), compiler.getConfig());
|
||||
var toTruffle = new IrToTruffle(context, src, m.getScopeBuilder(), compiler.getConfig());
|
||||
var expr = toTruffle.runInline(ir, sco, "<inline_source>");
|
||||
|
||||
if (shouldCaptureResultScope) {
|
||||
|
@ -53,18 +53,18 @@ import org.enso.text.buffer.Rope;
|
||||
/** Represents a source module with a known location. */
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public final class Module implements EnsoObject {
|
||||
private ModuleScope scope;
|
||||
private ModuleSources sources;
|
||||
private PatchedModuleValues patchedValues;
|
||||
private final Map<Source, Module> allSources = new WeakHashMap<>();
|
||||
private final Package<TruffleFile> pkg;
|
||||
private CompilationStage compilationStage = CompilationStage.INITIAL;
|
||||
private org.enso.compiler.core.ir.Module ir;
|
||||
private Map<UUID, IR> uuidsMap;
|
||||
private QualifiedName name;
|
||||
private ModuleScope.Builder scopeBuilder;
|
||||
private final Package<TruffleFile> pkg;
|
||||
private final Cache<ModuleCache.CachedModule, ModuleCache.Metadata> cache;
|
||||
private boolean wasLoadedFromCache;
|
||||
private final boolean synthetic;
|
||||
private PatchedModuleValues patchedValues;
|
||||
private final Map<Source, Module> allSources = new WeakHashMap<>();
|
||||
private CompilationStage compilationStage = CompilationStage.INITIAL;
|
||||
private org.enso.compiler.core.ir.Module ir;
|
||||
private Map<UUID, IR> uuidsMap;
|
||||
|
||||
/**
|
||||
* This list is filled in case there is a directory with the same name as this module. The
|
||||
@ -86,8 +86,9 @@ public final class Module implements EnsoObject {
|
||||
*/
|
||||
public Module(QualifiedName name, Package<TruffleFile> pkg, TruffleFile sourceFile) {
|
||||
this.sources = ModuleSources.NONE.newWith(sourceFile);
|
||||
this.pkg = pkg;
|
||||
this.name = name;
|
||||
this.scopeBuilder = new ModuleScope.Builder(this);
|
||||
this.pkg = pkg;
|
||||
this.cache = ModuleCache.create(this);
|
||||
this.wasLoadedFromCache = false;
|
||||
this.synthetic = false;
|
||||
@ -103,8 +104,9 @@ public final class Module implements EnsoObject {
|
||||
*/
|
||||
public Module(QualifiedName name, Package<TruffleFile> pkg, String literalSource) {
|
||||
this.sources = ModuleSources.NONE.newWith(Rope.apply(literalSource));
|
||||
this.pkg = pkg;
|
||||
this.name = name;
|
||||
this.scopeBuilder = new ModuleScope.Builder(this);
|
||||
this.pkg = pkg;
|
||||
this.cache = ModuleCache.create(this);
|
||||
this.wasLoadedFromCache = false;
|
||||
this.patchedValues = new PatchedModuleValues(this);
|
||||
@ -121,8 +123,9 @@ public final class Module implements EnsoObject {
|
||||
*/
|
||||
public Module(QualifiedName name, Package<TruffleFile> pkg, Rope literalSource) {
|
||||
this.sources = ModuleSources.NONE.newWith(literalSource);
|
||||
this.pkg = pkg;
|
||||
this.name = name;
|
||||
this.scopeBuilder = new ModuleScope.Builder(this);
|
||||
this.pkg = pkg;
|
||||
this.cache = ModuleCache.create(this);
|
||||
this.wasLoadedFromCache = false;
|
||||
this.patchedValues = new PatchedModuleValues(this);
|
||||
@ -141,12 +144,17 @@ public final class Module implements EnsoObject {
|
||||
this.sources =
|
||||
literalSource == null ? ModuleSources.NONE : ModuleSources.NONE.newWith(literalSource);
|
||||
this.name = name;
|
||||
this.scope = new ModuleScope(this);
|
||||
this.scopeBuilder = new ModuleScope.Builder(this);
|
||||
this.pkg = pkg;
|
||||
this.compilationStage = synthetic ? CompilationStage.INITIAL : CompilationStage.AFTER_CODEGEN;
|
||||
this.cache = ModuleCache.create(this);
|
||||
this.wasLoadedFromCache = false;
|
||||
this.synthetic = synthetic;
|
||||
if (synthetic) {
|
||||
this.compilationStage = CompilationStage.INITIAL;
|
||||
scopeBuilder.build();
|
||||
} else {
|
||||
this.compilationStage = CompilationStage.AFTER_CODEGEN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -254,7 +262,7 @@ public final class Module implements EnsoObject {
|
||||
* @see PatchedModuleValues
|
||||
*/
|
||||
public void setLiteralSource(Rope source, SimpleUpdate update) {
|
||||
if (this.scope != null && update != null) {
|
||||
if (update != null) {
|
||||
var change = update.ir();
|
||||
if (this.patchedValues == null) {
|
||||
this.patchedValues = new PatchedModuleValues(this);
|
||||
@ -314,22 +322,13 @@ public final class Module implements EnsoObject {
|
||||
* @return the scope defined by this module
|
||||
*/
|
||||
public ModuleScope compileScope(EnsoContext context) {
|
||||
ensureScopeExists();
|
||||
if (!compilationStage.isAtLeast(CompilationStage.AFTER_CODEGEN)) {
|
||||
try {
|
||||
compile(context);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
/** Create scope if it does not exist. */
|
||||
public void ensureScopeExists() {
|
||||
if (scope == null) {
|
||||
scope = new ModuleScope(this);
|
||||
compilationStage = CompilationStage.INITIAL;
|
||||
}
|
||||
return scopeBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -385,10 +384,9 @@ public final class Module implements EnsoObject {
|
||||
}
|
||||
|
||||
private void compile(EnsoContext context) throws IOException {
|
||||
ensureScopeExists();
|
||||
Source source = getSource();
|
||||
if (source == null) return;
|
||||
scope.reset();
|
||||
scopeBuilder = newScopeBuilder(false);
|
||||
compilationStage = CompilationStage.INITIAL;
|
||||
context.getCompiler().run(asCompilerModule());
|
||||
}
|
||||
@ -458,21 +456,20 @@ public final class Module implements EnsoObject {
|
||||
* @return the runtime scope of this module.
|
||||
*/
|
||||
public ModuleScope getScope() {
|
||||
return scope;
|
||||
return scopeBuilder.asModuleScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the runtime scope of this module that filters out only the requested types. If the list
|
||||
* of requested types is empty, returns the unchanged runtime scope.
|
||||
*
|
||||
* @param types a list of types to include in the scope
|
||||
*/
|
||||
public ModuleScope getScope(List<String> types) {
|
||||
if (types.isEmpty()) {
|
||||
return scope;
|
||||
public ModuleScope.Builder getScopeBuilder() {
|
||||
return scopeBuilder;
|
||||
}
|
||||
|
||||
public ModuleScope.Builder newScopeBuilder(boolean inheritTypes) {
|
||||
if (inheritTypes) {
|
||||
this.scopeBuilder = this.scopeBuilder.newBuilderInheritingTypes();
|
||||
} else {
|
||||
return scope.withTypes(types);
|
||||
this.scopeBuilder = new ModuleScope.Builder(this);
|
||||
}
|
||||
return this.scopeBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -584,7 +581,7 @@ public final class Module implements EnsoObject {
|
||||
throw UnsupportedTypeException.create(args, "First argument must be a string");
|
||||
}
|
||||
String name = iop.asString(args[0]);
|
||||
return scope.getTypes().get(name);
|
||||
return scope.getType(name, true);
|
||||
}
|
||||
|
||||
private static Module reparse(Module module, Object[] args, EnsoContext context)
|
||||
@ -601,7 +598,7 @@ public final class Module implements EnsoObject {
|
||||
}
|
||||
|
||||
private static Module setSource(Module module, Object[] args, EnsoContext context)
|
||||
throws ArityException, UnsupportedTypeException, UnsupportedMessageException {
|
||||
throws UnsupportedTypeException, UnsupportedMessageException {
|
||||
var iop = InteropLibrary.getUncached();
|
||||
if (!iop.isString(args[0])) {
|
||||
throw UnsupportedTypeException.create(args, "First argument must be a string");
|
||||
|
@ -137,10 +137,16 @@ final class TruffleCompilerContext implements CompilerContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truffleRunCodegen(CompilerContext.Module module, CompilerConfig config)
|
||||
public void truffleRunCodegen(
|
||||
CompilerContext.Module module,
|
||||
CompilerContext.ModuleScopeBuilder scopeBuilder,
|
||||
CompilerConfig config)
|
||||
throws IOException {
|
||||
var m = org.enso.interpreter.runtime.Module.fromCompilerModule(module);
|
||||
new IrToTruffle(context, m.getSource(), m.getScope(), config).run(module.getIr());
|
||||
var s =
|
||||
org.enso.interpreter.runtime.scope.ModuleScope.Builder.fromCompilerModuleScopeBuilder(
|
||||
scopeBuilder);
|
||||
new IrToTruffle(context, m.getSource(), s, config).run(module.getIr());
|
||||
}
|
||||
|
||||
// module related
|
||||
@ -241,8 +247,13 @@ final class TruffleCompilerContext implements CompilerContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runStubsGenerator(CompilerContext.Module module) {
|
||||
stubsGenerator.run(((Module) module).unsafeModule());
|
||||
public void runStubsGenerator(
|
||||
CompilerContext.Module module, CompilerContext.ModuleScopeBuilder scopeBuilder) {
|
||||
var m = ((Module) module).unsafeModule();
|
||||
var s =
|
||||
((org.enso.interpreter.runtime.scope.TruffleCompilerModuleScopeBuilder) scopeBuilder)
|
||||
.unsafeScopeBuilder();
|
||||
stubsGenerator.run(m.getIr(), s);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -723,8 +734,7 @@ final class TruffleCompilerContext implements CompilerContext {
|
||||
module.module.setLoadedFromCache(loadedFromCache);
|
||||
}
|
||||
if (resetScope) {
|
||||
module.module.ensureScopeExists();
|
||||
module.module.getScope().reset();
|
||||
module.module.newScopeBuilder(true);
|
||||
}
|
||||
if (invalidateCache) {
|
||||
module.module.getCache().invalidate(context);
|
||||
@ -817,6 +827,18 @@ final class TruffleCompilerContext implements CompilerContext {
|
||||
return module.isPrivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerContext.ModuleScopeBuilder getScopeBuilder() {
|
||||
return new org.enso.interpreter.runtime.scope.TruffleCompilerModuleScopeBuilder(
|
||||
module.getScopeBuilder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleScopeBuilder newScopeBuilder() {
|
||||
return new org.enso.interpreter.runtime.scope.TruffleCompilerModuleScopeBuilder(
|
||||
module.newScopeBuilder(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
|
@ -126,19 +126,20 @@ public final class Builtins {
|
||||
public Builtins(EnsoContext context) {
|
||||
EnsoLanguage language = context.getLanguage();
|
||||
module = Module.empty(QualifiedName.fromString(MODULE_NAME), null);
|
||||
scope = module.compileScope(context);
|
||||
module.compileScope(context); // Dummy compilation for an empty module
|
||||
ModuleScope.Builder scopeBuilder = module.newScopeBuilder(false);
|
||||
|
||||
builtins = initializeBuiltinTypes(loadedBuiltinConstructors, language, scope);
|
||||
builtins = initializeBuiltinTypes(loadedBuiltinConstructors, language, scopeBuilder);
|
||||
builtinsByName =
|
||||
builtins.values().stream()
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
v -> v.getType().getName(), java.util.function.Function.identity()));
|
||||
if (TruffleOptions.AOT) {
|
||||
builtinMethodNodes = readBuiltinMethodsMetadata(loadedBuiltinMethods, scope);
|
||||
registerBuiltinMethods(scope, language);
|
||||
builtinMethodNodes = readBuiltinMethodsMetadata(loadedBuiltinMethods, scopeBuilder);
|
||||
registerBuiltinMethods(scopeBuilder, language);
|
||||
} else {
|
||||
builtinMethodNodes = registerBuiltinMethodsLazily(scope, language);
|
||||
builtinMethodNodes = registerBuiltinMethodsLazily(scopeBuilder, language);
|
||||
}
|
||||
|
||||
ordering = getBuiltinType(Ordering.class);
|
||||
@ -172,6 +173,7 @@ public final class Builtins {
|
||||
system = new System(this);
|
||||
number = new Number(this);
|
||||
special = new Special(language);
|
||||
scope = scopeBuilder.build();
|
||||
}
|
||||
|
||||
private static Map<String, LoadedBuiltinMethod> loadBuiltinMethodClassesEarly(
|
||||
@ -192,7 +194,7 @@ public final class Builtins {
|
||||
* @param scope Builtins scope
|
||||
* @param language The language the resulting function nodes should be associated with
|
||||
*/
|
||||
private void registerBuiltinMethods(ModuleScope scope, EnsoLanguage language) {
|
||||
private void registerBuiltinMethods(ModuleScope.Builder scope, EnsoLanguage language) {
|
||||
for (Builtin builtin : builtins.values()) {
|
||||
var type = builtin.getType();
|
||||
Map<String, Supplier<LoadedBuiltinMethod>> methods = builtinMethodNodes.get(type.getName());
|
||||
@ -226,7 +228,7 @@ public final class Builtins {
|
||||
* @return map from types to builtin methods
|
||||
*/
|
||||
private Map<String, Map<String, Supplier<LoadedBuiltinMethod>>> registerBuiltinMethodsLazily(
|
||||
ModuleScope scope, EnsoLanguage language) {
|
||||
ModuleScope.Builder scope, EnsoLanguage language) {
|
||||
Map<String, Map<String, Supplier<LoadedBuiltinMethod>>> builtinMethodNodes = new HashMap<>();
|
||||
Map<String, Map<String, LoadedBuiltinMetaMethod>> builtinMetaMethods = new HashMap<>();
|
||||
loadedBuiltinMethodsMeta.forEach(
|
||||
@ -237,7 +239,7 @@ public final class Builtins {
|
||||
}
|
||||
String builtinMethodOwner = builtinName[0];
|
||||
String builtinMethodName = builtinName[1];
|
||||
Optional.ofNullable(scope.getTypes().get(builtinMethodOwner))
|
||||
Optional.ofNullable(scope.asModuleScope().getType(builtinMethodOwner, true))
|
||||
.ifPresentOrElse(
|
||||
constr -> {
|
||||
Map<String, Supplier<LoadedBuiltinMethod>> atomNodes =
|
||||
@ -375,7 +377,9 @@ public final class Builtins {
|
||||
|
||||
/** Initialize builting types in the context of the given language and module scope */
|
||||
private Map<Class<? extends Builtin>, Builtin> initializeBuiltinTypes(
|
||||
List<Constructor<? extends Builtin>> constrs, EnsoLanguage language, ModuleScope scope) {
|
||||
List<Constructor<? extends Builtin>> constrs,
|
||||
EnsoLanguage language,
|
||||
ModuleScope.Builder scope) {
|
||||
Map<Class<? extends Builtin>, Builtin> builtins = new HashMap<>();
|
||||
|
||||
for (var constr : constrs) {
|
||||
@ -400,7 +404,7 @@ public final class Builtins {
|
||||
* @return A map of builtin method nodes per builtin type name
|
||||
*/
|
||||
private Map<String, Map<String, Supplier<LoadedBuiltinMethod>>> readBuiltinMethodsMetadata(
|
||||
Map<String, LoadedBuiltinMethod> classes, ModuleScope scope) {
|
||||
Map<String, LoadedBuiltinMethod> classes, ModuleScope.Builder scope) {
|
||||
|
||||
Map<String, Map<String, Supplier<LoadedBuiltinMethod>>> methodNodes = new HashMap<>();
|
||||
classes.forEach(
|
||||
@ -411,7 +415,7 @@ public final class Builtins {
|
||||
}
|
||||
String builtinMethodOwner = builtinName[0];
|
||||
String builtinMethodName = builtinName[1];
|
||||
Optional.ofNullable(scope.getTypes().get(builtinMethodOwner))
|
||||
Optional.ofNullable(scope.asModuleScope().getType(builtinMethodOwner, true))
|
||||
.ifPresentOrElse(
|
||||
constr -> {
|
||||
Map<String, Supplier<LoadedBuiltinMethod>> atomNodes =
|
||||
|
@ -28,8 +28,9 @@ import org.enso.pkg.QualifiedName;
|
||||
@ExportLibrary(TypesLibrary.class)
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public final class Type implements EnsoObject {
|
||||
|
||||
private final String name;
|
||||
private @CompilerDirectives.CompilationFinal ModuleScope definitionScope;
|
||||
private @CompilerDirectives.CompilationFinal ModuleScope.Builder definitionScope;
|
||||
private final boolean builtin;
|
||||
private final Type supertype;
|
||||
private final Type eigentype;
|
||||
@ -40,7 +41,7 @@ public final class Type implements EnsoObject {
|
||||
|
||||
private Type(
|
||||
String name,
|
||||
ModuleScope definitionScope,
|
||||
ModuleScope.Builder definitionScope,
|
||||
Type supertype,
|
||||
Type eigentype,
|
||||
boolean builtin,
|
||||
@ -56,18 +57,16 @@ public final class Type implements EnsoObject {
|
||||
|
||||
public static Type createSingleton(
|
||||
String name,
|
||||
ModuleScope definitionScope,
|
||||
ModuleScope.Builder definitionScope,
|
||||
Type supertype,
|
||||
boolean builtin,
|
||||
boolean isProjectPrivate) {
|
||||
var result = new Type(name, definitionScope, supertype, null, builtin, isProjectPrivate);
|
||||
result.generateQualifiedAccessor();
|
||||
return result;
|
||||
return new Type(name, definitionScope, supertype, null, builtin, isProjectPrivate);
|
||||
}
|
||||
|
||||
public static Type create(
|
||||
String name,
|
||||
ModuleScope definitionScope,
|
||||
ModuleScope.Builder definitionScope,
|
||||
Type supertype,
|
||||
Type any,
|
||||
boolean builtin,
|
||||
@ -93,7 +92,8 @@ public final class Type implements EnsoObject {
|
||||
schemaBldr.projectPrivate();
|
||||
}
|
||||
var function = new Function(node.getCallTarget(), null, schemaBldr.build());
|
||||
definitionScope.registerMethod(definitionScope.getAssociatedType(), this.name, function);
|
||||
definitionScope.registerMethod(
|
||||
definitionScope.asModuleScope().getAssociatedType(), this.name, function);
|
||||
}
|
||||
|
||||
public QualifiedName getQualifiedName() {
|
||||
@ -104,11 +104,9 @@ public final class Type implements EnsoObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void setShadowDefinitions(ModuleScope scope, boolean generateAccessorsInTarget) {
|
||||
public void setShadowDefinitions(ModuleScope.Builder scope, boolean generateAccessorsInTarget) {
|
||||
if (builtin) {
|
||||
// Ensure that synthetic methods, such as getters for fields are in the scope
|
||||
// Some scopes won't have any methods at this point, e.g., Nil or Nothing, hence the null
|
||||
// check.
|
||||
// Ensure that synthetic methods, such as getters for fields are in the scope.
|
||||
CompilerAsserts.neverPartOfCompilation();
|
||||
this.definitionScope.registerAllMethodsOfTypeToScope(this, scope);
|
||||
this.definitionScope = scope;
|
||||
@ -129,7 +127,7 @@ public final class Type implements EnsoObject {
|
||||
}
|
||||
|
||||
public ModuleScope getDefinitionScope() {
|
||||
return definitionScope;
|
||||
return definitionScope.asModuleScope();
|
||||
}
|
||||
|
||||
public boolean isBuiltin() {
|
||||
|
@ -24,6 +24,7 @@ import org.enso.interpreter.node.MethodRootNode;
|
||||
import org.enso.interpreter.node.callable.argument.ReadArgumentNode;
|
||||
import org.enso.interpreter.node.callable.function.BlockNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.Module;
|
||||
import org.enso.interpreter.runtime.callable.Annotation;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
@ -43,7 +44,7 @@ import org.enso.pkg.QualifiedName;
|
||||
public final class AtomConstructor implements EnsoObject {
|
||||
|
||||
private final String name;
|
||||
private final ModuleScope definitionScope;
|
||||
private final Module definitionModule;
|
||||
private final boolean builtin;
|
||||
private @CompilerDirectives.CompilationFinal Atom cachedInstance;
|
||||
private @CompilerDirectives.CompilationFinal Function constructorFunction;
|
||||
@ -60,11 +61,11 @@ public final class AtomConstructor implements EnsoObject {
|
||||
* AtomConstructor#initializeFields} is called.
|
||||
*
|
||||
* @param name the name of the Atom constructor
|
||||
* @param definitionScope the scope in which this constructor was defined
|
||||
* @param definitionModule the module in which this constructor was defined
|
||||
* @param type associated type
|
||||
*/
|
||||
public AtomConstructor(String name, ModuleScope definitionScope, Type type) {
|
||||
this(name, definitionScope, type, false);
|
||||
public AtomConstructor(String name, Module definitionModule, Type type) {
|
||||
this(name, definitionModule, type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,13 +73,13 @@ public final class AtomConstructor implements EnsoObject {
|
||||
* AtomConstructor#initializeFields} is called.
|
||||
*
|
||||
* @param name the name of the Atom constructor
|
||||
* @param definitionScope the scope in which this constructor was defined
|
||||
* @param definitionModule the module in which this constructor was defined
|
||||
* @param type associated type
|
||||
* @param builtin if true, the constructor refers to a builtin type (annotated with @BuiltinType
|
||||
*/
|
||||
public AtomConstructor(String name, ModuleScope definitionScope, Type type, boolean builtin) {
|
||||
public AtomConstructor(String name, Module definitionModule, Type type, boolean builtin) {
|
||||
this.name = name;
|
||||
this.definitionScope = definitionScope;
|
||||
this.definitionModule = definitionModule;
|
||||
this.type = type;
|
||||
this.builtin = builtin;
|
||||
}
|
||||
@ -102,13 +103,21 @@ public final class AtomConstructor implements EnsoObject {
|
||||
*
|
||||
* @return {@code this}, for convenience
|
||||
*/
|
||||
public AtomConstructor initializeFields(EnsoLanguage language, ArgumentDefinition... args) {
|
||||
public AtomConstructor initializeFields(
|
||||
EnsoLanguage language, ModuleScope.Builder scopeBuilder, ArgumentDefinition... args) {
|
||||
ExpressionNode[] reads = new ExpressionNode[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
reads[i] = ReadArgumentNode.build(i, null, null);
|
||||
}
|
||||
return initializeFields(
|
||||
language, null, LocalScope.root(), new ExpressionNode[0], reads, new Annotation[0], args);
|
||||
language,
|
||||
null,
|
||||
LocalScope.root(),
|
||||
scopeBuilder,
|
||||
new ExpressionNode[0],
|
||||
reads,
|
||||
new Annotation[0],
|
||||
args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,6 +125,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
*
|
||||
* @param localScope a description of the local scope
|
||||
* @param assignments the expressions that evaluate and assign constructor arguments to local vars
|
||||
* @param scopeBuilder the module scope's builder where the accessor should be registered at
|
||||
* @param varReads the expressions that read field values from local vars
|
||||
* @return {@code this}, for convenience
|
||||
*/
|
||||
@ -123,6 +133,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
EnsoLanguage language,
|
||||
SourceSection section,
|
||||
LocalScope localScope,
|
||||
ModuleScope.Builder scopeBuilder,
|
||||
ExpressionNode[] assignments,
|
||||
ExpressionNode[] varReads,
|
||||
Annotation[] annotations,
|
||||
@ -137,8 +148,8 @@ public final class AtomConstructor implements EnsoObject {
|
||||
boxedLayout = Layout.createBoxed(args);
|
||||
this.constructorFunction =
|
||||
buildConstructorFunction(
|
||||
language, section, localScope, assignments, varReads, annotations, args);
|
||||
this.accessor = generateQualifiedAccessor(language);
|
||||
language, section, localScope, scopeBuilder, assignments, varReads, annotations, args);
|
||||
this.accessor = generateQualifiedAccessor(language, scopeBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -159,6 +170,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
EnsoLanguage language,
|
||||
SourceSection section,
|
||||
LocalScope localScope,
|
||||
ModuleScope.Builder scopeBuilder,
|
||||
ExpressionNode[] assignments,
|
||||
ExpressionNode[] varReads,
|
||||
Annotation[] annotations,
|
||||
@ -170,7 +182,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
BlockNode instantiateBlock = BlockNode.buildSilent(assignments, instantiateNode);
|
||||
RootNode rootNode =
|
||||
MethodRootNode.buildConstructor(
|
||||
language, localScope, definitionScope, instantiateBlock, section, this);
|
||||
language, localScope, scopeBuilder.asModuleScope(), instantiateBlock, section, this);
|
||||
RootCallTarget callTarget = rootNode.getCallTarget();
|
||||
var schemaBldr = FunctionSchema.newBuilder().annotations(annotations).argumentDefinitions(args);
|
||||
if (type.isProjectPrivate()) {
|
||||
@ -179,7 +191,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
return new Function(callTarget, null, schemaBldr.build());
|
||||
}
|
||||
|
||||
private Function generateQualifiedAccessor(EnsoLanguage lang) {
|
||||
private Function generateQualifiedAccessor(EnsoLanguage lang, ModuleScope.Builder scopeBuilder) {
|
||||
var node = new QualifiedAccessorNode(lang, this, getDefinitionScope());
|
||||
var callTarget = node.getCallTarget();
|
||||
var schemaBldr =
|
||||
@ -191,7 +203,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
schemaBldr.projectPrivate();
|
||||
}
|
||||
var function = new Function(callTarget, null, schemaBldr.build());
|
||||
definitionScope.registerMethod(type.getEigentype(), this.name, function);
|
||||
scopeBuilder.registerMethod(type.getEigentype(), this.name, function);
|
||||
return function;
|
||||
}
|
||||
|
||||
@ -221,7 +233,7 @@ public final class AtomConstructor implements EnsoObject {
|
||||
* @return the scope in which this constructor was defined
|
||||
*/
|
||||
public ModuleScope getDefinitionScope() {
|
||||
return definitionScope;
|
||||
return definitionModule.getScope();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,70 @@
|
||||
package org.enso.interpreter.runtime.scope;
|
||||
|
||||
import java.util.List;
|
||||
import org.enso.compiler.context.CompilerContext;
|
||||
import org.enso.interpreter.runtime.Module;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.EnsoObject;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
|
||||
/**
|
||||
* A proxy scope delegating to the underlying module's scope. Additionally, `ImportExportScope` may
|
||||
* limit the number of types that are imported/exported.
|
||||
*/
|
||||
public class ImportExportScope implements EnsoObject {
|
||||
|
||||
private final Module module;
|
||||
private final List<String> typesOnlyNames;
|
||||
|
||||
public ImportExportScope(CompilerContext.Module module, List<String> typesOnlyNames) {
|
||||
this.module = org.enso.interpreter.runtime.Module.fromCompilerModule(module);
|
||||
this.typesOnlyNames =
|
||||
typesOnlyNames != null && !typesOnlyNames.isEmpty() ? typesOnlyNames : null;
|
||||
}
|
||||
|
||||
public ImportExportScope(CompilerContext.Module module) {
|
||||
this.module = org.enso.interpreter.runtime.Module.fromCompilerModule(module);
|
||||
this.typesOnlyNames = null;
|
||||
}
|
||||
|
||||
private boolean isValidType(Type type) {
|
||||
if (typesOnlyNames == null) return true;
|
||||
return typesOnlyNames.contains(type.getName()) && module.getScope().hasType(type);
|
||||
}
|
||||
|
||||
public Function getExportedMethod(Type type, String name) {
|
||||
if (isValidType(type)) {
|
||||
return module.getScope().getExportedMethod(type, name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Function getExportedConversion(Type type, Type target) {
|
||||
if (isValidType(target)) {
|
||||
return module.getScope().getExportedConversion(type, target);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Function getMethodForType(Type type, String methodName) {
|
||||
if (isValidType(type)) {
|
||||
return module.getScope().getMethodForType(type, methodName);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Function getConversionForType(Type target, Type type) {
|
||||
if (isValidType(target)) {
|
||||
var result = module.getScope().getConversionsFor(target);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return result.get(type);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,12 @@
|
||||
package org.enso.interpreter.runtime.scope;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import org.enso.compiler.context.CompilerContext;
|
||||
import org.enso.interpreter.runtime.Module;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.EnsoObject;
|
||||
@ -27,12 +21,12 @@ import org.enso.interpreter.runtime.util.CachingSupplier;
|
||||
public final class ModuleScope implements EnsoObject {
|
||||
private final Type associatedType;
|
||||
private final Module module;
|
||||
private Map<String, Object> polyglotSymbols;
|
||||
private Map<String, Type> types;
|
||||
private Map<Type, Map<String, Supplier<Function>>> methods;
|
||||
private Map<Type, Map<Type, Function>> conversions;
|
||||
private Set<ModuleScope> imports;
|
||||
private Set<ModuleScope> exports;
|
||||
private final Map<String, Object> polyglotSymbols;
|
||||
private final Map<String, Type> types;
|
||||
private final Map<Type, Map<String, Supplier<Function>>> methods;
|
||||
private final Map<Type, Map<Type, Function>> conversions;
|
||||
private final Set<ImportExportScope> imports;
|
||||
private final Set<ImportExportScope> exports;
|
||||
|
||||
private static final Type noTypeKey;
|
||||
|
||||
@ -40,22 +34,6 @@ public final class ModuleScope implements EnsoObject {
|
||||
noTypeKey = Type.noType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object of this class.
|
||||
*
|
||||
* @param module the module related to the newly created scope.
|
||||
*/
|
||||
public ModuleScope(Module module) {
|
||||
this.polyglotSymbols = new LinkedHashMap<>();
|
||||
this.types = new LinkedHashMap<>();
|
||||
this.methods = new LinkedHashMap<>();
|
||||
this.conversions = new LinkedHashMap<>();
|
||||
this.imports = new LinkedHashSet<>();
|
||||
this.exports = new LinkedHashSet<>();
|
||||
this.module = module;
|
||||
this.associatedType = Type.createSingleton(module.getName().item(), this, null, false, false);
|
||||
}
|
||||
|
||||
public ModuleScope(
|
||||
Module module,
|
||||
Type associatedType,
|
||||
@ -63,8 +41,8 @@ public final class ModuleScope implements EnsoObject {
|
||||
Map<String, Type> types,
|
||||
Map<Type, Map<String, Supplier<Function>>> methods,
|
||||
Map<Type, Map<Type, Function>> conversions,
|
||||
Set<ModuleScope> imports,
|
||||
Set<ModuleScope> exports) {
|
||||
Set<ImportExportScope> imports,
|
||||
Set<ImportExportScope> exports) {
|
||||
this.module = module;
|
||||
this.associatedType = associatedType;
|
||||
this.polyglotSymbols = polyglotSymbols;
|
||||
@ -75,11 +53,6 @@ public final class ModuleScope implements EnsoObject {
|
||||
this.exports = exports;
|
||||
}
|
||||
|
||||
public Type registerType(Type type) {
|
||||
Type current = types.putIfAbsent(type.getName(), type);
|
||||
return current == null ? type : current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the associated type of this module.
|
||||
*/
|
||||
@ -94,115 +67,6 @@ public final class ModuleScope implements EnsoObject {
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the set of modules imported by this module.
|
||||
*/
|
||||
public Set<ModuleScope> getImports() {
|
||||
return imports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of methods defined in this module for a given type.
|
||||
*
|
||||
* @param type the type for which method map is requested
|
||||
* @return a map containing all the defined methods by name
|
||||
*/
|
||||
private Map<String, Supplier<Function>> ensureMethodMapFor(Type type) {
|
||||
Type tpeKey = type == null ? noTypeKey : type;
|
||||
return methods.computeIfAbsent(tpeKey, k -> new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
private Map<String, Supplier<Function>> getMethodMapFor(Type type) {
|
||||
Type tpeKey = type == null ? noTypeKey : type;
|
||||
Map<String, Supplier<Function>> result = methods.get(tpeKey);
|
||||
if (result == null) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a method defined for a given type.
|
||||
*
|
||||
* @param type the type the method was defined for
|
||||
* @param method method name
|
||||
* @param function the {@link Function} associated with this definition
|
||||
*/
|
||||
public void registerMethod(Type type, String method, Function function) {
|
||||
Map<String, Supplier<Function>> methodMap = ensureMethodMapFor(type);
|
||||
|
||||
// Builtin types will have double definition because of
|
||||
// BuiltinMethod and that's OK
|
||||
if (methodMap.containsKey(method) && !type.isBuiltin()) {
|
||||
throw new RedefinedMethodException(type.getName(), method);
|
||||
} else {
|
||||
methodMap.put(method, new CachingSupplier<>(function));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a lazily constructed method defined for a given type.
|
||||
*
|
||||
* @param type the type the method was defined for
|
||||
* @param method method name
|
||||
* @param supply provider of the {@link Function} associated with this definition
|
||||
*/
|
||||
public void registerMethod(Type type, String method, Supplier<Function> supply) {
|
||||
Map<String, Supplier<Function>> methodMap = ensureMethodMapFor(type);
|
||||
|
||||
// Builtin types will have double definition because of
|
||||
// BuiltinMethod and that's OK
|
||||
if (methodMap.containsKey(method) && !type.isBuiltin()) {
|
||||
throw new RedefinedMethodException(type.getName(), method);
|
||||
} else {
|
||||
methodMap.put(method, new CachingSupplier<>(supply));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the conversion methods defined in this module for a given constructor.
|
||||
*
|
||||
* @param type the type for which method map is requested
|
||||
* @return a list containing all the defined conversions in definition order
|
||||
*/
|
||||
private Map<Type, Function> ensureConversionsFor(Type type) {
|
||||
return conversions.computeIfAbsent(type, k -> new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
private Map<Type, Function> getConversionsFor(Type type) {
|
||||
var result = conversions.get(type);
|
||||
if (result == null) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a conversion method for a given type
|
||||
*
|
||||
* @param toType type the conversion was defined to
|
||||
* @param fromType type the conversion was defined from
|
||||
* @param function the {@link Function} associated with this definition
|
||||
*/
|
||||
public void registerConversionMethod(Type toType, Type fromType, Function function) {
|
||||
var sourceMap = ensureConversionsFor(toType);
|
||||
if (sourceMap.containsKey(fromType)) {
|
||||
throw new RedefinedConversionException(toType.getName(), fromType.getName());
|
||||
} else {
|
||||
sourceMap.put(fromType, function);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new symbol in the polyglot namespace.
|
||||
*
|
||||
* @param name the name of the symbol
|
||||
* @param sym the value being exposed
|
||||
*/
|
||||
public void registerPolyglotSymbol(String name, Object sym) {
|
||||
polyglotSymbols.put(name, sym);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the definition for a given type and method name.
|
||||
*
|
||||
@ -214,16 +78,16 @@ public final class ModuleScope implements EnsoObject {
|
||||
* @param name the method name.
|
||||
* @return the matching method definition or null if not found.
|
||||
*/
|
||||
@TruffleBoundary
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public Function lookupMethodDefinition(Type type, String name) {
|
||||
var definedWithAtom = type.getDefinitionScope().getMethodMapFor(type).get(name);
|
||||
var definedWithAtom = type.getDefinitionScope().getMethodForType(type, name);
|
||||
if (definedWithAtom != null) {
|
||||
return definedWithAtom.get();
|
||||
return definedWithAtom;
|
||||
}
|
||||
|
||||
var definedHere = getMethodMapFor(type).get(name);
|
||||
var definedHere = getMethodForType(type, name);
|
||||
if (definedHere != null) {
|
||||
return definedHere.get();
|
||||
return definedHere;
|
||||
}
|
||||
|
||||
return imports.stream()
|
||||
@ -233,7 +97,7 @@ public final class ModuleScope implements EnsoObject {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public Function lookupConversionDefinition(Type original, Type target) {
|
||||
Function definedWithOriginal =
|
||||
original.getDefinitionScope().getConversionsFor(target).get(original);
|
||||
@ -256,59 +120,49 @@ public final class ModuleScope implements EnsoObject {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private Function getExportedMethod(Type type, String name) {
|
||||
var here = getMethodMapFor(type).get(name);
|
||||
Function getExportedMethod(Type type, String name) {
|
||||
var here = getMethodForType(type, name);
|
||||
if (here != null) {
|
||||
return here.get();
|
||||
return here;
|
||||
}
|
||||
return exports.stream()
|
||||
.map(scope -> scope.getMethodMapFor(type).get(name))
|
||||
.map(scope -> scope.getMethodForType(type, name))
|
||||
.filter(Objects::nonNull)
|
||||
.map(s -> s.get())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private Function getExportedConversion(Type type, Type target) {
|
||||
Function getExportedConversion(Type type, Type target) {
|
||||
Function here = getConversionsFor(target).get(type);
|
||||
if (here != null) {
|
||||
return here;
|
||||
}
|
||||
return exports.stream()
|
||||
.map(scope -> scope.getConversionsFor(target).get(type))
|
||||
.map(scope -> scope.getConversionForType(target, type))
|
||||
.filter(Objects::nonNull)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a dependency for this module.
|
||||
*
|
||||
* @param scope the scope of the newly added dependency
|
||||
*/
|
||||
public void addImport(ModuleScope scope) {
|
||||
imports.add(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an information about the module exporting another module.
|
||||
*
|
||||
* @param scope the exported scope
|
||||
*/
|
||||
public void addExport(ModuleScope scope) {
|
||||
exports.add(scope);
|
||||
}
|
||||
|
||||
public Map<String, Type> getTypes() {
|
||||
return types;
|
||||
public List<Type> getAllTypes(String name) {
|
||||
var tpes = new ArrayList<Type>(types.size() + 1);
|
||||
var tpe0 = getType(name, false);
|
||||
if (tpe0 != null) tpes.add(tpe0);
|
||||
tpes.addAll(types.values());
|
||||
return tpes;
|
||||
}
|
||||
|
||||
@ExportMessage.Ignore
|
||||
public Optional<Type> getType(String name) {
|
||||
if (associatedType.getName().equals(name)) {
|
||||
return Optional.of(associatedType);
|
||||
public Type getType(String name, boolean ignoreAssociatedType) {
|
||||
if (!ignoreAssociatedType && associatedType.getName().equals(name)) {
|
||||
return associatedType;
|
||||
}
|
||||
return Optional.ofNullable(types.get(name));
|
||||
return types.get(name);
|
||||
}
|
||||
|
||||
@ExportMessage.Ignore
|
||||
public boolean hasType(Type type) {
|
||||
return types.get(type.getName()) == type;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,18 +206,12 @@ public final class ModuleScope implements EnsoObject {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all methods of a type in the provided scope.
|
||||
*
|
||||
* @param tpe the methods of which type should be registered
|
||||
* @param scope target scope where methods should be registered to
|
||||
*/
|
||||
public void registerAllMethodsOfTypeToScope(Type tpe, ModuleScope scope) {
|
||||
Type tpeKey = tpe == null ? noTypeKey : tpe;
|
||||
var allTypeMethods = methods.get(tpeKey);
|
||||
if (allTypeMethods != null) {
|
||||
allTypeMethods.forEach((name, fun) -> scope.registerMethod(tpeKey, name, fun));
|
||||
Map<Type, Function> getConversionsFor(Type type) {
|
||||
var result = conversions.get(type);
|
||||
if (result == null) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -392,60 +240,6 @@ public final class ModuleScope implements EnsoObject {
|
||||
return polyglotSymbols.get(symbolName);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
imports = new LinkedHashSet<>();
|
||||
exports = new LinkedHashSet<>();
|
||||
methods = new LinkedHashMap<>();
|
||||
conversions = new LinkedHashMap<>();
|
||||
polyglotSymbols = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this `ModuleScope` while taking into account only the provided list of types.
|
||||
*
|
||||
* @param typeNames list of types to copy to the new scope
|
||||
* @return a copy of this scope modulo the requested types
|
||||
*/
|
||||
public ModuleScope withTypes(List<String> typeNames) {
|
||||
Map<String, Object> polyglotSymbols = new LinkedHashMap<>(this.polyglotSymbols);
|
||||
Map<String, Type> requestedTypes = new LinkedHashMap<>(this.types);
|
||||
Map<Type, Map<String, Supplier<Function>>> methods = new LinkedHashMap<>();
|
||||
Map<Type, Map<Type, Function>> conversions = new LinkedHashMap<>();
|
||||
Set<ModuleScope> imports = new LinkedHashSet<>(this.imports);
|
||||
Set<ModuleScope> exports = new LinkedHashSet<>(this.exports);
|
||||
this.types
|
||||
.entrySet()
|
||||
.forEach(
|
||||
entry -> {
|
||||
if (typeNames.contains(entry.getKey())) {
|
||||
requestedTypes.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
});
|
||||
Collection<Type> validTypes = requestedTypes.values();
|
||||
this.methods.forEach(
|
||||
(tpe, meths) -> {
|
||||
if (validTypes.contains(tpe)) {
|
||||
methods.put(tpe, meths);
|
||||
}
|
||||
});
|
||||
this.conversions.forEach(
|
||||
(tpe, meths) -> {
|
||||
if (validTypes.contains(tpe)) {
|
||||
conversions.put(tpe, meths);
|
||||
}
|
||||
});
|
||||
|
||||
return new ModuleScope(
|
||||
module,
|
||||
associatedType,
|
||||
polyglotSymbols,
|
||||
requestedTypes,
|
||||
methods,
|
||||
conversions,
|
||||
imports,
|
||||
exports);
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean hasType() {
|
||||
return true;
|
||||
@ -460,4 +254,258 @@ public final class ModuleScope implements EnsoObject {
|
||||
public String toString() {
|
||||
return "Scope" + module;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
@CompilerDirectives.CompilationFinal private ModuleScope moduleScope = null;
|
||||
private final Module module;
|
||||
private final Type associatedType;
|
||||
private final Map<String, Object> polyglotSymbols;
|
||||
private final Map<String, Type> types;
|
||||
private final Map<Type, Map<String, Supplier<Function>>> methods;
|
||||
private final Map<Type, Map<Type, Function>> conversions;
|
||||
private final Set<ImportExportScope> imports;
|
||||
private final Set<ImportExportScope> exports;
|
||||
|
||||
public Builder(Module module) {
|
||||
this.module = module;
|
||||
this.polyglotSymbols = new LinkedHashMap<>();
|
||||
this.types = new LinkedHashMap<>();
|
||||
this.methods = new LinkedHashMap<>();
|
||||
this.conversions = new LinkedHashMap<>();
|
||||
this.imports = new LinkedHashSet<>();
|
||||
this.exports = new LinkedHashSet<>();
|
||||
this.associatedType = Type.createSingleton(module.getName().item(), this, null, false, false);
|
||||
}
|
||||
|
||||
public Builder(Module module, Map<String, Type> types) {
|
||||
this.module = module;
|
||||
this.polyglotSymbols = new LinkedHashMap<>();
|
||||
this.types = types;
|
||||
this.methods = new LinkedHashMap<>();
|
||||
this.conversions = new LinkedHashMap<>();
|
||||
this.imports = new LinkedHashSet<>();
|
||||
this.exports = new LinkedHashSet<>();
|
||||
this.associatedType = Type.createSingleton(module.getName().item(), this, null, false, false);
|
||||
}
|
||||
|
||||
public Builder(
|
||||
Module module,
|
||||
Type associatedType,
|
||||
Map<String, Object> polyglotSymbols,
|
||||
Map<String, Type> types,
|
||||
Map<Type, Map<String, Supplier<Function>>> methods,
|
||||
Map<Type, Map<Type, Function>> conversions,
|
||||
Set<ImportExportScope> imports,
|
||||
Set<ImportExportScope> exports) {
|
||||
this.module = module;
|
||||
this.associatedType = associatedType;
|
||||
this.polyglotSymbols = polyglotSymbols;
|
||||
this.types = types;
|
||||
this.methods = methods;
|
||||
this.conversions = conversions;
|
||||
this.imports = imports;
|
||||
this.exports = exports;
|
||||
}
|
||||
|
||||
public Type registerType(Type type) {
|
||||
assert moduleScope == null;
|
||||
Type current = types.putIfAbsent(type.getName(), type);
|
||||
return current == null ? type : current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of methods defined in this module for a given type.
|
||||
*
|
||||
* @param type the type for which method map is requested
|
||||
* @return a map containing all the defined methods by name
|
||||
*/
|
||||
private Map<String, Supplier<Function>> ensureMethodMapFor(Type type) {
|
||||
Type tpeKey = type == null ? noTypeKey : type;
|
||||
return methods.computeIfAbsent(tpeKey, k -> new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a method defined for a given type.
|
||||
*
|
||||
* @param type the type the method was defined for
|
||||
* @param method method name
|
||||
* @param function the {@link Function} associated with this definition
|
||||
*/
|
||||
public void registerMethod(Type type, String method, Function function) {
|
||||
assert moduleScope == null;
|
||||
Map<String, Supplier<Function>> methodMap = ensureMethodMapFor(type);
|
||||
|
||||
// Builtin types will have double definition because of
|
||||
// BuiltinMethod and that's OK
|
||||
if (methodMap.containsKey(method) && !type.isBuiltin()) {
|
||||
throw new RedefinedMethodException(type.getName(), method);
|
||||
} else {
|
||||
methodMap.put(method, new CachingSupplier<>(function));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a lazily constructed method defined for a given type.
|
||||
*
|
||||
* @param type the type the method was defined for
|
||||
* @param method method name
|
||||
* @param supply provider of the {@link Function} associated with this definition
|
||||
*/
|
||||
public void registerMethod(Type type, String method, Supplier<Function> supply) {
|
||||
assert moduleScope == null;
|
||||
Map<String, Supplier<Function>> methodMap = ensureMethodMapFor(type);
|
||||
|
||||
// Builtin types will have double definition because of
|
||||
// BuiltinMethod and that's OK
|
||||
if (methodMap.containsKey(method) && !type.isBuiltin()) {
|
||||
throw new RedefinedMethodException(type.getName(), method);
|
||||
} else {
|
||||
methodMap.put(method, new CachingSupplier<>(supply));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a conversion method for a given type
|
||||
*
|
||||
* @param toType type the conversion was defined to
|
||||
* @param fromType type the conversion was defined from
|
||||
* @param function the {@link Function} associated with this definition
|
||||
*/
|
||||
public void registerConversionMethod(Type toType, Type fromType, Function function) {
|
||||
assert moduleScope == null;
|
||||
var sourceMap = conversions.computeIfAbsent(toType, k -> new LinkedHashMap<>());
|
||||
if (sourceMap.containsKey(fromType)) {
|
||||
throw new RedefinedConversionException(toType.getName(), fromType.getName());
|
||||
} else {
|
||||
sourceMap.put(fromType, function);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new symbol in the polyglot namespace.
|
||||
*
|
||||
* @param name the name of the symbol
|
||||
* @param sym the value being exposed
|
||||
*/
|
||||
public void registerPolyglotSymbol(String name, Object sym) {
|
||||
assert moduleScope == null;
|
||||
polyglotSymbols.put(name, sym);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all methods of a type in the provided scope.
|
||||
*
|
||||
* @param tpe the methods of which type should be registered
|
||||
* @param scope target scope where methods should be registered to
|
||||
*/
|
||||
public void registerAllMethodsOfTypeToScope(Type tpe, ModuleScope.Builder scope) {
|
||||
// FIXME: because of Builtins can't enable 'assert moduleScope == null;'
|
||||
Type tpeKey = tpe == null ? noTypeKey : tpe;
|
||||
var allTypeMethods = methods.get(tpeKey);
|
||||
if (allTypeMethods != null) {
|
||||
allTypeMethods.forEach((name, fun) -> scope.registerMethod(tpeKey, name, fun));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a dependency for this module.
|
||||
*
|
||||
* @param scope the scope of the newly added dependency
|
||||
*/
|
||||
public void addImport(ImportExportScope scope) {
|
||||
assert moduleScope == null;
|
||||
imports.add(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an information about the module exporting another module.
|
||||
*
|
||||
* @param scope the exported scope
|
||||
*/
|
||||
public void addExport(ImportExportScope scope) {
|
||||
assert moduleScope == null;
|
||||
exports.add(scope);
|
||||
}
|
||||
|
||||
public Module getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ModuleScope.Builder which inherits from `this` `module` and `types` that need to
|
||||
* survive the compilation.
|
||||
*
|
||||
* @return new ModuleScope.Builder
|
||||
*/
|
||||
public Builder newBuilderInheritingTypes() {
|
||||
return new Builder(this.module, new LinkedHashMap<>(this.types));
|
||||
}
|
||||
|
||||
/**
|
||||
* Materializes the builder and ensures that no further modifications to ModuleScope are
|
||||
* possible. Action is idempotent.
|
||||
*
|
||||
* @return an immutable ModuleScope
|
||||
*/
|
||||
public ModuleScope build() {
|
||||
if (moduleScope == null) {
|
||||
moduleScope =
|
||||
new ModuleScope(
|
||||
module,
|
||||
associatedType,
|
||||
Collections.unmodifiableMap(polyglotSymbols),
|
||||
Collections.unmodifiableMap(types),
|
||||
Collections.unmodifiableMap(methods),
|
||||
Collections.unmodifiableMap(conversions),
|
||||
Collections.unmodifiableSet(imports),
|
||||
Collections.unmodifiableSet(exports));
|
||||
}
|
||||
return moduleScope;
|
||||
}
|
||||
|
||||
public static ModuleScope.Builder fromCompilerModuleScopeBuilder(
|
||||
CompilerContext.ModuleScopeBuilder scopeBuilder) {
|
||||
return ((TruffleCompilerModuleScopeBuilder) scopeBuilder).unsafeScopeBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view on `this` as a ModuleScope, rather than its builder.
|
||||
*
|
||||
* @return ModuleScope, if the builder has already been `built`, a proxy instance with the
|
||||
* currently registered entities
|
||||
*/
|
||||
public ModuleScope asModuleScope() {
|
||||
if (moduleScope != null) return moduleScope;
|
||||
else
|
||||
return new ModuleScope(
|
||||
module,
|
||||
associatedType,
|
||||
Collections.unmodifiableMap(polyglotSymbols),
|
||||
Collections.unmodifiableMap(types),
|
||||
Collections.unmodifiableMap(methods),
|
||||
Collections.unmodifiableMap(conversions),
|
||||
Collections.unmodifiableSet(imports),
|
||||
Collections.unmodifiableSet(exports));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.lang.String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("ModuleScope builder for " + module.getName());
|
||||
builder.append(",\n");
|
||||
builder.append("Polyglot Symbols: " + polyglotSymbols);
|
||||
builder.append(",\n");
|
||||
builder.append("Methods: " + methods);
|
||||
builder.append(",\n");
|
||||
builder.append("Conversions: " + conversions);
|
||||
builder.append(",\n");
|
||||
builder.append("Imports: " + imports);
|
||||
builder.append(",\n");
|
||||
builder.append("Exports: " + exports);
|
||||
builder.append(",\n");
|
||||
builder.append("Types: " + types);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.enso.interpreter.runtime.scope;
|
||||
|
||||
import org.enso.compiler.context.CompilerContext;
|
||||
|
||||
public final class TruffleCompilerModuleScopeBuilder extends CompilerContext.ModuleScopeBuilder {
|
||||
private final org.enso.interpreter.runtime.scope.ModuleScope.Builder scopeBuilder;
|
||||
|
||||
public TruffleCompilerModuleScopeBuilder(
|
||||
org.enso.interpreter.runtime.scope.ModuleScope.Builder scopeBuilder) {
|
||||
this.scopeBuilder = scopeBuilder;
|
||||
}
|
||||
|
||||
public org.enso.interpreter.runtime.scope.ModuleScope.Builder unsafeScopeBuilder() {
|
||||
return scopeBuilder;
|
||||
}
|
||||
}
|
@ -106,7 +106,7 @@ import org.enso.interpreter.runtime.callable.{
|
||||
}
|
||||
import org.enso.interpreter.runtime.data.Type
|
||||
import org.enso.interpreter.runtime.data.text.Text
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope
|
||||
import org.enso.interpreter.runtime.scope.{ImportExportScope, ModuleScope}
|
||||
import org.enso.interpreter.{Constants, EnsoLanguage}
|
||||
|
||||
import java.math.BigInteger
|
||||
@ -126,13 +126,13 @@ import org.enso.interpreter.runtime.error.DataflowError
|
||||
* @param context the language context instance for which this is executing
|
||||
* @param source the source code that corresponds to the text for which code
|
||||
* is being generated
|
||||
* @param moduleScope the scope of the module for which code is being generated
|
||||
* @param scopeBuilder the scope's builder of the module for which code is being generated
|
||||
* @param compilerConfig the configuration for the compiler
|
||||
*/
|
||||
class IrToTruffle(
|
||||
val context: EnsoContext,
|
||||
val source: Source,
|
||||
val moduleScope: ModuleScope,
|
||||
val scopeBuilder: ModuleScope.Builder,
|
||||
val compilerConfig: CompilerConfig
|
||||
) {
|
||||
|
||||
@ -171,7 +171,7 @@ class IrToTruffle(
|
||||
new ExpressionProcessor(
|
||||
localScope,
|
||||
scopeName,
|
||||
moduleScope.getModule().getName().toString()
|
||||
scopeBuilder.getModule().getName().toString()
|
||||
).runInline(ir)
|
||||
}
|
||||
|
||||
@ -197,17 +197,10 @@ class IrToTruffle(
|
||||
)
|
||||
|
||||
bindingsMap.resolvedExports
|
||||
.collect { case ExportedModule(ResolvedModule(module), _, _) =>
|
||||
module
|
||||
}
|
||||
.foreach { exp =>
|
||||
moduleScope.addExport(
|
||||
asScope(
|
||||
exp
|
||||
.unsafeAsModule()
|
||||
)
|
||||
)
|
||||
}
|
||||
.collect { case ExportedModule(ResolvedModule(module), _, _) => module }
|
||||
.foreach(exp =>
|
||||
scopeBuilder.addExport(new ImportExportScope(exp.unsafeAsModule()))
|
||||
)
|
||||
val importDefs = module.imports
|
||||
val methodDefs = module.bindings.collect {
|
||||
case method: definition.Method.Explicit => method
|
||||
@ -219,17 +212,10 @@ class IrToTruffle(
|
||||
case ResolvedModule(module) =>
|
||||
val mod = module
|
||||
.unsafeAsModule()
|
||||
val scope: ModuleScope = imp.importDef.onlyNames
|
||||
.map(only => {
|
||||
val requestedTypes = only.map(_.name).asJava
|
||||
if (requestedTypes.isEmpty()) {
|
||||
asScope(mod)
|
||||
} else {
|
||||
asScope(mod).withTypes(requestedTypes)
|
||||
}
|
||||
})
|
||||
.getOrElse(asScope(mod))
|
||||
moduleScope.addImport(scope)
|
||||
val scope: ImportExportScope = imp.importDef.onlyNames
|
||||
.map(only => new ImportExportScope(mod, only.map(_.name).asJava))
|
||||
.getOrElse(new ImportExportScope(mod))
|
||||
scopeBuilder.addImport(scope)
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +229,7 @@ class IrToTruffle(
|
||||
)
|
||||
hostSymbol = DataflowError.withoutTrace(err, null)
|
||||
}
|
||||
this.moduleScope.registerPolyglotSymbol(
|
||||
this.scopeBuilder.registerPolyglotSymbol(
|
||||
poly.getVisibleName,
|
||||
hostSymbol
|
||||
)
|
||||
@ -255,7 +241,7 @@ class IrToTruffle(
|
||||
typeDefs.foreach { tpDef =>
|
||||
// Register the atoms and their constructors in scope
|
||||
val atomDefs = tpDef.members
|
||||
val asType = moduleScope.getTypes.get(tpDef.name.name)
|
||||
val asType = scopeBuilder.asModuleScope().getType(tpDef.name.name, true)
|
||||
val atomConstructors =
|
||||
atomDefs.map(cons => asType.getConstructors.get(cons.name.name))
|
||||
atomConstructors
|
||||
@ -336,9 +322,9 @@ class IrToTruffle(
|
||||
val closureRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
expressionProcessor.scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
expressionNode,
|
||||
makeSection(moduleScope, annotation.location),
|
||||
makeSection(scopeBuilder.getModule, annotation.location),
|
||||
closureName,
|
||||
true,
|
||||
false
|
||||
@ -348,8 +334,9 @@ class IrToTruffle(
|
||||
if (!atomCons.isInitialized) {
|
||||
atomCons.initializeFields(
|
||||
language,
|
||||
makeSection(moduleScope, atomDefn.location),
|
||||
makeSection(scopeBuilder.getModule, atomDefn.location),
|
||||
localScope,
|
||||
scopeBuilder,
|
||||
assignments.toArray,
|
||||
reads.toArray,
|
||||
annotations.toArray,
|
||||
@ -392,23 +379,16 @@ class IrToTruffle(
|
||||
val declaredConsOpt =
|
||||
methodDef.methodReference.typePointer match {
|
||||
case None =>
|
||||
Some(moduleScope.getAssociatedType)
|
||||
Some(scopeAssociatedType)
|
||||
case Some(tpePointer) =>
|
||||
tpePointer
|
||||
.getMetadata(MethodDefinitions)
|
||||
.map { res =>
|
||||
res.target match {
|
||||
case BindingsMap.ResolvedType(module, tp) =>
|
||||
asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getTypes
|
||||
.get(tp.name)
|
||||
case binding @ BindingsMap.ResolvedType(_, _) =>
|
||||
asType(binding)
|
||||
case BindingsMap.ResolvedModule(module) =>
|
||||
asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getAssociatedType
|
||||
asAssociatedType(module.unsafeAsModule())
|
||||
case BindingsMap.ResolvedConstructor(_, _) =>
|
||||
throw new CompilerError(
|
||||
"Impossible, should be caught by MethodDefinitions pass"
|
||||
@ -446,7 +426,7 @@ class IrToTruffle(
|
||||
fullMethodDefName
|
||||
)
|
||||
|
||||
moduleScope.registerMethod(
|
||||
scopeBuilder.registerMethod(
|
||||
cons,
|
||||
methodDef.methodName.name,
|
||||
() => {
|
||||
@ -528,7 +508,7 @@ class IrToTruffle(
|
||||
m.getFunction.getCallTarget.getRootNode
|
||||
.asInstanceOf[BuiltinRootNode]
|
||||
builtinRootNode
|
||||
.setModuleName(moduleScope.getModule.getName)
|
||||
.setModuleName(scopeBuilder.getModule.getName)
|
||||
builtinRootNode.setTypeName(cons.getQualifiedName)
|
||||
val funcSchemaBldr = FunctionSchema
|
||||
.newBuilder()
|
||||
@ -570,11 +550,11 @@ class IrToTruffle(
|
||||
MethodRootNode.buildOperator(
|
||||
language,
|
||||
expressionProcessor.scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
() => bodyBuilder.argsExpr._1(0),
|
||||
() => bodyBuilder.argsExpr._1(1),
|
||||
() => bodyBuilder.argsExpr._2,
|
||||
makeSection(moduleScope, methodDef.location),
|
||||
makeSection(scopeBuilder.getModule, methodDef.location),
|
||||
cons,
|
||||
methodDef.methodName.name
|
||||
)
|
||||
@ -582,9 +562,9 @@ class IrToTruffle(
|
||||
MethodRootNode.build(
|
||||
language,
|
||||
expressionProcessor.scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
() => bodyBuilder.bodyNode(),
|
||||
makeSection(moduleScope, methodDef.location),
|
||||
makeSection(scopeBuilder.getModule, methodDef.location),
|
||||
cons,
|
||||
methodDef.methodName.name
|
||||
)
|
||||
@ -633,9 +613,12 @@ class IrToTruffle(
|
||||
val closureRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
expressionProcessor.scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
expressionNode,
|
||||
makeSection(moduleScope, annotation.location),
|
||||
makeSection(
|
||||
scopeBuilder.getModule,
|
||||
annotation.location
|
||||
),
|
||||
closureName,
|
||||
true,
|
||||
false
|
||||
@ -707,7 +690,7 @@ class IrToTruffle(
|
||||
case Some(tpePointer) =>
|
||||
getTypeResolution(tpePointer)
|
||||
case None =>
|
||||
Some(moduleScope.getAssociatedType)
|
||||
Some(scopeAssociatedType)
|
||||
}
|
||||
val fromOpt = getTypeResolution(methodDef.sourceTypeName)
|
||||
toOpt.zip(fromOpt).foreach { case (toType, fromType) =>
|
||||
@ -732,9 +715,9 @@ class IrToTruffle(
|
||||
val rootNode = MethodRootNode.build(
|
||||
language,
|
||||
expressionProcessor.scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
() => bodyBuilder.bodyNode(),
|
||||
makeSection(moduleScope, methodDef.location),
|
||||
makeSection(scopeBuilder.getModule, methodDef.location),
|
||||
toType,
|
||||
methodDef.methodName.name
|
||||
)
|
||||
@ -754,9 +737,10 @@ class IrToTruffle(
|
||||
"Conversion bodies must be functions at the point of codegen."
|
||||
)
|
||||
}
|
||||
moduleScope.registerConversionMethod(toType, fromType, function)
|
||||
scopeBuilder.registerConversionMethod(toType, fromType, function)
|
||||
}
|
||||
})
|
||||
scopeBuilder.build()
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
@ -788,16 +772,11 @@ class IrToTruffle(
|
||||
t.getMetadata(TypeNames) match {
|
||||
case Some(
|
||||
BindingsMap
|
||||
.Resolution(BindingsMap.ResolvedType(mod, tpe))
|
||||
.Resolution(binding @ BindingsMap.ResolvedType(_, _))
|
||||
) =>
|
||||
ReadArgumentCheckNode.build(
|
||||
comment,
|
||||
asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
.asInstanceOf[TruffleCompilerContext.Module]
|
||||
).getTypes
|
||||
.get(tpe.name)
|
||||
asType(binding)
|
||||
)
|
||||
case Some(
|
||||
BindingsMap
|
||||
@ -806,9 +785,7 @@ class IrToTruffle(
|
||||
ReadArgumentCheckNode.meta(
|
||||
comment,
|
||||
asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
.asInstanceOf[TruffleCompilerContext.Module]
|
||||
mod.unsafeAsModule().asInstanceOf[TruffleCompilerContext.Module]
|
||||
).getPolyglotSymbol(symbol.name)
|
||||
)
|
||||
case _ => null
|
||||
@ -843,14 +820,14 @@ class IrToTruffle(
|
||||
* @return the source section corresponding to `location`
|
||||
*/
|
||||
private def makeSection(
|
||||
module: ModuleScope,
|
||||
module: org.enso.interpreter.runtime.Module,
|
||||
location: Option[IdentifiedLocation]
|
||||
): SourceSection = {
|
||||
location
|
||||
.map(loc => {
|
||||
val m = module.getModule()
|
||||
val m = module
|
||||
if (m.isModuleSource(source)) {
|
||||
module.getModule().createSection(loc.start, loc.length)
|
||||
module.createSection(loc.start, loc.length)
|
||||
} else {
|
||||
source.createSection(loc.start, loc.length)
|
||||
}
|
||||
@ -861,17 +838,10 @@ class IrToTruffle(
|
||||
private def getTypeResolution(expr: IR): Option[Type] =
|
||||
expr.getMetadata(MethodDefinitions).map { res =>
|
||||
res.target match {
|
||||
case BindingsMap.ResolvedType(definitionModule, tp) =>
|
||||
asScope(
|
||||
definitionModule
|
||||
.unsafeAsModule()
|
||||
).getTypes
|
||||
.get(tp.name)
|
||||
case binding @ BindingsMap.ResolvedType(_, _) =>
|
||||
asType(binding)
|
||||
case BindingsMap.ResolvedModule(module) =>
|
||||
asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getAssociatedType
|
||||
asAssociatedType(module.unsafeAsModule())
|
||||
case BindingsMap.ResolvedConstructor(_, _) =>
|
||||
throw new CompilerError(
|
||||
"Impossible here, should be caught by MethodDefinitions pass."
|
||||
@ -960,55 +930,51 @@ class IrToTruffle(
|
||||
if (
|
||||
resolution.isInstanceOf[ResolvedConstructor] || !resolution.module
|
||||
.unsafeAsModule()
|
||||
.equals(moduleScope.getModule.asCompilerModule)
|
||||
.equals(scopeBuilder.getModule.asCompilerModule)
|
||||
) {
|
||||
resolution match {
|
||||
case BindingsMap.ResolvedType(module, tp) =>
|
||||
case binding @ BindingsMap.ResolvedType(_, _) =>
|
||||
val runtimeTp =
|
||||
asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getTypes
|
||||
.get(tp.name)
|
||||
asType(binding)
|
||||
val fun = mkTypeGetter(runtimeTp)
|
||||
moduleScope.registerMethod(
|
||||
moduleScope.getAssociatedType,
|
||||
scopeBuilder.registerMethod(
|
||||
scopeAssociatedType,
|
||||
name,
|
||||
fun
|
||||
)
|
||||
case BindingsMap.ResolvedConstructor(definitionType, cons) =>
|
||||
val runtimeCons = asType(definitionType).getConstructors
|
||||
.get(cons.name)
|
||||
val tpe = asType(definitionType)
|
||||
val runtimeCons =
|
||||
tpe.getConstructors
|
||||
.get(cons.name)
|
||||
val fun = mkConsGetter(runtimeCons)
|
||||
moduleScope.registerMethod(
|
||||
moduleScope.getAssociatedType,
|
||||
scopeBuilder.registerMethod(
|
||||
scopeAssociatedType,
|
||||
name,
|
||||
fun
|
||||
)
|
||||
case BindingsMap.ResolvedModule(module) =>
|
||||
val runtimeCons =
|
||||
asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getAssociatedType
|
||||
asAssociatedType(module.unsafeAsModule())
|
||||
val fun = mkTypeGetter(runtimeCons)
|
||||
moduleScope.registerMethod(
|
||||
moduleScope.getAssociatedType,
|
||||
scopeBuilder.registerMethod(
|
||||
scopeAssociatedType,
|
||||
name,
|
||||
fun
|
||||
)
|
||||
case BindingsMap.ResolvedMethod(module, method) =>
|
||||
val actualModule = module.unsafeAsModule()
|
||||
val fun = asScope(actualModule).getMethodForType(
|
||||
asScope(actualModule).getAssociatedType,
|
||||
method.name
|
||||
)
|
||||
val fun = asScope(actualModule)
|
||||
.getMethodForType(
|
||||
asAssociatedType(actualModule),
|
||||
method.name
|
||||
)
|
||||
assert(
|
||||
fun != null,
|
||||
s"exported symbol `${method.name}` needs to be registered first in the module "
|
||||
)
|
||||
moduleScope.registerMethod(
|
||||
moduleScope.getAssociatedType,
|
||||
scopeBuilder.registerMethod(
|
||||
scopeAssociatedType,
|
||||
name,
|
||||
fun
|
||||
)
|
||||
@ -1175,9 +1141,9 @@ class IrToTruffle(
|
||||
val defaultRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
childScope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
blockNode,
|
||||
makeSection(moduleScope, block.location),
|
||||
makeSection(scopeBuilder.getModule, block.location),
|
||||
currentVarName,
|
||||
false,
|
||||
false
|
||||
@ -1328,10 +1294,7 @@ class IrToTruffle(
|
||||
Right(
|
||||
ObjectEqualityBranchNode.build(
|
||||
branchCodeNode.getCallTarget,
|
||||
asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
).getAssociatedType,
|
||||
asAssociatedType(mod.unsafeAsModule()),
|
||||
branch.terminalBranch
|
||||
)
|
||||
)
|
||||
@ -1363,14 +1326,12 @@ class IrToTruffle(
|
||||
}
|
||||
Right(r)
|
||||
case Some(
|
||||
BindingsMap.Resolution(BindingsMap.ResolvedType(mod, tp))
|
||||
BindingsMap.Resolution(
|
||||
binding @ BindingsMap.ResolvedType(_, _)
|
||||
)
|
||||
) =>
|
||||
val tpe =
|
||||
asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
).getTypes
|
||||
.get(tp.name)
|
||||
asType(binding)
|
||||
val polyglot = context.getBuiltins.polyglot
|
||||
val branchNode = if (tpe == polyglot) {
|
||||
PolyglotBranchNode.build(
|
||||
@ -1391,10 +1352,8 @@ class IrToTruffle(
|
||||
BindingsMap.ResolvedPolyglotSymbol(mod, symbol)
|
||||
)
|
||||
) =>
|
||||
val polyglotSymbol = asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
).getPolyglotSymbol(symbol.name)
|
||||
val polyglotSymbol =
|
||||
asScope(mod.unsafeAsModule()).getPolyglotSymbol(symbol.name)
|
||||
Either.cond(
|
||||
polyglotSymbol != null,
|
||||
ObjectEqualityBranchNode
|
||||
@ -1411,10 +1370,8 @@ class IrToTruffle(
|
||||
)
|
||||
) =>
|
||||
val mod = typ.module
|
||||
val polyClass = asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
).getPolyglotSymbol(typ.symbol.name)
|
||||
val polyClass = asScope(mod.unsafeAsModule())
|
||||
.getPolyglotSymbol(typ.symbol.name)
|
||||
|
||||
val polyValueOrError =
|
||||
if (polyClass == null)
|
||||
@ -1515,15 +1472,13 @@ class IrToTruffle(
|
||||
case None =>
|
||||
Left(BadPatternMatch.NonVisibleType(tpeName.name))
|
||||
case Some(
|
||||
BindingsMap.Resolution(BindingsMap.ResolvedType(mod, tpe))
|
||||
BindingsMap.Resolution(
|
||||
binding @ BindingsMap.ResolvedType(_, _)
|
||||
)
|
||||
) =>
|
||||
// Using .getTypes because .getType may return an associated type
|
||||
Option(
|
||||
asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
).getTypes
|
||||
.get(tpe.name)
|
||||
asType(binding)
|
||||
) match {
|
||||
case Some(tpe) =>
|
||||
val argOfType = List(
|
||||
@ -1558,10 +1513,7 @@ class IrToTruffle(
|
||||
)
|
||||
) =>
|
||||
val polySymbol =
|
||||
asScope(
|
||||
mod
|
||||
.unsafeAsModule()
|
||||
).getPolyglotSymbol(symbol.name)
|
||||
asScope(mod.unsafeAsModule()).getPolyglotSymbol(symbol.name)
|
||||
if (polySymbol != null) {
|
||||
val argOfType = List(
|
||||
DefinitionArgument.Specified(
|
||||
@ -1724,10 +1676,12 @@ class IrToTruffle(
|
||||
val resolution = global.get.target
|
||||
nodeForResolution(resolution)
|
||||
} else if (nameStr == ConstantsNames.FROM_MEMBER) {
|
||||
ConstantObjectNode.build(UnresolvedConversion.build(moduleScope))
|
||||
ConstantObjectNode.build(
|
||||
UnresolvedConversion.build(scopeBuilder.asModuleScope())
|
||||
)
|
||||
} else {
|
||||
DynamicSymbolNode.build(
|
||||
UnresolvedSymbol.build(nameStr, moduleScope)
|
||||
UnresolvedSymbol.build(nameStr, scopeBuilder.asModuleScope())
|
||||
)
|
||||
}
|
||||
case Name.MethodReference(
|
||||
@ -1789,13 +1743,7 @@ class IrToTruffle(
|
||||
): RuntimeExpression = {
|
||||
resolution match {
|
||||
case tp: BindingsMap.ResolvedType =>
|
||||
ConstantObjectNode.build(
|
||||
asScope(
|
||||
tp.module
|
||||
.unsafeAsModule()
|
||||
).getTypes
|
||||
.get(tp.tp.name)
|
||||
)
|
||||
ConstantObjectNode.build(asType(tp))
|
||||
case BindingsMap.ResolvedConstructor(definitionType, cons) =>
|
||||
val c = asType(definitionType).getConstructors
|
||||
.get(cons.name)
|
||||
@ -1805,16 +1753,11 @@ class IrToTruffle(
|
||||
ConstructorNode.build(c)
|
||||
case BindingsMap.ResolvedModule(module) =>
|
||||
ConstantObjectNode.build(
|
||||
asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getAssociatedType
|
||||
asAssociatedType(module.unsafeAsModule())
|
||||
)
|
||||
case BindingsMap.ResolvedPolyglotSymbol(module, symbol) =>
|
||||
val s = asScope(
|
||||
module
|
||||
.unsafeAsModule()
|
||||
).getPolyglotSymbol(symbol.name)
|
||||
val s =
|
||||
asScope(module.unsafeAsModule()).getPolyglotSymbol(symbol.name)
|
||||
if (s == null) {
|
||||
throw new CompilerError(
|
||||
s"No polyglot symbol for ${symbol.name}"
|
||||
@ -1822,10 +1765,8 @@ class IrToTruffle(
|
||||
}
|
||||
ConstantObjectNode.build(s)
|
||||
case BindingsMap.ResolvedPolyglotField(symbol, name) =>
|
||||
val s = asScope(
|
||||
symbol.module
|
||||
.unsafeAsModule()
|
||||
).getPolyglotSymbol(name)
|
||||
val s =
|
||||
asScope(symbol.module.unsafeAsModule()).getPolyglotSymbol(name)
|
||||
if (s == null) {
|
||||
throw new CompilerError(
|
||||
s"No polyglot field for ${name}"
|
||||
@ -2076,9 +2017,9 @@ class IrToTruffle(
|
||||
val fnRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
bodyBuilder.bodyNode(),
|
||||
makeSection(moduleScope, location),
|
||||
makeSection(scopeBuilder.getModule, location),
|
||||
scopeName,
|
||||
false,
|
||||
binding
|
||||
@ -2272,7 +2213,7 @@ class IrToTruffle(
|
||||
val closureRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
childScope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
argumentExpression,
|
||||
section,
|
||||
displayName,
|
||||
@ -2358,9 +2299,12 @@ class IrToTruffle(
|
||||
val defaultRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
scope,
|
||||
moduleScope,
|
||||
scopeBuilder.asModuleScope(),
|
||||
defaultExpression,
|
||||
makeSection(moduleScope, arg.defaultValue.get.location()),
|
||||
makeSection(
|
||||
scopeBuilder.getModule,
|
||||
arg.defaultValue.get.location()
|
||||
),
|
||||
s"<default::$scopeName::${arg.name.showCode()}>",
|
||||
false,
|
||||
false
|
||||
@ -2394,7 +2338,21 @@ class IrToTruffle(
|
||||
m.getScope()
|
||||
}
|
||||
|
||||
private def asType(typ: BindingsMap.ResolvedType): Type = {
|
||||
asScope(typ.module.unsafeAsModule()).getTypes().get(typ.tp.name)
|
||||
private def asType(
|
||||
typ: BindingsMap.ResolvedType
|
||||
): Type = {
|
||||
val m = org.enso.interpreter.runtime.Module
|
||||
.fromCompilerModule(typ.module.unsafeAsModule())
|
||||
m.getScope().getType(typ.tp.name, true)
|
||||
}
|
||||
|
||||
private def asAssociatedType(
|
||||
module: CompilerContext.Module
|
||||
): Type = {
|
||||
val m = org.enso.interpreter.runtime.Module.fromCompilerModule(module)
|
||||
m.getScope().getAssociatedType()
|
||||
}
|
||||
|
||||
private def scopeAssociatedType =
|
||||
scopeBuilder.asModuleScope().getAssociatedType
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
package org.enso.interpreter.runtime
|
||||
|
||||
import org.enso.compiler.data.BindingsMap
|
||||
import org.enso.compiler.core.CompilerError
|
||||
import org.enso.compiler.core.{CompilerError, IR}
|
||||
import org.enso.compiler.core.Implicits.AsMetadata
|
||||
import org.enso.compiler.pass.analyse.BindingAnalysis
|
||||
import org.enso.interpreter.runtime.Module
|
||||
import org.enso.interpreter.runtime.builtin.Builtins
|
||||
import org.enso.interpreter.runtime.data.atom.AtomConstructor
|
||||
import org.enso.interpreter.runtime.data.Type
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope
|
||||
|
||||
/** Generates stubs of runtime representations of atom constructors, to allow
|
||||
* [[IrToTruffle the code generator]] to refer to constructors that are not
|
||||
@ -19,9 +19,7 @@ class RuntimeStubsGenerator(builtins: Builtins) {
|
||||
*
|
||||
* @param module the module to generate stubs in.
|
||||
*/
|
||||
def run(module: Module): Unit = {
|
||||
val ir = module.getIr
|
||||
val scope = module.getScope
|
||||
def run(ir: IR, scope: ModuleScope.Builder): Unit = {
|
||||
val localBindings = ir.unsafeGetMetadata(
|
||||
BindingAnalysis,
|
||||
"Non-parsed module used in stubs generator"
|
||||
@ -74,7 +72,7 @@ class RuntimeStubsGenerator(builtins: Builtins) {
|
||||
val constructor =
|
||||
new AtomConstructor(
|
||||
cons.name,
|
||||
scope,
|
||||
scope.getModule(),
|
||||
rtp,
|
||||
false
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user