Providing onScope

This commit is contained in:
Jaroslav Tulach 2024-06-11 09:24:38 +02:00
parent b4aaa51676
commit 8ebabd5c83
5 changed files with 76 additions and 55 deletions

View File

@ -1,12 +1,15 @@
package org.enso.interpreter.node.expression.builtin;
import com.oracle.truffle.api.CompilerDirectives;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import org.enso.interpreter.EnsoLanguage;
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.data.Type;
import org.enso.interpreter.runtime.data.atom.AtomConstructor;
@ -20,18 +23,20 @@ public abstract class Builtin {
}
private AtomConstructor build(
EnsoLanguage language, ModuleScope.Builder builder, ModuleScope scope, Type type) {
EnsoLanguage language, ModuleScope.Builder builder, Type type) {
var res = new AtomConstructor(name, builder.getModule(), type, true);
res.initializeBuilder(language, builder);
res.initializeFields(
language,
scope,
IntStream.range(0, params.size())
var args = IntStream.range(0, params.size())
.mapToObj(
i ->
new ArgumentDefinition(
i, params.get(i), null, null, ArgumentDefinition.ExecutionMode.EXECUTE))
.toArray(ArgumentDefinition[]::new));
.toArray(ArgumentDefinition[]::new);
res.initializeBuilder(language, builder, new Annotation[0],args);
builder.onScope(scope -> {
res.initializeFields(
language,
scope);
});
return res;
}
}
@ -57,14 +62,13 @@ public abstract class Builtin {
EnsoLanguage language,
Module module,
ModuleScope.Builder builder,
ModuleScope scope,
Map<Class<? extends Builtin>, Builtin> builtins) {
if (type == null) {
Type supertype = null;
if (getSuperType() != null) {
var s = builtins.get(getSuperType());
s.initialize(language, module, builder, scope, builtins);
supertype = s.getType();
s.initialize(language, module, builder, builtins);
}
type =
containsValues()
@ -76,7 +80,7 @@ public abstract class Builtin {
var conses = getDeclaredConstructors();
constructors = new AtomConstructor[conses.size()];
for (int i = 0; i < constructors.length; i++) {
var cons = conses.get(i).build(language, builder, scope, type);
var cons = conses.get(i).build(language, builder, type);
constructors[i] = cons;
type.registerConstructor(cons);
}

View File

@ -131,7 +131,7 @@ public final class Builtins {
builtins =
initializeBuiltinTypes(
loadedBuiltinConstructors, language, scopeBuilder, null /* as no scope */);
loadedBuiltinConstructors, language, scopeBuilder);
builtinsByName =
builtins.values().stream()
.collect(
@ -381,8 +381,7 @@ public final class Builtins {
private Map<Class<? extends Builtin>, Builtin> initializeBuiltinTypes(
List<Constructor<? extends Builtin>> constrs,
EnsoLanguage language,
ModuleScope.Builder builder,
ModuleScope scope) {
ModuleScope.Builder builder) {
Map<Class<? extends Builtin>, Builtin> builtins = new HashMap<>();
for (var constr : constrs) {
@ -394,7 +393,7 @@ public final class Builtins {
}
}
for (var b : builtins.values()) {
b.initialize(language, getModule(), builder, scope, builtins);
b.initialize(language, getModule(), builder, builtins);
}
return builtins;
}

View File

@ -55,6 +55,7 @@ public final class AtomConstructor implements EnsoObject {
private Layout[] unboxingLayouts = new Layout[0];
private final Type type;
private FunctionSchema schema;
/**
* Creates a new Atom constructor for a given name.The constructor is not valid until {@link
@ -115,20 +116,36 @@ public final class AtomConstructor implements EnsoObject {
LocalScope.root(),
scope,
new ExpressionNode[0],
reads,
new Annotation[0],
args);
reads);
}
/**
* Sets the fields of this {@link AtomConstructor} and generates a constructor function.
*
* @param scopeBuilder the module scope's builder where the accessor should be registered at
* @param args
* @return {@code this}, for convenience
*/
public AtomConstructor initializeBuilder(
EnsoLanguage language, ModuleScope.Builder scopeBuilder) {
EnsoLanguage language, ModuleScope.Builder scopeBuilder, ArgumentDefinition[] args) {
assert boxedLayout == null : "Don't initialize twice: " + this.name;
this.accessor = generateQualifiedAccessor(language, scopeBuilder);
var schemaBldr =
FunctionSchema.newBuilder()
.argumentDefinitions(
new ArgumentDefinition(
0, "self", null, null, ArgumentDefinition.ExecutionMode.EXECUTE));
if (type.isProjectPrivate()) {
schemaBldr.projectPrivate();
}
this.schema = schemaBldr.build();
if (args.length == 0) {
cachedInstance = BoxingAtom.singleton(this);
} else {
cachedInstance = null;
}
this.boxedLayout = Layout.createBoxed(args);
return this;
}
@ -147,20 +164,11 @@ public final class AtomConstructor implements EnsoObject {
LocalScope localScope,
ModuleScope scope,
ExpressionNode[] assignments,
ExpressionNode[] varReads,
Annotation[] annotations,
ArgumentDefinition... args) {
ExpressionNode[] varReads) {
CompilerDirectives.transferToInterpreterAndInvalidate();
assert boxedLayout == null : "Don't initialize twice: " + this.name;
if (args.length == 0) {
cachedInstance = BoxingAtom.singleton(this);
} else {
cachedInstance = null;
}
boxedLayout = Layout.createBoxed(args);
this.constructorFunction =
buildConstructorFunction(
language, section, localScope, scope, assignments, varReads, annotations, args);
language, section, localScope, scope, assignments, varReads);
return this;
}
@ -183,9 +191,8 @@ public final class AtomConstructor implements EnsoObject {
LocalScope localScope,
ModuleScope scope,
ExpressionNode[] assignments,
ExpressionNode[] varReads,
Annotation[] annotations,
ArgumentDefinition[] args) {
ExpressionNode[] varReads
) {
ExpressionNode instantiateNode = InstantiateNode.build(this, varReads);
if (section != null) {
instantiateNode.setSourceLocation(section.getCharIndex(), section.getCharLength());
@ -195,25 +202,13 @@ public final class AtomConstructor implements EnsoObject {
MethodRootNode.buildConstructor(
language, localScope, scope, instantiateBlock, section, this);
RootCallTarget callTarget = rootNode.getCallTarget();
var schemaBldr = FunctionSchema.newBuilder().annotations(annotations).argumentDefinitions(args);
if (type.isProjectPrivate()) {
schemaBldr.projectPrivate();
}
return new Function(callTarget, null, schemaBldr.build());
return new Function(callTarget, null, schema);
}
private Function generateQualifiedAccessor(EnsoLanguage lang, ModuleScope.Builder scopeBuilder) {
var node = new QualifiedAccessorNode(lang, this, getDefinitionScope());
var callTarget = node.getCallTarget();
var schemaBldr =
FunctionSchema.newBuilder()
.argumentDefinitions(
new ArgumentDefinition(
0, "self", null, null, ArgumentDefinition.ExecutionMode.EXECUTE));
if (type.isProjectPrivate()) {
schemaBldr.projectPrivate();
}
var function = new Function(callTarget, null, schemaBldr.build());
var function = new Function(callTarget, null, schema);
scopeBuilder.registerMethod(type.getEigentype(), this.name, function);
return function;
}

View File

@ -3,9 +3,12 @@ package org.enso.interpreter.runtime.scope;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import java.util.*;
import java.util.function.Consumer;
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;
@ -281,6 +284,7 @@ public final class ModuleScope implements EnsoObject {
private final Map<Type, Map<Type, Function>> conversions;
private final Set<ImportExportScope> imports;
private final Set<ImportExportScope> exports;
private final List<Consumer<ModuleScope>> onScope = new ArrayList<>();
public Builder(Module module) {
this.module = module;
@ -461,6 +465,15 @@ public final class ModuleScope implements EnsoObject {
return new Builder(this.module, new LinkedHashMap<>(this.types));
}
/** Registers a callback to be notified when {@link #build()} is called
* @param callback the callback to notify
* @return this builder
*/
public Builder onScope(Consumer<ModuleScope> callback) {
onScope.add(callback);
return this;
}
/**
* Materializes the builder and ensures that no further modifications to ModuleScope are
* possible. Action is idempotent.
@ -469,7 +482,7 @@ public final class ModuleScope implements EnsoObject {
*/
public ModuleScope build() {
if (moduleScope == null) {
return moduleScope =
moduleScope =
new ModuleScope(
module,
associatedType,
@ -479,6 +492,11 @@ public final class ModuleScope implements EnsoObject {
Collections.unmodifiableMap(conversions),
Collections.unmodifiableSet(imports),
Collections.unmodifiableSet(exports));
for (var c : onScope) {
c.accept(moduleScope);
}
onScope.clear();
return moduleScope;
} else {
throw new AssertionError("Already built");
}

View File

@ -247,13 +247,18 @@ class IrToTruffle(
val asType = scopeBuilder.getType(tpDef.name.name, true)
val atomConstructors =
atomDefs.map(cons => asType.getConstructors.get(cons.name.name))
atomConstructors
val trippleStream = atomConstructors
.zip(atomDefs)
.foreach { case (atomCons, _) =>
.foreach { case (atomCons, atomDefn) =>
val argDefs =
new Array[ArgumentDefinition](atomDefn.arguments.size)
atomCons.initializeBuilder(
language,
scopeBuilder
scopeBuilder,
argDefs
)
(atomCons, atomDefn, argDefs)
}
asType.generateGetters(scopeBuilder, language)
}
@ -364,7 +369,7 @@ class IrToTruffle(
assignments.toArray,
reads.toArray,
annotations.toArray,
argDefs: _*
argDefs
)
}
}