From 3244aa2a2d81f0b31bfc18f1e0db333000a1c44b Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 19 Nov 2023 21:52:51 +0000 Subject: Check vars can't be captured for specific function nodes --- .../TypeCheckerFunctionDefinitionTests.java | 28 +++++++++++++++++-- .../TypeCheckerFunctionExpressionTests.java | 31 +++++++++++++++++----- 2 files changed, 51 insertions(+), 8 deletions(-) (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java index 590beb7f..47813c25 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java @@ -3,10 +3,12 @@ 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.typechecker.errors.CannotCaptureVarError; import org.shedlang.compiler.typechecker.errors.FunctionSignatureMissingParamTypeError; import org.shedlang.compiler.typechecker.errors.FunctionSignatureMissingReturnTypeError; 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; @@ -18,8 +20,7 @@ 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; +import static org.zwobble.precisely.Matchers.*; public class TypeCheckerFunctionDefinitionTests { @Test @@ -72,4 +73,27 @@ public class TypeCheckerFunctionDefinitionTests { () -> typeCheckNamespaceStatement(untyped, context) ); } + + @Test + public void varsCannotBeCaptured() { + var untyped = UntypedFunctionDefinitionNode.builder() + .withReturnType(Untyped.typeLevelReference("Unit")) + .addStatement(Untyped.expressionStatement(Untyped.reference("x"))) + .build(); + var context = TypeCheckerContext.EMPTY + .enterNamespace(NamespaceName.of("Example"), P.map( + Map.entry("Unit", Variable.defined(Types.metaType(Types.UNIT), VariableType.CONSTANT)), + Map.entry("x", Variable.defined(Types.STRING, VariableType.VAR)) + )); + + var error = assertThrows( + CannotCaptureVarError.class, + () -> typeCheckNamespaceStatement( + untyped, + context + ) + ); + + assertThat(error.name(), equalTo("x")); + } } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionExpressionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionExpressionTests.java index ce2a0570..27b5b444 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionExpressionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionExpressionTests.java @@ -3,11 +3,9 @@ package org.shedlang.compiler.typechecker; import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.ast.untyped.UntypedFunctionExpressionNode; +import org.shedlang.compiler.typechecker.errors.CannotCaptureVarError; import org.shedlang.compiler.typechecker.errors.FunctionSignatureMissingParamTypeError; -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.types.*; import org.shedlang.compiler.util.P; import java.util.List; @@ -17,8 +15,7 @@ import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertThrows; 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; +import static org.zwobble.precisely.Matchers.*; public class TypeCheckerFunctionExpressionTests { @Test @@ -132,4 +129,26 @@ public class TypeCheckerFunctionExpressionTests { ) ); } + + @Test + public void varsCannotBeCaptured() { + var untyped = UntypedFunctionExpressionNode.builder() + .addStatement(Untyped.expressionStatement(Untyped.reference("x"))) + .build(); + var context = TypeCheckerContext.EMPTY + .enterNamespace(NamespaceName.of("Example"), P.map( + Map.entry("x", Variable.defined(Types.STRING, VariableType.VAR)) + )); + + var error = assertThrows( + CannotCaptureVarError.class, + () -> TypeChecker.typeCheckExpression( + untyped, + Optional.empty(), + context + ) + ); + + assertThat(error.name(), equalTo("x")); + } } -- cgit v1.2.3