diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-08-08 22:32:02 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-08-08 22:33:36 +0100 |
| commit | 39e34d4f524f5492065ba47b6cd33d5f272cd515 (patch) | |
| tree | f16782a9292d9da9564e4ce7d5d6efb791ef0498 /src/main/java/org | |
| parent | 6dd8f8fe274e11348b631abcf67ee7ccf8254997 (diff) | |
Partially support generic native types in java-transient-0
Diffstat (limited to 'src/main/java/org')
| -rw-r--r-- | src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java | 406 |
1 files changed, 289 insertions, 117 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 ff9b1e9..b0f63e7 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 @@ -63,7 +63,7 @@ public class JavaTransient0Generator implements Generator { var context = new Context(typesInfo); write(generateSupportTypes()); - write(generateBuiltins()); + write(generateBuiltins(context)); for (var namespace : namespaces) { var javaCompilationUnits = generateNamespace(namespace, context); @@ -77,66 +77,72 @@ public class JavaTransient0Generator implements Generator { } private List<JavaCompilationUnit> generateSupportTypes() { + return List.of( + generateTaggedSharedValueType(), + generateEncoderType(), + generateDecoderType() + ); + } + + private JavaCompilationUnit generateTaggedSharedValueType() { var typeId = JavaIdentifier.of("typeId"); var value = JavaIdentifier.of("value"); var other = JavaIdentifier.of("other"); var otherSharedValue = JavaIdentifier.of("otherSharedValue"); - return List.of( - new JavaCompilationUnit(new JavaRecordDeclaration( - this.taggedSharedValueRef(), - List.of( - new JavaRecordComponent(JavaTypeRef.LONG, typeId), - new JavaRecordComponent(JavaTypeRef.OBJECT, value) - ), - List.of(), - List.of( - new JavaMethodDeclaration( - JavaIdentifier.of("equals"), - JavaVisibility.PUBLIC, - JavaMemberKind.INSTANCE, - JavaTypeRef.BOOLEAN, - List.of(new JavaParam(JavaTypeRef.OBJECT, other)), - List.of(), - Optional.of(new JavaBlock(List.of( - new JavaReturn(new JavaBinaryOperation( + return new JavaCompilationUnit(new JavaRecordDeclaration( + this.taggedSharedValueRef(), + List.of( + new JavaRecordComponent(JavaTypeRef.LONG, typeId), + new JavaRecordComponent(JavaTypeRef.OBJECT, value) + ), + List.of(), + List.of( + new JavaMethodDeclaration( + JavaIdentifier.of("equals"), + JavaVisibility.PUBLIC, + JavaMemberKind.INSTANCE, + JavaTypeRef.BOOLEAN, + List.of(new JavaParam(JavaTypeRef.OBJECT, other)), + List.of(), + Optional.of(new JavaBlock(List.of( + new JavaReturn(new JavaBinaryOperation( + JavaBinaryOperator.LOGICAL_AND, + new JavaBinaryOperation( JavaBinaryOperator.LOGICAL_AND, - new JavaBinaryOperation( - JavaBinaryOperator.LOGICAL_AND, - new JavaInstanceofExpression( - new JavaRef(other), - new JavaPattern(taggedSharedValueRef(), otherSharedValue) - ), - new JavaBinaryOperation( - JavaBinaryOperator.EQUAL_TO, - new JavaFieldAccess(JavaRef.THIS, typeId), - new JavaFieldAccess(new JavaRef(otherSharedValue), typeId) - ) + new JavaInstanceofExpression( + new JavaRef(other), + new JavaPattern(taggedSharedValueRef(), otherSharedValue) ), new JavaBinaryOperation( JavaBinaryOperator.EQUAL_TO, - new JavaFieldAccess(JavaRef.THIS, value), - new JavaFieldAccess(new JavaRef(otherSharedValue), value) + new JavaFieldAccess(JavaRef.THIS, typeId), + new JavaFieldAccess(new JavaRef(otherSharedValue), typeId) ) - )) - ))) - ), - generateHashCode(List.of( - new JavaStaticMethodCall( - JavaTypeRef.LONG_BOXED, - JavaIdentifier.of("hashCode"), - List.of(new JavaFieldAccess(JavaRef.THIS, typeId)) - ), - new JavaStaticMethodCall( - JavaTypeRef.SYSTEM, - JavaIdentifier.of("identityHashCode"), - List.of(new JavaFieldAccess(JavaRef.THIS, value)) - ) - )) + ), + new JavaBinaryOperation( + JavaBinaryOperator.EQUAL_TO, + new JavaFieldAccess(JavaRef.THIS, value), + new JavaFieldAccess(new JavaRef(otherSharedValue), value) + ) + )) + ))) ), - DocComment.EMPTY - )) - ); + generateHashCode(List.of( + new JavaStaticMethodCall( + JavaTypeRef.LONG_BOXED, + JavaIdentifier.of("hashCode"), + List.of(new JavaFieldAccess(JavaRef.THIS, typeId)) + ), + new JavaStaticMethodCall( + JavaTypeRef.SYSTEM, + JavaIdentifier.of("identityHashCode"), + List.of(new JavaFieldAccess(JavaRef.THIS, value)) + ) + )) + ), + DocComment.EMPTY + )); } private JavaTypeRef taggedSharedValueRef() { @@ -160,7 +166,86 @@ public class JavaTransient0Generator implements Generator { .computeIfAbsent(type, _ -> (long) this.typeIds.size()); } - private List<JavaCompilationUnit> generateBuiltins() { + private JavaCompilationUnit generateEncoderType() { + return new JavaCompilationUnit(new JavaInterfaceDeclaration( + encoderRef(), + JavaInterfaceOpenness.OPEN, + List.of( + new JavaTypeParameter(JavaIdentifier.of("T")) + ), + List.of(), + List.of( + new JavaMethodDeclaration( + JavaIdentifier.of("encode"), + JavaVisibility.PUBLIC, + JavaMemberKind.INSTANCE, + JavaTypeRef.VOID, + generateEncodeParams(JavaTypeRef.local(JavaIdentifier.of("T"))), + List.of(JavaTypeRef.IO_EXCEPTION), + Optional.empty() + ) + ), + DocComment.EMPTY + )); + } + + private List<JavaParam> generateEncodeParams(JavaTypeRef valueType) { + return List.of( + new JavaParam(valueType, VALUE_NAME), + new JavaParam(JavaTypeRef.OUTPUT_STREAM, OUTPUT_STREAM_NAME), + new JavaParam(generateEncoderSharedValuesTypeRef(), SHARED_VALUES_NAME) + ); + } + + private JavaTypeRef encoderRef() { + var packageName = this.namespaceToJavaTransient0PackageName(NamespaceName.of()); + + return JavaTypeRef.topLevel( + packageName, + JavaIdentifier.of("Encoder") + ); + } + + private JavaCompilationUnit generateDecoderType() { + return new JavaCompilationUnit(new JavaInterfaceDeclaration( + decoderRef(), + JavaInterfaceOpenness.OPEN, + List.of( + new JavaTypeParameter(JavaIdentifier.of("T")) + ), + List.of(), + List.of( + new JavaMethodDeclaration( + JavaIdentifier.of("decode"), + JavaVisibility.PUBLIC, + JavaMemberKind.INSTANCE, + JavaTypeRef.local(JavaIdentifier.of("T")), + generateDecodeParams(), + List.of(JavaTypeRef.IO_EXCEPTION), + Optional.empty() + ) + ), + DocComment.EMPTY + )); + } + + private static List<JavaParam> generateDecodeParams() { + return List.of( + new JavaParam(JavaTypeRef.INPUT_STREAM, INPUT_STREAM_NAME), + new JavaParam(generateDecoderSharedValuesType(), SHARED_VALUES_NAME) + ); + } + + private JavaTypeRef decoderRef() { + var packageName = this.namespaceToJavaTransient0PackageName(NamespaceName.of()); + + return JavaTypeRef.topLevel( + packageName, + JavaIdentifier.of("Decoder") + ); + } + + private List<JavaCompilationUnit> generateBuiltins(Context context) { var packageName = this.namespaceToJavaTransient0PackageName(NamespaceName.of()); var transient0JavaName = generateTransient0ClassName("Builtins"); var transient0JavaTypeRef = JavaTypeRef.topLevel( @@ -182,7 +267,7 @@ public class JavaTransient0Generator implements Generator { generateDecodeInt32Method(), generateEncodeInt64Method(), generateDecodeInt64Method(), - generateEncodeStringMethod(), + generateEncodeStringMethod(context), generateDecodeStringMethod() ), DocComment.EMPTY @@ -323,7 +408,7 @@ public class JavaTransient0Generator implements Generator { return generateDecodeMethod(type, new JavaBlock(statements)); } - private JavaMethodDeclaration generateEncodeStringMethod() { + private JavaMethodDeclaration generateEncodeStringMethod(Context context) { var bytesVariableName = JavaIdentifier.of("bytes"); var statements = new ArrayList<JavaBlockStatement>(); @@ -347,7 +432,8 @@ public class JavaTransient0Generator implements Generator { new JavaRef(bytesVariableName), JavaIdentifier.of("length") )), - NativeTypes.INT_64 + NativeTypes.INT_64, + context )); statements.add(new JavaExpressionStatement(generateOutputStreamWrite( @@ -458,7 +544,7 @@ public class JavaTransient0Generator implements Generator { return switch (statement) { case TypedEnumDefinitionNode enumDefinition -> { yield Stream.concat( - Stream.of(generateEncodeEnumMethod(enumDefinition)), + Stream.of(generateEncodeEnumMethod(enumDefinition, context)), generateDecodeEnumMethod(enumDefinition) ); } @@ -469,21 +555,24 @@ public class JavaTransient0Generator implements Generator { case TypedStructDefinitionNode structDefinition -> { yield Stream.of( - generateEncodeStructMethod(structDefinition), + generateEncodeStructMethod(structDefinition, context), generateDecodeStructMethod(structDefinition) ); } case TypedSumDefinitionNode sumDefinition -> { yield Stream.of( - generateEncodeSumMethod(sumDefinition, context.typesInfo), + generateEncodeSumMethod(sumDefinition, context), generateDecodeSumMethod(sumDefinition, context.typesInfo) ); } }; } - private JavaMethodDeclaration generateEncodeEnumMethod(TypedEnumDefinitionNode enumDefinition) { + private JavaMethodDeclaration generateEncodeEnumMethod( + TypedEnumDefinitionNode enumDefinition, + Context context + ) { return generateEncodeMethod( enumDefinition.type(), new JavaBlock(generateEncode( @@ -492,7 +581,8 @@ public class JavaTransient0Generator implements Generator { JavaIdentifier.of("ordinal"), List.of() ), - NativeTypes.INT_32 + NativeTypes.INT_32, + context )) ); } @@ -528,7 +618,10 @@ public class JavaTransient0Generator implements Generator { ); } - private JavaMethodDeclaration generateEncodeStructMethod(TypedStructDefinitionNode structDefinition) { + private JavaMethodDeclaration generateEncodeStructMethod( + TypedStructDefinitionNode structDefinition, + Context context + ) { return generateEncodeMethod( structDefinition.type(), new JavaBlock( @@ -539,7 +632,8 @@ public class JavaTransient0Generator implements Generator { this.javaGenerator.generateFieldName(field.name()), List.of() ), - field.type().value() + field.type().value(), + context ).stream()) .toList() ) @@ -575,11 +669,11 @@ public class JavaTransient0Generator implements Generator { private JavaMethodDeclaration generateEncodeSumMethod( TypedSumDefinitionNode sumDefinition, - TypesInfo typesInfo + Context context ) { var encodeStatements = List.<JavaBlockStatement>of(new JavaSwitchStatement( new JavaRef(VALUE_NAME), - typesInfo.sumVariants(sumDefinition.type()).stream() + context.typesInfo.sumVariants(sumDefinition.type()).stream() .map(variant -> { var variantVariable = JavaIdentifier.of(VALUE_NAME.value() + "$" + variant.tag()); @@ -587,12 +681,14 @@ public class JavaTransient0Generator implements Generator { statements.addAll(generateEncode( new JavaIntegerLiteral(variant.tag()), - NativeTypes.INT_32 + NativeTypes.INT_32, + context )); statements.addAll(generateEncode( new JavaRef(variantVariable), - variant.containerType() + variant.containerType(), + context )); return new JavaSwitchRule( @@ -677,22 +773,16 @@ public class JavaTransient0Generator implements Generator { JavaVisibility.PUBLIC, JavaMemberKind.STATIC, JavaTypeRef.VOID, - List.of( - new JavaParam(javaTypeRef, VALUE_NAME), - new JavaParam( - JavaTypeRef.OUTPUT_STREAM, - OUTPUT_STREAM_NAME - ), - new JavaParam( - JavaTypeRef.map(this.taggedSharedValueRef(), JavaTypeRef.LONG_BOXED), - SHARED_VALUES_NAME - ) - ), + generateEncodeParams(javaTypeRef), List.of(JavaTypeRef.IO_EXCEPTION), body ); } + private JavaTypeRef generateEncoderSharedValuesTypeRef() { + return JavaTypeRef.map(this.taggedSharedValueRef(), JavaTypeRef.LONG_BOXED); + } + private JavaMethodDeclaration generateDecodeMethod( Type type, JavaBlock body @@ -704,34 +794,38 @@ public class JavaTransient0Generator implements Generator { JavaVisibility.PUBLIC, JavaMemberKind.STATIC, javaTypeRef, - List.of( - new JavaParam( - JavaTypeRef.INPUT_STREAM, - INPUT_STREAM_NAME - ), - new JavaParam( - JavaTypeRef.list(JavaTypeRef.OBJECT), - SHARED_VALUES_NAME - ) - ), + generateDecodeParams(), List.of(JavaTypeRef.IO_EXCEPTION), body ); } - private List<JavaBlockStatement> generateEncode(JavaExpression value, Type type) { + private static JavaTypeRef generateDecoderSharedValuesType() { + return JavaTypeRef.list(JavaTypeRef.OBJECT); + } + + private List<JavaBlockStatement> generateEncode(JavaExpression value, Type type, Context context) { return switch (type) { case ConstructedNativeType constructedNativeType -> { if (constructedNativeType.constructor().equals(NativeTypes.BOX)) { - yield generateEncode(value, constructedNativeType.args().getFirst()); + yield generateEncode(value, constructedNativeType.args().getFirst(), context); } else if (constructedNativeType.constructor().equals(NativeTypes.LIST)) { - yield generateEncodeList(value, constructedNativeType.args().getFirst()); + yield generateEncodeList(value, constructedNativeType.args().getFirst(), context); } else if (constructedNativeType.constructor().equals(NativeTypes.OPTION)) { - yield generateEncodeOption(value, constructedNativeType.args().getFirst()); + yield generateEncodeOption(value, constructedNativeType.args().getFirst(), context); } else if (constructedNativeType.constructor().equals(NativeTypes.SHARED)) { - yield generateEncodeShared(value, constructedNativeType.args().getFirst()); + yield generateEncodeShared(value, constructedNativeType.args().getFirst(), context); } else { - throw new UnsupportedOperationException("TODO"); + yield List.of( + generateEncode( + value, + constructedNativeType.namespaceName(), + constructedNativeType, + constructedNativeType.args().stream() + .<JavaExpression>map(typeArg -> generateEncodeMethodRef(typeArg, context)) + .toList() + ) + ); } } @@ -739,7 +833,8 @@ public class JavaTransient0Generator implements Generator { yield List.of(generateEncode( value, simpleType.namespaceName(), - simpleType + simpleType, + List.of() )); } @@ -753,20 +848,47 @@ public class JavaTransient0Generator implements Generator { }; } + private JavaMethodRef generateEncodeMethodRef(Type type, Context context) { + return switch (type) { + case ConstructedNativeType _ -> { + throw new UnsupportedOperationException("TODO"); + } + + case SimpleType simpleType -> { + yield new JavaMethodRef( + generateTransient0TypeRef(simpleType.namespaceName()), + encodeMethodName(simpleType) + ); + } + + case TypeLevelValueType _ -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeParam _ -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + private JavaBlockStatement generateEncode( JavaExpression value, NamespaceName typeNamespaceName, - Type type + Type type, + List<JavaExpression> encoders ) { return new JavaExpressionStatement( new JavaStaticMethodCall( generateTransient0TypeRef(typeNamespaceName), encodeMethodName(type), - List.of( - value, - new JavaRef(OUTPUT_STREAM_NAME), - new JavaRef(SHARED_VALUES_NAME) - ) + Lists.concat(List.of( + List.of( + value, + new JavaRef(OUTPUT_STREAM_NAME), + new JavaRef(SHARED_VALUES_NAME) + ), + encoders + )) ) ); } @@ -783,15 +905,26 @@ public class JavaTransient0Generator implements Generator { } else if (constructedNativeType.constructor().equals(NativeTypes.SHARED)) { yield generateDecodeShared(target, constructedNativeType.args().getFirst()); } else { - throw new UnsupportedOperationException("TODO"); + yield List.of( + generateDecode( + target, + constructedNativeType.namespaceName(), + constructedNativeType, + constructedNativeType.args().stream() + .<JavaExpression>map(typeArg -> generateDecodeMethodRef(typeArg)) + .toList() + ) + ); } } case SimpleType simpleType -> { + NamespaceName typeNamespaceName = simpleType.namespaceName(); yield List.of(generateDecode( target, - simpleType.namespaceName(), - simpleType + typeNamespaceName, + simpleType, + List.of() )); } @@ -805,10 +938,34 @@ public class JavaTransient0Generator implements Generator { }; } + private JavaMethodRef generateDecodeMethodRef(Type type) { + return switch (type) { + case ConstructedNativeType _ -> { + throw new UnsupportedOperationException("TODO"); + } + + case SimpleType simpleType -> { + yield new JavaMethodRef( + generateTransient0TypeRef(simpleType.namespaceName()), + decodeMethodName(simpleType) + ); + } + + case TypeLevelValueType _ -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeParam _ -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + private JavaBlockStatement generateDecode( JavaIdentifier target, NamespaceName typeNamespaceName, - Type type + Type type, + List<JavaExpression> decoders ) { return new JavaLocalVariableDeclaration( Optional.empty(), @@ -816,17 +973,21 @@ public class JavaTransient0Generator implements Generator { Optional.of(new JavaStaticMethodCall( generateTransient0TypeRef(typeNamespaceName), decodeMethodName(type), - List.of( - new JavaRef(INPUT_STREAM_NAME), - new JavaRef(SHARED_VALUES_NAME) - ) + Lists.concat(List.of( + List.of( + new JavaRef(INPUT_STREAM_NAME), + new JavaRef(SHARED_VALUES_NAME) + ), + decoders + )) )) ); } private List<JavaBlockStatement> generateEncodeList( JavaExpression value, - Type elementType + Type elementType, + Context context ) { var statements = new ArrayList<JavaBlockStatement>(); @@ -837,7 +998,8 @@ public class JavaTransient0Generator implements Generator { JavaIdentifier.of("size"), List.of() )), - NativeTypes.INT_64 + NativeTypes.INT_64, + context )); var element = JavaIdentifier.of("element"); @@ -847,7 +1009,8 @@ public class JavaTransient0Generator implements Generator { value, new JavaBlock(generateEncode( new JavaRef(element), - elementType + elementType, + context )) )); @@ -917,7 +1080,8 @@ public class JavaTransient0Generator implements Generator { private List<JavaBlockStatement> generateEncodeOption( JavaExpression value, - Type elementType + Type elementType, + Context context ) { var statements = new ArrayList<JavaBlockStatement>(); var isPresent = new JavaMethodCall( @@ -928,7 +1092,8 @@ public class JavaTransient0Generator implements Generator { statements.addAll(generateEncode( isPresent, - NativeTypes.BOOL + NativeTypes.BOOL, + context )); statements.add(new JavaIfStatement( @@ -939,7 +1104,8 @@ public class JavaTransient0Generator implements Generator { JavaIdentifier.of("get"), List.of() ), - elementType + elementType, + context )), new JavaBlock(List.of()) )); @@ -999,7 +1165,8 @@ public class JavaTransient0Generator implements Generator { private List<JavaBlockStatement> generateEncodeShared( JavaExpression value, - Type type + Type type, + Context context ) { var existingId = JavaIdentifier.of("existingId"); @@ -1021,7 +1188,11 @@ public class JavaTransient0Generator implements Generator { new JavaNullLiteral() ), new JavaBlock( - generateEncode(new JavaRef(existingId), NativeTypes.INT_64) + generateEncode( + new JavaRef(existingId), + NativeTypes.INT_64, + context + ) ), new JavaBlock(Lists.concat(List.of( generateEncode( @@ -1030,7 +1201,8 @@ public class JavaTransient0Generator implements Generator { JavaIdentifier.of("size"), List.of() ), - NativeTypes.INT_64 + NativeTypes.INT_64, + context ), List.of( new JavaExpressionStatement(new JavaMethodCall( @@ -1048,7 +1220,7 @@ public class JavaTransient0Generator implements Generator { ) )) ), - generateEncode(value, type) + generateEncode(value, type, context) ))) ) )) |
