diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-07-17 23:21:58 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-07-17 23:21:58 +0100 |
| commit | db477d8a01c7f4ee200826baaee0342f7f797604 (patch) | |
| tree | a6c22d9cbfb88996ff255841f258b7280503d515 /src/test/java | |
| parent | d1a79b6eff402257720c99ca873af2840f9d2595 (diff) | |
Handle free variables in inner scopes
Diffstat (limited to 'src/test/java')
| -rw-r--r-- | src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java | 25 | ||||
| -rw-r--r-- | src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java | 33 |
2 files changed, 56 insertions, 2 deletions
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java index 13f2486b..7c6e709b 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java @@ -12,8 +12,7 @@ import java.util.Map; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.equalTo; -import static org.zwobble.precisely.Matchers.isOptionalOf; +import static org.zwobble.precisely.Matchers.*; public class TypeCheckerContextTests { @Test @@ -75,4 +74,26 @@ public class TypeCheckerContextTests { assertThat(error.variableName(), equalTo("x")); } + + @Test + public void runtimeLookupUpdatesFreeVariablesUntilLexicalContextInWhichVariableIsDefined() { + var context = TypeCheckerContext.EMPTY + .enterBlock(P.map()) + .enterBlock(P.map( + Map.entry("x", TypeCheckerContext.undefined()) + )) + .enterBlock(P.map()) + .enterBlock(P.map()); + + var result = context.runtimeLookup("x").context(); + + assertThat(result.freeVariables(), containsExactly( + has("name", x -> x.name(), equalTo("x")) + )); + assertThat(result.exit().freeVariables(), containsExactly( + has("name", x -> x.name(), equalTo("x")) + )); + assertThat(result.exit().exit().freeVariables(), containsExactly()); + assertThat(result.exit().exit().exit().freeVariables(), containsExactly()); + } } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java index ee88b457..794dd2c3 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java @@ -315,6 +315,39 @@ public class TypeCheckerFunctionDefinitionTests { ); } + @Test + public void freeVariablesIncludeVariablesReferencedInBlockInFunctionButDefinedOutsideOfFunction() { + var untyped = UntypedFunctionDefinitionNode.builder() + .withReturnType(Untyped.typeLevelReference("Unit")) + .addStatement(Untyped.expressionStatement(Untyped.if_( + List.of( + Untyped.conditionalBranch( + Untyped.boolLiteral(true), + Untyped.block(List.of()) + ) + ), + Untyped.block(List.of( + Untyped.expressionStatement(Untyped.reference("x")) + )) + ))) + .build(); + var context = TypeCheckerContext.EMPTY + .enterNamespaceWithDefinedVariables(P.map( + Map.entry("Unit", Types.metaType(Types.UNIT)), + Map.entry("x", Types.STRING) + )); + + var typed = typeCheckNamespaceStatement(untyped, context); + + assertThat( + typed.value(), + isTypedFunctionDefinitionNode() + .withFreeVariables(containsExactly( + has("name", x -> x.name(), equalTo("x")) + )) + ); + } + private static TypeCheckerResult<? extends TypedNamespaceStatementNode> typeCheckNamespaceStatement( UntypedFunctionDefinitionNode untyped, TypeCheckerContext context |
