aboutsummaryrefslogtreecommitdiff
path: root/src/test/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-11-05 19:17:38 +0000
committerMichael Williamson <mike@zwobble.org>2023-11-05 19:17:38 +0000
commit9335b1d7d7dcc5fe1f5be8ebe8d8662ae86c7481 (patch)
treef13d3184d8648864b22034861f2c78861e5a4a6c /src/test/java
parentc240d003f4256713dad982f91beaf47b862ce5ad (diff)
Add tests for effects in try body
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java
index 32808834..566a93ee 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java
@@ -2,17 +2,23 @@ package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
import org.shedlang.compiler.ast.untyped.Untyped;
+import org.shedlang.compiler.ast.untyped.UntypedCallNode;
import org.shedlang.compiler.ast.untyped.UntypedTryNode;
+import org.shedlang.compiler.typechecker.errors.UnexpectedEffectError;
import org.shedlang.compiler.types.Effects;
+import org.shedlang.compiler.types.FunctionType;
import org.shedlang.compiler.types.NamespaceName;
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.typeCheckExpression;
import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.equalTo;
import static org.zwobble.precisely.Matchers.isSequence;
public class TypeCheckerTryTests {
@@ -40,4 +46,64 @@ public class TypeCheckerTryTests {
)))
);
}
+
+ @Test
+ public void whenEffectIsNotAllowedInExpressionScopeAndIsNotHandledEffectThenEffectIsNotAllowedInBodyScope() {
+ var handledEffect = Effects.userDefined(NAMESPACE_NAME, "HandledEmpty");
+ var unexpectedEffect = Effects.userDefined(NAMESPACE_NAME, "UnexpectedEffect");
+ var untyped = UntypedTryNode.builder()
+ .addBodyStatement(Untyped.expressionStatement(
+ UntypedCallNode.builder()
+ .withReceiver(Untyped.reference("f"))
+ .withHasEffects(true)
+ .build()
+ ))
+ .withHandledEffect(Untyped.typeLevelReference(handledEffect.name()))
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enterFunction(
+ P.map(
+ Map.entry(handledEffect.name(), Variable.defined(Types.effectType(handledEffect), VariableType.CONSTANT)),
+ Map.entry("f", Variable.defined(FunctionType.builder().withEffect(unexpectedEffect).build(), VariableType.VAL))
+ ),
+ Effects.NONE,
+ Optional.empty()
+ );
+
+ var error = assertThrows(
+ UnexpectedEffectError.class,
+ () -> typeCheckExpression(untyped, context)
+ );
+
+ assertThat(error.allowed(), equalTo(Effects.NONE));
+ assertThat(error.actual(), equalTo(unexpectedEffect));
+ }
+
+ @Test
+ public void effectsAllowedInExpressionScopeAreAllowedInBodyScope() {
+ var handledEffect = Effects.userDefined(NAMESPACE_NAME, "HandledEmpty");
+ var allowedEffect = Effects.userDefined(NAMESPACE_NAME, "AllowedEffect");
+ var untyped = UntypedTryNode.builder()
+ .addBodyStatement(Untyped.expressionStatement(
+ UntypedCallNode.builder()
+ .withReceiver(Untyped.reference("f"))
+ .withHasEffects(true)
+ .build()
+ ))
+ .withHandledEffect(Untyped.typeLevelReference(handledEffect.name()))
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enterFunction(
+ P.map(
+ Map.entry(handledEffect.name(), Variable.defined(Types.effectType(handledEffect), VariableType.CONSTANT)),
+ Map.entry("f", Variable.defined(FunctionType.builder().withEffect(allowedEffect).build(), VariableType.VAL))
+ ),
+ allowedEffect,
+ Optional.empty()
+ );
+
+ var result = typeCheckExpression(untyped, context);
+
+ assertThat(result.value(), isTypedTryNode());
+ }
}