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

View File

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

View File

@ -55,6 +55,7 @@ public final class AtomConstructor implements EnsoObject {
private Layout[] unboxingLayouts = new Layout[0]; private Layout[] unboxingLayouts = new Layout[0];
private final Type type; private final Type type;
private FunctionSchema schema;
/** /**
* Creates a new Atom constructor for a given name.The constructor is not valid until {@link * 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(), LocalScope.root(),
scope, scope,
new ExpressionNode[0], new ExpressionNode[0],
reads, reads);
new Annotation[0],
args);
} }
/** /**
* Sets the fields of this {@link AtomConstructor} and generates a constructor function. * 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 scopeBuilder the module scope's builder where the accessor should be registered at
* @param args
* @return {@code this}, for convenience * @return {@code this}, for convenience
*/ */
public AtomConstructor initializeBuilder( 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); 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; return this;
} }
@ -147,20 +164,11 @@ public final class AtomConstructor implements EnsoObject {
LocalScope localScope, LocalScope localScope,
ModuleScope scope, ModuleScope scope,
ExpressionNode[] assignments, ExpressionNode[] assignments,
ExpressionNode[] varReads, ExpressionNode[] varReads) {
Annotation[] annotations,
ArgumentDefinition... args) {
CompilerDirectives.transferToInterpreterAndInvalidate(); 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 = this.constructorFunction =
buildConstructorFunction( buildConstructorFunction(
language, section, localScope, scope, assignments, varReads, annotations, args); language, section, localScope, scope, assignments, varReads);
return this; return this;
} }
@ -183,9 +191,8 @@ public final class AtomConstructor implements EnsoObject {
LocalScope localScope, LocalScope localScope,
ModuleScope scope, ModuleScope scope,
ExpressionNode[] assignments, ExpressionNode[] assignments,
ExpressionNode[] varReads, ExpressionNode[] varReads
Annotation[] annotations, ) {
ArgumentDefinition[] args) {
ExpressionNode instantiateNode = InstantiateNode.build(this, varReads); ExpressionNode instantiateNode = InstantiateNode.build(this, varReads);
if (section != null) { if (section != null) {
instantiateNode.setSourceLocation(section.getCharIndex(), section.getCharLength()); instantiateNode.setSourceLocation(section.getCharIndex(), section.getCharLength());
@ -195,25 +202,13 @@ public final class AtomConstructor implements EnsoObject {
MethodRootNode.buildConstructor( MethodRootNode.buildConstructor(
language, localScope, scope, instantiateBlock, section, this); language, localScope, scope, instantiateBlock, section, this);
RootCallTarget callTarget = rootNode.getCallTarget(); RootCallTarget callTarget = rootNode.getCallTarget();
var schemaBldr = FunctionSchema.newBuilder().annotations(annotations).argumentDefinitions(args); return new Function(callTarget, null, schema);
if (type.isProjectPrivate()) {
schemaBldr.projectPrivate();
}
return new Function(callTarget, null, schemaBldr.build());
} }
private Function generateQualifiedAccessor(EnsoLanguage lang, ModuleScope.Builder scopeBuilder) { private Function generateQualifiedAccessor(EnsoLanguage lang, ModuleScope.Builder scopeBuilder) {
var node = new QualifiedAccessorNode(lang, this, getDefinitionScope()); var node = new QualifiedAccessorNode(lang, this, getDefinitionScope());
var callTarget = node.getCallTarget(); var callTarget = node.getCallTarget();
var schemaBldr = var function = new Function(callTarget, null, schema);
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());
scopeBuilder.registerMethod(type.getEigentype(), this.name, function); scopeBuilder.registerMethod(type.getEigentype(), this.name, function);
return 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.CompilerDirectives;
import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.library.ExportMessage;
import java.util.*; import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.enso.compiler.context.CompilerContext; import org.enso.compiler.context.CompilerContext;
import org.enso.interpreter.runtime.Module; import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.callable.function.Function; 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 Map<Type, Map<Type, Function>> conversions;
private final Set<ImportExportScope> imports; private final Set<ImportExportScope> imports;
private final Set<ImportExportScope> exports; private final Set<ImportExportScope> exports;
private final List<Consumer<ModuleScope>> onScope = new ArrayList<>();
public Builder(Module module) { public Builder(Module module) {
this.module = module; this.module = module;
@ -461,6 +465,15 @@ public final class ModuleScope implements EnsoObject {
return new Builder(this.module, new LinkedHashMap<>(this.types)); 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 * Materializes the builder and ensures that no further modifications to ModuleScope are
* possible. Action is idempotent. * possible. Action is idempotent.
@ -469,7 +482,7 @@ public final class ModuleScope implements EnsoObject {
*/ */
public ModuleScope build() { public ModuleScope build() {
if (moduleScope == null) { if (moduleScope == null) {
return moduleScope = moduleScope =
new ModuleScope( new ModuleScope(
module, module,
associatedType, associatedType,
@ -479,6 +492,11 @@ public final class ModuleScope implements EnsoObject {
Collections.unmodifiableMap(conversions), Collections.unmodifiableMap(conversions),
Collections.unmodifiableSet(imports), Collections.unmodifiableSet(imports),
Collections.unmodifiableSet(exports)); Collections.unmodifiableSet(exports));
for (var c : onScope) {
c.accept(moduleScope);
}
onScope.clear();
return moduleScope;
} else { } else {
throw new AssertionError("Already built"); throw new AssertionError("Already built");
} }

View File

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