summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java30
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java60
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/types/ConstructibleType.java1
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java11
4 files changed, 85 insertions, 17 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java
index 901171c..5421e58 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java
@@ -140,23 +140,34 @@ public class JavaGenerator {
}
public JavaTypeRef generateTypeRef(Type type) {
- return this.generateTypeRef(type, false);
+ return this.generateTypeRef(type, false, Set.of());
}
public JavaTypeRef generateReferenceTypeRef(Type type) {
- return this.generateTypeRef(type, true);
+ return this.generateTypeRef(type, true, Set.of());
}
- private JavaTypeRef generateTypeRef(Type type, boolean referenceType) {
+ public JavaTypeRef generateReferenceTypeRef(Type type, Set<TypeParam> wildcardTypeParams) {
+ return this.generateTypeRef(type, true, wildcardTypeParams);
+ }
+
+ private JavaTypeRef generateTypeRef(Type type, boolean referenceType, Set<TypeParam> wildcardTypeParams) {
return switch (collapseType(type)) {
case ConstructedType constructedType -> {
var innerTypeRef = generateTypeRef(
constructedType.constructor().genericType(),
- referenceType
+ referenceType,
+ wildcardTypeParams
);
var javaArgs = constructedType.args().stream()
- .map(arg -> JavaTypeArg.invariant(generateTypeRef(arg, true)))
+ .map(arg -> {
+ if (wildcardTypeParams.contains(arg)) {
+ return JavaTypeArg.wildcard();
+ } else {
+ return JavaTypeArg.invariant(generateTypeRef(arg, true, wildcardTypeParams));
+ }
+ })
.toList();
yield JavaTypeRef.generic(innerTypeRef.packageName(), innerTypeRef.typeNames(), javaArgs);
@@ -200,8 +211,13 @@ public class JavaGenerator {
case TypeLevelValueType typeLevelValueType ->
throw new UnsupportedOperationException("TODO");
- case TypeParam typeParam ->
- JavaTypeRef.local(this.generateTypeName(typeParam.name()));
+ case TypeParam typeParam -> {
+ if (wildcardTypeParams.contains(typeParam)) {
+ yield JavaTypeRef.OBJECT;
+ } else {
+ yield JavaTypeRef.local(this.generateTypeName(typeParam.name()));
+ }
+ }
};
}
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 760e01e..2a00d2b 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
@@ -16,6 +16,7 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
import static org.zwobble.hobgoblin.compiler.util.Casing.lowerCamelCaseToUpperCamelCase;
@@ -89,12 +90,25 @@ public class JavaPreciselyMatchersGenerator implements Generator {
TypedStructDefinitionNode structDefinition,
Context context
) {
- var structType = structDefinition.typeOrThrow();
+ var javaStructTypeRef = switch (structDefinition.typeOrConstructor()) {
+ case TypeOrConstructor.Constructor<SimpleStructType> constructor -> {
+ var args = constructor.value().params().stream()
+ .map(_ -> JavaTypeArg.wildcard())
+ .toList();
+
+ yield this.javaGenerator.generateTypeRef(constructor.unboundType())
+ .withArgs(args);
+ }
+
+ case TypeOrConstructor.Type<SimpleStructType> type -> {
+ yield this.javaGenerator.generateTypeRef(type.value());
+ }
+ };
- var javaStructTypeRef = this.javaGenerator.generateTypeRef(structType);
+ var javaStructRawTypeRef = this.javaGenerator.generateTypeRef(structDefinition.typeOrConstructor().unboundType());
- var javaMatcherTypeRef = this.structMatcherRef(structType);
- var matcherTypeName = this.structMatcherTypeName(structType);
+ var javaMatcherTypeRef = this.structMatcherRef(structDefinition.typeOrConstructor());
+ var matcherTypeName = this.structMatcherTypeName(structDefinition.typeOrConstructor());
var submatchersIdentifier = JavaIdentifier.of("submatchers");
var methods = new ArrayList<JavaClassBodyDeclaration>(List.of(
@@ -191,8 +205,19 @@ public class JavaPreciselyMatchersGenerator implements Generator {
List.of(),
JavaIdentifier.of("instanceOf"),
List.of(
- new JavaClassLiteral(javaStructTypeRef),
- new JavaFieldAccess(JavaRef.THIS, submatchersIdentifier)
+ new JavaClassLiteral(javaStructRawTypeRef),
+ switch (structDefinition.typeOrConstructor()) {
+ case TypeOrConstructor.Constructor<SimpleStructType> _ ->
+ // This should be a safe cast since X and X<?, ..., ?>
+ // should be compatible.
+ new JavaCast(
+ JavaTypeRef.LIST,
+ new JavaFieldAccess(JavaRef.THIS, submatchersIdentifier)
+ );
+
+ case TypeOrConstructor.Type<SimpleStructType> _ ->
+ new JavaFieldAccess(JavaRef.THIS, submatchersIdentifier);
+ }
)
))
))
@@ -201,7 +226,14 @@ public class JavaPreciselyMatchersGenerator implements Generator {
for (var field : structDefinition.fields().orElse(List.of())) {
var fieldType = field.type().value();
- var javaFieldTypeRef = this.javaGenerator.generateReferenceTypeRef(fieldType);
+ var typeParams = switch (structDefinition.typeOrConstructor()) {
+ case TypeOrConstructor.Constructor<SimpleStructType> constructor ->
+ Set.copyOf(constructor.value().params());
+
+ case TypeOrConstructor.Type<SimpleStructType> _ ->
+ Set.<TypeParam>of();
+ };
+ var javaFieldTypeRef = this.javaGenerator.generateReferenceTypeRef(fieldType, typeParams);
var javaFieldName = this.javaGenerator.generateFieldName(field.name());
methods.add(new JavaMethodDeclaration(
@@ -233,7 +265,15 @@ public class JavaPreciselyMatchersGenerator implements Generator {
List.of(
new JavaStringLiteral(field.name()),
new JavaMethodRef(javaStructTypeRef, javaFieldName),
- new JavaRef(javaFieldName)
+ // TODO: the use of wildcards should make this safe,
+ // but it would be nice to avoid the cast if possible.
+ new JavaCast(
+ JavaTypeRef.topLevel(
+ PRECISELY_PACKAGE_NAME,
+ JavaIdentifier.of("Matcher")
+ ),
+ new JavaRef(javaFieldName)
+ )
)
))
)),
@@ -291,7 +331,7 @@ public class JavaPreciselyMatchersGenerator implements Generator {
);
}
- private JavaTypeRef structMatcherRef(SimpleStructType structType) {
+ private JavaTypeRef structMatcherRef(TypeOrConstructor<SimpleStructType> structType) {
var matcherTypeName = structMatcherTypeName(structType);
return JavaTypeRef.topLevel(
@@ -300,7 +340,7 @@ public class JavaPreciselyMatchersGenerator implements Generator {
);
}
- private JavaIdentifier structMatcherTypeName(SimpleStructType structType) {
+ private JavaIdentifier structMatcherTypeName(TypeOrConstructor<SimpleStructType> structType) {
return this.javaGenerator.generateTypeName(structType.name() + "Matcher");
}
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/ConstructibleType.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/ConstructibleType.java
index 05fd042..8f3b931 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/types/ConstructibleType.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/ConstructibleType.java
@@ -1,4 +1,5 @@
package org.zwobble.hobgoblin.compiler.types;
public sealed interface ConstructibleType extends Type permits SimpleNativeType, SimpleStructType {
+ NamespaceName namespaceName();
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java
index 7904d29..4269686 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/TypeOrConstructor.java
@@ -11,6 +11,11 @@ public sealed interface TypeOrConstructor<T extends ConstructibleType> {
record Type<T extends ConstructibleType>(T value) implements TypeOrConstructor<T> {
@Override
+ public NamespaceName namespaceName() {
+ return this.value.namespaceName();
+ }
+
+ @Override
public String name() {
return this.value.name();
}
@@ -23,6 +28,11 @@ public sealed interface TypeOrConstructor<T extends ConstructibleType> {
record Constructor<T extends ConstructibleType>(TypeConstructor<T> value) implements TypeOrConstructor<T> {
@Override
+ public NamespaceName namespaceName() {
+ return value.genericType().namespaceName();
+ }
+
+ @Override
public String name() {
return this.value.name();
}
@@ -33,6 +43,7 @@ public sealed interface TypeOrConstructor<T extends ConstructibleType> {
}
}
+ NamespaceName namespaceName();
String name();
TypeLevelValue value();
T unboundType();