From ad3e527a337ba2c02eac1aafdc17124c76cc1b92 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 25 Jun 2026 18:17:19 +0100 Subject: Throw better error when value is not type --- .../typechecker/TypeCheckerMetaTypeTests.java | 63 ++++++++++++++++++++++ .../TypeCheckerTypeLevelReferenceTests.java | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerMetaTypeTests.java (limited to 'src/test') diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerMetaTypeTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerMetaTypeTests.java new file mode 100644 index 0000000..1f966b1 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerMetaTypeTests.java @@ -0,0 +1,63 @@ +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.*; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; +import static org.zwobble.precisely.Matchers.equalTo; + +public class TypeCheckerMetaTypeTests { + @Test + public void whenVariableIsNotTypeLevelValueThenErrorIsThrown() { + var untyped = UntypedArb.typeLevelReference("X"); + var context = TypeCheckerContextArb.namespaceContext(); + var nativeType = SimpleNativeType.builtin("Int"); + context.declare("X", nativeType); + + var error = assertThrows( + UnexpectedTypeError.class, + () -> TypeChecker.typeCheckMetaType(untyped, context) + ); + + assertThat(error.expected(), equalTo(new TypeSet.MetaType())); + assertThat(error.actual(), equalTo(nativeType)); + } + + @Test + public void whenVariableIsTypeLevelValueButNotMetaTypeThenErrorIsThrown() { + var untyped = UntypedArb.typeLevelReference("List"); + var context = TypeCheckerContextArb.namespaceContext(); + var typeConstructor = new TypeConstructor<>(List.of(new TypeParam("T")), SimpleNativeType.builtin("List")); + context.declare("List", new TypeLevelValueType(typeConstructor)); + + var error = assertThrows( + UnexpectedTypeError.class, + () -> TypeChecker.typeCheckMetaType(untyped, context) + ); + + assertThat(error.expected(), equalTo(new TypeSet.MetaType())); + assertThat(error.actual(), equalTo(new TypeLevelValueType(typeConstructor))); + } + + @Test + public void whenNameIsTypeLevelValueThenValueIsType() { + var untyped = UntypedArb.typeLevelReference("X"); + var context = TypeCheckerContextArb.namespaceContext(); + var nativeType = SimpleNativeType.builtin("Int"); + context.declare("X", new TypeLevelValueType(nativeType)); + + var typed = TypeChecker.typeCheckMetaType(untyped, context); + + assertThat(typed, instanceOf( + TypedTypeLevelReferenceNode.class, + has("name", TypedTypeLevelReferenceNode::name, equalTo("X")), + has("value", TypedTypeLevelReferenceNode::value, equalTo(nativeType)) + )); + } +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java index e633c94..0924eee 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTypeLevelReferenceTests.java @@ -42,7 +42,7 @@ public class TypeCheckerTypeLevelReferenceTests { } @Test - public void whenNameIsMetaTypeThenValueIsType() { + public void whenNameIsTypeLevelValueThenValueIsType() { var untyped = UntypedArb.typeLevelReference("X"); var context = TypeCheckerContextArb.namespaceContext(); var nativeType = SimpleNativeType.builtin("Int"); -- cgit v1.2.3