From 776fcb476f229030cb5d34f4b948603f05c01a79 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 24 Apr 2026 12:43:29 +0100 Subject: Type check type level reference --- .../hobgoblin/compiler/ast/untyped/UntypedArb.java | 12 ++++ .../typechecker/TypeCheckerContextArb.java | 10 +++ .../TypeCheckerTypeLevelReferenceTests.java | 75 ++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedArb.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java (limited to 'src/test/java/org/zwobble') diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedArb.java b/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedArb.java new file mode 100644 index 0000000..5a011d7 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedArb.java @@ -0,0 +1,12 @@ +package org.zwobble.hobgoblin.compiler.ast.untyped; + +import org.zwobble.hobgoblin.compiler.sources.NullSource; + +public class UntypedArb { + private UntypedArb() { + } + + public static UntypedTypeLevelReferenceNode typeLevelReference(String name) { + return new UntypedTypeLevelReferenceNode(name, NullSource.INSTANCE); + } +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java new file mode 100644 index 0000000..98d8064 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java @@ -0,0 +1,10 @@ +package org.zwobble.hobgoblin.compiler.typechecker; + +public class TypeCheckerContextArb { + private TypeCheckerContextArb() { + } + + public static TypeCheckerContext context() { + return new TypeCheckerContext(); + } +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java new file mode 100644 index 0000000..82704fc --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java @@ -0,0 +1,75 @@ +package org.zwobble.hobgoblin.compiler.typechecker; + +import org.junit.jupiter.api.Test; +import org.zwobble.hobgoblin.compiler.ast.typed.TypedTypeLevelReferenceNode; +import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedArb; +import org.zwobble.hobgoblin.compiler.types.ScalarType; +import org.zwobble.hobgoblin.compiler.types.TypeLevelValueType; +import org.zwobble.hobgoblin.compiler.types.TypeSet; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class TypeCheckerTypeLevelReferenceTests { + @Test + public void whenNameIsUnrecognisedThenErrorIsThrown() { + var untyped = UntypedArb.typeLevelReference("X"); + var context = TypeCheckerContextArb.context(); + + var error = assertThrows( + UndeclaredVariableError.class, + () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context) + ); + + assertThat(error.variableName(), equalTo("X")); + } + + @Test + public void whenNameIsUndefinedThenErrorIsThrown() { + var untyped = UntypedArb.typeLevelReference("X"); + var context = TypeCheckerContextArb.context(); + context.declare("X"); + + var error = assertThrows( + UndefinedVariableError.class, + () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context) + ); + + assertThat(error.variableName(), equalTo("X")); + } + + @Test + public void whenVariableIsNotTypeLevelValueThenErrorIsThrown() { + var untyped = UntypedArb.typeLevelReference("X"); + var context = TypeCheckerContextArb.context(); + context.declare("X"); + var scalarType = new ScalarType("Int"); + context.define("X", scalarType); + + var error = assertThrows( + UnexpectedTypeError.class, + () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context) + ); + + assertThat(error.expected(), equalTo(new TypeSet.MetaType())); + assertThat(error.actual(), equalTo(scalarType)); + } + + @Test + public void whenNameIsMetaTypeThenValueIsType() { + var untyped = UntypedArb.typeLevelReference("X"); + var context = TypeCheckerContextArb.context(); + context.declare("X"); + var scalarType = new ScalarType("Int"); + context.define("X", new TypeLevelValueType(scalarType)); + + var typed = TypeChecker.typeCheckTypeLevelExpression(untyped, context); + + assertThat(typed, instanceOf( + TypedTypeLevelReferenceNode.class, + has("name", TypedTypeLevelReferenceNode::name, equalTo("X")), + has("value", TypedTypeLevelReferenceNode::value, equalTo(scalarType)) + )); + } +} -- cgit v1.2.3