summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hobgoblin/src/output/lang/rust/ast.hob62
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java124
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java208
3 files changed, 211 insertions, 183 deletions
diff --git a/hobgoblin/src/output/lang/rust/ast.hob b/hobgoblin/src/output/lang/rust/ast.hob
index d230543..e6d1f11 100644
--- a/hobgoblin/src/output/lang/rust/ast.hob
+++ b/hobgoblin/src/output/lang/rust/ast.hob
@@ -15,6 +15,39 @@ sum RustItem {
variant RustStructStruct;
}
+// === Functions ===
+
+struct RustFunction {
+ field name: RustIdentifier;
+ field params: List[RustFunctionParam];
+ field returnType: Option[RustType];
+ field body: Option[RustBlockExpression];
+}
+
+struct RustFunctionParam {
+ field name: RustIdentifier;
+ field type: RustType;
+}
+
+// === Structs ===
+
+struct RustStructStruct {
+ field name: RustIdentifier;
+ field fields: List[RustStructField];
+ field docComment: DocComment;
+}
+
+struct RustStructField {
+ field name: RustIdentifier;
+ field type: RustType;
+}
+
+struct RustTupleField {
+ field type: RustType;
+}
+
+// === Enumerations ===
+
struct RustEnum {
field name: RustIdentifier;
field variants: List[RustEnumVariant];
@@ -38,42 +71,19 @@ struct RustEnumVariantTuple {
field fields: List[RustTupleField];
}
-struct RustFunction {
- field name: RustIdentifier;
- field params: List[RustFunctionParam];
- field returnType: Option[RustType];
- field body: Option[RustBlockExpression];
-}
-
-struct RustFunctionParam {
- field name: RustIdentifier;
- field type: RustType;
-}
+// === Implementations ===
struct RustInherentImpl {
field type: RustType;
field items: List[RustAssociatedItem];
}
+// === Associated items ===
+
sum RustAssociatedItem {
variant RustFunction;
}
-struct RustStructStruct {
- field name: RustIdentifier;
- field fields: List[RustStructField];
- field docComment: DocComment;
-}
-
-struct RustStructField {
- field name: RustIdentifier;
- field type: RustType;
-}
-
-struct RustTupleField {
- field type: RustType;
-}
-
// == Statements ==
sum RustStatement {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java
index b732390..6cd5860 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java
@@ -73,6 +73,70 @@ public class RustWriter implements AutoCloseable {
}
}
+ // === Functions ===
+
+ private void writeFunction(RustFunction function) throws IOException {
+ this.writer.write("pub fn ");
+ this.writeIdentifier(function.name());
+ this.writer.write("(");
+
+ writeWithSeparator(
+ function.params(),
+ param -> {
+ this.writeIdentifier(param.name());
+ this.writer.write(": ");
+ this.writeType(param.type());
+ },
+ () -> {
+ this.writer.write(", ");
+ }
+ );
+
+ this.writer.write(")");
+
+ if (function.returnType().isPresent()) {
+ this.writer.write(" ");
+ this.writer.write("-> ");
+ this.writeType(function.returnType().get());
+ }
+
+ if (function.body().isPresent()) {
+ this.writer.write(" ");
+ this.writeBlockExpression(function.body().get());
+ } else {
+ this.writer.write(";");
+ }
+ }
+
+ // === Structs ===
+
+ private void writeStructStruct(RustStructStruct structStruct) throws IOException {
+ this.writeDocComment(structStruct.docComment());
+ this.writer.write("pub struct ");
+ this.writeIdentifier(structStruct.name());
+ this.writer.write(" {");
+
+ if (!structStruct.fields().isEmpty()) {
+ this.writer.indent();
+
+ for (var field : structStruct.fields()) {
+ this.writer.newLine();
+ this.writer.write("pub ");
+ this.writeIdentifier(field.name());
+ this.writer.write(": ");
+ this.writeType(field.type());
+ this.writer.write(",");
+ }
+
+ this.writer.dedent();
+ }
+
+ this.writer.newLine();
+ this.writer.write("}");
+ }
+
+ // === Enumerations ===
+
private void writeEnum(RustEnum enum_) throws IOException {
this.writeDocComment(enum_.docComment());
this.writer.write("pub enum ");
@@ -112,38 +176,7 @@ public class RustWriter implements AutoCloseable {
this.writer.write("}");
}
- private void writeFunction(RustFunction function) throws IOException {
- this.writer.write("pub fn ");
- this.writeIdentifier(function.name());
- this.writer.write("(");
-
- writeWithSeparator(
- function.params(),
- param -> {
- this.writeIdentifier(param.name());
- this.writer.write(": ");
- this.writeType(param.type());
- },
- () -> {
- this.writer.write(", ");
- }
- );
-
- this.writer.write(")");
-
- if (function.returnType().isPresent()) {
- this.writer.write(" ");
- this.writer.write("-> ");
- this.writeType(function.returnType().get());
- }
-
- if (function.body().isPresent()) {
- this.writer.write(" ");
- this.writeBlockExpression(function.body().get());
- } else {
- this.writer.write(";");
- }
- }
+ // === Implementations ===
private void writeInherentImpl(RustInherentImpl inherentImpl) throws IOException {
this.writer.write("impl ");
@@ -173,6 +206,8 @@ public class RustWriter implements AutoCloseable {
this.writer.write("}");
}
+ // === Associated items ===
+
void writeAssociatedItem(RustAssociatedItem item) throws IOException {
switch (item) {
case RustFunction function -> {
@@ -181,31 +216,6 @@ public class RustWriter implements AutoCloseable {
}
}
- private void writeStructStruct(RustStructStruct structStruct) throws IOException {
- this.writeDocComment(structStruct.docComment());
- this.writer.write("pub struct ");
- this.writeIdentifier(structStruct.name());
- this.writer.write(" {");
-
- if (!structStruct.fields().isEmpty()) {
- this.writer.indent();
-
- for (var field : structStruct.fields()) {
- this.writer.newLine();
- this.writer.write("pub ");
- this.writeIdentifier(field.name());
- this.writer.write(": ");
- this.writeType(field.type());
- this.writer.write(",");
- }
-
- this.writer.dedent();
- }
-
- this.writer.newLine();
- this.writer.write("}");
- }
-
// == Statements ==
void writeStatement(RustStatement statement) throws IOException {
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java
index fe82fb9..3ed6e3e 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java
@@ -38,6 +38,113 @@ public class RustWriterTests {
// == Items ==
+ // === Functions ===
+
+ @Test
+ public void emptyFunction() throws IOException {
+ var rust = RustFunction.arbitrary()
+ .withName(new RustIdentifier("width"))
+ .build();
+
+ var string = write(writer -> writer.writeAssociatedItem(rust));
+
+ assertThat(string, equalTo("""
+ pub fn width();"""));
+ }
+
+ @Test
+ public void functionWithParams() throws IOException {
+ var rust = RustFunction.arbitrary()
+ .withName(new RustIdentifier("area"))
+ .addParam(new RustFunctionParam(new RustIdentifier("width"), RustTypePath.of("i32")))
+ .addParam(new RustFunctionParam(new RustIdentifier("height"), RustTypePath.of("u64")))
+ .build();
+
+ var string = write(writer -> writer.writeAssociatedItem(rust));
+
+ assertThat(string, equalTo("""
+ pub fn area(width: i32, height: u64);"""));
+ }
+
+ @Test
+ public void functionWithReturnType() throws IOException {
+ var rust = RustFunction.arbitrary()
+ .withName(new RustIdentifier("area"))
+ .withReturnType(Optional.of(RustTypePath.of("i32")))
+ .build();
+
+ var string = write(writer -> writer.writeAssociatedItem(rust));
+
+ assertThat(string, equalTo("""
+ pub fn area() -> i32;"""));
+ }
+
+ @Test
+ public void functionWithBody() throws IOException {
+ var rust = RustFunction.arbitrary()
+ .withName(new RustIdentifier("predicate"))
+ .withBody(RustBlockExpression.arbitrary()
+ .withFinalOperand(RustBoolLiteral.arbitrary().withValue(false).build())
+ .build())
+ .build();
+
+ var string = write(writer -> writer.writeAssociatedItem(rust));
+
+ assertThat(string, equalTo("""
+ pub fn predicate() {
+ false
+ }"""));
+ }
+
+ // === Structs ===
+
+ @Test
+ public void emptyStruct() throws IOException {
+ var rust = RustStructStruct.arbitrary().withName(new RustIdentifier("Rectangle")).build();
+
+ var string = write(writer -> writer.writeItem(rust));
+
+ assertThat(string, equalTo("""
+ pub struct Rectangle {
+ }"""));
+ }
+
+ @Test
+ public void structWithFields() throws IOException {
+ var rust = RustStructStruct.arbitrary()
+ .withName(new RustIdentifier("Rectangle"))
+ .withFields(List.of(
+ new RustStructField(new RustIdentifier("width"), RustTypePath.of("i32")),
+ new RustStructField(new RustIdentifier("height"), RustTypePath.of("i32"))
+ ))
+ .build();
+
+ var string = write(writer -> writer.writeItem(rust));
+
+ assertThat(string, equalTo("""
+ pub struct Rectangle {
+ pub width: i32,
+ pub height: i32,
+ }"""));
+ }
+
+ @Test
+ public void structWithDocComment() throws IOException {
+ var rust = RustStructStruct.arbitrary()
+ .withName(new RustIdentifier("Rectangle"))
+ .withDocComment(new DocComment("A 2D rectangle."))
+ .build();
+
+ var string = write(writer -> writer.writeItem(rust));
+
+ assertThat(string, equalTo("""
+ /// A 2D rectangle.
+ pub struct Rectangle {
+ }"""));
+ }
+
+ // === Enumerations ===
+
@Test
public void emptyEnum() throws IOException {
var rust = RustEnum.arbitrary().withName(new RustIdentifier("Shape")).build();
@@ -127,61 +234,7 @@ public class RustWriterTests {
}"""));
}
- @Test
- public void emptyFunction() throws IOException {
- var rust = RustFunction.arbitrary()
- .withName(new RustIdentifier("width"))
- .build();
-
- var string = write(writer -> writer.writeAssociatedItem(rust));
-
- assertThat(string, equalTo("""
- pub fn width();"""));
- }
-
- @Test
- public void functionWithParams() throws IOException {
- var rust = RustFunction.arbitrary()
- .withName(new RustIdentifier("area"))
- .addParam(new RustFunctionParam(new RustIdentifier("width"), RustTypePath.of("i32")))
- .addParam(new RustFunctionParam(new RustIdentifier("height"), RustTypePath.of("u64")))
- .build();
-
- var string = write(writer -> writer.writeAssociatedItem(rust));
-
- assertThat(string, equalTo("""
- pub fn area(width: i32, height: u64);"""));
- }
-
- @Test
- public void functionWithReturnType() throws IOException {
- var rust = RustFunction.arbitrary()
- .withName(new RustIdentifier("area"))
- .withReturnType(Optional.of(RustTypePath.of("i32")))
- .build();
-
- var string = write(writer -> writer.writeAssociatedItem(rust));
-
- assertThat(string, equalTo("""
- pub fn area() -> i32;"""));
- }
-
- @Test
- public void functionWithBody() throws IOException {
- var rust = RustFunction.arbitrary()
- .withName(new RustIdentifier("predicate"))
- .withBody(RustBlockExpression.arbitrary()
- .withFinalOperand(RustBoolLiteral.arbitrary().withValue(false).build())
- .build())
- .build();
-
- var string = write(writer -> writer.writeAssociatedItem(rust));
-
- assertThat(string, equalTo("""
- pub fn predicate() {
- false
- }"""));
- }
+ // === Implementations ===
@Test
public void emptyInherentImpl() throws IOException {
@@ -212,51 +265,6 @@ public class RustWriterTests {
}"""));
}
- @Test
- public void emptyStruct() throws IOException {
- var rust = RustStructStruct.arbitrary().withName(new RustIdentifier("Rectangle")).build();
-
- var string = write(writer -> writer.writeItem(rust));
-
- assertThat(string, equalTo("""
- pub struct Rectangle {
- }"""));
- }
-
- @Test
- public void structWithFields() throws IOException {
- var rust = RustStructStruct.arbitrary()
- .withName(new RustIdentifier("Rectangle"))
- .withFields(List.of(
- new RustStructField(new RustIdentifier("width"), RustTypePath.of("i32")),
- new RustStructField(new RustIdentifier("height"), RustTypePath.of("i32"))
- ))
- .build();
-
- var string = write(writer -> writer.writeItem(rust));
-
- assertThat(string, equalTo("""
- pub struct Rectangle {
- pub width: i32,
- pub height: i32,
- }"""));
- }
-
- @Test
- public void structWithDocComment() throws IOException {
- var rust = RustStructStruct.arbitrary()
- .withName(new RustIdentifier("Rectangle"))
- .withDocComment(new DocComment("A 2D rectangle."))
- .build();
-
- var string = write(writer -> writer.writeItem(rust));
-
- assertThat(string, equalTo("""
- /// A 2D rectangle.
- pub struct Rectangle {
- }"""));
- }
-
// == Statements ==
@Test