From 9acc7ef12df3f475bbf5f57c0e22d4be16639452 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 17 May 2026 10:30:04 +0100 Subject: Add Java return statement node --- .../compiler/output/lang/java/JavaWriter.java | 80 +++++++++++++++++----- .../compiler/output/lang/java/ast/JavaBlock.java | 10 ++- .../output/lang/java/ast/JavaBlockStatement.java | 4 ++ .../output/lang/java/ast/JavaExpression.java | 4 ++ .../output/lang/java/ast/JavaIntegerLiteral.java | 4 ++ .../compiler/output/lang/java/ast/JavaReturn.java | 4 ++ .../compiler/output/lang/java/JavaWriterTests.java | 50 ++++++++++++++ 7 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlockStatement.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaExpression.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaIntegerLiteral.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaReturn.java diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java index 1a5fe29..2b2cb58 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java @@ -45,6 +45,22 @@ public class JavaWriter implements AutoCloseable { } } + void writeBlock(JavaBlock block) throws IOException { + writeWithSeparator( + block.statements(), + this::writeBlockStatement, + () -> this.writer.newLine() + ); + } + + void writeBlockStatement(JavaBlockStatement statement) throws IOException { + switch (statement) { + case JavaReturn returnStatement -> { + writeReturnStatement(returnStatement); + } + } + } + private void writeDocComment(DocComment docComment) throws IOException { for (var line : docComment.lines()) { this.writer.write("/// "); @@ -83,26 +99,16 @@ public class JavaWriter implements AutoCloseable { } } - void writeMethodDeclaration(JavaMethodDeclaration method) throws IOException { - this.writer.write("public "); - writeTypeRef(method.returnType()); - this.writer.write(" "); - this.writer.write(method.name()); - this.writer.write("("); - - writeWithSeparator( - method.params(), - param -> { - writeTypeRef(param.type()); - writer.write(" "); - writer.write(param.name()); - }, - () -> writer.write(", ") - ); + void writeExpression(JavaExpression expression) throws IOException { + switch (expression) { + case JavaIntegerLiteral integerLiteral -> { + writeIntegerLiteral(integerLiteral); + } + } + } - this.writer.write(") {"); - this.writer.newLine(); - this.writer.write("}"); + private void writeIntegerLiteral(JavaIntegerLiteral integerLiteral) throws IOException { + this.writer.write(Long.toString(integerLiteral.value())); } private void writeInterfaceDeclaration(JavaInterfaceDeclaration interfaceDeclaration) throws IOException { @@ -127,6 +133,36 @@ public class JavaWriter implements AutoCloseable { this.writer.write("}"); } + void writeMethodDeclaration(JavaMethodDeclaration method) throws IOException { + this.writer.write("public "); + writeTypeRef(method.returnType()); + this.writer.write(" "); + this.writer.write(method.name()); + this.writer.write("("); + + writeWithSeparator( + method.params(), + param -> { + writeTypeRef(param.type()); + writer.write(" "); + writer.write(param.name()); + }, + () -> writer.write(", ") + ); + + this.writer.write(") {"); + this.writer.indent(); + + if (!method.body().isEmpty()) { + this.writer.newLine(); + writeBlock(method.body()); + } + + this.writer.dedent(); + this.writer.newLine(); + this.writer.write("}"); + } + private void writeRecordDeclaration(JavaRecordDeclaration recordDeclaration) throws IOException { writeDocComment(recordDeclaration.docComment()); @@ -173,6 +209,12 @@ public class JavaWriter implements AutoCloseable { this.writer.write("}"); } + private void writeReturnStatement(JavaReturn returnStatement) throws IOException { + this.writer.write("return "); + writeExpression(returnStatement.value()); + this.writer.write(";"); + } + void writeTypeRef(JavaTypeRef type) throws IOException { for (var part : type.packageName()) { writer.write(part); diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlock.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlock.java index 7ebbe29..f758831 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlock.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlock.java @@ -1,5 +1,11 @@ package org.zwobble.hobgoblin.compiler.output.lang.java.ast; -public record JavaBlock() { - public static final JavaBlock EMPTY = new JavaBlock(); +import java.util.List; + +public record JavaBlock(List statements) { + public static final JavaBlock EMPTY = new JavaBlock(List.of()); + + public boolean isEmpty() { + return this.statements.isEmpty(); + } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlockStatement.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlockStatement.java new file mode 100644 index 0000000..1ee5511 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaBlockStatement.java @@ -0,0 +1,4 @@ +package org.zwobble.hobgoblin.compiler.output.lang.java.ast; + +public sealed interface JavaBlockStatement permits JavaReturn { +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaExpression.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaExpression.java new file mode 100644 index 0000000..0aa202c --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaExpression.java @@ -0,0 +1,4 @@ +package org.zwobble.hobgoblin.compiler.output.lang.java.ast; + +public sealed interface JavaExpression permits JavaIntegerLiteral { +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaIntegerLiteral.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaIntegerLiteral.java new file mode 100644 index 0000000..0f0342d --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaIntegerLiteral.java @@ -0,0 +1,4 @@ +package org.zwobble.hobgoblin.compiler.output.lang.java.ast; + +public record JavaIntegerLiteral(long value) implements JavaExpression { +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaReturn.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaReturn.java new file mode 100644 index 0000000..f297f33 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaReturn.java @@ -0,0 +1,4 @@ +package org.zwobble.hobgoblin.compiler.output.lang.java.ast; + +public record JavaReturn(JavaExpression value) implements JavaBlockStatement { +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java index b6ad5d5..a19f5a2 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java @@ -242,6 +242,56 @@ public class JavaWriterTests { )); } + @Test + public void methodWithBody() throws IOException { + var java = new JavaMethodDeclaration( + "a", + JavaTypeRef.INT, + List.of(), + new JavaBlock(List.of( + new JavaReturn(new JavaIntegerLiteral(42)) + )) + ); + + var string = write(writer -> writer.writeMethodDeclaration(java)); + + assertThat(string, equalTo(""" + public int a() { + return 42; + }""" + )); + } + + @Test + public void block() throws IOException { + var java = new JavaBlock(List.of( + new JavaReturn(new JavaIntegerLiteral(42)), + new JavaReturn(new JavaIntegerLiteral(47)) + )); + + var string = write(writer -> writer.writeBlock(java)); + + assertThat(string, equalTo("return 42;\nreturn 47;")); + } + + @Test + public void returnStatement() throws IOException { + var java = new JavaReturn(new JavaIntegerLiteral(42)); + + var string = write(writer -> writer.writeBlockStatement(java)); + + assertThat(string, equalTo("return 42;")); + } + + @Test + public void integerLiteral() throws IOException { + var java = new JavaIntegerLiteral(42); + + var string = write(writer -> writer.writeExpression(java)); + + assertThat(string, equalTo("42")); + } + @Test public void typeRefWithoutArgsHasNoAngleBrackets() throws IOException { var java = new JavaTypeRef(List.of("abc", "def"), "One", List.of()); -- cgit v1.2.3