Skip to content

Commit

Permalink
add a test for the type extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
radeusgd committed Apr 27, 2024
1 parent 3b0e743 commit bc40260
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.enso.compiler.pass.analyse.types;

import java.util.List;
import java.util.UUID;
import org.enso.compiler.context.InlineContext;
import org.enso.compiler.context.ModuleContext;
import org.enso.compiler.core.ir.Expression;
Expand All @@ -22,9 +24,6 @@
import scala.jdk.javaapi.CollectionConverters;
import scala.jdk.javaapi.CollectionConverters$;

import java.util.List;
import java.util.UUID;

/**
* A precursor pass that prepares the IR for type inference, run before the main propagation logic
* runs in {@link TypeInferencePropagation}.
Expand Down Expand Up @@ -77,6 +76,7 @@ public Seq<IRPass> precursorPasses() {
}

@Override
@SuppressWarnings("unchecked")
public Seq<IRPass> invalidatedPasses() {
return (Seq<IRPass>) Seq$.MODULE$.empty();
}
Expand All @@ -90,9 +90,14 @@ public Module runModule(Module ir, ModuleContext moduleContext) {
case Method.Explicit b -> {
TypeRepresentation resolvedType = resolveTopLevelTypeSignature(b.body());
if (resolvedType != null) {
System.out.println("Resolved "+b.methodReference().showCode()+" to type "+resolvedType);
System.out.println(
"Resolved "
+ b.methodReference().showCode()
+ " to type "
+ resolvedType);
// TODO maybe different metadata class?
// TODO use this in TypeInferencePropagation if its own metadata is not yet available
// TODO use this in TypeInferencePropagation if its own metadata is not yet
// available
ir.passData().update(INSTANCE, new InferredType(resolvedType));
}
yield b;
Expand All @@ -114,7 +119,7 @@ public Expression runExpression(Expression ir, InlineContext inlineContext) {

private TypeRepresentation resolveTopLevelTypeSignature(Expression expression) {
return switch (expression) {
// Combine argument types with ascribed type (if available) for a function type signature
// Combine argument types with ascribed type (if available) for a function type signature
case Function.Lambda lambda -> {
boolean hasAnyDefaults =
lambda.arguments().find((arg) -> arg.defaultValue().isDefined()).isDefined();
Expand All @@ -141,11 +146,20 @@ private TypeRepresentation resolveTopLevelTypeSignature(Expression expression) {
});

TypeRepresentation ascribedReturnType = typeResolver.findTypeAscription(lambda.body());
TypeRepresentation returnType = ascribedReturnType != null ? ascribedReturnType : TypeRepresentation.UNKNOWN;
yield TypeRepresentation.buildFunction(CollectionConverters$.MODULE$.asJava(argTypesScala), returnType);

if (ascribedReturnType == null && argTypesScala.isEmpty()) {
// If we did not infer return type NOR arity, we know nothing useful about this function, so we withdraw.
yield null;
}

TypeRepresentation returnType =
ascribedReturnType != null ? ascribedReturnType : TypeRepresentation.UNKNOWN;
yield TypeRepresentation.buildFunction(
CollectionConverters$.MODULE$.asJava(argTypesScala), returnType);
}

// Otherwise, we encountered a 0-argument method, so its type is just its return type (if its known).
// Otherwise, we encountered a 0-argument method, so its type is just its return type (if
// its known).
default -> typeResolver.findTypeAscription(expression);
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.enso.compiler.pass.analyse.types;

import static org.enso.compiler.MetadataInteropHelpers.getMetadata;
import static org.enso.compiler.MetadataInteropHelpers.getMetadataOrNull;

import java.util.List;
import org.enso.compiler.context.NameResolutionAlgorithm;
Expand All @@ -19,8 +18,6 @@
import org.enso.compiler.pass.analyse.AliasAnalysis$;
import org.enso.compiler.pass.analyse.alias.Graph;
import org.enso.compiler.pass.analyse.alias.Info;
import org.enso.compiler.pass.resolve.TypeSignatures;
import org.enso.compiler.pass.resolve.TypeSignatures$;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.Option;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,12 @@ package org.enso.compiler
import org.enso.compiler.data.CompilerConfig
import org.enso.compiler.pass.PassConfiguration._
import org.enso.compiler.pass.analyse._
import org.enso.compiler.pass.analyse.types.TypeInferencePropagation
import org.enso.compiler.pass.analyse.types.{TypeInferencePropagation, TypeInferenceSignatures}
import org.enso.compiler.pass.desugar._
import org.enso.compiler.pass.lint.{
ModuleNameConflicts,
NoSelfInStatic,
ShadowedPatternFields,
UnusedBindings
}
import org.enso.compiler.pass.optimise.{
LambdaConsolidate,
UnreachableMatchBranches
}
import org.enso.compiler.pass.lint.{ModuleNameConflicts, NoSelfInStatic, ShadowedPatternFields, UnusedBindings}
import org.enso.compiler.pass.optimise.{LambdaConsolidate, UnreachableMatchBranches}
import org.enso.compiler.pass.resolve._
import org.enso.compiler.pass.{
IRPass,
PassConfiguration,
PassGroup,
PassManager
}
import org.enso.compiler.pass.{IRPass, PassConfiguration, PassGroup, PassManager}

class Passes(
config: CompilerConfig,
Expand Down Expand Up @@ -100,6 +87,7 @@ class Passes(
GenericAnnotations
) ++ (if (config.staticTypeInferenceEnabled) {
List(
TypeInferenceSignatures.INSTANCE,
TypeInferencePropagation.INSTANCE
)
} else List())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.enso.compiler;

import static org.junit.Assert.assertTrue;

import java.util.List;
import org.enso.compiler.context.FreshNameSupply;
import org.enso.compiler.context.ModuleContext;
import org.enso.compiler.core.IR;
Expand All @@ -18,10 +21,6 @@
import scala.collection.immutable.Seq$;
import scala.jdk.javaapi.CollectionConverters;

import java.util.List;

import static org.junit.Assert.assertTrue;

public abstract class CompilerTest extends ParserTest {
/**
* Note that this `compile` method will not run import resolution. For now we just have tests that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,19 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.enso.compiler.context.FreshNameSupply;
import org.enso.compiler.context.ModuleContext;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.Diagnostic;
import org.enso.compiler.core.ir.Expression;
import org.enso.compiler.core.ir.Module;
import org.enso.compiler.core.ir.ProcessingPass;
import org.enso.compiler.core.ir.Warning;
import org.enso.compiler.core.ir.expression.Application;
import org.enso.compiler.core.ir.module.scope.definition.Method;
import org.enso.compiler.data.CompilerConfig;
import org.enso.compiler.pass.PassConfiguration;
import org.enso.compiler.pass.PassManager;
import org.enso.compiler.pass.analyse.types.InferredType;
import org.enso.compiler.pass.analyse.types.TypeInferencePropagation;
import org.enso.compiler.pass.analyse.types.TypeRepresentation;
import org.enso.compiler.test.CompilerRunner;
import org.enso.pkg.QualifiedName;
import org.graalvm.polyglot.Source;
import org.junit.Ignore;
import org.junit.Test;
import scala.Option;
import scala.collection.immutable.Seq;
import scala.collection.immutable.Seq$;
import scala.jdk.javaapi.CollectionConverters;

public class TypeInferenceTest extends CompilerTest {
@Ignore("TODO resolving global methods")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.enso.compiler;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.net.URI;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.ProcessingPass;
import org.enso.compiler.pass.analyse.types.InferredType;
import org.enso.compiler.pass.analyse.types.TypeInferenceSignatures;
import org.enso.compiler.pass.analyse.types.TypeRepresentation;
import org.graalvm.polyglot.Source;
import org.junit.Test;
import scala.Option;

public class TypesFromSignaturesTest extends CompilerTest {

@Test
public void simpleCheck() throws Exception {
final URI uri = new URI("memory://simpleCheck.enso");
final Source src =
Source.newBuilder(
"enso",
"""
type A
type B
type C
Value v
f (x : A) (y : B) -> C = C.Value [x, y]
""",
uri.getAuthority())
.uri(uri)
.buildLiteral();

var module = compile(src);

var f1 = findStaticMethod(module, "f");

assertInferredType(f1, "(A -> (B -> C))");
}


@Test
public void justArity() throws Exception {
final URI uri = new URI("memory://justArity.enso");
final Source src =
Source.newBuilder(
"enso",
"""
type A
type B
type C
Value v
f0 = 0
f4 x y z w = [x, y, z, w]
f2 : A -> B -> C
f2 x y = [x, y]
""",
uri.getAuthority())
.uri(uri)
.buildLiteral();

var module = compile(src);

var f0 = findStaticMethod(module, "f0");
var f4 = findStaticMethod(module, "f4");
var f2 = findStaticMethod(module, "f2");

// For 0 arguments and unknown return type we know nothing useful, so no information is registered.
assertNoInferredType(f0);

// For a function without ascriptions, we can at least infer the _arity_
// Currently that is denoted by replacing unknowns with Any. Later this may be free type variables.
assertInferredType(f4, "(Any -> (Any -> (Any -> (Any -> Any))))");


// For the 'opted-out' ascription, the types are ignored, because they are not checked types. But we still infer arity.
assertInferredType(f2, "(Any -> (Any -> Any))");
}

private void assertInferredType(IR ir, String expected) {
TypeRepresentation inferred = getInferredType(ir);
assertEquals(expected, inferred.toString());
}

private TypeRepresentation getInferredType(IR ir) {
Option<ProcessingPass.Metadata> metadata = ir.passData().get(TypeInferenceSignatures.INSTANCE);
assertTrue(
"Expecting " + ir.showCode() + " to contain a type within metadata.", metadata.isDefined());
InferredType inferred = (InferredType) metadata.get();
return inferred.type();
}

private void assertNoInferredType(IR ir) {
Option<ProcessingPass.Metadata> metadata = ir.passData().get(TypeInferenceSignatures.INSTANCE);
assertTrue(
"Expecting " + ir.showCode() + " to contain no type within metadata.", metadata.isEmpty());
}
}

0 comments on commit bc40260

Please sign in to comment.