diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-10 15:01:43 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-10 15:01:43 +0100 |
| commit | 3352299423098fa32275345f46beec19892f6e99 (patch) | |
| tree | f46760d005e82a841fd69fc87d9125d1f3867205 /src/test/java | |
| parent | 01bd9f9bdfa3d6257d5fd0177c769b30de8f4930 (diff) | |
Add minimal type checking for function definition
Diffstat (limited to 'src/test/java')
4 files changed, 118 insertions, 4 deletions
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNodeMatcher.java new file mode 100644 index 00000000..04a06f64 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNodeMatcher.java @@ -0,0 +1,51 @@ +package org.shedlang.compiler.ast.typed; + +import org.pcollections.Empty; +import org.pcollections.PVector; +import org.shedlang.compiler.testing.MatcherBuilder; +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 TypedFunctionDefinitionNodeMatcher extends MatcherBuilder<TypedNamespaceStatementNode, TypedFunctionDefinitionNode, TypedFunctionDefinitionNodeMatcher> { + public static TypedFunctionDefinitionNodeMatcher empty() { + return new TypedFunctionDefinitionNodeMatcher(Empty.vector()); + } + + public TypedFunctionDefinitionNodeMatcher(PVector<Matcher<? super TypedFunctionDefinitionNode>> submatchers) { + super(submatchers); + } + + @Override + protected Class<TypedFunctionDefinitionNode> expectedType() { + return TypedFunctionDefinitionNode.class; + } + + @Override + protected TypedFunctionDefinitionNodeMatcher create(PVector<Matcher<? super TypedFunctionDefinitionNode>> submatchers) { + return new TypedFunctionDefinitionNodeMatcher(submatchers); + } + + public TypedFunctionDefinitionNodeMatcher withBody(Matcher<Iterable<TypedFunctionStatementNode>> body) { + return with(has("body", x -> x.body(), body)); + } + + public TypedFunctionDefinitionNodeMatcher withEffect(Matcher<Optional<? extends TypedTypeLevelExpressionNode<?>>> effect) { + return with(has("effect", x -> x.effect(), effect)); + } + + public TypedFunctionDefinitionNodeMatcher withName(String name) { + return with(has("name", x -> x.name(), equalTo(name))); + } + + public TypedFunctionDefinitionNodeMatcher withParams(Matcher<TypedParamsNode> params) { + return with(has("params", x -> x.params(), params)); + } + + public TypedFunctionDefinitionNodeMatcher withReturnType(Matcher<TypedTypeLevelExpressionNode<?>> returnType) { + return with(has("returnType", x -> x.returnType(), returnType)); + } +} 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 c3aaa729..474646d4 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -36,6 +36,10 @@ public class TypedNodeMatchers { ); } + public static TypedFunctionDefinitionNodeMatcher isTypedFunctionDefinitionNode() { + return TypedFunctionDefinitionNodeMatcher.empty(); + } + public static Matcher<TypedExpressionNode> isTypedIntLiteralNode(int value) { return isTypedIntLiteralNode(BigInteger.valueOf(value)); } @@ -57,6 +61,26 @@ public class TypedNodeMatchers { ); } + public static Matcher<TypedParamNode> isTypedParamNode( + String name, + Matcher<TypedTypeLevelExpressionNode<?>> type + ) { + return allOf( + has("name", x -> x.name(), equalTo(name)), + has("type", x -> x.type(), type) + ); + } + + public static Matcher<TypedParamsNode> isTypedParamsNode( + Matcher<Iterable<TypedParamNode>> positional, + Matcher<Iterable<TypedParamNode>> named + ) { + return allOf( + has("positional", x -> x.positional(), positional), + has("named", x -> x.named(), named) + ); + } + public static Matcher<TypedExpressionNode> isTypedReferenceNode(String name, Type type) { return instanceOf( TypedReferenceNode.class, @@ -72,7 +96,7 @@ public class TypedNodeMatchers { ); } - public static Matcher<TypedTypeLevelExpressionNode> isTypedTypeLevelReferenceNode( + public static Matcher<TypedTypeLevelExpressionNode<?>> isTypedTypeLevelReferenceNode( String name, TypeLevelValue value ) { diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java new file mode 100644 index 00000000..88027a69 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java @@ -0,0 +1,38 @@ +package org.shedlang.compiler.typechecker; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.ast.untyped.Untyped; +import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode; +import org.shedlang.compiler.types.Types; +import org.shedlang.compiler.util.P; + +import java.util.Map; + +import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.isOptionalEmpty; +import static org.zwobble.precisely.Matchers.isSequence; + +public class TypeCheckerFunctionDefinitionTests { + @Test + public void canTypeCheckMinimalFunctionDefinition() { + var untyped = UntypedFunctionDefinitionNode.builder() + .withName("f") + .withReturnType(Untyped.typeLevelReference("Unit")) + .build(); + var context = TypeCheckerContext.EMPTY + .enter(P.map(Map.entry("Unit", Types.metaType(Types.UNIT)))); + + var typed = TypeChecker.typeCheckNamespaceStatement(untyped, context); + + assertThat( + typed, + isTypedFunctionDefinitionNode() + .withName("f") + .withParams(isTypedParamsNode(isSequence(), isSequence())) + .withEffect(isOptionalEmpty()) + .withReturnType(isTypedTypeLevelReferenceNode("Unit", Types.UNIT)) + .withBody(isSequence()) + ); + } +} diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java index a0597778..13e7dc2c 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java @@ -5,6 +5,7 @@ import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; import org.shedlang.compiler.typechecker.errors.UnknownVariableError; import org.shedlang.compiler.typechecker.typesets.TypeSets; +import org.shedlang.compiler.types.Type; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -22,7 +23,7 @@ public class TypeCheckerTypeLevelReferenceTests { var context = TypeCheckerContext.EMPTY .enter(P.map(Map.entry("String", Types.metaType(Types.STRING)))); - var typed = TypeChecker.typeCheckTypeLevelExpression(untyped, context); + var typed = TypeChecker.typeCheckTypeLevelExpression(Type.class, untyped, context); assertThat(typed, isTypedTypeLevelReferenceNode("String", Types.STRING)); } @@ -35,7 +36,7 @@ public class TypeCheckerTypeLevelReferenceTests { var error = assertThrows( UnexpectedTypeError.class, - () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context) + () -> TypeChecker.typeCheckTypeLevelExpression(Type.class, untyped, context) ); assertThat(error.expected(), equalTo(TypeSets.TYPE_LEVEL_VALUE)); @@ -50,7 +51,7 @@ public class TypeCheckerTypeLevelReferenceTests { var error = assertThrows( UnknownVariableError.class, - () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context) + () -> TypeChecker.typeCheckTypeLevelExpression(Type.class, untyped, context) ); assertThat(error.variableName(), equalTo("String")); |
