From 9c2421d317068021c64a42be9f785e5ec73afd43 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 26 Jun 2026 16:25:34 +0100 Subject: Treat variant as subtype of sum --- .../compiler/typechecker/TypeChecker.java | 25 ++++++++++++++++------ .../typechecker/TypeCheckerGlobalContext.java | 6 ++++-- .../typechecker/TypeCheckerNamespaceContext.java | 5 +++++ .../compiler/typechecker/TypeCheckerSubtyping.java | 14 ++++++++++-- .../hobgoblin/compiler/typechecker/TypesInfo.java | 2 ++ 5 files changed, 42 insertions(+), 10 deletions(-) (limited to 'src/main/java') 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 34c05cb..8b930aa 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -189,7 +189,8 @@ public class TypeChecker { sumType, sumTypeFields, structType, - typeCheckedFieldDefinitions.fields + typeCheckedFieldDefinitions.fields, + context.toTypesInfo() ); } @@ -265,7 +266,8 @@ public class TypeChecker { sumType, typeCheckedFieldDefinitions.fields, variantType, - context.fieldsOf(variantType) + context.fieldsOf(variantType), + context.toTypesInfo() ); } } @@ -299,7 +301,8 @@ public class TypeChecker { SumType sumType, List sumTypeFields, StructType variantType, - List variantTypeFields + List variantTypeFields, + TypesInfo typesInfo ) { for (var sumTypeField : sumTypeFields) { var variantTypeField = variantTypeFields.stream() @@ -310,7 +313,12 @@ public class TypeChecker { throw new SubtypeIsMissingFieldError(sumType, variantType, sumTypeField.name(), sumTypeField.source()); } - checkIsSubtype(variantTypeField.get().type(), sumTypeField.type(), variantTypeField.get().source()); + checkIsSubtype( + variantTypeField.get().type(), + sumTypeField.type(), + variantTypeField.get().source(), + typesInfo + ); } } @@ -384,8 +392,13 @@ public class TypeChecker { return value; } - private static void checkIsSubtype(Type subtype, Type supertype, Source source) { - if (!isSubtype(subtype, supertype)) { + private static void checkIsSubtype( + Type subtype, + Type supertype, + Source source, + TypesInfo typesInfo + ) { + if (!isSubtype(subtype, supertype, typesInfo)) { throw new UnexpectedTypeError( new TypeSet.SingleType(supertype), subtype, diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java index cf61a22..c66c999 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java @@ -1,9 +1,11 @@ package org.zwobble.hobgoblin.compiler.typechecker; import org.zwobble.hobgoblin.compiler.types.*; -import org.zwobble.hobgoblin.compiler.util.ManyToMany; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; public class TypeCheckerGlobalContext { private final Map nativeTypes = new HashMap<>(); diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java index 0ffbe66..82c8273 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java @@ -34,6 +34,11 @@ public class TypeCheckerNamespaceContext { this.typesInfo = typesInfo; } + public TypesInfo toTypesInfo() { + return this.typesInfo; + } + + public NamespaceName namespaceName() { return this.namespaceName; } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java index 673d931..335fa8d 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java @@ -1,12 +1,22 @@ package org.zwobble.hobgoblin.compiler.typechecker; +import org.zwobble.hobgoblin.compiler.types.SumType; import org.zwobble.hobgoblin.compiler.types.Type; class TypeCheckerSubtyping { private TypeCheckerSubtyping() { } - static boolean isSubtype(Type subtype, Type supertype) { - return subtype.equals(supertype); + static boolean isSubtype(Type subtype, Type supertype, TypesInfo typesInfo) { + if (subtype.equals(supertype)) { + return true; + } + + if (supertype instanceof SumType supertypeSum) { + return typesInfo.sumVariants(supertypeSum).stream() + .anyMatch(variantType -> isSubtype(variantType, subtype, typesInfo)); + } + + return false; } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java index 4e896dd..814466c 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java @@ -5,6 +5,8 @@ import org.zwobble.hobgoblin.compiler.types.*; import java.util.List; public interface TypesInfo { + TypesInfo EMPTY = TypesInfoInMemory.empty(); + boolean isDefined(StructType type); List fieldsOf(StructType structType); -- cgit v1.2.3