diff options
Diffstat (limited to 'src')
4 files changed, 72 insertions, 4 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java index b5dbd5d..532d8de 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java @@ -10,6 +10,8 @@ public sealed interface UntypedTypeLevelExpressionNode permits org.zwobble.hobgo // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelExpressionNode.Builder body } + public org.zwobble.hobgoblin.compiler.sources.Source source(); + // Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelExpressionNode body // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelExpressionNode body } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java index 5003e3a..c291aaf 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -258,7 +258,7 @@ public class TypeChecker { ); } - private static TypedTypeLevelExpressionNode<Type> typeCheckMetaType( + static TypedTypeLevelExpressionNode<Type> typeCheckMetaType( UntypedTypeLevelExpressionNode untyped, TypeCheckerNamespaceContext context ) { @@ -266,8 +266,11 @@ public class TypeChecker { if (typed.value() instanceof Type) { return (TypedTypeLevelExpressionNode<Type>) typed; } else { - // TODO: better error - throw new RuntimeException("not a metatype"); + throw new UnexpectedTypeError( + new TypeSet.MetaType(), + new TypeLevelValueType(typed.value()), + untyped.source() + ); } } 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"); |
