Skip to content

Commit

Permalink
WIP replacing BindingsMap access and AtomTypeInterface with StaticMod…
Browse files Browse the repository at this point in the history
…uleScope
  • Loading branch information
radeusgd committed Dec 31, 2024
1 parent 2a3c789 commit 5853a1e
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private BuiltinTypes() {}

private static TypeRepresentation fromQualifiedName(String qualifiedName) {
var fqn = QualifiedName$.MODULE$.fromString(qualifiedName);
return new TypeRepresentation.AtomType(fqn, null);
return new TypeRepresentation.AtomType(fqn);
}

public static boolean isAny(QualifiedName qualifiedName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.compiler.pass.analyse.types;

import org.enso.compiler.pass.analyse.types.scope.AtomType;
import org.enso.compiler.pass.analyse.types.scope.BuiltinsFallbackScope;
import org.enso.compiler.pass.analyse.types.scope.ModuleResolver;
import org.enso.compiler.pass.analyse.types.scope.StaticMethodResolution;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
import org.enso.compiler.pass.analyse.alias.AliasMetadata;
import org.enso.compiler.pass.analyse.alias.graph.Graph;
import org.enso.compiler.pass.analyse.alias.graph.GraphOccurrence;
import org.enso.compiler.pass.analyse.types.scope.AtomType;
import org.enso.compiler.pass.analyse.types.scope.ModuleResolver;
import org.enso.compiler.pass.analyse.types.scope.StaticModuleScope;
import org.enso.compiler.pass.analyse.types.scope.TypeScopeReference;
import org.enso.pkg.QualifiedName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.Option;
Expand All @@ -41,6 +43,7 @@ abstract class TypePropagation {
private static final Logger logger = LoggerFactory.getLogger(TypePropagation.class);
private final TypeResolver typeResolver;
private final TypeCompatibility compatibilityChecker;
private final ModuleResolver moduleResolver;
private final MethodTypeResolver methodTypeResolver;

TypePropagation(
Expand All @@ -50,6 +53,7 @@ abstract class TypePropagation {
ModuleResolver moduleResolver) {
this.typeResolver = typeResolver;
this.compatibilityChecker = compatibilityChecker;
this.moduleResolver = moduleResolver;

var currentModuleScope = StaticModuleScope.forIR(currentModule);
this.methodTypeResolver = new MethodTypeResolver(moduleResolver, currentModuleScope);
Expand Down Expand Up @@ -81,6 +85,11 @@ protected abstract void encounteredInvocationOfNonFunctionType(
protected abstract void encounteredNoSuchMethod(
IR relatedIr, TypeRepresentation type, String methodName, MethodCallKind kind);

/**
* The callback that is called when a constructor is being invoked on a type that does not have such a constructor.
*/
protected abstract void encounteredNoSuchConstructor(IR relatedIr, TypeRepresentation type, String constructorName);

enum MethodCallKind {
MEMBER,
STATIC,
Expand Down Expand Up @@ -323,6 +332,12 @@ private TypeRepresentation processSingleApplication(
return null;
}

private AtomType findTypeDefinition(QualifiedName name) {
var module = moduleResolver.findContainingModule(TypeScopeReference.atomType(name));
var moduleScope = StaticModuleScope.forIR(module);
return moduleScope.getType(name.item());
}

private TypeRepresentation processUnresolvedSymbolApplication(
TypeRepresentation.UnresolvedSymbol function,
Expression argument,
Expand All @@ -336,14 +351,26 @@ private TypeRepresentation processUnresolvedSymbolApplication(
switch (argumentType) {
case TypeRepresentation.TypeObject typeObject -> {
if (isConstructorOrType(function.name())) {
var ctorCandidate =
typeObject.typeInterface().constructors().stream()
.filter(ctor -> ctor.name().equals(function.name()))
.findFirst();
if (ctorCandidate.isPresent()) {
return typeResolver.buildAtomConstructorType(typeObject, ctorCandidate.get());
var typeDefinition = findTypeDefinition(typeObject.name());
if (typeDefinition == null) {
logger.warn(
"processUnresolvedSymbolApplication: {} - no type definition found for {}",
relatedWholeApplicationIR.showCode(),
typeObject.name());
return null;
}

var constructor = typeDefinition.getConstructor(function.name());
if (constructor != null) {
if (constructor.type() == null) {
// type is unknown due to default arguments
// TODO later on this should be assert != null because all constructors should have a type (once we can deal with default arguments)
return null;
}

return constructor.type();
} else {
// TODO we could report that no valid constructor was found
encounteredNoSuchConstructor(relatedWholeApplicationIR, argumentType, function.name());
return null;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public QualifiedName getAssociatedType() {
* <p>Instances that are assigned this type are built with one of the available constructors, but
* statically we do not necessarily know which one.
*/
record AtomType(QualifiedName fqn, AtomTypeInterface typeInterface)
record AtomType(QualifiedName fqn)
implements TypeRepresentation {
@Override
public String toString() {
Expand Down Expand Up @@ -157,10 +157,8 @@ public String toString() {
* using its constructors, which will be assigned the corresponding AtomType.
*
* @param name the qualified name of the type
* @param typeInterface the declared interface of the type
*/
record TypeObject(QualifiedName name, AtomTypeInterface typeInterface)
implements TypeRepresentation {
record TypeObject(QualifiedName name) implements TypeRepresentation {
@Override
public String toString() {
return "(type " + name.item() + ")";
Expand All @@ -179,7 +177,7 @@ public TypeRepresentation instanceType() {
return new ArrowType(TypeRepresentation.ANY, TypeRepresentation.ANY);
}

return new AtomType(name, typeInterface);
return new AtomType(name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ TypeRepresentation resolvedTypeAsAtomType(BindingsMap.ResolvedType resolvedType)
return resolvedTypeAsTypeObject(resolvedType).instanceType();
}

TypeRepresentation buildAtomConstructorType(
public TypeRepresentation buildAtomConstructorType(
TypeRepresentation.TypeObject parentType, AtomTypeInterface.Constructor constructor) {
boolean hasAnyDefaults =
constructor.arguments().stream().anyMatch(AtomTypeInterface.Argument::hasDefaultValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,28 @@

public final class AtomType {
private final String name;
private final List<Constructor> constructors;

public AtomType(String name, List<Constructor> constructors) {
this.name = name;
this.constructors = constructors;
}

public String getName() {
return name;
}

// TODO mark type in constructor only if no default arguments, treat same as function?
// TODO this should replace AtomTypeInterface
public Constructor getConstructor(String name) {
return constructors.stream().filter(c -> c.name().equals(name)).findFirst().orElse(null);
}

/**
* Represents a constructor of the atom type.
*
* @param name the name of the constructor
* @param isProjectPrivate whether the constructor is project private
* @param type the type ascribed to the constructor, it may be null if it is unknown
* TODO the type will soon be always non-null - once we can handle default arguments
*/
public record Constructor(String name, boolean isProjectPrivate, TypeRepresentation type) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,8 @@ public TypeRepresentation getConversionFor(TypeScopeReference target, TypeScopeR
// TODO conversions in static analysis
return null;
}

public AtomType getType(String name) {
return typesDefinedHere.get(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ protected void processTypeDefinition(Definition.Type typ) {
List<AtomType.Constructor> constructors =
CollectionConverters$.MODULE$.asJava(typ.members()).stream()
.map(
constructorDef ->
new AtomType.Constructor(
constructorDef.name().name(), constructorDef.isPrivate()))
constructorDef -> {
TypeRepresentation type = buildAtomConstructorType(constructorDef);
return new AtomType.Constructor(
constructorDef.name().name(), constructorDef.isPrivate(), type);
})
.toList();

AtomType atomType = new AtomType(typ.name().name(), constructors);
Expand All @@ -151,6 +153,25 @@ protected void processTypeDefinition(Definition.Type typ) {
registerFieldGetters(scopeBuilder, atomTypeScope, typ);
}

private TypeRepresentation buildAtomConstructorType(Definition.Data constructorDef) {
boolean hasDefaults = constructorDef.arguments().exists(a -> a.defaultValue().isDefined());
if (hasDefaults) {
// TODO implement handling of default arguments - not only ctors will need this!
return null;
}

var arguments =
constructorDef.arguments().map(
(arg) -> {
var typ = arg.ascribedType();
// TODO
return typ != null ? typ : TypeRepresentation.UNKNOWN;
})
.toList();
var resultType = parentType.instanceType();
return TypeRepresentation.buildFunction(arguments, resultType);
}

@Override
protected TypeScopeReference associatedTypeFromResolvedModule(
BindingsMap.ResolvedModule module) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -595,15 +595,7 @@ object BindingsMap {
def allFieldsDefaulted: Boolean = arguments.forall(_.hasDefaultValue)
}

case class Argument(
name: String,
hasDefaultValue: Boolean,
typReference: Reference[Expression]
) {
def typ(): Option[Expression] = Option(
typReference.get(classOf[Expression])
)
}
case class Argument(name: String, hasDefaultValue: Boolean)

/** A representation of a sum type
*
Expand All @@ -629,15 +621,9 @@ object BindingsMap {
Cons(
m.name.name,
m.arguments.map { arg =>
val ascribedType: Reference[Expression] =
arg.ascribedType match {
case Some(value) => Reference.of(value, true)
case None => Reference.none()
}
BindingsMap.Argument(
arg.name.name,
arg.defaultValue.isDefined,
ascribedType
arg.defaultValue.isDefined
)
},
m.isPrivate
Expand Down

0 comments on commit 5853a1e

Please sign in to comment.