summaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-08-02 10:07:28 +0100
committerMichael Williamson <mike@zwobble.org>2026-08-02 10:17:47 +0100
commit74e48f7b3961bb84b68b9dd795e564735196489c (patch)
treec73a8a337d17f590c9dc9bc2cd0a7e265feff0f7 /src/main/java/org
parent113f53a4268d05618f91eda2fc6c379bb7c23383 (diff)
Introduce SumVariant
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java10
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java14
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java50
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java64
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java21
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java40
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/types/SumVariant.java16
11 files changed, 112 insertions, 111 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java
index 61af40e..bea3f1d 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java
@@ -261,7 +261,7 @@ public class JavaPreciselyMatchersGenerator implements Generator {
return this.typesInfo.variantOf(type);
}
- public List<Type> variants(SumType type) {
+ public List<SumVariant> variants(SumType type) {
return this.typesInfo.sumVariants(type);
}
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java
index ff9bcd4..f64370c 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java
@@ -606,9 +606,10 @@ public class JavaTypesGenerator implements Generator {
seenTypes.add(sumType);
// TODO: better error
return context.sumVariants(sumType).stream()
- .filter(variant -> isNonRecursivelyConstructable(variant, seenTypes, context))
+ .filter(variant -> isNonRecursivelyConstructable(variant.valueType(), seenTypes, context))
.findFirst()
- .orElseThrow();
+ .orElseThrow()
+ .containerType();
}
private boolean isNonRecursivelyConstructable(Type type, Set<Type> seenTypes, Context context) {
@@ -618,6 +619,7 @@ public class JavaTypesGenerator implements Generator {
return switch (type) {
case ConstructedNativeType constructedNativeType ->
+ // TODO: Handle Box and Shared
true;
case EnumType enumType ->
@@ -638,7 +640,7 @@ public class JavaTypesGenerator implements Generator {
var newSeenTypes = new HashSet<>(seenTypes);
newSeenTypes.add(type);
var result = context.sumVariants(sumType).stream()
- .anyMatch(variant -> isNonRecursivelyConstructable(variant, seenTypes, context));
+ .anyMatch(variant -> isNonRecursivelyConstructable(variant.valueType(), seenTypes, context));
yield result;
}
@@ -685,7 +687,7 @@ public class JavaTypesGenerator implements Generator {
return this.typesInfo.variantOf(type);
}
- public List<Type> sumVariants(SumType type) {
+ public List<SumVariant> sumVariants(SumType type) {
return this.typesInfo.sumVariants(type);
}
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java
index d9df4eb..ec10107 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java
@@ -1,6 +1,5 @@
package org.zwobble.hobgoblin.compiler.output.generators.rust;
-import org.zwobble.hobgoblin.compiler.builtins.NativeTypes;
import org.zwobble.hobgoblin.compiler.output.lang.rust.RustWriter;
import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*;
import org.zwobble.hobgoblin.compiler.types.*;
@@ -117,16 +116,7 @@ public class RustGenerator {
return generateTypeName(Casing.lowerCamelCaseToUpperCamelCase(enumVariantName));
}
- public RustIdentifier generateVariantName(Type type) {
- if (type instanceof StructType structType) {
- return generateTypeName(structType.name());
- } else if (
- type instanceof ConstructedNativeType constructedNativeType &&
- constructedNativeType.constructor().equals(NativeTypes.BOX)
- ) {
- return generateVariantName(constructedNativeType.args().getFirst());
- } else {
- throw new UnsupportedOperationException("TODO");
- }
+ public RustIdentifier generateVariantName(SumVariant variant) {
+ return generateTypeName(variant.valueType().name());
}
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
index 83ad2fe..20b21de 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
@@ -59,7 +59,7 @@ public class RustTransient0Generator implements Generator {
generateBuiltins();
for (var namespace : namespaces) {
- var rustModule = generateNamespace(namespace);
+ var rustModule = generateNamespace(namespace, typesInfo);
this.rustGenerator.write(rustModule);
}
@@ -282,14 +282,17 @@ public class RustTransient0Generator implements Generator {
);
}
- private RustModule generateNamespace(TypedNamespaceNode namespace) {
+ private RustModule generateNamespace(
+ TypedNamespaceNode namespace,
+ TypesInfo typesInfo
+ ) {
var namespaceName = namespace.namespaceName();
var moduleName = generateTransient0ModuleName(namespaceName);
return new RustModule(
moduleName,
namespace.body().stream()
- .flatMap(statement -> this.generateNamespaceStatement(statement))
+ .flatMap(statement -> this.generateNamespaceStatement(statement, typesInfo))
.toList()
);
}
@@ -301,7 +304,8 @@ public class RustTransient0Generator implements Generator {
}
private Stream<RustItem> generateNamespaceStatement(
- TypedNamespaceStatementNode statement
+ TypedNamespaceStatementNode statement,
+ TypesInfo typesInfo
) {
return switch (statement) {
case TypedEnumDefinitionNode enumDefinition -> {
@@ -324,8 +328,8 @@ public class RustTransient0Generator implements Generator {
case TypedSumDefinitionNode sumDefinition -> {
yield Stream.of(
- generateEncodeSumFunction(sumDefinition),
- generateDecodeSumFunction(sumDefinition)
+ generateEncodeSumFunction(sumDefinition, typesInfo),
+ generateDecodeSumFunction(sumDefinition, typesInfo)
);
}
};
@@ -439,18 +443,19 @@ public class RustTransient0Generator implements Generator {
);
}
- private RustItem generateEncodeSumFunction(TypedSumDefinitionNode sumDefinition) {
+ private RustItem generateEncodeSumFunction(
+ TypedSumDefinitionNode sumDefinition,
+ TypesInfo typesInfo
+ ) {
return generateEncodeFunction(
sumDefinition.type(),
List.of(
new RustExpressionStatement(new RustMatchExpression(
RustPath.of(VALUE_NAME),
- IntStream.range(0, sumDefinition.variants().size())
- .mapToObj(variantIndex -> {
- var variant = sumDefinition.variants().get(variantIndex);
- var variantType = variant.type().value();
+ typesInfo.sumVariants(sumDefinition.type()).stream()
+ .map(variant -> {
var variantPath = this.rustGenerator.generateRustTypeExpression(sumDefinition.type())
- .addSegment(RustPathSegment.of(this.rustGenerator.generateVariantName(variantType)));
+ .addSegment(RustPathSegment.of(this.rustGenerator.generateVariantName(variant)));
return new RustMatchArm(
new RustTupleStructPattern(variantPath, List.of(new RustIdentifierPattern(VALUE_NAME))),
@@ -459,11 +464,11 @@ public class RustTransient0Generator implements Generator {
generateEncode(
new RustPrefixExpression(
RustPrefixOperator.BORROW,
- new RustIntegerLiteral(variantIndex, Optional.empty())
+ new RustIntegerLiteral(variant.tag(), Optional.empty())
),
NativeTypes.INT_32
),
- generateEncode(RustPath.of(VALUE_NAME), variantType)
+ generateEncode(RustPath.of(VALUE_NAME), variant.containerType())
),
Optional.empty()
)
@@ -475,18 +480,19 @@ public class RustTransient0Generator implements Generator {
);
}
- private RustItem generateDecodeSumFunction(TypedSumDefinitionNode sumDefinition) {
- var decodeMatchArms = IntStream.range(0, sumDefinition.variants().size())
- .mapToObj(variantIndex -> {
- var variant = sumDefinition.variants().get(variantIndex);
- var variantType = variant.type().value();
+ private RustItem generateDecodeSumFunction(
+ TypedSumDefinitionNode sumDefinition,
+ TypesInfo typesInfo
+ ) {
+ var decodeMatchArms = typesInfo.sumVariants(sumDefinition.type()).stream()
+ .map(variant -> {
var variantPath = this.rustGenerator.generateRustTypeExpression(sumDefinition.type())
- .addSegment(RustPathSegment.of(this.rustGenerator.generateVariantName(variantType)));
+ .addSegment(RustPathSegment.of(this.rustGenerator.generateVariantName(variant)));
- var valueExpression = generateDecode(variantType);
+ var valueExpression = generateDecode(variant.containerType());
return new RustMatchArm(
- new RustLiteralPattern(new RustIntegerLiteral(variantIndex, Optional.empty())),
+ new RustLiteralPattern(new RustIntegerLiteral(variant.tag(), Optional.empty())),
new RustCallExpression(variantPath, List.of(valueExpression))
);
})
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java
index c39e9a3..4744322 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java
@@ -1,15 +1,12 @@
package org.zwobble.hobgoblin.compiler.output.generators.rusttypes;
import org.zwobble.hobgoblin.compiler.ast.typed.*;
-import org.zwobble.hobgoblin.compiler.builtins.NativeTypes;
import org.zwobble.hobgoblin.compiler.config.OutputConfig;
import org.zwobble.hobgoblin.compiler.output.generators.Generator;
import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGenerator;
import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGeneratorConfig;
import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*;
import org.zwobble.hobgoblin.compiler.typechecker.TypesInfo;
-import org.zwobble.hobgoblin.compiler.types.ConstructedNativeType;
-import org.zwobble.hobgoblin.compiler.types.NamespaceName;
import org.zwobble.hobgoblin.compiler.types.Type;
import org.zwobble.json5.reader.Json5ObjectReader;
@@ -50,18 +47,17 @@ public class RustTypesGenerator implements Generator {
@Override
public void generate(List<TypedNamespaceNode> namespaces, TypesInfo typesInfo) throws IOException {
for (var namespace : namespaces) {
- var context = new Context(namespace.namespaceName());
- var rustModule = generateNamespace(namespace, context);
+ var rustModule = generateNamespace(namespace, typesInfo);
this.rustGenerator.write(rustModule);
}
}
- private RustModule generateNamespace(TypedNamespaceNode namespace, Context context) {
+ private RustModule generateNamespace(TypedNamespaceNode namespace, TypesInfo typesInfo) {
var rustModuleName = this.rustGenerator.namespaceNameToRustCrateModulePath(namespace.namespaceName());
var rustItems = namespace.body().stream()
- .flatMap(statement -> generateNamespaceStatement(statement, context).stream())
+ .flatMap(statement -> generateNamespaceStatement(statement, typesInfo).stream())
.toList();
return new RustModule(rustModuleName, rustItems);
@@ -69,11 +65,11 @@ public class RustTypesGenerator implements Generator {
private List<RustItem> generateNamespaceStatement(
TypedNamespaceStatementNode statement,
- Context context
+ TypesInfo typesInfo
) {
return switch (statement) {
case TypedEnumDefinitionNode enumDefinition -> {
- yield generateEnumDefinition(enumDefinition, context);
+ yield generateEnumDefinition(enumDefinition);
}
case TypedNativeTypeDefinitionNode nativeTypeDefinition -> {
@@ -81,18 +77,17 @@ public class RustTypesGenerator implements Generator {
}
case TypedStructDefinitionNode structDefinition -> {
- yield generateStructDefinition(structDefinition, context);
+ yield generateStructDefinition(structDefinition);
}
case TypedSumDefinitionNode sumDefinition -> {
- yield generateSumDefinition(sumDefinition, context);
+ yield generateSumDefinition(sumDefinition, typesInfo);
}
};
}
private List<RustItem> generateEnumDefinition(
- TypedEnumDefinitionNode enumDefinition,
- Context context
+ TypedEnumDefinitionNode enumDefinition
) {
var rustAttributes = List.of(ENUM_DERIVE_ATTRIBUTE);
@@ -126,8 +121,7 @@ public class RustTypesGenerator implements Generator {
);
private List<RustItem> generateStructDefinition(
- TypedStructDefinitionNode structDefinition,
- Context context
+ TypedStructDefinitionNode structDefinition
) {
var rustAttributes = List.of(STRUCT_DERIVE_ATTRIBUTE);
@@ -137,7 +131,7 @@ public class RustTypesGenerator implements Generator {
fields -> fields.stream()
.map(field -> new RustStructField(
this.rustGenerator.generateFieldName(field.name()),
- generateRustTypeExpression(field.type(), context)
+ generateRustTypeExpression(field.type())
))
.toList()
);
@@ -154,7 +148,7 @@ public class RustTypesGenerator implements Generator {
private List<RustItem> generateSumDefinition(
TypedSumDefinitionNode sumDefinition,
- Context context
+ TypesInfo typesInfo
) {
var rustAttributes = List.of(STRUCT_DERIVE_ATTRIBUTE);
@@ -162,12 +156,12 @@ public class RustTypesGenerator implements Generator {
var rustEnumName = this.rustGenerator.generateTypeName(sumDefinition.name());
- var rustVariants = sumDefinition.variants().stream()
+ var rustVariants = typesInfo.sumVariants(sumDefinition.type()).stream()
.map(variant -> {
- var variantType = generateRustTypeExpression(variant.type(), context);
+ var variantType = this.rustGenerator.generateRustTypeExpression(variant.containerType());
return new RustEnumVariant(
- this.rustGenerator.generateVariantName(variant.type().value()),
+ this.rustGenerator.generateVariantName(variant),
new RustEnumVariantTuple(List.of(
new RustTupleField(variantType)
))
@@ -183,21 +177,10 @@ public class RustTypesGenerator implements Generator {
);
items.add(rustEnum);
- for (var variant : sumDefinition.variants()) {
- var variantName = this.rustGenerator.generateVariantName(variant.type().value());
+ for (var variant : typesInfo.sumVariants(sumDefinition.type())) {
+ var variantName = this.rustGenerator.generateVariantName(variant);
- var fromType = variant.type().value();
- var isBox = false;
-
- if (
- variant.type().value() instanceof ConstructedNativeType variantConstructedNativeType &&
- variantConstructedNativeType.constructor().equals(NativeTypes.BOX)
- ) {
- fromType = variantConstructedNativeType.args().getFirst();
- isBox = true;
- }
-
- var fromRustType = this.rustGenerator.generateRustTypeExpression(fromType);
+ var fromRustType = this.rustGenerator.generateRustTypeExpression(variant.valueType());
var innerValueName = new RustIdentifier("value");
RustExpression innerValue = new RustPath(List.of(
@@ -207,7 +190,7 @@ public class RustTypesGenerator implements Generator {
)
));
- if (isBox) {
+ if (variant.isBox()) {
innerValue = new RustCallExpression(
RustPath.global("std", "boxed", "Box", "new"),
List.of(innerValue)
@@ -243,17 +226,8 @@ public class RustTypesGenerator implements Generator {
}
private RustType generateRustTypeExpression(
- TypedTypeLevelExpressionNode<Type> type,
- Context context
+ TypedTypeLevelExpressionNode<Type> type
) {
return this.rustGenerator.generateRustTypeExpression(type.value());
}
-
- private static class Context {
- private final NamespaceName currentNamespaceName;
-
- private Context(NamespaceName currentNamespaceName) {
- this.currentNamespaceName = currentNamespaceName;
- }
- }
}
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 7ac14fe..d87b7ff 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
@@ -268,7 +268,7 @@ public class TypeChecker {
var sumType = (SumType) lookupMetaType(untyped.name(), untyped.source(), context);
var typedVariants = new ArrayList<TypedSumVariantDefinitionNode>();
- var variantTypes = new ArrayList<StructType>();
+ var variants = new ArrayList<SumVariant>();
for (var untypedVariant : untyped.variants()) {
var variantType = typeCheckMetaType(untypedVariant.type(), context);
var typedVariant = new TypedSumVariantDefinitionNode(
@@ -277,28 +277,31 @@ public class TypeChecker {
);
typedVariants.add(typedVariant);
- // TODO: handle not struct type
+ Type variantValueType;
if (
variantType.value() instanceof ConstructedNativeType variantConstructedNativeType &&
variantConstructedNativeType.constructor().equals(NativeTypes.BOX)
) {
- variantTypes.add((StructType) variantConstructedNativeType.args().getFirst());
+ variantValueType = variantConstructedNativeType.args().getFirst();
} else {
- variantTypes.add((StructType) variantType.value());
+ variantValueType = variantType.value();
}
+ // TODO: handle not struct type
+ var variant = new SumVariant(variants.size(), variantType.value(), (StructType) variantValueType);
+ variants.add(variant);
}
var typeCheckedFieldDefinitions = typeCheckFieldDefinitions(untyped.fields(), context);
- context.defineSumType(sumType, variantTypes, typeCheckedFieldDefinitions.fields);
+ context.defineSumType(sumType, variants, typeCheckedFieldDefinitions.fields);
- for (var variantType : variantTypes) {
- if (context.isDefined(variantType)) {
+ for (var variant : variants) {
+ if (context.isDefined(variant.valueType())) {
typeCheckVariantType(
sumType,
typeCheckedFieldDefinitions.fields,
- variantType,
- context.fieldsOf(variantType),
+ variant.valueType(),
+ context.fieldsOf(variant.valueType()),
context.toTypesInfo()
);
}
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 5484904..804fd68 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java
@@ -75,7 +75,7 @@ public class TypeCheckerNamespaceContext {
public void defineSumType(
SumType sumType,
- List<StructType> variantTypes,
+ List<SumVariant> variantTypes,
List<Field> fields
) {
this.typesInfo.defineSumType(sumType, variantTypes, fields);
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 335fa8d..957c53b 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSubtyping.java
@@ -14,7 +14,7 @@ class TypeCheckerSubtyping {
if (supertype instanceof SumType supertypeSum) {
return typesInfo.sumVariants(supertypeSum).stream()
- .anyMatch(variantType -> isSubtype(variantType, subtype, typesInfo));
+ .anyMatch(variantType -> isSubtype(variantType.containerType(), 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 697be9b..97a8c74 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java
@@ -12,7 +12,7 @@ public interface TypesInfo {
Optional<List<Field>> fieldsOf(StructType structType);
List<SumType> variantOf(StructType variantType);
- List<Type> sumVariants(SumType type);
+ List<SumVariant> sumVariants(SumType type);
List<EnumVariant> enumVariants(EnumType enumType);
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java
index 821238b..7da4d2c 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java
@@ -1,12 +1,8 @@
package org.zwobble.hobgoblin.compiler.typechecker;
import org.zwobble.hobgoblin.compiler.types.*;
-import org.zwobble.hobgoblin.compiler.util.ManyToMany;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
public class TypesInfoInMemory implements TypesInfo {
public static TypesInfoInMemory empty() {
@@ -14,25 +10,31 @@ public class TypesInfoInMemory implements TypesInfo {
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
- new ManyToMany<>()
+ new HashMap<>(),
+ new HashMap<>()
);
}
private final Map<EnumType, List<EnumVariant>> enumVariants;
+
private final Map<Type, Optional<List<Field>>> structFields;
+
private final Map<Type, List<Field>> sumFields;
- private final ManyToMany<SumType, Type> sumVariants;
+ private final Map<SumType, List<SumVariant>> sumToVariants;
+ private final Map<StructType, List<SumType>> variantToSums;
public TypesInfoInMemory(
Map<EnumType, List<EnumVariant>> enumVariants,
Map<Type, Optional<List<Field>>> structFields,
Map<Type, List<Field>> sumFields,
- ManyToMany<SumType, Type> sumVariants
+ Map<SumType, List<SumVariant>> sumToVariants,
+ Map<StructType, List<SumType>> variantToSums
) {
this.enumVariants = enumVariants;
this.structFields = structFields;
this.sumFields = sumFields;
- this.sumVariants = sumVariants;
+ this.sumToVariants = sumToVariants;
+ this.variantToSums = variantToSums;
}
public void defineEnumType(EnumType enumType, List<EnumVariant> enumVariants) {
@@ -65,21 +67,29 @@ public class TypesInfoInMemory implements TypesInfo {
public void defineSumType(
SumType sumType,
- List<StructType> variantTypes,
+ List<SumVariant> variants,
List<Field> fields
) {
- for (var variantType : variantTypes) {
- this.sumVariants.add(sumType, variantType);
+ this.sumToVariants.put(sumType, variants);
+ for (var variant : variants) {
+ this.variantToSums.putIfAbsent(variant.valueType(), new ArrayList<>());
+ this.variantToSums.get(variant.valueType()).add(sumType);
}
this.sumFields.put(sumType, fields);
}
public List<SumType> variantOf(StructType variantType) {
- return this.sumVariants.rightToLeft(variantType);
+ return this.variantToSums.getOrDefault(variantType, List.of());
}
- public List<Type> sumVariants(SumType type) {
- return this.sumVariants.leftToRight(type);
+ public List<SumVariant> sumVariants(SumType type) {
+ var variants = this.sumToVariants.get(type);
+ if (variants == null) {
+ // TODO: better error
+ throw new RuntimeException("sum not defined");
+ } else {
+ return variants;
+ }
}
public List<Field> fieldsOf(SumType sumType) {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/SumVariant.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/SumVariant.java
new file mode 100644
index 0000000..72dbe71
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/SumVariant.java
@@ -0,0 +1,16 @@
+package org.zwobble.hobgoblin.compiler.types;
+
+import org.zwobble.hobgoblin.compiler.builtins.NativeTypes;
+
+public record SumVariant(
+ int tag,
+ Type containerType,
+ StructType valueType
+) {
+ public boolean isBox() {
+ return (
+ containerType instanceof ConstructedNativeType containerConstructedNativeType &&
+ containerConstructedNativeType.constructor().equals(NativeTypes.BOX)
+ );
+ }
+}