diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-12-03 00:21:36 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-12-03 00:21:36 +0000 |
| commit | 86f4db9a9daf5207e047284fef93bceec3b5e0c9 (patch) | |
| tree | acb6a871763a1a3998ef865f43cecda7d8e70d3e /src/test/java/org | |
| parent | 2dbc90aacf38c68fe06209b998bb2c7b2ef9f560 (diff) | |
Use break statements to determine type of try expression
Diffstat (limited to 'src/test/java/org')
| -rw-r--r-- | src/test/java/org/shedlang/compiler/ast/typed/TypedTryNodeMatcher.java | 7 | ||||
| -rw-r--r-- | src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java | 70 |
2 files changed, 77 insertions, 0 deletions
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedTryNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedTryNodeMatcher.java index 9bc549d3..5efbc24d 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedTryNodeMatcher.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedTryNodeMatcher.java @@ -2,6 +2,7 @@ package org.shedlang.compiler.ast.typed; import org.pcollections.PVector; import org.shedlang.compiler.testing.MatcherBuilder; +import org.shedlang.compiler.types.Type; import org.shedlang.compiler.util.P; import org.zwobble.precisely.Matcher; @@ -38,6 +39,12 @@ public class TypedTryNodeMatcher extends MatcherBuilder< return with(has("body", x -> x.body(), body)); } + public TypedTryNodeMatcher withType( + Matcher<Type> type + ) { + return with(has("type", x -> x.type(), type)); + } + public TypedTryNodeMatcher withHandlerMethods( Matcher<? super Iterable<TypedTryHandlerMethodNode>> handlerMethods ) { diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java index 2d60446b..23be48ef 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java @@ -8,6 +8,7 @@ import org.shedlang.compiler.typechecker.typesets.TypeSets; import org.shedlang.compiler.types.*; import org.shedlang.compiler.util.P; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -46,6 +47,75 @@ public class TypeCheckerTryTests { } @Test + public void typeIsCommonSupertypeOfBodyTypeAndBreaksInHandlerMethods() { + var untyped = UntypedTryNode.builder() + .addBodyStatement(Untyped.blockReturn(Untyped.intLiteral(42))) + .withHandledEffect(Untyped.typeLevelReference("Effect")) + .addHandlerMethod( + UntypedTryHandlerMethodNode.builder() + .withName("a") + .addStatement(Untyped.break_(Untyped.stringLiteral(""))) + .build() + ) + .build(); + var effect = Effects.userDefined(NAMESPACE_NAME, "Effect"); + var effectInfo = UserDefinedEffectInfo.builder() + .addMethod("a", FunctionType.builder().withReturnType(Types.UNIT).build()) + .build(); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry("Effect", Types.effectType(effect)) + )) + .addUserDefinedEffectInfo(effect, effectInfo); + + var result = typeCheckExpression(untyped, context); + + assertThat( + result.value(), + isTypedTryNode() + .withType(equalTo(Types.commonSupertype(List.of(Types.INT, Types.STRING)))) + ); + } + + @Test + public void resumeStatementsAreIgnoredWhenDeterminingTypeOfTry() { + var untyped = UntypedTryNode.builder() + .addBodyStatement(Untyped.blockReturn(Untyped.intLiteral(42))) + .withHandledEffect(Untyped.typeLevelReference("Effect")) + .addHandlerMethod( + UntypedTryHandlerMethodNode.builder() + .withName("a") + .addStatement(Untyped.resume()) + .build() + ) + .addHandlerMethod( + UntypedTryHandlerMethodNode.builder() + .withName("b") + .addStatement(Untyped.break_(Untyped.intLiteral(0))) + .build() + ) + .build(); + var effect = Effects.userDefined(NAMESPACE_NAME, "Effect"); + var effectInfo = UserDefinedEffectInfo.builder() + .addMethod("a", FunctionType.builder().withReturnType(Types.UNIT).build()) + .addMethod("b", FunctionType.builder().withReturnType(Types.UNIT).build()) + .build(); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry("Effect", Types.effectType(effect)) + )) + .addUserDefinedEffectInfo(effect, effectInfo); + + var result = typeCheckExpression(untyped, context); + + assertThat( + result.value(), + isTypedTryNode() + .withType(equalTo(Types.INT)) + ); + } + + @Test public void whenEffectIsNotAllowedInExpressionScopeAndIsNotHandledEffectThenEffectIsNotAllowedInBodyScope() { var handledEffect = Effects.userDefined(NAMESPACE_NAME, "HandledEffect"); var unexpectedEffect = Effects.userDefined(NAMESPACE_NAME, "UnexpectedEffect"); |
