summaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-07-06 21:27:02 +0100
committerMichael Williamson <mike@zwobble.org>2026-07-06 21:35:22 +0100
commit8bb79efe44cf56df9e232de89ce304618e23f2e2 (patch)
treec2192230681069c4630f607185cc89935410d18c /src/main/java/org/zwobble
parent4ea28d73cdd9fb7a5f653b3c3c5291a1b8a1a7dc (diff)
Generate methods for encoding/decoding builtin types
Diffstat (limited to 'src/main/java/org/zwobble')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java289
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/types/NamespaceName.java9
2 files changed, 171 insertions, 127 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 7a29814..6078578 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
@@ -60,6 +60,8 @@ public class JavaTransient0Generator implements Generator {
) throws IOException {
var context = new Context(typesInfo);
+ generateBuiltins();
+
for (var namespace : namespaces) {
var javaCompilationUnits = generateNamespace(namespace, context);
@@ -67,6 +69,143 @@ public class JavaTransient0Generator implements Generator {
}
}
+ private void generateBuiltins() throws IOException {
+ var packageName = this.javaGenerator.namespaceToJavaPackageName(NamespaceName.of());
+ var transient0JavaName = generateTransient0ClassName("Builtins");
+ var transient0JavaTypeRef = JavaTypeRef.topLevel(
+ packageName,
+ transient0JavaName
+ );
+
+ JavaGenerator.write(this.sourceRootDirectory, List.of(
+ new JavaCompilationUnit(
+ packageName,
+ new JavaCustomArea(transient0JavaTypeRef, "imports"),
+ new JavaClassDeclaration(
+ transient0JavaName,
+ List.of(),
+ List.of(
+ generateEncodeBoolMethod(),
+ generateDecodeBoolMethod(),
+ generateEncodeInt32Method(),
+ generateDecodeInt32Method(),
+ generateEncodeInt64Method(),
+ generateDecodeInt64Method()
+ ),
+ new JavaCustomArea(transient0JavaTypeRef, "body"),
+ DocComment.EMPTY
+ )
+ )
+ ));
+ }
+
+ private JavaMethodDeclaration generateEncodeBoolMethod() {
+ return generateEncodeMethod(
+ NativeTypes.BOOL,
+ new JavaBlock(List.of(
+ new JavaExpressionStatement(generateOutputStreamWrite(new JavaTernaryConditional(
+ new JavaRef(VALUE_NAME),
+ new JavaIntegerLiteral(1),
+ new JavaIntegerLiteral(0)
+ )))
+ ))
+ );
+ }
+
+ private JavaMethodDeclaration generateDecodeBoolMethod() {
+ return generateDecodeMethod(
+ NativeTypes.BOOL,
+ new JavaBlock(List.of(
+ new JavaReturn(new JavaBinaryOperation(
+ JavaBinaryOperator.NOT_EQUAL_TO,
+ generateInputStreamRead(),
+ new JavaIntegerLiteral(0)
+ ))
+ ))
+ );
+ }
+
+ private JavaMethodDeclaration generateEncodeInt32Method() {
+ return generateEncodeIntMethod(NativeTypes.INT_32, 32);
+ }
+
+ private JavaMethodDeclaration generateDecodeInt32Method() {
+ return generateDecodeIntMethod(NativeTypes.INT_32, 32);
+ }
+
+ private JavaMethodDeclaration generateEncodeInt64Method() {
+ return generateEncodeIntMethod(NativeTypes.INT_64, 64);
+ }
+
+ private JavaMethodDeclaration generateDecodeInt64Method() {
+ return generateDecodeIntMethod(NativeTypes.INT_64, 64);
+ }
+
+ private JavaMethodDeclaration generateEncodeIntMethod(
+ Type type,
+ int bits
+ ) {
+ var statements = byteIndicesInBits(bits)
+ .<JavaBlockStatement>mapToObj(shiftBy -> {
+ JavaExpression byteToWrite = new JavaBinaryOperation(
+ JavaBinaryOperator.BITWISE_AND,
+ new JavaBinaryOperation(
+ JavaBinaryOperator.UNSIGNED_RIGHT_SHIFT,
+ new JavaRef(VALUE_NAME),
+ new JavaIntegerLiteral(shiftBy)
+ ),
+ new JavaIntegerLiteral(0xff)
+ );
+
+ if (bits > 32) {
+ byteToWrite = new JavaCast(JavaTypeRef.INT, byteToWrite);
+ }
+
+ return new JavaExpressionStatement(
+ generateOutputStreamWrite(byteToWrite)
+ );
+ })
+ .toList();
+
+ return generateEncodeMethod(type, new JavaBlock(statements));
+ }
+
+ private JavaMethodDeclaration generateDecodeIntMethod(
+ Type type,
+ int bits
+ ) {
+ var statements = new ArrayList<JavaBlockStatement>();
+
+ statements.add(new JavaLocalVariableDeclaration(
+ Optional.of(this.javaGenerator.generateTypeRef(type)),
+ VALUE_NAME,
+ new JavaIntegerLiteral(0)
+ ));
+
+ Iterable<Integer> shiftBys = () -> byteIndicesInBits(bits)
+ .iterator();
+
+ for (var shiftBy : shiftBys) {
+ statements.add(new JavaExpressionStatement(new JavaBinaryOperation(
+ JavaBinaryOperator.ASSIGN,
+ new JavaRef(VALUE_NAME),
+ new JavaBinaryOperation(
+ JavaBinaryOperator.BITWISE_OR,
+ new JavaRef(VALUE_NAME),
+ new JavaBinaryOperation(
+ JavaBinaryOperator.LEFT_SHIFT,
+ generateInputStreamRead(),
+ new JavaIntegerLiteral(shiftBy)
+ )
+ )
+ )));
+ }
+
+ statements.add(new JavaReturn(new JavaRef(VALUE_NAME)));
+
+ return generateDecodeMethod(type, new JavaBlock(statements));
+ }
+
private List<JavaCompilationUnit> generateNamespace(
TypedNamespaceNode namespace,
Context context
@@ -103,9 +242,12 @@ public class JavaTransient0Generator implements Generator {
}
private JavaIdentifier generateTransient0ClassName(NamespaceName namespaceName) {
- var namespaceShortName = namespaceName.shortName();
+ return generateTransient0ClassName(namespaceName.shortName().orElse("Builtins"));
+ }
+
+ private JavaIdentifier generateTransient0ClassName(String shortName) {
return this.javaGenerator.generateTypeName(
- "HobgoblinTransient0" + Casing.lowerCamelCaseToUpperCamelCase(namespaceShortName)
+ "HobgoblinTransient0" + Casing.lowerCamelCaseToUpperCamelCase(shortName)
);
}
@@ -224,15 +366,15 @@ public class JavaTransient0Generator implements Generator {
}
case SimpleNativeType simpleNativeType -> {
- if (simpleNativeType.equals(NativeTypes.BOOL)) {
- yield generateEncodeBool(value);
- } else if (simpleNativeType.equals(NativeTypes.INT_32)) {
- yield generateEncodeInt32(value);
- } else if (simpleNativeType.equals(NativeTypes.INT_64)) {
- yield generateEncodeInt64(value);
- } else {
- throw new UnsupportedOperationException("TODO");
- }
+ yield Stream.of(
+ new JavaExpressionStatement(
+ new JavaStaticMethodCall(
+ generateTransient0TypeRef(simpleNativeType.namespaceName()),
+ encodeMethodName(simpleNativeType),
+ List.of(value, new JavaRef(OUTPUT_STREAM_NAME))
+ )
+ )
+ );
}
case StructType structType -> {
@@ -272,15 +414,17 @@ public class JavaTransient0Generator implements Generator {
}
case SimpleNativeType simpleNativeType -> {
- if (simpleNativeType.equals(NativeTypes.BOOL)) {
- yield generateDecodeBool(target);
- } else if (simpleNativeType.equals(NativeTypes.INT_32)) {
- yield generateDecodeInt32(target);
- } else if (simpleNativeType.equals(NativeTypes.INT_64)) {
- yield generateDecodeInt64(target);
- } else {
- throw new UnsupportedOperationException("TODO");
- }
+ yield Stream.of(
+ new JavaLocalVariableDeclaration(
+ Optional.empty(),
+ target,
+ new JavaStaticMethodCall(
+ generateTransient0TypeRef(simpleNativeType.namespaceName()),
+ decodeMethodName(simpleNativeType),
+ List.of(new JavaRef(INPUT_STREAM_NAME))
+ )
+ )
+ );
}
case StructType structType -> {
@@ -311,111 +455,6 @@ public class JavaTransient0Generator implements Generator {
};
}
- private static Stream<JavaBlockStatement> generateEncodeBool(JavaExpression value) {
- return Stream.of(
- new JavaExpressionStatement(generateOutputStreamWrite(new JavaTernaryConditional(
- value,
- new JavaIntegerLiteral(1),
- new JavaIntegerLiteral(0)
- ))
- ));
- }
-
- private static Stream<JavaBlockStatement> generateDecodeBool(JavaIdentifier target) {
- return Stream.of(
- new JavaLocalVariableDeclaration(
- Optional.empty(),
- target,
- new JavaBinaryOperation(
- JavaBinaryOperator.NOT_EQUAL_TO,
- generateInputStreamRead(),
- new JavaIntegerLiteral(0)
- )
- )
- );
- }
-
- private static Stream<JavaBlockStatement> generateEncodeInt32(JavaExpression value) {
- return generateEncodeInt(value, 32);
- }
-
- private static Stream<JavaBlockStatement> generateDecodeInt32(
- JavaIdentifier target
- ) {
- return generateDecodeInt(target, 32, JavaTypeRef.INT);
- }
-
- private static Stream<JavaBlockStatement> generateEncodeInt64(JavaExpression value) {
- return generateEncodeInt(value, 64);
- }
-
- private static Stream<JavaBlockStatement> generateDecodeInt64(
- JavaIdentifier target
- ) {
- return generateDecodeInt(target, 64, JavaTypeRef.INT);
- }
-
- private static Stream<JavaBlockStatement> generateEncodeInt(
- JavaExpression value,
- int bits
- ) {
- return byteIndicesInBits(bits)
- .mapToObj(shiftBy -> {
- JavaExpression byteToWrite = new JavaBinaryOperation(
- JavaBinaryOperator.BITWISE_AND,
- new JavaBinaryOperation(
- JavaBinaryOperator.UNSIGNED_RIGHT_SHIFT,
- value,
- new JavaIntegerLiteral(shiftBy)
- ),
- new JavaIntegerLiteral(0xff)
- );
-
- if (bits > 32) {
- byteToWrite = new JavaCast(JavaTypeRef.INT, byteToWrite);
- }
-
- return new JavaExpressionStatement(
- generateOutputStreamWrite(byteToWrite)
- );
- });
- }
-
- private static Stream<JavaBlockStatement> generateDecodeInt(
- JavaIdentifier target,
- int bits,
- JavaTypeRef javaType
- ) {
- var statements = new ArrayList<JavaBlockStatement>();
-
- statements.add(new JavaLocalVariableDeclaration(
- Optional.of(javaType),
- target,
- new JavaIntegerLiteral(0)
- ));
-
- Iterable<Integer> shiftBys = () -> byteIndicesInBits(bits)
- .iterator();
-
- for (var shiftBy : shiftBys) {
- statements.add(new JavaExpressionStatement(new JavaBinaryOperation(
- JavaBinaryOperator.ASSIGN,
- new JavaRef(target),
- new JavaBinaryOperation(
- JavaBinaryOperator.BITWISE_OR,
- new JavaRef(target),
- new JavaBinaryOperation(
- JavaBinaryOperator.LEFT_SHIFT,
- generateInputStreamRead(),
- new JavaIntegerLiteral(shiftBy)
- )
- )
- )));
- }
-
- return statements.stream();
- }
-
private static JavaMethodCall generateOutputStreamWrite(JavaExpression byteToWrite) {
return new JavaMethodCall(
new JavaRef(OUTPUT_STREAM_NAME),
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/NamespaceName.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/NamespaceName.java
index c7f4431..c01140a 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/types/NamespaceName.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/NamespaceName.java
@@ -2,6 +2,7 @@ package org.zwobble.hobgoblin.compiler.types;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
public record NamespaceName(List<String> parts) {
public static NamespaceName of(String... parts) {
@@ -12,8 +13,12 @@ public record NamespaceName(List<String> parts) {
return new NamespaceName(parts.subList(0, parts.size() - 1));
}
- public String shortName() {
- return parts.getLast();
+ public Optional<String> shortName() {
+ if (parts.isEmpty()) {
+ return Optional.empty();
+ } else {
+ return Optional.of(parts.getLast());
+ }
}
public boolean isRoot() {