aboutsummaryrefslogtreecommitdiff
path: root/src/test/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2025-01-12 21:41:15 +0000
committerMichael Williamson <mike@zwobble.org>2025-01-12 21:41:15 +0000
commit6b3d2b650c8e6d0dbb35091e279d142db8bedb02 (patch)
tree2d00c8c199b4bac5bc4ad29d1b938b61a58caf90 /src/test/java
parente806ce6188342e3356941b70f11e630b2167b17d (diff)
Type check native function declarations
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNodeMatcher.java59
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java4
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNativeFunctionDeclarationTests.java72
3 files changed, 135 insertions, 0 deletions
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNodeMatcher.java
new file mode 100644
index 00000000..94c8c65a
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNodeMatcher.java
@@ -0,0 +1,59 @@
+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.*;
+
+public class TypedNativeFunctionDeclarationNodeMatcher extends MatcherBuilder<
+ TypedNamespaceStatementNode,
+ TypedNativeFunctionDeclarationNode,
+ TypedNativeFunctionDeclarationNodeMatcher
+> {
+ public static TypedNativeFunctionDeclarationNodeMatcher empty() {
+ return new TypedNativeFunctionDeclarationNodeMatcher(Empty.vector());
+ }
+
+ public TypedNativeFunctionDeclarationNodeMatcher(
+ PVector<Matcher<? super TypedNativeFunctionDeclarationNode>> submatchers
+ ) {
+ super(submatchers);
+ }
+
+ @Override
+ protected Class<TypedNativeFunctionDeclarationNode> expectedType() {
+ return TypedNativeFunctionDeclarationNode.class;
+ }
+
+ @Override
+ protected TypedNativeFunctionDeclarationNodeMatcher create(
+ PVector<Matcher<? super TypedNativeFunctionDeclarationNode>> submatchers
+ ) {
+ return new TypedNativeFunctionDeclarationNodeMatcher(submatchers);
+ }
+
+ public TypedNativeFunctionDeclarationNodeMatcher withEffect(Matcher<Optional<? extends TypedTypeLevelExpressionNode<?>>> effect) {
+ return with(has("effect", x -> x.signature().effect(), effect));
+ }
+
+ public TypedNativeFunctionDeclarationNodeMatcher withName(String name) {
+ return with(has("name", x -> x.name(), equalTo(name)));
+ }
+
+ public TypedNativeFunctionDeclarationNodeMatcher withParams(Matcher<TypedParamsNode> params) {
+ return with(has("params", x -> x.signature().params(), params));
+ }
+
+ public TypedNativeFunctionDeclarationNodeMatcher withReturnType(Matcher<TypedTypeLevelExpressionNode<?>> returnType) {
+ return with(has("returnType", x -> x.signature().returnType(), isOptionalOf(returnType)));
+ }
+
+ public TypedNativeFunctionDeclarationNodeMatcher 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 2002577f..902ba59d 100644
--- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
@@ -244,6 +244,10 @@ public class TypedNodeMatchers {
return TypedNamespaceNodeMatcher.empty();
}
+ public static TypedNativeFunctionDeclarationNodeMatcher isTypedNativeFunctionDeclarationNode() {
+ return TypedNativeFunctionDeclarationNodeMatcher.empty();
+ }
+
public static Matcher<TypedParamNode> isTypedParamNode(
String name,
Matcher<Optional<? extends TypedTypeLevelExpressionNode<?>>> type
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNativeFunctionDeclarationTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNativeFunctionDeclarationTests.java
new file mode 100644
index 00000000..b6a5ce9d
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNativeFunctionDeclarationTests.java
@@ -0,0 +1,72 @@
+package org.shedlang.compiler.typechecker;
+
+import org.junit.jupiter.api.Test;
+import org.shedlang.compiler.ast.untyped.Untyped;
+import org.shedlang.compiler.ast.untyped.UntypedNativeFunctionDeclarationNode;
+import org.shedlang.compiler.typechecker.errors.FunctionSignatureMissingParamTypeError;
+import org.shedlang.compiler.typechecker.errors.FunctionSignatureMissingReturnTypeError;
+import org.shedlang.compiler.types.FunctionType;
+import org.shedlang.compiler.types.Types;
+import org.shedlang.compiler.util.P;
+
+import java.util.Map;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*;
+import static org.shedlang.compiler.typechecker.TypeCheckerTesting.typeCheckNamespaceStatement;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.isOptionalEmpty;
+import static org.zwobble.precisely.Matchers.isSequence;
+
+public class TypeCheckerNativeFunctionDeclarationTests {
+ @Test
+ public void canTypeCheckMinimalNativeFunctionDeclaration() {
+ var untyped = UntypedNativeFunctionDeclarationNode.builder()
+ .withName("f")
+ .withReturnType(Untyped.typeLevelReference("Unit"))
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enterGlobal(P.map(Map.entry("Unit", Types.metaType(Types.UNIT))));
+
+ var typed = typeCheckNamespaceStatement(untyped, context);
+
+ assertThat(
+ typed.value(),
+ isTypedNativeFunctionDeclarationNode()
+ .withName("f")
+ .withParams(isTypedParamsNode(isSequence(), isSequence()))
+ .withEffect(isOptionalEmpty())
+ .withReturnType(isTypedTypeLevelReferenceNode("Unit", Types.UNIT))
+ .withType(FunctionType.builder().withReturnType(Types.UNIT).build())
+ );
+ }
+
+ @Test
+ public void whenSignatureIsMissingReturnTypeThenErrorIsThrown() {
+ var untyped = UntypedNativeFunctionDeclarationNode.builder()
+ .withoutReturnType()
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThrows(
+ FunctionSignatureMissingReturnTypeError.class,
+ () -> typeCheckNamespaceStatement(untyped, context)
+ );
+ }
+
+ @Test
+ public void whenSignatureIsMissingParamTypeThenErrorIsThrown() {
+ var untyped = UntypedNativeFunctionDeclarationNode.builder()
+ .addPositionalParam("x", Optional.empty())
+ .withReturnType(Untyped.typeLevelReference("Unit"))
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enterGlobal(P.map(Map.entry("Unit", Types.metaType(Types.UNIT))));
+
+ assertThrows(
+ FunctionSignatureMissingParamTypeError.class,
+ () -> typeCheckNamespaceStatement(untyped, context)
+ );
+ }
+}