From f3da8bbffe9cdf80ba3f422ec2d8ff7ce13ea2ae Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 28 Jul 2023 22:18:28 +0100 Subject: Type check var statements --- .../compiler/ast/typed/TypedNodeMatchers.java | 11 +++ .../org/shedlang/compiler/ast/untyped/Untyped.java | 7 ++ .../compiler/typechecker/TypeCheckerVarTests.java | 79 ++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java (limited to 'src/test/java') 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 3a46fa54..ef2e4686 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -237,4 +237,15 @@ public class TypedNodeMatchers { has("expression", x -> x.expression(), expression) ); } + + public static Matcher isTypedVarNode( + Matcher target, + Matcher expression + ) { + return instanceOf( + TypedVarNode.class, + has("target", x -> x.target(), target), + has("expression", x -> x.expression(), expression) + ); + } } 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 8dddfa58..141212cc 100644 --- a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java +++ b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java @@ -157,4 +157,11 @@ public class Untyped { ) { return new UntypedValNode(target, expression, Sources.NULL); } + + public static UntypedVarNode var( + UntypedTargetNode target, + UntypedExpressionNode expression + ) { + return new UntypedVarNode(target, expression, Sources.NULL); + } } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java new file mode 100644 index 00000000..244ddc98 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java @@ -0,0 +1,79 @@ +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.Types; +import org.shedlang.compiler.util.P; + +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.anything; +import static org.zwobble.precisely.Matchers.isSequence; + +public class TypeCheckerVarTests { + @Test + public void canTypeCheckAsFunctionStatement() { + var untyped = Untyped.var(Untyped.targetVariable("x"), Untyped.stringLiteral("hello")); + + var typed = typeCheckFunctionStatement(untyped, TypeCheckerContext.EMPTY); + + assertThat(typed.value(), isTypedVarNode( + isTypedTargetVariable("x"), + isTypedStringLiteralNode("hello") + )); + } + + @Test + public void varCanBeReferencedAfterDefinitionInFunction() { + var untyped = UntypedFunctionDefinitionNode.builder() + .addStatement(Untyped.var(Untyped.targetVariable("x"), Untyped.stringLiteral("hello"))) + .addStatement(Untyped.expressionStatement(Untyped.reference("x"))) + .build(); + var context = TypeCheckerContext.EMPTY + .enterNamespaceWithDefinedVariables(P.map( + Map.entry("Unit", Types.metaType(Types.UNIT)) + )); + + var typed = typeCheckNamespaceStatement(untyped, context); + + assertThat( + typed.value(), + isTypedFunctionDefinitionNode() + .withBody(isTypedBlockNode(isSequence( + isTypedVarNode(anything(), anything()), + isTypedExpressionStatementNode(isTypedReferenceNode("x", Types.STRING)) + ))) + ); + } + + private static TypeCheckerResult typeCheckFunctionStatement( + UntypedFunctionStatementNode untyped, + TypeCheckerContext context + ) { + var declaredVariables = DeclaredVariables.forFunctionStatement(untyped, P.vector()); + var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); + + context = context.enterNamespace(environment.build()); + + return TypeChecker.typeCheckFunctionStatement(untyped, context); + } + + private static TypeCheckerResult typeCheckNamespaceStatement( + UntypedNamespaceStatementNode untyped, + TypeCheckerContext context + ) { + var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector()); + var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); + + context = context.enterNamespace(environment.build()); + + return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context); + } +} -- cgit v1.2.3