diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-08-05 18:44:26 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-08-05 18:44:26 +0100 |
| commit | 8455bb19b7d4235e667cab9112aa276557969dcc (patch) | |
| tree | 3ad5a7cf2941c4918f9e6de612a711cd8846570f /src | |
| parent | 266e826749b62c46e14d9590351f8c3b2de53512 (diff) | |
Type check generic native types
Diffstat (limited to 'src')
5 files changed, 54 insertions, 8 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedNativeTypeDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedNativeTypeDefinitionNode.java index e81705b..487a80b 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedNativeTypeDefinitionNode.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedNativeTypeDefinitionNode.java @@ -3,13 +3,14 @@ package org.zwobble.hobgoblin.compiler.ast.typed; import org.zwobble.hobgoblin.compiler.ast.DocComment; import org.zwobble.hobgoblin.compiler.sources.Source; import org.zwobble.hobgoblin.compiler.types.SimpleNativeType; +import org.zwobble.hobgoblin.compiler.types.TypeOrConstructor; public record TypedNativeTypeDefinitionNode( - SimpleNativeType type, + TypeOrConstructor<SimpleNativeType> typeOrConstructor, DocComment docComment, Source source ) implements TypedNamespaceStatementNode { public String name() { - return this.type.name(); + return this.typeOrConstructor.name(); } } 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 eb47870..e403f5b 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -165,7 +165,17 @@ public class TypeChecker { TypeCheckerNamespaceContext context ) { var nativeType = new SimpleNativeType(context.namespaceName(), untyped.name()); - var metaType = new TypeLevelValueType(nativeType); + + var nativeTypeOrConstructor = untyped.typeParams().isEmpty() + ? new TypeOrConstructor.Type<>(nativeType) + : new TypeOrConstructor.Constructor<>(new NativeTypeConstructor( + untyped.typeParams().stream() + .map(typeParam -> new TypeParam(typeParam.name())) + .toList(), + nativeType + )); + + var metaType = new TypeLevelValueType(nativeTypeOrConstructor.value()); context.declare(untyped.name(), metaType, untyped.source()); return metaType; } @@ -174,10 +184,20 @@ public class TypeChecker { UntypedNativeTypeDefinitionNode untyped, TypeCheckerNamespaceContext context ) { - var nativeType = (SimpleNativeType) lookupMetaType(untyped.name(), untyped.source(), context); + var nativeMetaType = lookupTypeLevelValue(untyped.name(), untyped.source(), context); + var nativeTypeOrConstructor = switch (nativeMetaType) { + case SimpleNativeType type -> + new TypeOrConstructor.Type<>(type); + + case NativeTypeConstructor typeConstructor -> + new TypeOrConstructor.Constructor<>(typeConstructor); + + default -> + throw new UnsupportedOperationException("TODO"); + }; return new TypedNativeTypeDefinitionNode( - nativeType, + nativeTypeOrConstructor, untyped.docComment(), untyped.source() ); diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeConstructor.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeConstructor.java index e2726fb..2c779d2 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeConstructor.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeConstructor.java @@ -9,4 +9,8 @@ public sealed interface TypeConstructor<T extends ConstructibleType> extends Typ default String describe() { return genericType().describe(); } + + default String name() { + return genericType().name(); + } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java new file mode 100644 index 0000000..8844669 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java @@ -0,0 +1,20 @@ +package org.zwobble.hobgoblin.compiler.types; + +public sealed interface TypeOrConstructor<T extends ConstructibleType> { + record Type<T extends ConstructibleType>(T value) implements TypeOrConstructor<T> { + @Override + public String name() { + return this.value.name(); + } + } + + record Constructor<T extends ConstructibleType>(TypeConstructor<T> value) implements TypeOrConstructor<T> { + @Override + public String name() { + return this.value.name(); + } + } + + String name(); + TypeLevelValue value(); +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNativeTypeDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNativeTypeDefinitionTests.java index c0a329a..1777506 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNativeTypeDefinitionTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNativeTypeDefinitionTests.java @@ -5,6 +5,7 @@ import org.zwobble.hobgoblin.compiler.ast.typed.TypedNativeTypeDefinitionNode; import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNativeTypeDefinitionNode; import org.zwobble.hobgoblin.compiler.types.NamespaceName; import org.zwobble.hobgoblin.compiler.types.SimpleNativeType; +import org.zwobble.hobgoblin.compiler.types.TypeOrConstructor; import static org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerTesting.typeCheckNamespaceStatement; import static org.zwobble.precisely.AssertThat.assertThat; @@ -23,9 +24,9 @@ public class TypeCheckerNativeTypeDefinitionTests { assertThat(typed, instanceOf( TypedNativeTypeDefinitionNode.class, has( - "type", - TypedNativeTypeDefinitionNode::type, - equalTo(new SimpleNativeType(NamespaceName.of("a", "b"), "X")) + "typeOrConstructor", + TypedNativeTypeDefinitionNode::typeOrConstructor, + equalTo(new TypeOrConstructor.Type<>(new SimpleNativeType(NamespaceName.of("a", "b"), "X"))) ) )); } |
