From 06ae500619b2c2401548f6eac9e97fce09fceb58 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 4 Jul 2026 23:31:53 +0100 Subject: Support encode/decode of Int32 and structs --- .../javatransient0/JavaTransient0Generator.java | 175 +++++++++++++++++++-- .../compiler/output/lang/java/ast/JavaTypeRef.java | 2 + 2 files changed, 161 insertions(+), 16 deletions(-) (limited to 'src/main/java/org') 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 5f91c1f..0837855 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 @@ -2,17 +2,20 @@ package org.zwobble.hobgoblin.compiler.output.generators.javatransient0; import org.zwobble.hobgoblin.compiler.ast.DocComment; import org.zwobble.hobgoblin.compiler.ast.typed.*; +import org.zwobble.hobgoblin.compiler.builtins.NativeTypes; import org.zwobble.hobgoblin.compiler.config.OutputConfig; import org.zwobble.hobgoblin.compiler.output.generators.Generator; import org.zwobble.hobgoblin.compiler.output.generators.java.JavaGenerator; import org.zwobble.hobgoblin.compiler.output.generators.java.JavaGeneratorConfig; import org.zwobble.hobgoblin.compiler.output.lang.java.ast.*; import org.zwobble.hobgoblin.compiler.typechecker.TypesInfo; +import org.zwobble.hobgoblin.compiler.types.*; import org.zwobble.hobgoblin.compiler.util.Casing; import org.zwobble.json5.reader.Json5ObjectReader; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -22,6 +25,9 @@ public class JavaTransient0Generator implements Generator { private static final JavaIdentifier ENCODE_METHOD_NAME = JavaIdentifier.of("encode"); private static final JavaIdentifier DECODE_METHOD_NAME = JavaIdentifier.of("decode"); + private static final JavaIdentifier VALUE_NAME = JavaIdentifier.of("value"); + private static final JavaIdentifier OUTPUT_STREAM_NAME = JavaIdentifier.of("outputStream"); + private static final JavaIdentifier INPUT_STREAM_NAME = JavaIdentifier.of("inputStream"); public static OutputConfig parseGeneratorConfig( Path projectRoot, @@ -107,10 +113,6 @@ public class JavaTransient0Generator implements Generator { } case TypedStructDefinitionNode structDefinition -> { - var valueName = JavaIdentifier.of("value"); - var outputStreamName = JavaIdentifier.of("outputStream"); - var inputStreamName = JavaIdentifier.of("inputStream"); - var structJavaTypeRef = this.javaGenerator.generateTypeRef(structDefinition.type()); yield Stream.of( @@ -120,17 +122,25 @@ public class JavaTransient0Generator implements Generator { JavaMethodKind.STATIC, JavaTypeRef.VOID, List.of( - new JavaParam( - structJavaTypeRef, - valueName - ), + new JavaParam(structJavaTypeRef, VALUE_NAME), new JavaParam( JavaTypeRef.OUTPUT_STREAM, - outputStreamName + OUTPUT_STREAM_NAME ) ), - List.of(), - new JavaBlock(List.of()) + List.of(JavaTypeRef.IO_EXCEPTION), + new JavaBlock( + structDefinition.fields().stream() + .flatMap(field -> generateEncode( + new JavaMethodCall( + new JavaRef(VALUE_NAME), + this.javaGenerator.generateFieldName(field.name()), + List.of() + ), + field.type().value() + )) + .toList() + ) ), new JavaMethodDeclaration( DECODE_METHOD_NAME, @@ -140,13 +150,25 @@ public class JavaTransient0Generator implements Generator { List.of( new JavaParam( JavaTypeRef.INPUT_STREAM, - inputStreamName + INPUT_STREAM_NAME ) ), - List.of(), - new JavaBlock(List.of( - new JavaReturn(new JavaNullLiteral()) - )) + List.of(JavaTypeRef.IO_EXCEPTION), + new JavaBlock( + Stream.concat( + structDefinition.fields().stream() + .flatMap(field -> generateDecode( + this.javaGenerator.generateFieldName(field.name()), + field.type().value() + )), + Stream.of(new JavaReturn(new JavaNewExpression( + structJavaTypeRef, + structDefinition.fields().stream() + .map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name()))) + .toList() + ))) + ).toList() + ) ) ); } @@ -157,6 +179,127 @@ public class JavaTransient0Generator implements Generator { }; } + private Stream generateEncode(JavaExpression value, Type type) { + return switch (type) { + case ConstructedNativeType constructedNativeType -> { + throw new UnsupportedOperationException("TODO"); + } + + case EnumType enumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case SimpleNativeType simpleNativeType -> { + if (simpleNativeType.equals(NativeTypes.INT_32)) { + yield generateEncodeInt32(value); + } else { + throw new UnsupportedOperationException("TODO"); + } + } + + case StructType structType -> { + throw new UnsupportedOperationException("TODO"); + } + + case SumType sumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeLevelValueType typeLevelValueType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeParam typeParam -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + + private Stream generateDecode(JavaIdentifier target, Type type) { + return switch (type) { + case ConstructedNativeType constructedNativeType -> { + throw new UnsupportedOperationException("TODO"); + } + + case EnumType enumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case SimpleNativeType simpleNativeType -> { + if (simpleNativeType.equals(NativeTypes.INT_32)) { + yield generateDecodeInt32(target); + } else { + throw new UnsupportedOperationException("TODO"); + } + } + + case StructType structType -> { + throw new UnsupportedOperationException("TODO"); + } + + case SumType sumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeLevelValueType typeLevelValueType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeParam typeParam -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + + private static Stream generateEncodeInt32(JavaExpression value) { + return Stream.of(0, 8, 16, 24) + .map(shiftBy -> new JavaExpressionStatement( + new JavaMethodCall( + new JavaRef(OUTPUT_STREAM_NAME), + JavaIdentifier.of("write"), + List.of(new JavaBinaryOperation( + JavaBinaryOperator.BITWISE_AND, + new JavaBinaryOperation( + JavaBinaryOperator.UNSIGNED_RIGHT_SHIFT, + value, + new JavaIntegerLiteral(shiftBy) + ), + new JavaIntegerLiteral(0xff) + )) + ) + )); + } + + private static Stream generateDecodeInt32( + JavaIdentifier target + ) { + var statements = new ArrayList(); + + statements.add(new JavaLocalVariableDeclaration(target, new JavaIntegerLiteral(0))); + + for (var shiftBy : List.of(0, 8, 16, 24)) { + statements.add(new JavaExpressionStatement(new JavaBinaryOperation( + JavaBinaryOperator.ASSIGN, + new JavaRef(target), + new JavaBinaryOperation( + JavaBinaryOperator.BITWISE_OR, + new JavaRef(target), + new JavaBinaryOperation( + JavaBinaryOperator.LEFT_SHIFT, + new JavaMethodCall( + new JavaRef(INPUT_STREAM_NAME), + JavaIdentifier.of("read"), + List.of() + ), + new JavaIntegerLiteral(shiftBy) + ) + ) + ))); + } + + return statements.stream(); + } + private static class Context { private final TypesInfo typesInfo; diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaTypeRef.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaTypeRef.java index b2478ed..1d1274e 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaTypeRef.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaTypeRef.java @@ -58,6 +58,8 @@ public record JavaTypeRef(JavaPackageName packageName, List type public static final JavaTypeRef INPUT_STREAM = topLevel(JavaPackages.JAVA_IO, JavaIdentifier.of("InputStream")); + public static final JavaTypeRef IO_EXCEPTION = topLevel(JavaPackages.JAVA_IO, JavaIdentifier.of("IOException")); + public static final JavaTypeRef LIST = topLevel(JavaPackages.JAVA_UTIL, JavaIdentifier.of("List")); public static JavaTypeRef list(JavaTypeRef elementType) { -- cgit v1.2.3