mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 03:32:23 +03:00
Providing onScope
This commit is contained in:
parent
b4aaa51676
commit
8ebabd5c83
@ -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())
|
||||
.mapToObj(
|
||||
i ->
|
||||
new ArgumentDefinition(
|
||||
i, params.get(i), null, null, ArgumentDefinition.ExecutionMode.EXECUTE))
|
||||
.toArray(ArgumentDefinition[]::new));
|
||||
var args = IntStream.range(0, params.size())
|
||||
.mapToObj(
|
||||
i ->
|
||||
new ArgumentDefinition(
|
||||
i, params.get(i), null, null, ArgumentDefinition.ExecutionMode.EXECUTE))
|
||||
.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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user