From 91c5ecad55a7011ed883b3e06a197938af6dfd23 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 10 Jul 2026 21:02:42 +0100 Subject: Support lists in Java transient-0 --- .../javatransient0/JavaTransient0Generator.java | 239 +++++++++++++++------ 1 file changed, 171 insertions(+), 68 deletions(-) (limited to 'src/main') 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 572ab29..bf53ad0 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 @@ -208,32 +208,36 @@ public class JavaTransient0Generator implements Generator { private JavaMethodDeclaration generateEncodeStringMethod() { var bytesVariableName = JavaIdentifier.of("bytes"); + var statements = new ArrayList(); + + statements.add(new JavaLocalVariableDeclaration( + Optional.empty(), + bytesVariableName, + new JavaMethodCall( + new JavaRef(VALUE_NAME), + JavaIdentifier.of("getBytes"), + List.of(new JavaStaticFieldAccess( + JavaTypeRef.STANDARD_CHARSETS, + JavaIdentifier.of("UTF_8") + )) + ) + )); + + statements.addAll(generateEncode( + new JavaCast(JavaTypeRef.LONG, new JavaFieldAccess( + new JavaRef(bytesVariableName), + JavaIdentifier.of("length") + )), + NativeTypes.INT_64 + )); + + statements.add(new JavaExpressionStatement(generateOutputStreamWrite( + new JavaRef(bytesVariableName) + ))); + return generateEncodeMethod( NativeTypes.STRING, - new JavaBlock(List.of( - new JavaLocalVariableDeclaration( - Optional.empty(), - bytesVariableName, - new JavaMethodCall( - new JavaRef(VALUE_NAME), - JavaIdentifier.of("getBytes"), - List.of(new JavaStaticFieldAccess( - JavaTypeRef.STANDARD_CHARSETS, - JavaIdentifier.of("UTF_8") - )) - ) - ), - generateEncode( - new JavaCast(JavaTypeRef.LONG, new JavaFieldAccess( - new JavaRef(bytesVariableName), - JavaIdentifier.of("length") - )), - NativeTypes.INT_64 - ), - new JavaExpressionStatement(generateOutputStreamWrite( - new JavaRef(bytesVariableName) - )) - )) + new JavaBlock(statements) ); } @@ -241,36 +245,40 @@ public class JavaTransient0Generator implements Generator { var bytesLengthVariableName = JavaIdentifier.of("bytesLength"); var bytesVariableName = JavaIdentifier.of("bytes"); - return generateDecodeMethod( - NativeTypes.STRING, - new JavaBlock(List.of( - generateDecode( - bytesLengthVariableName, - NativeTypes.INT_64 - ), - new JavaLocalVariableDeclaration( - Optional.empty(), - bytesVariableName, - new JavaMethodCall( - new JavaRef(INPUT_STREAM_NAME), - JavaIdentifier.of("readNBytes"), - // TODO: handle very long strings - List.of(new JavaCast(JavaTypeRef.INT, new JavaRef(bytesLengthVariableName))) - ) - ), - new JavaReturn( - new JavaNewExpression( - JavaTypeRef.STRING, - List.of( - new JavaRef(bytesVariableName), - new JavaStaticFieldAccess( - JavaTypeRef.STANDARD_CHARSETS, - JavaIdentifier.of("UTF_8") - ) - ) + var statements = new ArrayList(); + + statements.addAll(generateDecode( + bytesLengthVariableName, + NativeTypes.INT_64 + )); + + statements.add(new JavaLocalVariableDeclaration( + Optional.empty(), + bytesVariableName, + new JavaMethodCall( + new JavaRef(INPUT_STREAM_NAME), + JavaIdentifier.of("readNBytes"), + // TODO: handle very long strings + List.of(new JavaCast(JavaTypeRef.INT, new JavaRef(bytesLengthVariableName))) + ) + )); + + statements.add(new JavaReturn( + new JavaNewExpression( + JavaTypeRef.STRING, + List.of( + new JavaRef(bytesVariableName), + new JavaStaticFieldAccess( + JavaTypeRef.STANDARD_CHARSETS, + JavaIdentifier.of("UTF_8") ) ) - )) + ) + )); + + return generateDecodeMethod( + NativeTypes.STRING, + new JavaBlock(statements) ); } @@ -337,14 +345,14 @@ public class JavaTransient0Generator implements Generator { structDefinition.type(), new JavaBlock( structDefinition.fields().stream() - .map(field -> generateEncode( + .flatMap(field -> generateEncode( new JavaMethodCall( new JavaRef(VALUE_NAME), this.javaGenerator.generateFieldName(field.name()), List.of() ), field.type().value() - )) + ).stream()) .toList() ) ), @@ -353,10 +361,10 @@ public class JavaTransient0Generator implements Generator { new JavaBlock( Stream.concat( structDefinition.fields().stream() - .map(field -> generateDecode( + .flatMap(field -> generateDecode( this.javaGenerator.generateFieldName(field.name()), field.type().value() - )), + ).stream()), Stream.of(new JavaReturn(new JavaNewExpression( structJavaTypeRef, structDefinition.fields().stream() @@ -420,10 +428,14 @@ public class JavaTransient0Generator implements Generator { ); } - private JavaBlockStatement generateEncode(JavaExpression value, Type type) { + private List generateEncode(JavaExpression value, Type type) { return switch (type) { case ConstructedNativeType constructedNativeType -> { - throw new UnsupportedOperationException("TODO"); + if (constructedNativeType.constructor().equals(NativeTypes.LIST)) { + yield generateEncodeList(value, constructedNativeType.args().getFirst()); + } else { + throw new UnsupportedOperationException("TODO"); + } } case EnumType enumType -> { @@ -431,19 +443,19 @@ public class JavaTransient0Generator implements Generator { } case SimpleNativeType simpleNativeType -> { - yield generateEncode( + yield List.of(generateEncode( value, simpleNativeType.namespaceName(), simpleNativeType - ); + )); } case StructType structType -> { - yield generateEncode( + yield List.of(generateEncode( value, structType.namespaceName(), structType - ); + )); } case SumType sumType -> { @@ -474,10 +486,14 @@ public class JavaTransient0Generator implements Generator { ); } - private JavaBlockStatement generateDecode(JavaIdentifier target, Type type) { + private List generateDecode(JavaIdentifier target, Type type) { return switch (type) { case ConstructedNativeType constructedNativeType -> { - throw new UnsupportedOperationException("TODO"); + if (constructedNativeType.constructor().equals(NativeTypes.LIST)) { + yield generateDecodeList(target, constructedNativeType.args().getFirst()); + } else { + throw new UnsupportedOperationException("TODO"); + } } case EnumType enumType -> { @@ -485,19 +501,19 @@ public class JavaTransient0Generator implements Generator { } case SimpleNativeType simpleNativeType -> { - yield generateDecode( + yield List.of(generateDecode( target, simpleNativeType.namespaceName(), simpleNativeType - ); + )); } case StructType structType -> { - yield generateDecode( + yield List.of(generateDecode( target, structType.namespaceName(), structType - ); + )); } case SumType sumType -> { @@ -530,6 +546,93 @@ public class JavaTransient0Generator implements Generator { ); } + private List generateEncodeList( + JavaExpression value, + Type elementType + ) { + var statements = new ArrayList(); + + statements.addAll(generateEncode( + new JavaCast(JavaTypeRef.LONG, new JavaMethodCall( + value, + JavaIdentifier.of("size"), + List.of() + )), + NativeTypes.INT_64 + )); + + var element = JavaIdentifier.of("element"); + statements.add(new JavaEnhancedForStatement( + Optional.empty(), + element, + value, + new JavaBlock(generateEncode( + new JavaRef(element), + elementType + )) + )); + + return statements; + } + + private List generateDecodeList( + JavaIdentifier target, + Type elementType + ) { + var size = JavaIdentifier.of(target.value() + "$size"); + var index = JavaIdentifier.of(target.value() + "$index"); + var element = JavaIdentifier.of(target.value() + "$element"); + + var statements = new ArrayList(); + + statements.addAll(generateDecode(size, NativeTypes.INT_64)); + + statements.add(new JavaLocalVariableDeclaration( + Optional.empty(), + target, + new JavaNewExpression( + JavaTypeRef.arrayList(this.javaGenerator.generateReferenceTypeRef(elementType)), + List.of() + ) + )); + + var forBodyStatements = new ArrayList(); + + forBodyStatements.addAll(generateDecode(element, elementType)); + + forBodyStatements.add(new JavaExpressionStatement(new JavaMethodCall( + new JavaRef(target), + JavaIdentifier.of("add"), + List.of(new JavaRef(element)) + ))); + + statements.add(new JavaBasicForStatement( + Optional.of(new JavaLocalVariableDeclaration( + Optional.of(JavaTypeRef.LONG), + index, + new JavaIntegerLiteral(0) + )), + Optional.of(new JavaBinaryOperation( + JavaBinaryOperator.LESS_THAN, + new JavaRef(index), + new JavaRef(size) + )), + // TODO: use ++ + Optional.of(new JavaBinaryOperation( + JavaBinaryOperator.ASSIGN, + new JavaRef(index), + new JavaBinaryOperation( + JavaBinaryOperator.ADD, + new JavaRef(index), + new JavaIntegerLiteral(1) + ) + )), + new JavaBlock(forBodyStatements) + )); + + return statements; + } + private static JavaMethodCall generateOutputStreamWrite(JavaExpression byteToWrite) { return new JavaMethodCall( new JavaRef(OUTPUT_STREAM_NAME), -- cgit v1.2.3