diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-10-25 21:58:28 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-10-25 21:59:51 +0100 |
| commit | ce0b25de9fa8f7423391357db75bd72ad6c9e7df (patch) | |
| tree | 7234f305f56cd9f146014794614dbd78daf30216 /src/test/java | |
| parent | 693c3afe929b693de48346f281ce5b1d95d0fcdb (diff) | |
Extract tests for type-checking function signatures
Diffstat (limited to 'src/test/java')
4 files changed, 156 insertions, 56 deletions
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNodeMatcher.java new file mode 100644 index 00000000..e93d45fe --- /dev/null +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNodeMatcher.java @@ -0,0 +1,56 @@ +package org.shedlang.compiler.ast.typed; + +import org.pcollections.Empty; +import org.pcollections.PVector; +import org.shedlang.compiler.testing.MatcherBuilder; +import org.shedlang.compiler.types.FunctionType; +import org.zwobble.precisely.Matcher; + +import java.util.Optional; + +import static org.zwobble.precisely.Matchers.equalTo; +import static org.zwobble.precisely.Matchers.has; + +public class TypedFunctionSignatureNodeMatcher extends MatcherBuilder< + TypedFunctionSignatureNode, + TypedFunctionSignatureNode, + TypedFunctionSignatureNodeMatcher +> { + public static TypedFunctionSignatureNodeMatcher empty() { + return new TypedFunctionSignatureNodeMatcher(Empty.vector()); + } + + public TypedFunctionSignatureNodeMatcher( + PVector<Matcher<? super TypedFunctionSignatureNode>> submatchers + ) { + super(submatchers); + } + + @Override + protected Class<TypedFunctionSignatureNode> expectedType() { + return TypedFunctionSignatureNode.class; + } + + @Override + protected TypedFunctionSignatureNodeMatcher create( + PVector<Matcher<? super TypedFunctionSignatureNode>> submatchers + ) { + return new TypedFunctionSignatureNodeMatcher(submatchers); + } + + public TypedFunctionSignatureNodeMatcher withEffect(Matcher<Optional<? extends TypedTypeLevelExpressionNode<?>>> effect) { + return with(has("effect", x -> x.effect(), effect)); + } + + public TypedFunctionSignatureNodeMatcher withParams(Matcher<TypedParamsNode> params) { + return with(has("params", x -> x.params(), params)); + } + + public TypedFunctionSignatureNodeMatcher withReturnType(Matcher<TypedTypeLevelExpressionNode<?>> returnType) { + return with(has("returnType", x -> x.returnType(), returnType)); + } + + public TypedFunctionSignatureNodeMatcher withType(FunctionType type) { + return with(has("type", x -> x.type(), equalTo(type))); + } +} 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 112b2f02..2723883e 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -125,6 +125,10 @@ public class TypedNodeMatchers { ); } + public static TypedFunctionSignatureNodeMatcher isTypedFunctionSignatureNode() { + return TypedFunctionSignatureNodeMatcher.empty(); + } + public static Matcher<TypedTypeLevelExpressionNode<?>> isTypedFunctionTypeNode( Matcher<FunctionType> value ) { diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java index 00fa8e9e..3354f0bf 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java @@ -9,7 +9,6 @@ import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; import org.shedlang.compiler.typechecker.typesets.TypeSets; import org.shedlang.compiler.types.Effects; import org.shedlang.compiler.types.FunctionType; -import org.shedlang.compiler.types.NamedParam; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -47,42 +46,9 @@ public class TypeCheckerFunctionDefinitionTests { } @Test - public void paramsAreTypeChecked() { - var untyped = UntypedFunctionDefinitionNode.builder() - .addPositionalParam("x", Untyped.typeLevelReference("String")) - .addNamedParam("y", Untyped.typeLevelReference("Int")) - .withReturnType(Untyped.typeLevelReference("Unit")) - .build(); - var context = TypeCheckerContext.EMPTY - .enterGlobal(P.map( - Map.entry("Int", Types.metaType(Types.INT)), - Map.entry("String", Types.metaType(Types.STRING)), - Map.entry("Unit", Types.metaType(Types.UNIT)) - )); - - var typed = typeCheckNamespaceStatement(untyped, context); - - assertThat( - typed.value(), - isTypedFunctionDefinitionNode() - .withParams( - isTypedParamsNode( - isSequence(isTypedParamNode("x", isTypedTypeLevelReferenceNode("String", Types.STRING))), - isSequence(isTypedParamNode("y", isTypedTypeLevelReferenceNode("Int", Types.INT))) - ) - ) - .withType(new FunctionType( - List.of(Types.STRING), - List.of(new NamedParam("y", Types.INT)), - Effects.NONE, - Types.UNIT - )) - ); - } - - @Test public void paramsMustHaveUniqueNames() { var untyped = UntypedFunctionDefinitionNode.builder() + .withName("f") .addPositionalParam("x", Untyped.typeLevelReference("String")) .addPositionalParam("x", Untyped.typeLevelReference("Int")) .withReturnType(Untyped.typeLevelReference("Unit")) @@ -103,27 +69,6 @@ public class TypeCheckerFunctionDefinitionTests { } @Test - public void effectIsTypeChecked() { - var untyped = UntypedFunctionDefinitionNode.builder() - .withEffect(Untyped.typeLevelReference("Io")) - .withReturnType(Untyped.typeLevelReference("Unit")) - .build(); - var context = TypeCheckerContext.EMPTY - .enterGlobal(P.map( - Map.entry("Io", Types.effectType(Effects.IO)), - Map.entry("Unit", Types.metaType(Types.UNIT)) - )); - - var typed = typeCheckNamespaceStatement(untyped, context); - - assertThat( - typed.value(), - isTypedFunctionDefinitionNode() - .withEffect(isOptionalOf(isTypedTypeLevelReferenceNode("Io", Effects.IO))) - ); - } - - @Test public void bodyIsTypeChecked() { var untyped = UntypedFunctionDefinitionNode.builder() .withReturnType(Untyped.typeLevelReference("Unit")) diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionSignatureTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionSignatureTests.java new file mode 100644 index 00000000..512c5650 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionSignatureTests.java @@ -0,0 +1,95 @@ +package org.shedlang.compiler.typechecker; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.ast.untyped.Untyped; +import org.shedlang.compiler.ast.untyped.UntypedFunctionSignatureNode; +import org.shedlang.compiler.types.Effects; +import org.shedlang.compiler.types.FunctionType; +import org.shedlang.compiler.types.NamedParam; +import org.shedlang.compiler.types.Types; +import org.shedlang.compiler.util.P; + +import java.util.List; +import java.util.Map; + +import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*; +import static org.shedlang.compiler.typechecker.TypeChecker.typeCheckFunctionSignature; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class TypeCheckerFunctionSignatureTests { + @Test + public void canTypeCheckMinimalFunctionSignature() { + var untyped = UntypedFunctionSignatureNode.builder() + .withReturnType(Untyped.typeLevelReference("Unit")) + .build(); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map(Map.entry("Unit", Types.metaType(Types.UNIT)))); + + var typed = typeCheckFunctionSignature(untyped, context); + + assertThat( + typed, + isTypedFunctionSignatureNode() + .withParams(isTypedParamsNode(isSequence(), isSequence())) + .withEffect(isOptionalEmpty()) + .withReturnType(isTypedTypeLevelReferenceNode("Unit", Types.UNIT)) + .withType(new FunctionType(List.of(), List.of(), Effects.NONE, Types.UNIT)) + ); + } + + @Test + public void paramsAreTypeChecked() { + var untyped = UntypedFunctionSignatureNode.builder() + .addPositionalParam("x", Untyped.typeLevelReference("String")) + .addNamedParam("y", Untyped.typeLevelReference("Int")) + .withReturnType(Untyped.typeLevelReference("Unit")) + .build(); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry("Int", Types.metaType(Types.INT)), + Map.entry("String", Types.metaType(Types.STRING)), + Map.entry("Unit", Types.metaType(Types.UNIT)) + )); + + var typed = typeCheckFunctionSignature(untyped, context); + + assertThat( + typed, + isTypedFunctionSignatureNode() + .withParams( + isTypedParamsNode( + isSequence(isTypedParamNode("x", isTypedTypeLevelReferenceNode("String", Types.STRING))), + isSequence(isTypedParamNode("y", isTypedTypeLevelReferenceNode("Int", Types.INT))) + ) + ) + .withType(new FunctionType( + List.of(Types.STRING), + List.of(new NamedParam("y", Types.INT)), + Effects.NONE, + Types.UNIT + )) + ); + } + + @Test + public void effectIsTypeChecked() { + var untyped = UntypedFunctionSignatureNode.builder() + .withEffect(Untyped.typeLevelReference("Io")) + .withReturnType(Untyped.typeLevelReference("Unit")) + .build(); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry("Io", Types.effectType(Effects.IO)), + Map.entry("Unit", Types.metaType(Types.UNIT)) + )); + + var typed = typeCheckFunctionSignature(untyped, context); + + assertThat( + typed, + isTypedFunctionSignatureNode() + .withEffect(isOptionalOf(isTypedTypeLevelReferenceNode("Io", Effects.IO))) + ); + } +} |
