aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-01-03 21:23:18 +0000
committerMichael Williamson <mike@zwobble.org>2024-01-03 21:23:18 +0000
commit09f15965cf8fb86077e06bcf6c4f34af4ad7b0e7 (patch)
treedde7d4e74a4b1fd9d0959b4b34d979d295c46f2f /src/main/java
parentcddbde16fa288781732853db226fc02434491aa5 (diff)
Introduce specific subtypes for constructed types
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java25
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeCheckerSubTyping.java11
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java2
-rw-r--r--src/main/java/org/shedlang/compiler/types/ConstructedStructType.java9
-rw-r--r--src/main/java/org/shedlang/compiler/types/ConstructedSumType.java9
-rw-r--r--src/main/java/org/shedlang/compiler/types/ConstructedType.java26
-rw-r--r--src/main/java/org/shedlang/compiler/types/SumVariant.java4
-rw-r--r--src/main/java/org/shedlang/compiler/types/TypeSubstitution.java39
-rw-r--r--src/main/java/org/shedlang/compiler/types/Types.java26
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) {