aboutsummaryrefslogtreecommitdiff
path: root/src/test/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-01 19:37:52 +0100
committerMichael Williamson <mike@zwobble.org>2023-10-01 19:37:52 +0100
commit0f40994a60b060bddba5f08f5f43e4c49099c015 (patch)
tree41d67d5d4adb3a112127f89780c783d8267668ae /src/test/java
parent1dc8b36afbdb164029212d199d225c728c1fa5d9 (diff)
Add basic type checking for when expressions
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java21
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java14
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java14
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java19
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java18
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java18
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java19
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java15
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java68
9 files changed, 118 insertions, 88 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 1f64f631..c5281090 100644
--- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
@@ -348,6 +348,27 @@ public class TypedNodeMatchers {
);
}
+ public static Matcher<TypedExpressionNode> isTypedWhenNode(
+ Matcher<TypedExpressionNode> expression,
+ Matcher<Iterable<? extends TypedWhenCaseNode>> cases
+ ) {
+ return instanceOf(
+ TypedWhenNode.class,
+ has("expression", x -> x.expression(), expression),
+ has("cases", x -> x.cases(), cases)
+ );
+ }
+
+ public static Matcher<TypedWhenCaseNode> isTypedWhenCaseNode(
+ Matcher<TypedTypeLevelExpressionNode<?>> caseType,
+ Matcher<TypedBlockNode> body
+ ) {
+ return allOf(
+ has("caseType", x -> x.caseType(), caseType),
+ has("body", x -> x.body(), body)
+ );
+ }
+
public static Matcher<TypedFunctionStatementNode> isTypedWhileNode(
Matcher<? super TypedExpressionNode> condition,
Matcher<? super TypedBlockNode> body
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
index 21335011..09067087 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
@@ -207,6 +207,20 @@ public class Untyped {
return new UntypedAssignNode(targetVal(targetName), expression, Sources.NULL);
}
+ public static UntypedWhenNode when(
+ UntypedExpressionNode expression,
+ List<UntypedWhenCaseNode> cases
+ ) {
+ return new UntypedWhenNode(expression, cases, Sources.NULL);
+ }
+
+ public static UntypedWhenCaseNode whenCase(
+ UntypedTypeLevelExpressionNode caseType,
+ UntypedBlockNode body
+ ) {
+ return new UntypedWhenCaseNode(caseType, body, Sources.NULL);
+ }
+
public static UntypedWhileNode while_(
UntypedExpressionNode condition,
UntypedBlockNode body
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java
index cc161b56..ff2e3f1d 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java
@@ -2,10 +2,8 @@ package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
import org.shedlang.compiler.ast.typed.TypedFunctionStatementNode;
-import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.Untyped;
import org.shedlang.compiler.ast.untyped.UntypedFunctionStatementNode;
-import org.shedlang.compiler.ast.untyped.UntypedNamespaceStatementNode;
import org.shedlang.compiler.typechecker.errors.CanOnlyAssignToVarError;
import org.shedlang.compiler.typechecker.errors.TargetTupleHasWrongElementCount;
import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError;
@@ -177,16 +175,4 @@ public class TypeCheckerAssignTests {
return TypeChecker.typeCheckFunctionStatement(untyped, context);
}
-
- private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement(
- UntypedNamespaceStatementNode untyped,
- TypeCheckerContext context
- ) {
- var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector());
- var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables);
-
- context = context.enterNamespace(NamespaceName.of("Example"), environment.build());
-
- return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context);
- }
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java
index d6a600bc..78b89e90 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java
@@ -1,13 +1,15 @@
package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
-import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.Untyped;
import org.shedlang.compiler.ast.untyped.UntypedCallNode;
import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode;
import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError;
import org.shedlang.compiler.typechecker.typesets.TypeSets;
-import org.shedlang.compiler.types.*;
+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;
@@ -15,6 +17,7 @@ import java.util.Map;
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.*;
@@ -383,16 +386,4 @@ public class TypeCheckerFunctionDefinitionTests {
)))
);
}
-
- private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement(
- UntypedFunctionDefinitionNode untyped,
- TypeCheckerContext context
- ) {
- var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector());
- var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables);
-
- context = context.enterNamespace(NamespaceName.of("Example"), environment.build());
-
- return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context);
- }
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java
index 53c5d5e8..344cfa66 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java
@@ -1,9 +1,7 @@
package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
-import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.Untyped;
-import org.shedlang.compiler.ast.untyped.UntypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.UntypedStructDefinitionNode;
import org.shedlang.compiler.typechecker.errors.CannotDefineStructOutsideOfNamespace;
import org.shedlang.compiler.types.NamespaceName;
@@ -14,6 +12,7 @@ import java.util.Map;
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.shedlang.compiler.types.TypeMatchers.isStructType;
import static org.zwobble.precisely.AssertThat.assertThat;
import static org.zwobble.precisely.Matchers.*;
@@ -30,7 +29,7 @@ public class TypeCheckerStructDefinitionTests {
assertThrows(
CannotDefineStructOutsideOfNamespace.class,
- () -> TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context)
+ () -> TypeChecker.typeCheckStepsNamespaceStatement(untyped).typeCheckAllPhases(context)
);
}
@@ -126,17 +125,4 @@ public class TypeCheckerStructDefinitionTests {
))
);
}
-
- private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement(
- UntypedNamespaceStatementNode untyped,
- TypeCheckerContext context
- ) {
- // TODO: remove duplication of this method
- var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector());
- var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables);
-
- context = context.enterNamespace(NAMESPACE_NAME, environment.build());
-
- return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context);
- }
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java
index d70d3660..f93cea14 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerSumTypeDefinitionTests.java
@@ -1,9 +1,7 @@
package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
-import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.Untyped;
-import org.shedlang.compiler.ast.untyped.UntypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.UntypedSumTypeDefinitionNode;
import org.shedlang.compiler.typechecker.errors.CannotDefineSumTypeOutsideOfNamespace;
import org.shedlang.compiler.types.NamespaceName;
@@ -14,6 +12,7 @@ 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.zwobble.precisely.AssertThat.assertThat;
import static org.zwobble.precisely.Matchers.*;
@@ -29,7 +28,7 @@ public class TypeCheckerSumTypeDefinitionTests {
assertThrows(
CannotDefineSumTypeOutsideOfNamespace.class,
- () -> TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context)
+ () -> TypeChecker.typeCheckStepsNamespaceStatement(untyped).typeCheckAllPhases(context)
);
}
@@ -82,17 +81,4 @@ public class TypeCheckerSumTypeDefinitionTests {
))
);
}
-
- private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement(
- UntypedNamespaceStatementNode untyped,
- TypeCheckerContext context
- ) {
- // TODO: remove duplication of this method
- var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector());
- var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables);
-
- context = context.enterNamespace(NAMESPACE_NAME, environment.build());
-
- return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context);
- }
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java
index 9fd948ba..2688a4c1 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java
@@ -2,8 +2,10 @@ package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
import org.shedlang.compiler.ast.typed.TypedFunctionStatementNode;
-import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode;
-import org.shedlang.compiler.ast.untyped.*;
+import org.shedlang.compiler.ast.untyped.Untyped;
+import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode;
+import org.shedlang.compiler.ast.untyped.UntypedFunctionStatementNode;
+import org.shedlang.compiler.ast.untyped.UntypedNamespaceNode;
import org.shedlang.compiler.typechecker.errors.DuplicateVariableName;
import org.shedlang.compiler.typechecker.errors.ReferenceBeforeDefinitionError;
import org.shedlang.compiler.types.NamespaceName;
@@ -14,6 +16,7 @@ import java.util.Map;
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.*;
@@ -157,16 +160,4 @@ public class TypeCheckerValTests {
return TypeChecker.typeCheckFunctionStatement(untyped, context);
}
-
- private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement(
- UntypedNamespaceStatementNode untyped,
- TypeCheckerContext context
- ) {
- var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector());
- var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables);
-
- context = context.enterNamespace(NamespaceName.of("Example"), environment.build());
-
- return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context);
- }
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java
index 466ab16c..53e2e65f 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java
@@ -2,11 +2,9 @@ package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
import org.shedlang.compiler.ast.typed.TypedFunctionStatementNode;
-import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode;
import org.shedlang.compiler.ast.untyped.Untyped;
import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode;
import org.shedlang.compiler.ast.untyped.UntypedFunctionStatementNode;
-import org.shedlang.compiler.ast.untyped.UntypedNamespaceStatementNode;
import org.shedlang.compiler.types.NamespaceName;
import org.shedlang.compiler.types.Types;
import org.shedlang.compiler.util.P;
@@ -14,6 +12,7 @@ import org.shedlang.compiler.util.P;
import java.util.Map;
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.anything;
import static org.zwobble.precisely.Matchers.isSequence;
@@ -65,16 +64,4 @@ public class TypeCheckerVarTests {
return TypeChecker.typeCheckFunctionStatement(untyped, context);
}
-
- private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement(
- UntypedNamespaceStatementNode untyped,
- TypeCheckerContext context
- ) {
- var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector());
- var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables);
-
- context = context.enterNamespace(NamespaceName.of("Example"), environment.build());
-
- return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context);
- }
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java
new file mode 100644
index 00000000..4fdaf950
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java
@@ -0,0 +1,68 @@
+package org.shedlang.compiler.typechecker;
+
+import org.junit.jupiter.api.Test;
+import org.shedlang.compiler.ast.untyped.Untyped;
+import org.shedlang.compiler.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.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.isSequence;
+
+public class TypeCheckerWhenTests {
+ private static final NamespaceName NAMESPACE_NAME = NamespaceName.of("Example", "Project");
+ private static final SumType SUM_TYPE = Types.sum(NAMESPACE_NAME, "SumType");
+ private static final StructType VARIANT_TYPE_1 = Types.struct(NAMESPACE_NAME, "Variant1");
+ private static final StructType VARIANT_TYPE_2 = Types.struct(NAMESPACE_NAME, "Variant2");
+
+ @Test
+ public void whenAllCasesAreHandledThenExpressionTypeChecks() {
+ var untyped = Untyped.when(
+ Untyped.reference("x"),
+ List.of(
+ Untyped.whenCase(
+ Untyped.typeLevelReference(VARIANT_TYPE_1.name()),
+ Untyped.block(List.of(
+ Untyped.blockReturn(Untyped.stringLiteral("a"))
+ ))
+ ),
+ Untyped.whenCase(
+ Untyped.typeLevelReference(VARIANT_TYPE_2.name()),
+ Untyped.block(List.of(
+ Untyped.blockReturn(Untyped.stringLiteral("b"))
+ ))
+ )
+ )
+ );
+ var context = TypeCheckerContext.EMPTY
+ .addSumTypeInfo(SUM_TYPE, new SumTypeInfo(P.orderedSet(VARIANT_TYPE_1, VARIANT_TYPE_2)))
+ .enterGlobal(P.map(
+ Map.entry("x", SUM_TYPE),
+ Map.entry(VARIANT_TYPE_1.name(), Types.metaType(VARIANT_TYPE_1)),
+ Map.entry(VARIANT_TYPE_2.name(), Types.metaType(VARIANT_TYPE_2))
+ ));
+
+ var result = TypeChecker.typeCheckExpression(untyped, context);
+
+ assertThat(result.value(), isTypedWhenNode(
+ isTypedReferenceNode("x", SUM_TYPE),
+ isSequence(
+ isTypedWhenCaseNode(
+ isTypedTypeLevelReferenceNode("Variant1", VARIANT_TYPE_1),
+ isTypedBlockNode(isSequence(
+ isTypedBlockReturnNode(isTypedStringLiteralNode("a"))
+ ))
+ ),
+ isTypedWhenCaseNode(
+ isTypedTypeLevelReferenceNode("Variant2", VARIANT_TYPE_2),
+ isTypedBlockNode(isSequence(
+ isTypedBlockReturnNode(isTypedStringLiteralNode("b"))
+ ))
+ )
+ )
+ ));
+ }
+}