diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-08-09 22:16:47 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-08-09 22:16:47 +0100 |
| commit | eb145887ab57b75299a55c85c753d3b4707105be (patch) | |
| tree | 0cb1c1cf9668a90accc95fe59c211f1599f28ade /src/test/java/org | |
| parent | 1e2d86b9d7f2f659f4c53f8543f7931ea81c5781 (diff) | |
Introduce variables for type params
Diffstat (limited to 'src/test/java/org')
| -rw-r--r-- | src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java index 91839f6..1de6cbf 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java @@ -18,7 +18,7 @@ import static org.zwobble.precisely.Matchers.*; public class TypeCheckerStructDefinitionTests { @Test - public void whenStructDefinitionHasNoTypeParamsThenNameIsBoundToType() { + public void whenStructDefinitionHasNoTypeParamsThenStructNameIsBoundToType() { var untyped = UntypedStructDefinitionNode.arbitrary() .withName("X") .build(); @@ -41,7 +41,7 @@ public class TypeCheckerStructDefinitionTests { } @Test - public void whenStructDefinitionHasTypeParamsThenNameIsBoundToTypeConstructor() { + public void whenStructDefinitionHasTypeParamsThenStructNameIsBoundToTypeConstructor() { var untyped = UntypedStructDefinitionNode.arbitrary() .withName("X") .withTypeParams(Optional.of(List.of( @@ -160,6 +160,67 @@ public class TypeCheckerStructDefinitionTests { } @Test + public void whenStructDefinitionHasTypeParamsThenTypeParamsAreBoundWithinStructDefinition() { + var untyped = UntypedStructDefinitionNode.arbitrary() + .withName("X") + .withTypeParams(Optional.of(List.of( + UntypedTypeParamNode.arbitrary().withName("A").build(), + UntypedTypeParamNode.arbitrary().withName("B").build() + ))) + .withFields(List.of( + UntypedStructFieldDefinitionNode.arbitrary() + .withName("a") + .withType(UntypedArb.typeLevelReference("A")) + .build(), + UntypedStructFieldDefinitionNode.arbitrary() + .withName("b") + .withType(UntypedArb.typeLevelReference("B")) + .build() + )) + .build(); + var globalContext = TypeCheckerGlobalContext.initial(); + var namespaceName = NamespaceName.of("a", "b"); + var namespaceContext = globalContext.enterNamespace(namespaceName); + + var typed = typeCheckNamespaceStatement(untyped, namespaceContext); + + var expectedInnerType = new SimpleStructType(NamespaceName.of("a", "b"), "X"); + assertThat(typed, instanceOf( + TypedStructDefinitionNode.class, + has( + "fields", + TypedStructDefinitionNode::fields, + isOptionalOf(isSequence( + allOf( + has("name", TypedStructFieldDefinitionNode::name, equalTo("a")), + has("type", TypedStructFieldDefinitionNode::type, has( + "value", + TypedTypeLevelExpressionNode::value, + equalTo(new TypeParam(expectedInnerType, "A")) + )) + ), + allOf( + has("name", TypedStructFieldDefinitionNode::name, equalTo("b")), + has("type", TypedStructFieldDefinitionNode::type, has( + "value", + TypedTypeLevelExpressionNode::value, + equalTo(new TypeParam(expectedInnerType, "B")) + )) + ) + )) + ) + )); + var typesInfo = globalContext.toTypesInfo(); + assertThat( + typesInfo.fieldsOf(new SimpleStructType(namespaceName, "X")), + isOptionalOf(isSequence( + isField("a", new TypeParam(expectedInnerType, "A")), + isField("b", new TypeParam(expectedInnerType, "B")) + )) + ); + } + + @Test public void structCanUseTypeDefinedLater() { var int32Type = SimpleNativeType.builtin("Int32"); var namespaceName = NamespaceName.of("a", "b"); |
