diff options
| author | Michael Williamson <mike@zwobble.org> | 2024-01-03 21:23:18 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2024-01-03 21:23:18 +0000 |
| commit | 09f15965cf8fb86077e06bcf6c4f34af4ad7b0e7 (patch) | |
| tree | dde7d4e74a4b1fd9d0959b4b34d979d295c46f2f /src/main/java | |
| parent | cddbde16fa288781732853db226fc02434491aa5 (diff) | |
Introduce specific subtypes for constructed types
Diffstat (limited to 'src/main/java')
9 files changed, 105 insertions, 46 deletions
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 854fdbfe..8ac346a3 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -435,11 +435,9 @@ public class TypeChecker { if ( receiverType instanceof TypeLevelValueType typeLevelValueType && - typeLevelValueType.value() instanceof ConstructedType<?> constructedType && - constructedType.genericType() instanceof StructType + typeLevelValueType.value() instanceof ConstructedStructType constructedType ) { - // TODO: make specific constructed types to avoid generic casting? - var structTypeInfo = context.structTypeInfo((ConstructedType<StructType>) constructedType, receiverSource); + var structTypeInfo = context.structTypeInfo(constructedType, receiverSource); return receiverStructTypeInfoToFunctionType( constructedType, structTypeInfo @@ -1664,13 +1662,8 @@ public class TypeChecker { if (variantType instanceof StructType variantStructType) { return SumVariant.struct(variantStructType); - } else if ( - variantType instanceof ConstructedType<?> variantConstructedType && - variantConstructedType.genericType() instanceof StructType - ) { - return SumVariant.constructedStruct( - (ConstructedType<StructType>) variantConstructedType - ); + } else if (variantType instanceof ConstructedStructType variantConstructedType) { + return SumVariant.constructedStruct(variantConstructedType); } else { throw new VariantTypeIsNotStructError( variantType, @@ -1723,7 +1716,7 @@ public class TypeChecker { var args = constructedTypeNode.args().stream() .map(arg -> typeCheckTypeExpression(arg, context).value()) .toList(); - var constructedType = new ConstructedType<>(constructor, args); + var constructedType = Types.constructedType(constructor, args); // TODO: tidy this (and other similar checks in this function) up if (valueType.valueClass().equals(Type.class)) { @@ -2102,8 +2095,8 @@ public class TypeChecker { context = typedExpressionResult.context(); var expressionTypeInfo = switch (typedExpression.type()) { - case ConstructedType<?> constructedType when constructedType.genericType() instanceof SumType -> - context.sumTypeInfo((ConstructedType<SumType>) constructedType, untyped.source()); + case ConstructedSumType constructedType -> + context.sumTypeInfo(constructedType, untyped.source()); case SumType expressionType -> context.sumTypeInfo(expressionType, untyped.source()); @@ -2176,8 +2169,8 @@ public class TypeChecker { ); var variant = switch (typedCaseType.value()) { - case ConstructedType<?> constructedType when constructedType.genericType() instanceof StructType -> - SumVariant.constructedStruct((ConstructedType<StructType>) constructedType); + case ConstructedStructType constructedStructType -> + SumVariant.constructedStruct(constructedStructType); case StructType structType -> SumVariant.struct(structType); diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerSubTyping.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerSubTyping.java index 898cacf9..1ffd9ee2 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerSubTyping.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerSubTyping.java @@ -125,13 +125,10 @@ public class TypeCheckerSubTyping { return tryAddVariantSubtypeConstraint(subtype, superTypeInfo, constraints); } - if ( - supertype instanceof ConstructedType<?> supertypeConstructedType && - supertypeConstructedType.genericType() instanceof SumType - ) { - var superTypeInfo = constraints.typeInfos.sumTypeInfo( - (ConstructedType<SumType>) supertypeConstructedType - ).orElseThrow(); + if (supertype instanceof ConstructedSumType supertypeConstructedType) { + var superTypeInfo = constraints.typeInfos + .sumTypeInfo(supertypeConstructedType) + .orElseThrow(); return tryAddVariantSubtypeConstraint(subtype, superTypeInfo, constraints); } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java b/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java index 99947094..1e00a354 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java @@ -103,7 +103,7 @@ public class TypeInfos { var variants = typeInfo.variants().stream() .map(variant -> switch (variant) { case SumVariant.ConstructedStruct constructedStruct -> - SumVariant.constructedStruct(TypeSubstitution.substituteConstructedType( + SumVariant.constructedStruct(TypeSubstitution.substituteConstructedStructType( constructedStruct.type(), typeSubstitutionMap )); diff --git a/src/main/java/org/shedlang/compiler/types/ConstructedStructType.java b/src/main/java/org/shedlang/compiler/types/ConstructedStructType.java new file mode 100644 index 00000000..df454e5d --- /dev/null +++ b/src/main/java/org/shedlang/compiler/types/ConstructedStructType.java @@ -0,0 +1,9 @@ +package org.shedlang.compiler.types; + +import java.util.List; + +public record ConstructedStructType( + TypeConstructor<StructType> constructor, + List<? extends Type> args +) implements ConstructedType<StructType> { +} diff --git a/src/main/java/org/shedlang/compiler/types/ConstructedSumType.java b/src/main/java/org/shedlang/compiler/types/ConstructedSumType.java new file mode 100644 index 00000000..ee3c6f80 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/types/ConstructedSumType.java @@ -0,0 +1,9 @@ +package org.shedlang.compiler.types; + +import java.util.List; + +public record ConstructedSumType( + TypeConstructor<SumType> constructor, + List<? extends Type> args +) implements ConstructedType<SumType> { +} diff --git a/src/main/java/org/shedlang/compiler/types/ConstructedType.java b/src/main/java/org/shedlang/compiler/types/ConstructedType.java index d4f688dc..daf7bcb4 100644 --- a/src/main/java/org/shedlang/compiler/types/ConstructedType.java +++ b/src/main/java/org/shedlang/compiler/types/ConstructedType.java @@ -4,28 +4,28 @@ import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; -public record ConstructedType<T extends StructuredType>( - TypeConstructor<T> constructor, - List<? extends Type> args -) implements Type { +public sealed interface ConstructedType<T extends StructuredType> extends Type permits ConstructedStructType, ConstructedSumType { + TypeConstructor<T> constructor(); + List<? extends Type> args(); + @Override - public String describe() { - var argsString = args.stream() + default String describe() { + var argsString = args().stream() .map(arg -> arg.describe()) .collect(Collectors.joining(", ")); - return constructor.describe() + "[" + argsString + "]"; + return constructor().describe() + "[" + argsString + "]"; } - public T genericType() { - return constructor.genericType(); + default T genericType() { + return constructor().genericType(); } - public TypeSubstitutionMap typeSubstitutionMap() { + default TypeSubstitutionMap typeSubstitutionMap() { var map = new HashMap<TypeParam, Type>(); - for (var argIndex = 0; argIndex < args.size(); argIndex++) { - var param = constructor.params().get(argIndex); - var arg = args.get(argIndex); + for (var argIndex = 0; argIndex < args().size(); argIndex++) { + var param = constructor().params().get(argIndex); + var arg = args().get(argIndex); map.put(param, arg); } diff --git a/src/main/java/org/shedlang/compiler/types/SumVariant.java b/src/main/java/org/shedlang/compiler/types/SumVariant.java index 74ff287b..5c04d77b 100644 --- a/src/main/java/org/shedlang/compiler/types/SumVariant.java +++ b/src/main/java/org/shedlang/compiler/types/SumVariant.java @@ -1,7 +1,7 @@ package org.shedlang.compiler.types; public sealed interface SumVariant { - static SumVariant constructedStruct(ConstructedType<StructType> type) { + static SumVariant constructedStruct(ConstructedStructType type) { return new ConstructedStruct(type); } @@ -14,7 +14,7 @@ public sealed interface SumVariant { Type type(); StructType rawType(); - record ConstructedStruct(ConstructedType<StructType> type) implements SumVariant { + record ConstructedStruct(ConstructedStructType type) implements SumVariant { @Override public String describe() { return type.describe(); diff --git a/src/main/java/org/shedlang/compiler/types/TypeSubstitution.java b/src/main/java/org/shedlang/compiler/types/TypeSubstitution.java index 60edfdfb..db6d554f 100644 --- a/src/main/java/org/shedlang/compiler/types/TypeSubstitution.java +++ b/src/main/java/org/shedlang/compiler/types/TypeSubstitution.java @@ -1,6 +1,8 @@ package org.shedlang.compiler.types; +import java.util.List; import java.util.Optional; +import java.util.function.BiFunction; public class TypeSubstitution { private TypeSubstitution() {} @@ -13,8 +15,11 @@ public class TypeSubstitution { case BottomType bottomType -> type; - case ConstructedType<?> constructedType -> - substituteConstructedType(constructedType, map); + case ConstructedStructType constructedType -> + substituteConstructedStructType(constructedType, map); + + case ConstructedSumType constructedType -> + substituteConstructedSumType(constructedType, map); case FunctionType functionType -> new FunctionType( Optional.empty(), @@ -66,11 +71,37 @@ public class TypeSubstitution { }; } - public static <T extends StructuredType> ConstructedType<T> substituteConstructedType( + public static ConstructedStructType substituteConstructedStructType( + ConstructedStructType constructedType, + TypeSubstitutionMap map + ) { + return substituteConstructedType( + ConstructedStructType::new, + constructedType, + map + ); + } + + private static ConstructedSumType substituteConstructedSumType( + ConstructedSumType constructedType, + TypeSubstitutionMap map + ) { + return substituteConstructedType( + ConstructedSumType::new, + constructedType, + map + ); + } + + private static < + T extends StructuredType, + TConstructedType extends ConstructedType<T> + > TConstructedType substituteConstructedType( + BiFunction<TypeConstructor<T>, List<Type>, TConstructedType> createConstructedType, ConstructedType<T> constructedType, TypeSubstitutionMap map ) { - return new ConstructedType<>( + return createConstructedType.apply( constructedType.constructor(), constructedType.args().stream() .map(arg -> substituteType(arg, map)) diff --git a/src/main/java/org/shedlang/compiler/types/Types.java b/src/main/java/org/shedlang/compiler/types/Types.java index d05f4665..dbf5b441 100644 --- a/src/main/java/org/shedlang/compiler/types/Types.java +++ b/src/main/java/org/shedlang/compiler/types/Types.java @@ -49,11 +49,31 @@ public class Types { return new TypeConstructor<>(params, genericType); } - public static <T extends StructuredType> ConstructedType<T> constructedType( - TypeConstructor<T> constructor, + @SuppressWarnings("unchecked") + public static ConstructedType<?> constructedType( + TypeConstructor<?> constructor, List<? extends Type> args ) { - return new ConstructedType<>(constructor, args); + return switch (constructor.genericType()) { + case StructType structType -> + constructedStructType((TypeConstructor<StructType>) constructor, args); + case SumType sumType -> + constructedSumType((TypeConstructor<SumType>) constructor, args); + }; + } + + public static ConstructedStructType constructedStructType( + TypeConstructor<StructType> constructor, + List<? extends Type> args + ) { + return new ConstructedStructType(constructor, args); + } + + public static ConstructedSumType constructedSumType( + TypeConstructor<SumType> constructor, + List<? extends Type> args + ) { + return new ConstructedSumType(constructor, args); } public static Type commonSupertype(List<Type> subtypes) { |
