summaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-06-06 16:47:25 +0100
committerMichael Williamson <mike@zwobble.org>2026-06-08 23:40:56 +0100
commit450fd165619e6c3f2822bbb0d906fd439b867071 (patch)
tree9904536c0990159dc7341f58ea66339c9b4a4aae /src/main/java/org
parenta1c4c7f89107deb3f59d8569d2463281e6179fb4 (diff)
Improve selection of arbitrary variant
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java52
2 files changed, 52 insertions, 2 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java
index c2e484c..67f56e6 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java
@@ -1,6 +1,6 @@
package org.zwobble.hobgoblin.compiler.ast.untyped;
-public sealed interface UntypedTypeLevelExpressionNode permits org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelReferenceNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedConstructedTypeNode {
+public sealed interface UntypedTypeLevelExpressionNode permits org.zwobble.hobgoblin.compiler.ast.untyped.UntypedConstructedTypeNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelReferenceNode {
public interface Builder {
public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelExpressionNode build();
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 6e09b7d..653da8d 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
@@ -408,7 +408,7 @@ public class JavaTypesGenerator implements Generator {
}
case SumType sumType -> {
- var firstVariant = context.variants(sumType).getFirst();
+ var firstVariant = selectArbitraryVariant(sumType, context);
yield arbitraryValue(firstVariant, context);
}
@@ -422,6 +422,52 @@ public class JavaTypesGenerator implements Generator {
};
}
+ private Type selectArbitraryVariant(SumType sumType, Context context) {
+ var seenTypes = new HashSet<Type>();
+ seenTypes.add(sumType);
+ // TODO: better error
+ return context.variants(sumType).stream()
+ .filter(variant -> isNonRecursivelyConstructable(variant, seenTypes, context))
+ .findFirst()
+ .orElseThrow();
+ }
+
+ private boolean isNonRecursivelyConstructable(Type type, Set<Type> seenTypes, Context context) {
+ if (seenTypes.contains(type)) {
+ return false;
+ }
+
+ return switch (type) {
+ case ConstructedNativeType constructedNativeType ->
+ true;
+
+ case SimpleNativeType simpleNativeType ->
+ true;
+
+ case StructType structType -> {
+ var newSeenTypes = new HashSet<>(seenTypes);
+ newSeenTypes.add(type);
+ var result = context.fieldsOf(structType).stream()
+ .allMatch(field -> isNonRecursivelyConstructable(field.type(), newSeenTypes, context));
+ yield result;
+ }
+
+ case SumType sumType -> {
+ var newSeenTypes = new HashSet<>(seenTypes);
+ newSeenTypes.add(type);
+ var result = context.variants(sumType).stream()
+ .anyMatch(variant -> isNonRecursivelyConstructable(variant, seenTypes, context));
+ yield result;
+ }
+
+ case TypeLevelValueType typeLevelValueType ->
+ false;
+
+ case TypeParam typeParam ->
+ false;
+ };
+ }
+
private String lowerCamelCaseToUpperCamelCase(String name) {
return name.substring(0, 1).toUpperCase(Locale.ROOT) + name.substring(1);
}
@@ -437,6 +483,10 @@ public class JavaTypesGenerator implements Generator {
this.typesInfo = typesInfo;
}
+ public List<Field> fieldsOf(StructType type) {
+ return this.typesInfo.fieldsOf(type);
+ }
+
public List<SumType> variantOf(StructType type) {
return this.typesInfo.variantOf(type);
}