diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-08-22 00:44:07 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-08-22 00:44:07 +0100 |
| commit | 8f09d9afd09b1831ec979f38c624c438f8102794 (patch) | |
| tree | 8d882a7d47198df1db6c2816eed87a5bb9383253 /src/main/java/org/zwobble | |
| parent | a3deea1a8f8b8a4f476637d111f766de43badf65 (diff) | |
Handle generic structs in java-transient-0
Diffstat (limited to 'src/main/java/org/zwobble')
| -rw-r--r-- | src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java | 237 |
1 files changed, 187 insertions, 50 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java index 6d3177d..52539ce 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java @@ -17,6 +17,7 @@ import org.zwobble.json5.reader.Json5ObjectReader; import java.io.IOException; import java.nio.file.Path; import java.util.*; +import java.util.function.Function; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -27,6 +28,8 @@ public class JavaTransient0Generator implements Generator { private static final JavaIdentifier OUTPUT_STREAM_NAME = JavaIdentifier.of("outputStream"); private static final JavaIdentifier INPUT_STREAM_NAME = JavaIdentifier.of("inputStream"); private static final JavaIdentifier SHARED_VALUES_NAME = JavaIdentifier.of("sharedValues"); + private static final JavaIdentifier ENCODER_ENCODE_METHOD_NAME = JavaIdentifier.of("encode"); + private static final JavaIdentifier DECODE_DECODE_METHOD_NAME = JavaIdentifier.of("decode"); public static OutputConfig parseGeneratorConfig( Path projectRoot, @@ -171,7 +174,7 @@ public class JavaTransient0Generator implements Generator { private JavaCompilationUnit generateEncoderType() { return new JavaCompilationUnit(new JavaInterfaceDeclaration( - encoderRef(), + encoderTypeRef(), JavaInterfaceOpenness.OPEN, List.of( new JavaTypeParameter(JavaIdentifier.of("T")) @@ -179,7 +182,7 @@ public class JavaTransient0Generator implements Generator { List.of(), List.of( new JavaMethodDeclaration( - JavaIdentifier.of("encode"), + ENCODER_ENCODE_METHOD_NAME, JavaVisibility.PUBLIC, JavaMemberKind.INSTANCE, List.of(), @@ -201,7 +204,7 @@ public class JavaTransient0Generator implements Generator { ); } - private JavaTypeRef encoderRef() { + private JavaTypeRef encoderTypeRef() { var packageName = this.namespaceToJavaTransient0PackageName(NamespaceName.of()); return JavaTypeRef.topLevel( @@ -210,9 +213,13 @@ public class JavaTransient0Generator implements Generator { ); } + private JavaTypeRef encoderTypeRef(JavaTypeRef valueType) { + return encoderTypeRef().withArgs(List.of(JavaTypeArg.invariant(valueType))); + } + private JavaCompilationUnit generateDecoderType() { return new JavaCompilationUnit(new JavaInterfaceDeclaration( - decoderRef(), + decoderTypeRef(), JavaInterfaceOpenness.OPEN, List.of( new JavaTypeParameter(JavaIdentifier.of("T")) @@ -220,7 +227,7 @@ public class JavaTransient0Generator implements Generator { List.of(), List.of( new JavaMethodDeclaration( - JavaIdentifier.of("decode"), + DECODE_DECODE_METHOD_NAME, JavaVisibility.PUBLIC, JavaMemberKind.INSTANCE, List.of(), @@ -241,7 +248,7 @@ public class JavaTransient0Generator implements Generator { ); } - private JavaTypeRef decoderRef() { + private JavaTypeRef decoderTypeRef() { var packageName = this.namespaceToJavaTransient0PackageName(NamespaceName.of()); return JavaTypeRef.topLevel( @@ -250,6 +257,10 @@ public class JavaTransient0Generator implements Generator { ); } + private JavaTypeRef decoderTypeRef(JavaTypeRef valueType) { + return decoderTypeRef().withArgs(List.of(JavaTypeArg.invariant(valueType))); + } + private List<JavaCompilationUnit> generateBuiltins(Context context) { var packageName = this.namespaceToJavaTransient0PackageName(NamespaceName.of()); var transient0JavaName = generateTransient0ClassName("Builtins"); @@ -378,7 +389,7 @@ public class JavaTransient0Generator implements Generator { } private JavaMethodDeclaration generateDecodeIntMethod( - Type type, + SimpleType type, int bits ) { var statements = new ArrayList<JavaBlockStatement>(); @@ -654,53 +665,70 @@ public class JavaTransient0Generator implements Generator { TypedStructDefinitionNode structDefinition, Context context ) { - return generateEncodeMethod( - structDefinition.typeOrThrow(), - new JavaBlock( - structDefinition.fields().orElse(List.of()).stream() - .flatMap(field -> generateEncode( - new JavaMethodCall( - new JavaRef(VALUE_NAME), - this.javaGenerator.generateFieldName(field.name()), - List.of() - ), - field.type().value(), - context - ).stream()) - .toList() - ) + var fields = structDefinition.fields().orElse(List.of()); + + var encodeBody = new JavaBlock( + fields.stream() + .flatMap(field -> generateEncode( + new JavaMethodCall( + new JavaRef(VALUE_NAME), + this.javaGenerator.generateFieldName(field.name()), + List.of() + ), + field.type().value(), + context + ).stream()) + .toList() ); + + + return switch (structDefinition.typeOrConstructor()) { + case TypeOrConstructor.Constructor<SimpleStructType> constructor -> + generateEncodeMethod(constructor.value(), encodeBody); + + case TypeOrConstructor.Type<SimpleStructType> type -> + generateEncodeMethod(type.value(), encodeBody); + }; } private JavaMethodDeclaration generateDecodeStructMethod( TypedStructDefinitionNode structDefinition, Context context ) { - var structJavaTypeRef = this.javaGenerator.generateTypeRef(structDefinition.typeOrThrow()); - - return generateDecodeMethod( - structDefinition.typeOrThrow(), - new JavaBlock( - structDefinition.fields().isEmpty() - ? List.of(new JavaReturn( - new JavaStaticFieldAccess(structJavaTypeRef, JavaGenerator.INSTANCE_FIELD_NAME) - )) - : Stream.concat( + Function<JavaTypeRef, JavaBlock> decodeBody = structJavaTypeRef -> new JavaBlock( + structDefinition.fields().isEmpty() + ? List.of(new JavaReturn( + new JavaStaticFieldAccess(structJavaTypeRef, JavaGenerator.INSTANCE_FIELD_NAME) + )) + : Stream.concat( + structDefinition.fields().get().stream() + .flatMap(field -> generateDecode( + this.javaGenerator.generateFieldName(field.name()), + field.type().value(), + context + ).stream()), + Stream.of(new JavaReturn(new JavaNewExpression( + structJavaTypeRef, structDefinition.fields().get().stream() - .flatMap(field -> generateDecode( - this.javaGenerator.generateFieldName(field.name()), - field.type().value(), - context - ).stream()), - Stream.of(new JavaReturn(new JavaNewExpression( - structJavaTypeRef, - structDefinition.fields().get().stream() - .<JavaExpression>map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name()))) - .toList() - ))) - ).toList() - ) + .<JavaExpression>map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name()))) + .toList() + ))) + ).toList() ); + + return switch (structDefinition.typeOrConstructor()) { + case TypeOrConstructor.Constructor<SimpleStructType> constructor -> + generateDecodeMethod( + constructor.value(), + decodeBody + ); + + case TypeOrConstructor.Type<SimpleStructType> type -> + generateDecodeMethod( + type.value(), + decodeBody.apply(this.javaGenerator.generateTypeRef(type.value())) + ); + }; } private JavaMethodDeclaration generateEncodeSumMethod( @@ -816,12 +844,57 @@ public class JavaTransient0Generator implements Generator { ); } + private JavaMethodDeclaration generateEncodeMethod( + TypeConstructor<?> constructor, + JavaBlock body + ) { + var javaTypeParams = constructor.params().stream() + .map(typeParam -> new JavaTypeParameter(this.javaGenerator.generateTypeName(typeParam.name()))) + .toList(); + + var javaTypeArgs = javaTypeParams.stream() + .map(javaTypeParam -> JavaTypeArg.invariant(JavaTypeRef.local(javaTypeParam.name()))) + .toList(); + + var javaTypeRef = this.javaGenerator.generateTypeRef(constructor.genericType()) + .withArgs(javaTypeArgs); + + var typeArgEncoderParams = IntStream.range(0, constructor.params().size()) + .mapToObj(typeParamIndex -> { + var typeParam = constructor.params().get(typeParamIndex); + var javaTypeParam = javaTypeParams.get(typeParamIndex); + return new JavaParam( + encoderTypeRef(JavaTypeRef.local(javaTypeParam.name())), + generateEncoderVariableName(typeParam) + ); + }) + .toList(); + + return new JavaMethodDeclaration( + encodeMethodName(constructor.genericType()), + JavaVisibility.PUBLIC, + JavaMemberKind.STATIC, + javaTypeParams, + JavaTypeRef.VOID, + Lists.concat(List.of( + generateEncodeParams(javaTypeRef), + typeArgEncoderParams + )), + List.of(JavaTypeRef.IO_EXCEPTION), + body + ); + } + + private JavaIdentifier generateEncoderVariableName(TypeParam typeParam) { + return JavaIdentifier.of("encoder$" + this.javaGenerator.generateTypeName(typeParam.name()).value()); + } + private JavaTypeRef generateEncoderSharedValuesTypeRef() { return JavaTypeRef.map(this.taggedSharedValueRef(), JavaTypeRef.LONG_BOXED); } private JavaMethodDeclaration generateDecodeMethod( - Type type, + SimpleType type, JavaBlock body ) { var javaTypeRef = this.javaGenerator.generateTypeRef(type); @@ -838,6 +911,51 @@ public class JavaTransient0Generator implements Generator { ); } + private JavaMethodDeclaration generateDecodeMethod( + TypeConstructor<?> constructor, + Function<JavaTypeRef, JavaBlock> generateBody + ) { + var javaTypeParams = constructor.params().stream() + .map(typeParam -> new JavaTypeParameter(this.javaGenerator.generateTypeName(typeParam.name()))) + .toList(); + + var javaTypeArgs = javaTypeParams.stream() + .map(javaTypeParam -> JavaTypeArg.invariant(JavaTypeRef.local(javaTypeParam.name()))) + .toList(); + + var javaTypeRef = this.javaGenerator.generateTypeRef(constructor.genericType()) + .withArgs(javaTypeArgs); + + var typeArgDecoderParams = IntStream.range(0, constructor.params().size()) + .mapToObj(typeParamIndex -> { + var typeParam = constructor.params().get(typeParamIndex); + var javaTypeParam = javaTypeParams.get(typeParamIndex); + return new JavaParam( + decoderTypeRef(JavaTypeRef.local(javaTypeParam.name())), + generateDecoderVariableName(typeParam) + ); + }) + .toList(); + + return new JavaMethodDeclaration( + decodeMethodName(constructor.genericType()), + JavaVisibility.PUBLIC, + JavaMemberKind.STATIC, + javaTypeParams, + javaTypeRef, + Lists.concat(List.of( + generateDecodeParams(), + typeArgDecoderParams + )), + List.of(JavaTypeRef.IO_EXCEPTION), + generateBody.apply(javaTypeRef) + ); + } + + private JavaIdentifier generateDecoderVariableName(TypeParam typeParam) { + return JavaIdentifier.of("decoder$" + this.javaGenerator.generateTypeName(typeParam.name()).value()); + } + private static JavaTypeRef generateDecoderSharedValuesType() { return JavaTypeRef.list(JavaTypeRef.OBJECT); } @@ -880,8 +998,16 @@ public class JavaTransient0Generator implements Generator { throw new UnsupportedOperationException("TODO"); } - case TypeParam _ -> { - throw new UnsupportedOperationException("TODO"); + case TypeParam typeParam -> { + yield List.of(new JavaExpressionStatement(new JavaMethodCall( + new JavaRef(generateEncoderVariableName(typeParam)), + ENCODER_ENCODE_METHOD_NAME, + List.of( + value, + new JavaRef(OUTPUT_STREAM_NAME), + new JavaRef(SHARED_VALUES_NAME) + ) + ))); } }; } @@ -1003,8 +1129,19 @@ public class JavaTransient0Generator implements Generator { throw new UnsupportedOperationException("TODO"); } - case TypeParam _ -> { - throw new UnsupportedOperationException("TODO"); + case TypeParam typeParam -> { + yield List.of(new JavaLocalVariableDeclaration( + Optional.empty(), + target, + Optional.of(new JavaMethodCall( + new JavaRef(generateDecoderVariableName(typeParam)), + DECODE_DECODE_METHOD_NAME, + List.of( + new JavaRef(INPUT_STREAM_NAME), + new JavaRef(SHARED_VALUES_NAME) + ) + )) + )); } }; } |
