From fe0cb0f6ed1be2da385a10fcb72734b5e01d57ca Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 11 Feb 2025 19:24:43 +0000 Subject: Type check type-level params for function type --- .../typechecker/TypeCheckerFunctionTypeTests.java | 56 ++++++++++++++++++---- 1 file changed, 47 insertions(+), 9 deletions(-) (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionTypeTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionTypeTests.java index f4a2a6a2..22d994ea 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionTypeTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionTypeTests.java @@ -5,11 +5,10 @@ import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.ast.untyped.UntypedFunctionTypeNode; import org.shedlang.compiler.typechecker.errors.DuplicateVariableNameError; import org.shedlang.compiler.typechecker.typesets.TypeSets; -import org.shedlang.compiler.types.Effects; -import org.shedlang.compiler.types.FunctionType; -import org.shedlang.compiler.types.Types; +import org.shedlang.compiler.types.*; import org.shedlang.compiler.util.P; +import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -18,6 +17,8 @@ import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.equalTo; public class TypeCheckerFunctionTypeTests { + private static final NamespaceName NAMESPACE_NAME = NamespaceName.of("Example", "Project"); + @Test public void returnTypeIsTypeChecked() { var untyped = UntypedFunctionTypeNode.builder() @@ -26,7 +27,8 @@ public class TypeCheckerFunctionTypeTests { var context = TypeCheckerContext.EMPTY .enterGlobal(P.map( Map.entry("String", Types.metaType(Types.STRING)) - )); + )) + .enterNamespace(NAMESPACE_NAME, P.map()); var result = TypeChecker.typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped, context); @@ -48,7 +50,8 @@ public class TypeCheckerFunctionTypeTests { var context = TypeCheckerContext.EMPTY .enterGlobal(P.map( Map.entry("String", Types.metaType(Types.STRING)) - )); + )) + .enterNamespace(NAMESPACE_NAME, P.map()); var result = TypeChecker.typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped, context); @@ -73,7 +76,8 @@ public class TypeCheckerFunctionTypeTests { .enterGlobal(P.map( Map.entry("Io", Types.effectType(Effects.IO)), Map.entry("String", Types.metaType(Types.STRING)) - )); + )) + .enterNamespace(NAMESPACE_NAME, P.map()); var result = TypeChecker.typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped, context); @@ -100,7 +104,8 @@ public class TypeCheckerFunctionTypeTests { Map.entry("Bool", Types.metaType(Types.BOOL)), Map.entry("Int", Types.metaType(Types.INT)), Map.entry("String", Types.metaType(Types.STRING)) - )); + )) + .enterNamespace(NAMESPACE_NAME, P.map()); var result = TypeChecker.typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped, context); @@ -128,7 +133,8 @@ public class TypeCheckerFunctionTypeTests { Map.entry("Bool", Types.metaType(Types.BOOL)), Map.entry("Int", Types.metaType(Types.INT)), Map.entry("String", Types.metaType(Types.STRING)) - )); + )) + .enterNamespace(NAMESPACE_NAME, P.map()); var result = TypeChecker.typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped, context); @@ -156,7 +162,8 @@ public class TypeCheckerFunctionTypeTests { Map.entry("Bool", Types.metaType(Types.BOOL)), Map.entry("Int", Types.metaType(Types.INT)), Map.entry("String", Types.metaType(Types.STRING)) - )); + )) + .enterNamespace(NAMESPACE_NAME, P.map()); var error = assertThrows( DuplicateVariableNameError.class, @@ -165,4 +172,35 @@ public class TypeCheckerFunctionTypeTests { assertThat(error.variableName(), equalTo("a")); } + + @Test + public void typeLevelParamsAreTypeChecked() { + var namespaceName = NamespaceName.of("Example", "Project"); + var untyped = UntypedFunctionTypeNode.builder() + .withTypeLevelParams(List.of( + Untyped.typeParam("T"), + Untyped.typeParam("R") + )) + .addPositionalParam(Untyped.typeLevelReference("T")) + .withReturnType(Untyped.typeLevelReference("R")) + .build(); + var context = TypeCheckerContext.EMPTY + .enterNamespace(NAMESPACE_NAME, P.map()); + + var result = TypeChecker.typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped, context); + + assertThat( + result.value(), + isTypedFunctionTypeNode(equalTo( + FunctionType.builder() + .withTypeLevelParams(List.of( + TypeParam.forFunctionType(namespaceName, 0, "T"), + TypeParam.forFunctionType(namespaceName, 0, "R") + )) + .addPositionalParam(TypeParam.forFunctionType(namespaceName, 0, "T")) + .withReturnType(TypeParam.forFunctionType(namespaceName, 0, "R")) + .build() + )) + ); + } } -- cgit v1.2.3