From 96de72e5f761eb4bf07536f4dfe282e2e10a2081 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 27 Aug 2023 20:23:30 +0100 Subject: Add type-checking for while nodes --- .../compiler/ast/typed/TypedNodeMatchers.java | 11 ++++ .../org/shedlang/compiler/ast/untyped/Untyped.java | 7 +++ .../typechecker/TypeCheckerWhileTests.java | 69 ++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhileTests.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 9ee8c8fa..5b841f4f 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -259,4 +259,15 @@ public class TypedNodeMatchers { has("expression", x -> x.expression(), expression) ); } + + public static Matcher isTypedWhileNode( + Matcher condition, + Matcher body + ) { + return instanceOf( + TypedWhileNode.class, + has("condition", x -> x.condition(), condition), + has("body", x -> x.body(), body) + ); + } } 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 1fe48649..753bec1a 100644 --- a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java +++ b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java @@ -171,4 +171,11 @@ public class Untyped { ) { return new UntypedVarNode(target, expression, Sources.NULL); } + + public static UntypedWhileNode while_( + UntypedExpressionNode condition, + UntypedBlockNode body + ) { + return new UntypedWhileNode(condition, body, Sources.NULL); + } } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhileTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhileTests.java new file mode 100644 index 00000000..209be5e1 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhileTests.java @@ -0,0 +1,69 @@ +package org.shedlang.compiler.typechecker; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.ast.untyped.Untyped; +import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; +import org.shedlang.compiler.typechecker.typesets.TypeSets; +import org.shedlang.compiler.types.Types; + +import java.util.List; + +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.*; + +public class TypeCheckerWhileTests { + @Test + public void conditionIsTypeChecked() { + var untyped = Untyped.while_( + Untyped.boolLiteral(true), + Untyped.block(List.of()) + ); + var context = TypeCheckerContext.EMPTY; + + var typed = TypeChecker.typeCheckFunctionStatement(untyped, context); + + assertThat(typed.value(), isTypedWhileNode( + isTypedBoolLiteralNode(true), + anything() + )); + } + + @Test + public void whenConditionIsNotBoolThenErrorIsThrown() { + var untyped = Untyped.while_( + Untyped.intLiteral(0), + Untyped.block(List.of()) + ); + var context = TypeCheckerContext.EMPTY; + + var error = assertThrows( + UnexpectedTypeError.class, + () -> TypeChecker.typeCheckFunctionStatement(untyped, context) + ); + + assertThat(error.expected(), equalTo(TypeSets.type(Types.BOOL))); + assertThat(error.actual(), equalTo(Types.INT)); + } + + @Test + public void bodyIsTypeChecked() { + var untyped = Untyped.while_( + Untyped.boolLiteral(true), + Untyped.block(List.of( + Untyped.expressionStatement(Untyped.intLiteral(42)) + )) + ); + var context = TypeCheckerContext.EMPTY; + + var typed = TypeChecker.typeCheckFunctionStatement(untyped, context); + + assertThat(typed.value(), isTypedWhileNode( + anything(), + isTypedBlockNode(isSequence( + isTypedExpressionStatementNode(isTypedIntLiteralNode(42)) + )) + )); + } +} -- cgit v1.2.3