diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-12-29 10:46:07 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-12-29 10:46:07 +0000 |
| commit | 907ace120be1b6127115cee25be0968d0013b074 (patch) | |
| tree | 2ab16273bfd4dc2fe90565d998d9fc86e6a5fffc /src/test/java | |
| parent | 14f24c1cf3a3e80929b11451bece33198198a882 (diff) | |
Create type constructor for generic sum type definitions
Diffstat (limited to 'src/test/java')
4 files changed, 107 insertions, 9 deletions
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java index 73aa5c2f..52813dd4 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -302,14 +302,11 @@ public class TypedNodeMatchers { } public static Matcher<TypedNamespaceStatementNode> isTypedSumTypeDefinitionNode( - SumType type + Matcher<TypeOrConstructor<SumType>> typeOrConstructor ) { return instanceOf( TypedSumTypeDefinitionNode.class, - has("typeOrConstructor", x -> x.typeOrConstructor(), instanceOf( - TypeOrConstructor.Type.class, - has("value", x -> x.value(), equalTo(type)) - )) + has("typeOrConstructor", x -> x.typeOrConstructor(), typeOrConstructor) ); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java index 76d399db..3478bd2e 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java @@ -118,8 +118,8 @@ public class TypeCheckerStructDefinitionTests { ), isStructType(NAMESPACE_NAME, "ExampleStruct") )))), - has("variableType", x -> x.variableType(), equalTo(VariableType.CONSTANT) - ))) + has("variableType", x -> x.variableType(), equalTo(VariableType.CONSTANT)) + )) ); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java index 562e24e0..a028b21f 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java @@ -9,11 +9,13 @@ import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; +import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.isTypedSumTypeDefinitionNode; import static org.shedlang.compiler.typechecker.TypeCheckerTesting.typeCheckNamespaceStatement; +import static org.shedlang.compiler.types.TypeMatchers.*; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.*; @@ -34,7 +36,55 @@ public class TypeCheckerSumTypeDefinitionTests { } @Test - public void typeIsAddedToEnvironment() { + public void whenDefinitionHasNoTypeLevelParamsThenTypedNodeHasType() { + var untyped = UntypedSumTypeDefinitionNode.builder() + .withName("ExampleSumType") + .addVariant(Untyped.typeLevelReference("A")) + .build(); + var variantType1 = Types.struct(NAMESPACE_NAME, "A"); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry("A", Types.metaType(variantType1)) + )); + + var typed = typeCheckNamespaceStatement(untyped, context); + + assertThat(typed.value(), isTypedSumTypeDefinitionNode( + isTypeNotConstructor(isSumType(NAMESPACE_NAME, "ExampleSumType")) + )); + } + + @Test + public void whenDefinitionHasTypeLevelParamsThenTypedNodeHasTypeConstructor() { + var untyped = UntypedSumTypeDefinitionNode.builder() + .withName("ExampleSumType") + .withTypeLevelParams(List.of( + Untyped.typeLevelParam("T1"), + Untyped.typeLevelParam("T2") + )) + .addVariant(Untyped.typeLevelReference("A")) + .build(); + var variantType1 = Types.struct(NAMESPACE_NAME, "A"); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry("A", Types.metaType(variantType1)) + )); + + var typed = typeCheckNamespaceStatement(untyped, context); + + assertThat(typed.value(), isTypedSumTypeDefinitionNode( + isConstructorNotType(isTypeConstructor( + isSequence( + isSumTypeLevelParam(NAMESPACE_NAME, "ExampleSumType", "T1"), + isSumTypeLevelParam(NAMESPACE_NAME, "ExampleSumType", "T2") + ), + isSumType(NAMESPACE_NAME, "ExampleSumType") + )) + )); + } + + @Test + public void whenDefinitionHasNoTypeParamsThenTypeIsAddedToEnvironment() { var untyped = UntypedSumTypeDefinitionNode.builder() .withName("ExampleSumType") .build(); @@ -52,6 +102,34 @@ public class TypeCheckerSumTypeDefinitionTests { } @Test + public void whenDefinitionHasTypeParamsThenTypeConstructorIsAddedToEnvironment() { + var untyped = UntypedSumTypeDefinitionNode.builder() + .withName("ExampleSumType") + .withTypeLevelParams(List.of( + Untyped.typeLevelParam("T1"), + Untyped.typeLevelParam("T2") + )) + .build(); + var context = TypeCheckerContext.EMPTY; + + var typed = typeCheckNamespaceStatement(untyped, context); + + assertThat( + typed.context().compileTimeLookup("ExampleSumType"), + isOptionalOf(allOf( + has("type", x -> x.type(), isOptionalOf(isTypeLevelValueType(isTypeConstructor( + isSequence( + isSumTypeLevelParam(NAMESPACE_NAME, "ExampleSumType", "T1"), + isSumTypeLevelParam(NAMESPACE_NAME, "ExampleSumType", "T2") + ), + isSumType(NAMESPACE_NAME, "ExampleSumType") + )))), + has("variableType", x -> x.variableType(), equalTo(VariableType.CONSTANT)) + )) + ); + } + + @Test public void canTypeCheckSumTypeWithVariantsInSameNamespace() { var untyped = UntypedSumTypeDefinitionNode.builder() .withName("ExampleSumType") @@ -69,7 +147,7 @@ public class TypeCheckerSumTypeDefinitionTests { var typed = typeCheckNamespaceStatement(untyped, context); assertThat(typed.value(), isTypedSumTypeDefinitionNode( - Types.sum(NAMESPACE_NAME, "ExampleSumType") + isTypeNotConstructor(equalTo(Types.sum(NAMESPACE_NAME, "ExampleSumType"))) )); var sumTypeInfo = typed.context().toTypeInfos() .sumTypeInfo(Types.sum(NAMESPACE_NAME, "ExampleSumType")) diff --git a/src/test/java/org/shedlang/compiler/types/TypeMatchers.java b/src/test/java/org/shedlang/compiler/types/TypeMatchers.java index 3f7de1ee..24d2d0df 100644 --- a/src/test/java/org/shedlang/compiler/types/TypeMatchers.java +++ b/src/test/java/org/shedlang/compiler/types/TypeMatchers.java @@ -18,6 +18,14 @@ public class TypeMatchers { ); } + public static Matcher<TypeLevelValue> isSumType(NamespaceName namespaceName, String name) { + return instanceOf( + SumType.class, + has("namespaceName", x -> x.namespaceName(), equalTo(namespaceName)), + has("name", x -> x.name(), equalTo(name)) + ); + } + public static Matcher<TypeLevelValue> isTypeConstructor( Matcher<? super Iterable<? extends TypeParam>> params, Matcher<? super Type> genericType @@ -62,6 +70,21 @@ public class TypeMatchers { ); } + public static Matcher<Type> isSumTypeLevelParam( + NamespaceName namespaceName, + String sumTypeName, + String paramName + ) { + return instanceOf( + TypeParam.class, + has("scope", x -> x.scope(), instanceOf( + Scope.Sum.class, + has("type", x -> x.type(), isSumType(namespaceName, sumTypeName)) + )), + has("name", x -> x.name(), equalTo(paramName)) + ); + } + public static Matcher<ConstructedType<?>> isConstructedType( Matcher<TypeConstructor<?>> constructor, Matcher<Iterable<? extends Type>> args |
