summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-07-31 10:50:10 +0100
committerMichael Williamson <mike@zwobble.org>2026-07-31 10:50:10 +0100
commit578bf1f04b48f48225cfa794a27426cca4f6384a (patch)
treefc5c2737ffa65e20305f165a593111463a36166d
parent1831d27671abe87bcbea5da40517093c37efb9b7 (diff)
Support singleton structs
-rw-r--r--examples/02-struct-singleton/hobgoblin.json5 (renamed from examples/08-shared/hobgoblin.json5)0
-rw-r--r--examples/02-struct-singleton/output/java/.gitignore (renamed from examples/02-sum/output/java/.gitignore)0
l---------examples/02-struct-singleton/output/java/pom.xml (renamed from examples/02-sum/output/java/pom.xml)0
-rw-r--r--examples/02-struct-singleton/output/java/src/test/java/org/zwobble/example/PointTests.java12
-rw-r--r--examples/02-struct-singleton/output/rust/.gitignore (renamed from examples/02-sum/output/rust/.gitignore)0
-rw-r--r--examples/02-struct-singleton/output/rust/Cargo.lock (renamed from examples/02-sum/output/rust/Cargo.lock)0
-rw-r--r--examples/02-struct-singleton/output/rust/Cargo.toml (renamed from examples/02-sum/output/rust/Cargo.toml)0
-rw-r--r--examples/02-struct-singleton/output/rust/rust-toolchain.toml (renamed from examples/02-sum/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/02-struct-singleton/output/rust/src/lib.rs11
-rw-r--r--examples/02-struct-singleton/output/rust/src/point.rs5
-rw-r--r--examples/02-struct-singleton/src/point.hob3
-rw-r--r--examples/03-sum/hobgoblin.json5 (renamed from examples/02-sum/hobgoblin.json5)0
-rw-r--r--examples/03-sum/output/java/.gitignore (renamed from examples/03-inductive-data-types/output/java/.gitignore)0
l---------examples/03-sum/output/java/pom.xml (renamed from examples/03-inductive-data-types/output/java/pom.xml)0
-rw-r--r--examples/03-sum/output/java/src/main/java/org/zwobble/example/Shapes.java (renamed from examples/02-sum/output/java/src/main/java/org/zwobble/example/Shapes.java)0
-rw-r--r--examples/03-sum/output/java/src/test/java/org/zwobble/example/ShapesTests.java (renamed from examples/02-sum/output/java/src/test/java/org/zwobble/example/ShapesTests.java)0
-rw-r--r--examples/03-sum/output/rust/.gitignore (renamed from examples/03-inductive-data-types/output/rust/.gitignore)0
-rw-r--r--examples/03-sum/output/rust/Cargo.lock (renamed from examples/03-inductive-data-types/output/rust/Cargo.lock)0
-rw-r--r--examples/03-sum/output/rust/Cargo.toml (renamed from examples/03-inductive-data-types/output/rust/Cargo.toml)0
-rw-r--r--examples/03-sum/output/rust/rust-toolchain.toml (renamed from examples/03-inductive-data-types/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/03-sum/output/rust/src/lib.rs (renamed from examples/02-sum/output/rust/src/lib.rs)0
-rw-r--r--examples/03-sum/output/rust/src/shapes.rs (renamed from examples/02-sum/output/rust/src/shapes.rs)0
-rw-r--r--examples/03-sum/src/shapes.hob (renamed from examples/02-sum/src/shapes.hob)0
-rw-r--r--examples/04-inductive-data-types/hobgoblin.json5 (renamed from examples/03-inductive-data-types/hobgoblin.json5)0
-rw-r--r--examples/04-inductive-data-types/output/java/.gitignore (renamed from examples/04-enum/output/java/.gitignore)0
l---------examples/04-inductive-data-types/output/java/pom.xml (renamed from examples/04-enum/output/java/pom.xml)0
-rw-r--r--examples/04-inductive-data-types/output/java/src/main/java/org/zwobble/example/Arithmetic.java (renamed from examples/03-inductive-data-types/output/java/src/main/java/org/zwobble/example/Arithmetic.java)0
-rw-r--r--examples/04-inductive-data-types/output/java/src/test/java/org/zwobble/example/ArithmeticTests.java (renamed from examples/03-inductive-data-types/output/java/src/test/java/org/zwobble/example/ArithmeticTests.java)0
-rw-r--r--examples/04-inductive-data-types/output/rust/.gitignore (renamed from examples/04-enum/output/rust/.gitignore)0
-rw-r--r--examples/04-inductive-data-types/output/rust/Cargo.lock (renamed from examples/04-enum/output/rust/Cargo.lock)0
-rw-r--r--examples/04-inductive-data-types/output/rust/Cargo.toml (renamed from examples/04-enum/output/rust/Cargo.toml)0
-rw-r--r--examples/04-inductive-data-types/output/rust/rust-toolchain.toml (renamed from examples/04-enum/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/04-inductive-data-types/output/rust/src/arithmetic.rs (renamed from examples/03-inductive-data-types/output/rust/src/arithmetic.rs)0
-rw-r--r--examples/04-inductive-data-types/output/rust/src/lib.rs (renamed from examples/03-inductive-data-types/output/rust/src/lib.rs)0
-rw-r--r--examples/04-inductive-data-types/src/arithmetic.hob (renamed from examples/03-inductive-data-types/src/arithmetic.hob)0
-rw-r--r--examples/05-enum/hobgoblin.json5 (renamed from examples/04-enum/hobgoblin.json5)0
-rw-r--r--examples/05-enum/output/java/.gitignore (renamed from examples/05-list/output/java/.gitignore)0
l---------examples/05-enum/output/java/pom.xml (renamed from examples/05-list/output/java/pom.xml)0
-rw-r--r--examples/05-enum/output/java/src/main/java/org/zwobble/example/Numbers.java (renamed from examples/04-enum/output/java/src/main/java/org/zwobble/example/Numbers.java)0
-rw-r--r--examples/05-enum/output/java/src/test/java/org/zwobble/example/NumbersTests.java (renamed from examples/04-enum/output/java/src/test/java/org/zwobble/example/NumbersTests.java)0
-rw-r--r--examples/05-enum/output/rust/.gitignore (renamed from examples/05-list/output/rust/.gitignore)0
-rw-r--r--examples/05-enum/output/rust/Cargo.lock (renamed from examples/05-list/output/rust/Cargo.lock)0
-rw-r--r--examples/05-enum/output/rust/Cargo.toml (renamed from examples/05-list/output/rust/Cargo.toml)0
-rw-r--r--examples/05-enum/output/rust/rust-toolchain.toml (renamed from examples/05-list/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/05-enum/output/rust/src/lib.rs (renamed from examples/04-enum/output/rust/src/lib.rs)0
-rw-r--r--examples/05-enum/output/rust/src/numbers.rs (renamed from examples/04-enum/output/rust/src/numbers.rs)0
-rw-r--r--examples/05-enum/src/numbers.hob (renamed from examples/04-enum/src/numbers.hob)0
-rw-r--r--examples/06-list/hobgoblin.json5 (renamed from examples/05-list/hobgoblin.json5)0
-rw-r--r--examples/06-list/output/java/.gitignore (renamed from examples/06-native-type/output/java/.gitignore)0
l---------examples/06-list/output/java/pom.xml (renamed from examples/06-native-type/output/java/pom.xml)0
-rw-r--r--examples/06-list/output/java/src/test/java/org/zwobble/example/PointTests.java (renamed from examples/05-list/output/java/src/test/java/org/zwobble/example/PointTests.java)0
-rw-r--r--examples/06-list/output/rust/.gitignore (renamed from examples/06-native-type/output/rust/.gitignore)0
-rw-r--r--examples/06-list/output/rust/Cargo.lock (renamed from examples/06-native-type/output/rust/Cargo.lock)0
-rw-r--r--examples/06-list/output/rust/Cargo.toml (renamed from examples/06-native-type/output/rust/Cargo.toml)0
-rw-r--r--examples/06-list/output/rust/rust-toolchain.toml (renamed from examples/06-native-type/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/06-list/output/rust/src/lib.rs (renamed from examples/05-list/output/rust/src/lib.rs)0
-rw-r--r--examples/06-list/output/rust/src/point.rs (renamed from examples/05-list/output/rust/src/point.rs)0
-rw-r--r--examples/06-list/src/point.hob (renamed from examples/05-list/src/point.hob)0
-rw-r--r--examples/07-native-type/hobgoblin.json5 (renamed from examples/06-native-type/hobgoblin.json5)0
-rw-r--r--examples/07-native-type/output/java/.gitignore (renamed from examples/07-native-type-custom-config/output/java/.gitignore)0
l---------examples/07-native-type/output/java/pom.xml (renamed from examples/07-native-type-custom-config/output/java/pom.xml)0
-rw-r--r--examples/07-native-type/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java (renamed from examples/06-native-type/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java)0
-rw-r--r--examples/07-native-type/output/java/src/main/java/org/zwobble/example/types/point/Point.java (renamed from examples/06-native-type/output/java/src/main/java/org/zwobble/example/types/point/Point.java)0
-rw-r--r--examples/07-native-type/output/java/src/test/java/org/zwobble/example/PointTests.java (renamed from examples/06-native-type/output/java/src/test/java/org/zwobble/example/PointTests.java)0
-rw-r--r--examples/07-native-type/output/rust/.gitignore (renamed from examples/07-native-type-custom-config/output/rust/.gitignore)0
-rw-r--r--examples/07-native-type/output/rust/Cargo.lock (renamed from examples/07-native-type-custom-config/output/rust/Cargo.lock)0
-rw-r--r--examples/07-native-type/output/rust/Cargo.toml (renamed from examples/07-native-type-custom-config/output/rust/Cargo.toml)0
-rw-r--r--examples/07-native-type/output/rust/rust-toolchain.toml (renamed from examples/07-native-type-custom-config/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/07-native-type/output/rust/src/gen/point.rs (renamed from examples/06-native-type/output/rust/src/gen/point.rs)0
-rw-r--r--examples/07-native-type/output/rust/src/lib.rs (renamed from examples/06-native-type/output/rust/src/lib.rs)0
-rw-r--r--examples/07-native-type/output/rust/src/point.rs (renamed from examples/06-native-type/output/rust/src/point.rs)0
-rw-r--r--examples/07-native-type/src/point.hob (renamed from examples/06-native-type/src/point.hob)0
-rw-r--r--examples/08-native-type-custom-config/hobgoblin.json5 (renamed from examples/07-native-type-custom-config/hobgoblin.json5)0
-rw-r--r--examples/08-native-type-custom-config/output/java/.gitignore (renamed from examples/08-shared/output/java/.gitignore)0
l---------examples/08-native-type-custom-config/output/java/pom.xml (renamed from examples/08-shared/output/java/pom.xml)0
-rw-r--r--examples/08-native-type-custom-config/output/java/src/main/java/org/zwobble/example/Point.java (renamed from examples/07-native-type-custom-config/output/java/src/main/java/org/zwobble/example/Point.java)0
-rw-r--r--examples/08-native-type-custom-config/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java (renamed from examples/07-native-type-custom-config/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java)0
-rw-r--r--examples/08-native-type-custom-config/output/java/src/test/java/org/zwobble/example/PointTests.java (renamed from examples/07-native-type-custom-config/output/java/src/test/java/org/zwobble/example/PointTests.java)0
-rw-r--r--examples/08-native-type-custom-config/output/rust/.gitignore (renamed from examples/08-shared/output/rust/.gitignore)0
-rw-r--r--examples/08-native-type-custom-config/output/rust/Cargo.lock (renamed from examples/08-shared/output/rust/Cargo.lock)0
-rw-r--r--examples/08-native-type-custom-config/output/rust/Cargo.toml (renamed from examples/08-shared/output/rust/Cargo.toml)0
-rw-r--r--examples/08-native-type-custom-config/output/rust/rust-toolchain.toml (renamed from examples/08-shared/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/08-native-type-custom-config/output/rust/src/main.rs (renamed from examples/07-native-type-custom-config/output/rust/src/main.rs)0
-rw-r--r--examples/08-native-type-custom-config/output/rust/src/point.rs (renamed from examples/07-native-type-custom-config/output/rust/src/point.rs)0
-rw-r--r--examples/08-native-type-custom-config/src/point.hob (renamed from examples/07-native-type-custom-config/src/point.hob)0
-rw-r--r--examples/09-shared/hobgoblin.json523
-rw-r--r--examples/09-shared/output/java/.gitignore (renamed from examples/09-custom-code/output/java/.gitignore)0
l---------examples/09-shared/output/java/pom.xml (renamed from examples/09-custom-code/output/java/pom.xml)0
-rw-r--r--examples/09-shared/output/java/src/test/java/org/zwobble/example/PointTests.java (renamed from examples/08-shared/output/java/src/test/java/org/zwobble/example/PointTests.java)0
-rw-r--r--examples/09-shared/output/rust/.gitignore (renamed from examples/09-custom-code/output/rust/.gitignore)0
-rw-r--r--examples/09-shared/output/rust/Cargo.lock (renamed from examples/09-custom-code/output/rust/Cargo.lock)0
-rw-r--r--examples/09-shared/output/rust/Cargo.toml (renamed from examples/09-custom-code/output/rust/Cargo.toml)0
-rw-r--r--examples/09-shared/output/rust/rust-toolchain.toml (renamed from examples/09-custom-code/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/09-shared/output/rust/src/lib.rs (renamed from examples/08-shared/output/rust/src/lib.rs)0
-rw-r--r--examples/09-shared/output/rust/src/point.rs (renamed from examples/08-shared/output/rust/src/point.rs)0
-rw-r--r--examples/09-shared/src/point.hob (renamed from examples/08-shared/src/point.hob)0
-rw-r--r--examples/10-custom-code/hobgoblin.json5 (renamed from examples/09-custom-code/hobgoblin.json5)0
-rw-r--r--examples/10-custom-code/output/java/.gitignore (renamed from examples/10-imports/output/java/.gitignore)0
l---------examples/10-custom-code/output/java/pom.xml (renamed from examples/10-imports/output/java/pom.xml)0
-rw-r--r--examples/10-custom-code/output/java/src/main/java/org/zwobble/example/types/shapes/Square.java (renamed from examples/09-custom-code/output/java/src/main/java/org/zwobble/example/types/shapes/Square.java)0
-rw-r--r--examples/10-custom-code/output/java/src/test/java/org/zwobble/example/ShapesTests.java (renamed from examples/09-custom-code/output/java/src/test/java/org/zwobble/example/ShapesTests.java)0
-rw-r--r--examples/10-custom-code/output/rust/.gitignore (renamed from examples/10-imports/output/rust/.gitignore)0
-rw-r--r--examples/10-custom-code/output/rust/Cargo.lock (renamed from examples/10-imports/output/rust/Cargo.lock)0
-rw-r--r--examples/10-custom-code/output/rust/Cargo.toml (renamed from examples/10-imports/output/rust/Cargo.toml)0
-rw-r--r--examples/10-custom-code/output/rust/rust-toolchain.toml (renamed from examples/10-imports/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/10-custom-code/output/rust/src/gen/shapes.rs (renamed from examples/09-custom-code/output/rust/src/gen/shapes.rs)0
-rw-r--r--examples/10-custom-code/output/rust/src/lib.rs (renamed from examples/09-custom-code/output/rust/src/lib.rs)0
-rw-r--r--examples/10-custom-code/output/rust/src/shapes.rs (renamed from examples/09-custom-code/output/rust/src/shapes.rs)0
-rw-r--r--examples/10-custom-code/src/shapes.hob (renamed from examples/09-custom-code/src/shapes.hob)0
-rw-r--r--examples/11-imports/hobgoblin.json5 (renamed from examples/10-imports/hobgoblin.json5)0
-rw-r--r--examples/11-imports/output/java/.gitignore2
l---------examples/11-imports/output/java/pom.xml (renamed from examples/11-transient-0/output/java/pom.xml)0
-rw-r--r--examples/11-imports/output/java/src/test/java/org/zwobble/example/LineTests.java (renamed from examples/10-imports/output/java/src/test/java/org/zwobble/example/LineTests.java)0
-rw-r--r--examples/11-imports/output/rust/.gitignore1
-rw-r--r--examples/11-imports/output/rust/Cargo.lock (renamed from examples/11-transient-0/output/rust/Cargo.lock)0
-rw-r--r--examples/11-imports/output/rust/Cargo.toml (renamed from examples/11-transient-0/output/rust/Cargo.toml)0
-rw-r--r--examples/11-imports/output/rust/rust-toolchain.toml (renamed from examples/11-transient-0/output/rust/rust-toolchain.toml)0
-rw-r--r--examples/11-imports/output/rust/src/lib.rs (renamed from examples/10-imports/output/rust/src/lib.rs)0
-rw-r--r--examples/11-imports/output/rust/src/line.rs (renamed from examples/10-imports/output/rust/src/line.rs)0
-rw-r--r--examples/11-imports/output/rust/src/point.rs (renamed from examples/10-imports/output/rust/src/point.rs)0
-rw-r--r--examples/11-imports/src/line.hob (renamed from examples/10-imports/src/line.hob)0
-rw-r--r--examples/11-imports/src/point.hob (renamed from examples/10-imports/src/point.hob)0
-rw-r--r--examples/12-transient-0/hobgoblin.json5 (renamed from examples/11-transient-0/hobgoblin.json5)0
-rw-r--r--examples/12-transient-0/output/java/.gitignore (renamed from examples/11-transient-0/output/java/.gitignore)0
l---------examples/12-transient-0/output/java/pom.xml1
-rw-r--r--examples/12-transient-0/output/java/src/test/java/org/zwobble/example/Transient0Tests.java (renamed from examples/11-transient-0/output/java/src/test/java/org/zwobble/example/Transient0Tests.java)0
-rw-r--r--examples/12-transient-0/output/rust/.gitignore (renamed from examples/11-transient-0/output/rust/.gitignore)0
-rw-r--r--examples/12-transient-0/output/rust/Cargo.lock7
-rw-r--r--examples/12-transient-0/output/rust/Cargo.toml6
-rw-r--r--examples/12-transient-0/output/rust/rust-toolchain.toml2
-rw-r--r--examples/12-transient-0/output/rust/src/data.rs (renamed from examples/11-transient-0/output/rust/src/data.rs)0
-rw-r--r--examples/12-transient-0/output/rust/src/gen/data.rs (renamed from examples/11-transient-0/output/rust/src/gen/data.rs)0
-rw-r--r--examples/12-transient-0/output/rust/src/gen/data/transient_0.rs (renamed from examples/11-transient-0/output/rust/src/gen/data/transient_0.rs)0
-rw-r--r--examples/12-transient-0/output/rust/src/gen/transient_0.rs (renamed from examples/11-transient-0/output/rust/src/gen/transient_0.rs)0
-rw-r--r--examples/12-transient-0/output/rust/src/lib.rs (renamed from examples/11-transient-0/output/rust/src/lib.rs)0
-rw-r--r--examples/12-transient-0/output/rust/src/transient_0.rs (renamed from examples/11-transient-0/output/rust/src/transient_0.rs)0
-rw-r--r--examples/12-transient-0/src/data.hob (renamed from examples/11-transient-0/src/data.hob)0
-rw-r--r--hobgoblin/src/ast/untyped.hob2
-rw-r--r--makefile2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java3
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java20
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java6
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java32
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java90
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java36
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java21
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java10
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java23
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java4
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java3
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java29
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNodeMatcher.java2
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java25
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java4
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java46
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSumDefinitionTests.java7
158 files changed, 313 insertions, 129 deletions
diff --git a/examples/08-shared/hobgoblin.json5 b/examples/02-struct-singleton/hobgoblin.json5
index 19e0f93..19e0f93 100644
--- a/examples/08-shared/hobgoblin.json5
+++ b/examples/02-struct-singleton/hobgoblin.json5
diff --git a/examples/02-sum/output/java/.gitignore b/examples/02-struct-singleton/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/02-sum/output/java/.gitignore
+++ b/examples/02-struct-singleton/output/java/.gitignore
diff --git a/examples/02-sum/output/java/pom.xml b/examples/02-struct-singleton/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/02-sum/output/java/pom.xml
+++ b/examples/02-struct-singleton/output/java/pom.xml
diff --git a/examples/02-struct-singleton/output/java/src/test/java/org/zwobble/example/PointTests.java b/examples/02-struct-singleton/output/java/src/test/java/org/zwobble/example/PointTests.java
new file mode 100644
index 0000000..cec3047
--- /dev/null
+++ b/examples/02-struct-singleton/output/java/src/test/java/org/zwobble/example/PointTests.java
@@ -0,0 +1,12 @@
+package org.zwobble.example;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+import org.zwobble.example.types.point.Origin;
+
+public class PointTests {
+ @Test
+ public void origin() {
+ var origin = Origin.INSTANCE;
+ }
+}
diff --git a/examples/02-sum/output/rust/.gitignore b/examples/02-struct-singleton/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/02-sum/output/rust/.gitignore
+++ b/examples/02-struct-singleton/output/rust/.gitignore
diff --git a/examples/02-sum/output/rust/Cargo.lock b/examples/02-struct-singleton/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/02-sum/output/rust/Cargo.lock
+++ b/examples/02-struct-singleton/output/rust/Cargo.lock
diff --git a/examples/02-sum/output/rust/Cargo.toml b/examples/02-struct-singleton/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/02-sum/output/rust/Cargo.toml
+++ b/examples/02-struct-singleton/output/rust/Cargo.toml
diff --git a/examples/02-sum/output/rust/rust-toolchain.toml b/examples/02-struct-singleton/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/02-sum/output/rust/rust-toolchain.toml
+++ b/examples/02-struct-singleton/output/rust/rust-toolchain.toml
diff --git a/examples/02-struct-singleton/output/rust/src/lib.rs b/examples/02-struct-singleton/output/rust/src/lib.rs
new file mode 100644
index 0000000..7182bd8
--- /dev/null
+++ b/examples/02-struct-singleton/output/rust/src/lib.rs
@@ -0,0 +1,11 @@
+mod point;
+
+#[cfg(test)]
+mod test {
+ use super::point::Origin;
+
+ #[test]
+ fn origin() {
+ let origin = Origin {};
+ }
+}
diff --git a/examples/02-struct-singleton/output/rust/src/point.rs b/examples/02-struct-singleton/output/rust/src/point.rs
new file mode 100644
index 0000000..e2d608c
--- /dev/null
+++ b/examples/02-struct-singleton/output/rust/src/point.rs
@@ -0,0 +1,5 @@
+// Generated by hobgoblin.
+
+#[derive(Debug, Hash, PartialEq)]
+pub struct Origin {
+}
diff --git a/examples/02-struct-singleton/src/point.hob b/examples/02-struct-singleton/src/point.hob
new file mode 100644
index 0000000..930a1b5
--- /dev/null
+++ b/examples/02-struct-singleton/src/point.hob
@@ -0,0 +1,3 @@
+struct Origin {
+ singleton;
+}
diff --git a/examples/02-sum/hobgoblin.json5 b/examples/03-sum/hobgoblin.json5
index 12713d4..12713d4 100644
--- a/examples/02-sum/hobgoblin.json5
+++ b/examples/03-sum/hobgoblin.json5
diff --git a/examples/03-inductive-data-types/output/java/.gitignore b/examples/03-sum/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/03-inductive-data-types/output/java/.gitignore
+++ b/examples/03-sum/output/java/.gitignore
diff --git a/examples/03-inductive-data-types/output/java/pom.xml b/examples/03-sum/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/03-inductive-data-types/output/java/pom.xml
+++ b/examples/03-sum/output/java/pom.xml
diff --git a/examples/02-sum/output/java/src/main/java/org/zwobble/example/Shapes.java b/examples/03-sum/output/java/src/main/java/org/zwobble/example/Shapes.java
index a6a468f..a6a468f 100644
--- a/examples/02-sum/output/java/src/main/java/org/zwobble/example/Shapes.java
+++ b/examples/03-sum/output/java/src/main/java/org/zwobble/example/Shapes.java
diff --git a/examples/02-sum/output/java/src/test/java/org/zwobble/example/ShapesTests.java b/examples/03-sum/output/java/src/test/java/org/zwobble/example/ShapesTests.java
index 893a544..893a544 100644
--- a/examples/02-sum/output/java/src/test/java/org/zwobble/example/ShapesTests.java
+++ b/examples/03-sum/output/java/src/test/java/org/zwobble/example/ShapesTests.java
diff --git a/examples/03-inductive-data-types/output/rust/.gitignore b/examples/03-sum/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/03-inductive-data-types/output/rust/.gitignore
+++ b/examples/03-sum/output/rust/.gitignore
diff --git a/examples/03-inductive-data-types/output/rust/Cargo.lock b/examples/03-sum/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/03-inductive-data-types/output/rust/Cargo.lock
+++ b/examples/03-sum/output/rust/Cargo.lock
diff --git a/examples/03-inductive-data-types/output/rust/Cargo.toml b/examples/03-sum/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/03-inductive-data-types/output/rust/Cargo.toml
+++ b/examples/03-sum/output/rust/Cargo.toml
diff --git a/examples/03-inductive-data-types/output/rust/rust-toolchain.toml b/examples/03-sum/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/03-inductive-data-types/output/rust/rust-toolchain.toml
+++ b/examples/03-sum/output/rust/rust-toolchain.toml
diff --git a/examples/02-sum/output/rust/src/lib.rs b/examples/03-sum/output/rust/src/lib.rs
index f961002..f961002 100644
--- a/examples/02-sum/output/rust/src/lib.rs
+++ b/examples/03-sum/output/rust/src/lib.rs
diff --git a/examples/02-sum/output/rust/src/shapes.rs b/examples/03-sum/output/rust/src/shapes.rs
index a0a9b7f..a0a9b7f 100644
--- a/examples/02-sum/output/rust/src/shapes.rs
+++ b/examples/03-sum/output/rust/src/shapes.rs
diff --git a/examples/02-sum/src/shapes.hob b/examples/03-sum/src/shapes.hob
index 03a727a..03a727a 100644
--- a/examples/02-sum/src/shapes.hob
+++ b/examples/03-sum/src/shapes.hob
diff --git a/examples/03-inductive-data-types/hobgoblin.json5 b/examples/04-inductive-data-types/hobgoblin.json5
index 12713d4..12713d4 100644
--- a/examples/03-inductive-data-types/hobgoblin.json5
+++ b/examples/04-inductive-data-types/hobgoblin.json5
diff --git a/examples/04-enum/output/java/.gitignore b/examples/04-inductive-data-types/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/04-enum/output/java/.gitignore
+++ b/examples/04-inductive-data-types/output/java/.gitignore
diff --git a/examples/04-enum/output/java/pom.xml b/examples/04-inductive-data-types/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/04-enum/output/java/pom.xml
+++ b/examples/04-inductive-data-types/output/java/pom.xml
diff --git a/examples/03-inductive-data-types/output/java/src/main/java/org/zwobble/example/Arithmetic.java b/examples/04-inductive-data-types/output/java/src/main/java/org/zwobble/example/Arithmetic.java
index 08cb75c..08cb75c 100644
--- a/examples/03-inductive-data-types/output/java/src/main/java/org/zwobble/example/Arithmetic.java
+++ b/examples/04-inductive-data-types/output/java/src/main/java/org/zwobble/example/Arithmetic.java
diff --git a/examples/03-inductive-data-types/output/java/src/test/java/org/zwobble/example/ArithmeticTests.java b/examples/04-inductive-data-types/output/java/src/test/java/org/zwobble/example/ArithmeticTests.java
index cd4fdd0..cd4fdd0 100644
--- a/examples/03-inductive-data-types/output/java/src/test/java/org/zwobble/example/ArithmeticTests.java
+++ b/examples/04-inductive-data-types/output/java/src/test/java/org/zwobble/example/ArithmeticTests.java
diff --git a/examples/04-enum/output/rust/.gitignore b/examples/04-inductive-data-types/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/04-enum/output/rust/.gitignore
+++ b/examples/04-inductive-data-types/output/rust/.gitignore
diff --git a/examples/04-enum/output/rust/Cargo.lock b/examples/04-inductive-data-types/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/04-enum/output/rust/Cargo.lock
+++ b/examples/04-inductive-data-types/output/rust/Cargo.lock
diff --git a/examples/04-enum/output/rust/Cargo.toml b/examples/04-inductive-data-types/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/04-enum/output/rust/Cargo.toml
+++ b/examples/04-inductive-data-types/output/rust/Cargo.toml
diff --git a/examples/04-enum/output/rust/rust-toolchain.toml b/examples/04-inductive-data-types/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/04-enum/output/rust/rust-toolchain.toml
+++ b/examples/04-inductive-data-types/output/rust/rust-toolchain.toml
diff --git a/examples/03-inductive-data-types/output/rust/src/arithmetic.rs b/examples/04-inductive-data-types/output/rust/src/arithmetic.rs
index 121c355..121c355 100644
--- a/examples/03-inductive-data-types/output/rust/src/arithmetic.rs
+++ b/examples/04-inductive-data-types/output/rust/src/arithmetic.rs
diff --git a/examples/03-inductive-data-types/output/rust/src/lib.rs b/examples/04-inductive-data-types/output/rust/src/lib.rs
index 3265e69..3265e69 100644
--- a/examples/03-inductive-data-types/output/rust/src/lib.rs
+++ b/examples/04-inductive-data-types/output/rust/src/lib.rs
diff --git a/examples/03-inductive-data-types/src/arithmetic.hob b/examples/04-inductive-data-types/src/arithmetic.hob
index b1ef6e5..b1ef6e5 100644
--- a/examples/03-inductive-data-types/src/arithmetic.hob
+++ b/examples/04-inductive-data-types/src/arithmetic.hob
diff --git a/examples/04-enum/hobgoblin.json5 b/examples/05-enum/hobgoblin.json5
index 12713d4..12713d4 100644
--- a/examples/04-enum/hobgoblin.json5
+++ b/examples/05-enum/hobgoblin.json5
diff --git a/examples/05-list/output/java/.gitignore b/examples/05-enum/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/05-list/output/java/.gitignore
+++ b/examples/05-enum/output/java/.gitignore
diff --git a/examples/05-list/output/java/pom.xml b/examples/05-enum/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/05-list/output/java/pom.xml
+++ b/examples/05-enum/output/java/pom.xml
diff --git a/examples/04-enum/output/java/src/main/java/org/zwobble/example/Numbers.java b/examples/05-enum/output/java/src/main/java/org/zwobble/example/Numbers.java
index fc17869..fc17869 100644
--- a/examples/04-enum/output/java/src/main/java/org/zwobble/example/Numbers.java
+++ b/examples/05-enum/output/java/src/main/java/org/zwobble/example/Numbers.java
diff --git a/examples/04-enum/output/java/src/test/java/org/zwobble/example/NumbersTests.java b/examples/05-enum/output/java/src/test/java/org/zwobble/example/NumbersTests.java
index 141d5d1..141d5d1 100644
--- a/examples/04-enum/output/java/src/test/java/org/zwobble/example/NumbersTests.java
+++ b/examples/05-enum/output/java/src/test/java/org/zwobble/example/NumbersTests.java
diff --git a/examples/05-list/output/rust/.gitignore b/examples/05-enum/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/05-list/output/rust/.gitignore
+++ b/examples/05-enum/output/rust/.gitignore
diff --git a/examples/05-list/output/rust/Cargo.lock b/examples/05-enum/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/05-list/output/rust/Cargo.lock
+++ b/examples/05-enum/output/rust/Cargo.lock
diff --git a/examples/05-list/output/rust/Cargo.toml b/examples/05-enum/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/05-list/output/rust/Cargo.toml
+++ b/examples/05-enum/output/rust/Cargo.toml
diff --git a/examples/05-list/output/rust/rust-toolchain.toml b/examples/05-enum/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/05-list/output/rust/rust-toolchain.toml
+++ b/examples/05-enum/output/rust/rust-toolchain.toml
diff --git a/examples/04-enum/output/rust/src/lib.rs b/examples/05-enum/output/rust/src/lib.rs
index ae0b67c..ae0b67c 100644
--- a/examples/04-enum/output/rust/src/lib.rs
+++ b/examples/05-enum/output/rust/src/lib.rs
diff --git a/examples/04-enum/output/rust/src/numbers.rs b/examples/05-enum/output/rust/src/numbers.rs
index 1c62012..1c62012 100644
--- a/examples/04-enum/output/rust/src/numbers.rs
+++ b/examples/05-enum/output/rust/src/numbers.rs
diff --git a/examples/04-enum/src/numbers.hob b/examples/05-enum/src/numbers.hob
index 125082d..125082d 100644
--- a/examples/04-enum/src/numbers.hob
+++ b/examples/05-enum/src/numbers.hob
diff --git a/examples/05-list/hobgoblin.json5 b/examples/06-list/hobgoblin.json5
index 12713d4..12713d4 100644
--- a/examples/05-list/hobgoblin.json5
+++ b/examples/06-list/hobgoblin.json5
diff --git a/examples/06-native-type/output/java/.gitignore b/examples/06-list/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/06-native-type/output/java/.gitignore
+++ b/examples/06-list/output/java/.gitignore
diff --git a/examples/06-native-type/output/java/pom.xml b/examples/06-list/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/06-native-type/output/java/pom.xml
+++ b/examples/06-list/output/java/pom.xml
diff --git a/examples/05-list/output/java/src/test/java/org/zwobble/example/PointTests.java b/examples/06-list/output/java/src/test/java/org/zwobble/example/PointTests.java
index e1528b5..e1528b5 100644
--- a/examples/05-list/output/java/src/test/java/org/zwobble/example/PointTests.java
+++ b/examples/06-list/output/java/src/test/java/org/zwobble/example/PointTests.java
diff --git a/examples/06-native-type/output/rust/.gitignore b/examples/06-list/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/06-native-type/output/rust/.gitignore
+++ b/examples/06-list/output/rust/.gitignore
diff --git a/examples/06-native-type/output/rust/Cargo.lock b/examples/06-list/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/06-native-type/output/rust/Cargo.lock
+++ b/examples/06-list/output/rust/Cargo.lock
diff --git a/examples/06-native-type/output/rust/Cargo.toml b/examples/06-list/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/06-native-type/output/rust/Cargo.toml
+++ b/examples/06-list/output/rust/Cargo.toml
diff --git a/examples/06-native-type/output/rust/rust-toolchain.toml b/examples/06-list/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/06-native-type/output/rust/rust-toolchain.toml
+++ b/examples/06-list/output/rust/rust-toolchain.toml
diff --git a/examples/05-list/output/rust/src/lib.rs b/examples/06-list/output/rust/src/lib.rs
index 907ab8b..907ab8b 100644
--- a/examples/05-list/output/rust/src/lib.rs
+++ b/examples/06-list/output/rust/src/lib.rs
diff --git a/examples/05-list/output/rust/src/point.rs b/examples/06-list/output/rust/src/point.rs
index 2625f9f..2625f9f 100644
--- a/examples/05-list/output/rust/src/point.rs
+++ b/examples/06-list/output/rust/src/point.rs
diff --git a/examples/05-list/src/point.hob b/examples/06-list/src/point.hob
index 8dd438c..8dd438c 100644
--- a/examples/05-list/src/point.hob
+++ b/examples/06-list/src/point.hob
diff --git a/examples/06-native-type/hobgoblin.json5 b/examples/07-native-type/hobgoblin.json5
index a0f60c3..a0f60c3 100644
--- a/examples/06-native-type/hobgoblin.json5
+++ b/examples/07-native-type/hobgoblin.json5
diff --git a/examples/07-native-type-custom-config/output/java/.gitignore b/examples/07-native-type/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/07-native-type-custom-config/output/java/.gitignore
+++ b/examples/07-native-type/output/java/.gitignore
diff --git a/examples/07-native-type-custom-config/output/java/pom.xml b/examples/07-native-type/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/07-native-type-custom-config/output/java/pom.xml
+++ b/examples/07-native-type/output/java/pom.xml
diff --git a/examples/06-native-type/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java b/examples/07-native-type/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java
index bdb5427..bdb5427 100644
--- a/examples/06-native-type/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java
+++ b/examples/07-native-type/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java
diff --git a/examples/06-native-type/output/java/src/main/java/org/zwobble/example/types/point/Point.java b/examples/07-native-type/output/java/src/main/java/org/zwobble/example/types/point/Point.java
index cd26290..cd26290 100644
--- a/examples/06-native-type/output/java/src/main/java/org/zwobble/example/types/point/Point.java
+++ b/examples/07-native-type/output/java/src/main/java/org/zwobble/example/types/point/Point.java
diff --git a/examples/06-native-type/output/java/src/test/java/org/zwobble/example/PointTests.java b/examples/07-native-type/output/java/src/test/java/org/zwobble/example/PointTests.java
index 8482673..8482673 100644
--- a/examples/06-native-type/output/java/src/test/java/org/zwobble/example/PointTests.java
+++ b/examples/07-native-type/output/java/src/test/java/org/zwobble/example/PointTests.java
diff --git a/examples/07-native-type-custom-config/output/rust/.gitignore b/examples/07-native-type/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/07-native-type-custom-config/output/rust/.gitignore
+++ b/examples/07-native-type/output/rust/.gitignore
diff --git a/examples/07-native-type-custom-config/output/rust/Cargo.lock b/examples/07-native-type/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/07-native-type-custom-config/output/rust/Cargo.lock
+++ b/examples/07-native-type/output/rust/Cargo.lock
diff --git a/examples/07-native-type-custom-config/output/rust/Cargo.toml b/examples/07-native-type/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/07-native-type-custom-config/output/rust/Cargo.toml
+++ b/examples/07-native-type/output/rust/Cargo.toml
diff --git a/examples/07-native-type-custom-config/output/rust/rust-toolchain.toml b/examples/07-native-type/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/07-native-type-custom-config/output/rust/rust-toolchain.toml
+++ b/examples/07-native-type/output/rust/rust-toolchain.toml
diff --git a/examples/06-native-type/output/rust/src/gen/point.rs b/examples/07-native-type/output/rust/src/gen/point.rs
index d383b15..d383b15 100644
--- a/examples/06-native-type/output/rust/src/gen/point.rs
+++ b/examples/07-native-type/output/rust/src/gen/point.rs
diff --git a/examples/06-native-type/output/rust/src/lib.rs b/examples/07-native-type/output/rust/src/lib.rs
index 1179cff..1179cff 100644
--- a/examples/06-native-type/output/rust/src/lib.rs
+++ b/examples/07-native-type/output/rust/src/lib.rs
diff --git a/examples/06-native-type/output/rust/src/point.rs b/examples/07-native-type/output/rust/src/point.rs
index c5b73d7..c5b73d7 100644
--- a/examples/06-native-type/output/rust/src/point.rs
+++ b/examples/07-native-type/output/rust/src/point.rs
diff --git a/examples/06-native-type/src/point.hob b/examples/07-native-type/src/point.hob
index 7178dcb..7178dcb 100644
--- a/examples/06-native-type/src/point.hob
+++ b/examples/07-native-type/src/point.hob
diff --git a/examples/07-native-type-custom-config/hobgoblin.json5 b/examples/08-native-type-custom-config/hobgoblin.json5
index f925903..f925903 100644
--- a/examples/07-native-type-custom-config/hobgoblin.json5
+++ b/examples/08-native-type-custom-config/hobgoblin.json5
diff --git a/examples/08-shared/output/java/.gitignore b/examples/08-native-type-custom-config/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/08-shared/output/java/.gitignore
+++ b/examples/08-native-type-custom-config/output/java/.gitignore
diff --git a/examples/08-shared/output/java/pom.xml b/examples/08-native-type-custom-config/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/08-shared/output/java/pom.xml
+++ b/examples/08-native-type-custom-config/output/java/pom.xml
diff --git a/examples/07-native-type-custom-config/output/java/src/main/java/org/zwobble/example/Point.java b/examples/08-native-type-custom-config/output/java/src/main/java/org/zwobble/example/Point.java
index 8862a62..8862a62 100644
--- a/examples/07-native-type-custom-config/output/java/src/main/java/org/zwobble/example/Point.java
+++ b/examples/08-native-type-custom-config/output/java/src/main/java/org/zwobble/example/Point.java
diff --git a/examples/07-native-type-custom-config/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java b/examples/08-native-type-custom-config/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java
index 74ac856..74ac856 100644
--- a/examples/07-native-type-custom-config/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java
+++ b/examples/08-native-type-custom-config/output/java/src/main/java/org/zwobble/example/types/point/HobgoblinNativePoint.java
diff --git a/examples/07-native-type-custom-config/output/java/src/test/java/org/zwobble/example/PointTests.java b/examples/08-native-type-custom-config/output/java/src/test/java/org/zwobble/example/PointTests.java
index ea635ca..ea635ca 100644
--- a/examples/07-native-type-custom-config/output/java/src/test/java/org/zwobble/example/PointTests.java
+++ b/examples/08-native-type-custom-config/output/java/src/test/java/org/zwobble/example/PointTests.java
diff --git a/examples/08-shared/output/rust/.gitignore b/examples/08-native-type-custom-config/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/08-shared/output/rust/.gitignore
+++ b/examples/08-native-type-custom-config/output/rust/.gitignore
diff --git a/examples/08-shared/output/rust/Cargo.lock b/examples/08-native-type-custom-config/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/08-shared/output/rust/Cargo.lock
+++ b/examples/08-native-type-custom-config/output/rust/Cargo.lock
diff --git a/examples/08-shared/output/rust/Cargo.toml b/examples/08-native-type-custom-config/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/08-shared/output/rust/Cargo.toml
+++ b/examples/08-native-type-custom-config/output/rust/Cargo.toml
diff --git a/examples/08-shared/output/rust/rust-toolchain.toml b/examples/08-native-type-custom-config/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/08-shared/output/rust/rust-toolchain.toml
+++ b/examples/08-native-type-custom-config/output/rust/rust-toolchain.toml
diff --git a/examples/07-native-type-custom-config/output/rust/src/main.rs b/examples/08-native-type-custom-config/output/rust/src/main.rs
index 10dc437..10dc437 100644
--- a/examples/07-native-type-custom-config/output/rust/src/main.rs
+++ b/examples/08-native-type-custom-config/output/rust/src/main.rs
diff --git a/examples/07-native-type-custom-config/output/rust/src/point.rs b/examples/08-native-type-custom-config/output/rust/src/point.rs
index 6ab4330..6ab4330 100644
--- a/examples/07-native-type-custom-config/output/rust/src/point.rs
+++ b/examples/08-native-type-custom-config/output/rust/src/point.rs
diff --git a/examples/07-native-type-custom-config/src/point.hob b/examples/08-native-type-custom-config/src/point.hob
index 7178dcb..7178dcb 100644
--- a/examples/07-native-type-custom-config/src/point.hob
+++ b/examples/08-native-type-custom-config/src/point.hob
diff --git a/examples/09-shared/hobgoblin.json5 b/examples/09-shared/hobgoblin.json5
new file mode 100644
index 0000000..19e0f93
--- /dev/null
+++ b/examples/09-shared/hobgoblin.json5
@@ -0,0 +1,23 @@
+{
+ outputs: {
+ langs: {
+ java: {
+ packageName: "org.zwobble.example.types",
+ },
+ },
+ generators: [
+ {
+ generator: "java-types",
+ path: "output/java/src/gen/java",
+ },
+ {
+ generator: "java-precisely-matchers",
+ path: "output/java/src/gen/java",
+ },
+ {
+ generator: "rust-types",
+ path: "output/rust/src",
+ },
+ ],
+ }
+}
diff --git a/examples/09-custom-code/output/java/.gitignore b/examples/09-shared/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/09-custom-code/output/java/.gitignore
+++ b/examples/09-shared/output/java/.gitignore
diff --git a/examples/09-custom-code/output/java/pom.xml b/examples/09-shared/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/09-custom-code/output/java/pom.xml
+++ b/examples/09-shared/output/java/pom.xml
diff --git a/examples/08-shared/output/java/src/test/java/org/zwobble/example/PointTests.java b/examples/09-shared/output/java/src/test/java/org/zwobble/example/PointTests.java
index b4c140d..b4c140d 100644
--- a/examples/08-shared/output/java/src/test/java/org/zwobble/example/PointTests.java
+++ b/examples/09-shared/output/java/src/test/java/org/zwobble/example/PointTests.java
diff --git a/examples/09-custom-code/output/rust/.gitignore b/examples/09-shared/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/09-custom-code/output/rust/.gitignore
+++ b/examples/09-shared/output/rust/.gitignore
diff --git a/examples/09-custom-code/output/rust/Cargo.lock b/examples/09-shared/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/09-custom-code/output/rust/Cargo.lock
+++ b/examples/09-shared/output/rust/Cargo.lock
diff --git a/examples/09-custom-code/output/rust/Cargo.toml b/examples/09-shared/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/09-custom-code/output/rust/Cargo.toml
+++ b/examples/09-shared/output/rust/Cargo.toml
diff --git a/examples/09-custom-code/output/rust/rust-toolchain.toml b/examples/09-shared/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/09-custom-code/output/rust/rust-toolchain.toml
+++ b/examples/09-shared/output/rust/rust-toolchain.toml
diff --git a/examples/08-shared/output/rust/src/lib.rs b/examples/09-shared/output/rust/src/lib.rs
index af2c87f..af2c87f 100644
--- a/examples/08-shared/output/rust/src/lib.rs
+++ b/examples/09-shared/output/rust/src/lib.rs
diff --git a/examples/08-shared/output/rust/src/point.rs b/examples/09-shared/output/rust/src/point.rs
index dea7678..dea7678 100644
--- a/examples/08-shared/output/rust/src/point.rs
+++ b/examples/09-shared/output/rust/src/point.rs
diff --git a/examples/08-shared/src/point.hob b/examples/09-shared/src/point.hob
index 7b9a8e6..7b9a8e6 100644
--- a/examples/08-shared/src/point.hob
+++ b/examples/09-shared/src/point.hob
diff --git a/examples/09-custom-code/hobgoblin.json5 b/examples/10-custom-code/hobgoblin.json5
index 1d08a40..1d08a40 100644
--- a/examples/09-custom-code/hobgoblin.json5
+++ b/examples/10-custom-code/hobgoblin.json5
diff --git a/examples/10-imports/output/java/.gitignore b/examples/10-custom-code/output/java/.gitignore
index ff511d4..ff511d4 100644
--- a/examples/10-imports/output/java/.gitignore
+++ b/examples/10-custom-code/output/java/.gitignore
diff --git a/examples/10-imports/output/java/pom.xml b/examples/10-custom-code/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/10-imports/output/java/pom.xml
+++ b/examples/10-custom-code/output/java/pom.xml
diff --git a/examples/09-custom-code/output/java/src/main/java/org/zwobble/example/types/shapes/Square.java b/examples/10-custom-code/output/java/src/main/java/org/zwobble/example/types/shapes/Square.java
index 69a1ab1..69a1ab1 100644
--- a/examples/09-custom-code/output/java/src/main/java/org/zwobble/example/types/shapes/Square.java
+++ b/examples/10-custom-code/output/java/src/main/java/org/zwobble/example/types/shapes/Square.java
diff --git a/examples/09-custom-code/output/java/src/test/java/org/zwobble/example/ShapesTests.java b/examples/10-custom-code/output/java/src/test/java/org/zwobble/example/ShapesTests.java
index fba8e6c..fba8e6c 100644
--- a/examples/09-custom-code/output/java/src/test/java/org/zwobble/example/ShapesTests.java
+++ b/examples/10-custom-code/output/java/src/test/java/org/zwobble/example/ShapesTests.java
diff --git a/examples/10-imports/output/rust/.gitignore b/examples/10-custom-code/output/rust/.gitignore
index ea8c4bf..ea8c4bf 100644
--- a/examples/10-imports/output/rust/.gitignore
+++ b/examples/10-custom-code/output/rust/.gitignore
diff --git a/examples/10-imports/output/rust/Cargo.lock b/examples/10-custom-code/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/10-imports/output/rust/Cargo.lock
+++ b/examples/10-custom-code/output/rust/Cargo.lock
diff --git a/examples/10-imports/output/rust/Cargo.toml b/examples/10-custom-code/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/10-imports/output/rust/Cargo.toml
+++ b/examples/10-custom-code/output/rust/Cargo.toml
diff --git a/examples/10-imports/output/rust/rust-toolchain.toml b/examples/10-custom-code/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/10-imports/output/rust/rust-toolchain.toml
+++ b/examples/10-custom-code/output/rust/rust-toolchain.toml
diff --git a/examples/09-custom-code/output/rust/src/gen/shapes.rs b/examples/10-custom-code/output/rust/src/gen/shapes.rs
index 815db2a..815db2a 100644
--- a/examples/09-custom-code/output/rust/src/gen/shapes.rs
+++ b/examples/10-custom-code/output/rust/src/gen/shapes.rs
diff --git a/examples/09-custom-code/output/rust/src/lib.rs b/examples/10-custom-code/output/rust/src/lib.rs
index 1825d72..1825d72 100644
--- a/examples/09-custom-code/output/rust/src/lib.rs
+++ b/examples/10-custom-code/output/rust/src/lib.rs
diff --git a/examples/09-custom-code/output/rust/src/shapes.rs b/examples/10-custom-code/output/rust/src/shapes.rs
index f806bbb..f806bbb 100644
--- a/examples/09-custom-code/output/rust/src/shapes.rs
+++ b/examples/10-custom-code/output/rust/src/shapes.rs
diff --git a/examples/09-custom-code/src/shapes.hob b/examples/10-custom-code/src/shapes.hob
index 5dfe833..5dfe833 100644
--- a/examples/09-custom-code/src/shapes.hob
+++ b/examples/10-custom-code/src/shapes.hob
diff --git a/examples/10-imports/hobgoblin.json5 b/examples/11-imports/hobgoblin.json5
index 12713d4..12713d4 100644
--- a/examples/10-imports/hobgoblin.json5
+++ b/examples/11-imports/hobgoblin.json5
diff --git a/examples/11-imports/output/java/.gitignore b/examples/11-imports/output/java/.gitignore
new file mode 100644
index 0000000..ff511d4
--- /dev/null
+++ b/examples/11-imports/output/java/.gitignore
@@ -0,0 +1,2 @@
+/src/gen/
+/target/
diff --git a/examples/11-transient-0/output/java/pom.xml b/examples/11-imports/output/java/pom.xml
index 445fa65..445fa65 120000
--- a/examples/11-transient-0/output/java/pom.xml
+++ b/examples/11-imports/output/java/pom.xml
diff --git a/examples/10-imports/output/java/src/test/java/org/zwobble/example/LineTests.java b/examples/11-imports/output/java/src/test/java/org/zwobble/example/LineTests.java
index c376b19..c376b19 100644
--- a/examples/10-imports/output/java/src/test/java/org/zwobble/example/LineTests.java
+++ b/examples/11-imports/output/java/src/test/java/org/zwobble/example/LineTests.java
diff --git a/examples/11-imports/output/rust/.gitignore b/examples/11-imports/output/rust/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/examples/11-imports/output/rust/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/examples/11-transient-0/output/rust/Cargo.lock b/examples/11-imports/output/rust/Cargo.lock
index 9dc6e3e..9dc6e3e 100644
--- a/examples/11-transient-0/output/rust/Cargo.lock
+++ b/examples/11-imports/output/rust/Cargo.lock
diff --git a/examples/11-transient-0/output/rust/Cargo.toml b/examples/11-imports/output/rust/Cargo.toml
index 5d4c622..5d4c622 100644
--- a/examples/11-transient-0/output/rust/Cargo.toml
+++ b/examples/11-imports/output/rust/Cargo.toml
diff --git a/examples/11-transient-0/output/rust/rust-toolchain.toml b/examples/11-imports/output/rust/rust-toolchain.toml
index 4fedb95..4fedb95 100644
--- a/examples/11-transient-0/output/rust/rust-toolchain.toml
+++ b/examples/11-imports/output/rust/rust-toolchain.toml
diff --git a/examples/10-imports/output/rust/src/lib.rs b/examples/11-imports/output/rust/src/lib.rs
index ffbcbf4..ffbcbf4 100644
--- a/examples/10-imports/output/rust/src/lib.rs
+++ b/examples/11-imports/output/rust/src/lib.rs
diff --git a/examples/10-imports/output/rust/src/line.rs b/examples/11-imports/output/rust/src/line.rs
index d383b15..d383b15 100644
--- a/examples/10-imports/output/rust/src/line.rs
+++ b/examples/11-imports/output/rust/src/line.rs
diff --git a/examples/10-imports/output/rust/src/point.rs b/examples/11-imports/output/rust/src/point.rs
index 943331f..943331f 100644
--- a/examples/10-imports/output/rust/src/point.rs
+++ b/examples/11-imports/output/rust/src/point.rs
diff --git a/examples/10-imports/src/line.hob b/examples/11-imports/src/line.hob
index 562d77f..562d77f 100644
--- a/examples/10-imports/src/line.hob
+++ b/examples/11-imports/src/line.hob
diff --git a/examples/10-imports/src/point.hob b/examples/11-imports/src/point.hob
index 87f9953..87f9953 100644
--- a/examples/10-imports/src/point.hob
+++ b/examples/11-imports/src/point.hob
diff --git a/examples/11-transient-0/hobgoblin.json5 b/examples/12-transient-0/hobgoblin.json5
index 2160c60..2160c60 100644
--- a/examples/11-transient-0/hobgoblin.json5
+++ b/examples/12-transient-0/hobgoblin.json5
diff --git a/examples/11-transient-0/output/java/.gitignore b/examples/12-transient-0/output/java/.gitignore
index 2fcf0b8..2fcf0b8 100644
--- a/examples/11-transient-0/output/java/.gitignore
+++ b/examples/12-transient-0/output/java/.gitignore
diff --git a/examples/12-transient-0/output/java/pom.xml b/examples/12-transient-0/output/java/pom.xml
new file mode 120000
index 0000000..445fa65
--- /dev/null
+++ b/examples/12-transient-0/output/java/pom.xml
@@ -0,0 +1 @@
+../../../templates/java-junit/pom.xml \ No newline at end of file
diff --git a/examples/11-transient-0/output/java/src/test/java/org/zwobble/example/Transient0Tests.java b/examples/12-transient-0/output/java/src/test/java/org/zwobble/example/Transient0Tests.java
index a924d1e..a924d1e 100644
--- a/examples/11-transient-0/output/java/src/test/java/org/zwobble/example/Transient0Tests.java
+++ b/examples/12-transient-0/output/java/src/test/java/org/zwobble/example/Transient0Tests.java
diff --git a/examples/11-transient-0/output/rust/.gitignore b/examples/12-transient-0/output/rust/.gitignore
index fc03479..fc03479 100644
--- a/examples/11-transient-0/output/rust/.gitignore
+++ b/examples/12-transient-0/output/rust/.gitignore
diff --git a/examples/12-transient-0/output/rust/Cargo.lock b/examples/12-transient-0/output/rust/Cargo.lock
new file mode 100644
index 0000000..9dc6e3e
--- /dev/null
+++ b/examples/12-transient-0/output/rust/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "example"
+version = "0.1.0"
diff --git a/examples/12-transient-0/output/rust/Cargo.toml b/examples/12-transient-0/output/rust/Cargo.toml
new file mode 100644
index 0000000..5d4c622
--- /dev/null
+++ b/examples/12-transient-0/output/rust/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "example"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
diff --git a/examples/12-transient-0/output/rust/rust-toolchain.toml b/examples/12-transient-0/output/rust/rust-toolchain.toml
new file mode 100644
index 0000000..4fedb95
--- /dev/null
+++ b/examples/12-transient-0/output/rust/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "1.96"
diff --git a/examples/11-transient-0/output/rust/src/data.rs b/examples/12-transient-0/output/rust/src/data.rs
index 7a0c4fa..7a0c4fa 100644
--- a/examples/11-transient-0/output/rust/src/data.rs
+++ b/examples/12-transient-0/output/rust/src/data.rs
diff --git a/examples/11-transient-0/output/rust/src/gen/data.rs b/examples/12-transient-0/output/rust/src/gen/data.rs
index 4ec0524..4ec0524 100644
--- a/examples/11-transient-0/output/rust/src/gen/data.rs
+++ b/examples/12-transient-0/output/rust/src/gen/data.rs
diff --git a/examples/11-transient-0/output/rust/src/gen/data/transient_0.rs b/examples/12-transient-0/output/rust/src/gen/data/transient_0.rs
index ea4a459..ea4a459 100644
--- a/examples/11-transient-0/output/rust/src/gen/data/transient_0.rs
+++ b/examples/12-transient-0/output/rust/src/gen/data/transient_0.rs
diff --git a/examples/11-transient-0/output/rust/src/gen/transient_0.rs b/examples/12-transient-0/output/rust/src/gen/transient_0.rs
index d88284e..d88284e 100644
--- a/examples/11-transient-0/output/rust/src/gen/transient_0.rs
+++ b/examples/12-transient-0/output/rust/src/gen/transient_0.rs
diff --git a/examples/11-transient-0/output/rust/src/lib.rs b/examples/12-transient-0/output/rust/src/lib.rs
index 3a02936..3a02936 100644
--- a/examples/11-transient-0/output/rust/src/lib.rs
+++ b/examples/12-transient-0/output/rust/src/lib.rs
diff --git a/examples/11-transient-0/output/rust/src/transient_0.rs b/examples/12-transient-0/output/rust/src/transient_0.rs
index 8b2b800..8b2b800 100644
--- a/examples/11-transient-0/output/rust/src/transient_0.rs
+++ b/examples/12-transient-0/output/rust/src/transient_0.rs
diff --git a/examples/11-transient-0/src/data.hob b/examples/12-transient-0/src/data.hob
index 9c715e9..9c715e9 100644
--- a/examples/11-transient-0/src/data.hob
+++ b/examples/12-transient-0/src/data.hob
diff --git a/hobgoblin/src/ast/untyped.hob b/hobgoblin/src/ast/untyped.hob
index 94f7c29..4c70d5e 100644
--- a/hobgoblin/src/ast/untyped.hob
+++ b/hobgoblin/src/ast/untyped.hob
@@ -46,7 +46,7 @@ struct UntypedNativeTypeDefinitionNode {
struct UntypedStructDefinitionNode {
field name: String;
- field fields: List[UntypedStructFieldDefinitionNode];
+ field fields: Option[List[UntypedStructFieldDefinitionNode]];
field docComment: DocComment;
field source: Source;
}
diff --git a/makefile b/makefile
index 589f61d..df051f9 100644
--- a/makefile
+++ b/makefile
@@ -11,4 +11,4 @@ codegen: package
.PHONY: codegen-only
codegen-only:
- java -jar target/hobgoblin-0.1.0.jar compile hobgoblin
+ hobgoblin compile hobgoblin
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java
index dc9a8fe..f2e6b97 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java
@@ -5,10 +5,11 @@ import org.zwobble.hobgoblin.compiler.sources.Source;
import org.zwobble.hobgoblin.compiler.types.StructType;
import java.util.List;
+import java.util.Optional;
public record TypedStructDefinitionNode(
StructType type,
- List<TypedStructFieldDefinitionNode> fields,
+ Optional<List<TypedStructFieldDefinitionNode>> fields,
DocComment docComment,
Source source
) implements TypedNamespaceStatementNode {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java
index 72f45eb..0239ff8 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java
@@ -7,17 +7,17 @@ package org.zwobble.hobgoblin.compiler.ast.untyped;
public record UntypedStructDefinitionNode(
String name,
- java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields,
+ java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields,
org.zwobble.hobgoblin.compiler.ast.DocComment docComment,
org.zwobble.hobgoblin.compiler.sources.Source source
) implements org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode {
public static org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder arbitrary() {
- return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder("", java.util.List.of(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource());
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder("", java.util.Optional.empty(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource());
}
public record Builder(
String name,
- java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields,
+ java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields,
org.zwobble.hobgoblin.compiler.ast.DocComment docComment,
org.zwobble.hobgoblin.compiler.sources.Source source
) implements org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode.Builder {
@@ -29,20 +29,12 @@ public record UntypedStructDefinitionNode(
return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source);
}
- public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withFields(java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields) {
- return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source);
- }
-
- public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder addField(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode field) {
- var fields = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>(this.fields);
- fields.add(field);
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withFields(java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields) {
return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source);
}
- public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder addField(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode.Builder field) {
- var fields = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>(this.fields);
- fields.add(field.build());
- return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source);
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withFields(java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, java.util.Optional.of(fields), docComment, source);
}
public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withDocComment(org.zwobble.hobgoblin.compiler.ast.DocComment docComment) {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java
index d7f4bb0..35bb931 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java
@@ -15,6 +15,8 @@ import java.util.Set;
import java.util.stream.Collectors;
public class JavaGenerator {
+ public static final JavaIdentifier INSTANCE_FIELD_NAME = JavaIdentifier.of("INSTANCE");
+
private final JavaGeneratorConfig config;
public JavaGenerator(JavaGeneratorConfig config) {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java
index 72f6339..1069f4a 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java
@@ -195,7 +195,7 @@ public class JavaPreciselyMatchersGenerator implements Generator {
)
));
- for (var field : structDefinition.fields()) {
+ for (var field : structDefinition.fields().orElse(List.of())) {
var fieldType = field.type().value();
var javaFieldTypeRef = this.javaGenerator.generateReferenceTypeRef(fieldType);
var javaFieldName = this.javaGenerator.generateFieldName(field.name());
@@ -258,10 +258,6 @@ public class JavaPreciselyMatchersGenerator implements Generator {
this.typesInfo = typesInfo;
}
- public List<Field> fieldsOf(StructType type) {
- return this.typesInfo.fieldsOf(type);
- }
-
public List<SumType> variantOf(StructType type) {
return this.typesInfo.variantOf(type);
}
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 d8a0f5f..1c7c962 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
@@ -492,7 +492,7 @@ public class JavaTransient0Generator implements Generator {
return generateEncodeMethod(
structDefinition.type(),
new JavaBlock(
- structDefinition.fields().stream()
+ structDefinition.fields().orElse(List.of()).stream()
.flatMap(field -> generateEncode(
new JavaMethodCall(
new JavaRef(VALUE_NAME),
@@ -512,19 +512,23 @@ public class JavaTransient0Generator implements Generator {
return generateDecodeMethod(
structDefinition.type(),
new JavaBlock(
- Stream.concat(
- structDefinition.fields().stream()
- .flatMap(field -> generateDecode(
- this.javaGenerator.generateFieldName(field.name()),
- field.type().value()
- ).stream()),
- Stream.of(new JavaReturn(new JavaNewExpression(
- structJavaTypeRef,
- structDefinition.fields().stream()
- .<JavaExpression>map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name())))
- .toList()
- )))
- ).toList()
+ structDefinition.fields().isEmpty()
+ ? List.of(new JavaReturn(
+ new JavaStaticFieldAccess(structJavaTypeRef, JavaGenerator.INSTANCE_FIELD_NAME)
+ ))
+ : Stream.concat(
+ structDefinition.fields().get().stream()
+ .flatMap(field -> generateDecode(
+ this.javaGenerator.generateFieldName(field.name()),
+ field.type().value()
+ ).stream()),
+ Stream.of(new JavaReturn(new JavaNewExpression(
+ structJavaTypeRef,
+ structDefinition.fields().get().stream()
+ .<JavaExpression>map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name())))
+ .toList()
+ )))
+ ).toList()
)
);
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java
index 62c73ff..e8ecaa7 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java
@@ -122,7 +122,7 @@ public class JavaTypesGenerator implements Generator {
TypedStructDefinitionNode structDefinition,
Context context
) {
- var components = structDefinition.fields().stream()
+ var components = structDefinition.fields().orElse(List.of()).stream()
.map(field -> new JavaRecordComponent(
generateTypeRef(field.type(), context),
generateFieldName(field.name())
@@ -135,31 +135,51 @@ public class JavaTypesGenerator implements Generator {
var builderJavaTypeRef = generateBuilderTypeRef(structDefinition.type());
- var arbitraryComponentValues = structDefinition.fields().stream()
- .map(field -> arbitraryValue(field.type(), context))
- .toList();
+ var arbitraryValueExpression = new JavaNewExpression(
+ builderJavaTypeRef,
+ structDefinition.fields().orElse(List.of()).stream()
+ .map(field -> arbitraryValue(field.type(), context))
+ .toList()
+ );
+
+ var body = new ArrayList<JavaClassBodyDeclaration>();
+
+ if (structDefinition.fields().isEmpty()) {
+ body.add(new JavaFieldDeclaration(
+ JavaVisibility.PUBLIC,
+ JavaMemberKind.STATIC,
+ this.generateTypeRef(structDefinition.type(), context),
+ JavaGenerator.INSTANCE_FIELD_NAME,
+ Optional.of(new JavaNewExpression(
+ generateTypeRef(structDefinition.type(), context),
+ List.of()
+ ))
+ ));
+ }
+
+ body.add(new JavaMethodDeclaration(
+ ARBITRARY_METHOD_NAME,
+ JavaVisibility.PUBLIC,
+ JavaMemberKind.STATIC,
+ builderJavaTypeRef,
+ List.of(),
+ List.of(),
+ new JavaBlock(List.of(
+ new JavaReturn(arbitraryValueExpression)
+ ))
+ ));
+
+ body.add(generateStructDefinitionBuilder(
+ structDefinition,
+ components,
+ context
+ ));
return new JavaRecordDeclaration(
generateTypeRef(structDefinition.type(), context),
components,
implementsTypes,
- List.of(
- new JavaMethodDeclaration(
- ARBITRARY_METHOD_NAME,
- JavaVisibility.PUBLIC,
- JavaMemberKind.STATIC,
- builderJavaTypeRef,
- List.of(),
- List.of(),
- new JavaBlock(List.of(
- new JavaReturn(new JavaNewExpression(
- builderJavaTypeRef,
- arbitraryComponentValues
- ))
- ))
- ),
- generateStructDefinitionBuilder(structDefinition, components, context)
- ),
+ body,
structDefinition.docComment()
);
}
@@ -169,9 +189,11 @@ public class JavaTypesGenerator implements Generator {
List<JavaRecordComponent> components,
Context context
) {
- var builderJavaTypeRef = generateBuilderTypeRef(structDefinition.type());
+ var structType = structDefinition.type();
- var implementsTypes = context.variantOf(structDefinition.type()).stream()
+ var builderJavaTypeRef = generateBuilderTypeRef(structType);
+
+ var implementsTypes = context.variantOf(structType).stream()
.map(sumType -> this.generateBuilderTypeRef(sumType))
.toList();
@@ -180,18 +202,22 @@ public class JavaTypesGenerator implements Generator {
BUILD_METHOD_NAME,
JavaVisibility.PUBLIC,
JavaMemberKind.INSTANCE,
- generateTypeRef(structDefinition.type(), context),
+ generateTypeRef(structType, context),
List.of(),
List.of(),
new JavaBlock(List.of(
- new JavaReturn(new JavaNewExpression(
- generateTypeRef(structDefinition.type(), context),
- components.stream().<JavaExpression>map(component -> new JavaRef(component.name())).toList()
- ))
+ new JavaReturn(
+ structDefinition.fields().isPresent()
+ ? new JavaNewExpression(
+ generateTypeRef(structType, context),
+ components.stream().<JavaExpression>map(component -> new JavaRef(component.name())).toList()
+ )
+ : new JavaStaticFieldAccess(this.generateTypeRef(structType, context), JavaGenerator.INSTANCE_FIELD_NAME)
+ )
))
));
- for (var field : structDefinition.fields()) {
+ for (var field : structDefinition.fields().orElse(List.of())) {
body.addAll(generateBuilderMethodsForField(field, components, builderJavaTypeRef, context));
}
@@ -585,9 +611,9 @@ public class JavaTypesGenerator implements Generator {
case StructType structType -> {
var newSeenTypes = new HashSet<>(seenTypes);
newSeenTypes.add(type);
- var result = context.fieldsOf(structType).stream()
+ var fields = context.fieldsOf(structType);
+ yield fields.orElse(List.of()).stream()
.allMatch(field -> isNonRecursivelyConstructable(field.type(), newSeenTypes, context));
- yield result;
}
case SumType sumType -> {
@@ -633,7 +659,7 @@ public class JavaTypesGenerator implements Generator {
return this.typesInfo.enumVariants(type);
}
- public List<Field> fieldsOf(StructType type) {
+ public Optional<List<Field>> fieldsOf(StructType type) {
return this.typesInfo.fieldsOf(type);
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
index 15e9e9d..1401b83 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
@@ -386,7 +386,7 @@ public class RustTransient0Generator implements Generator {
private RustItem generateEncodeStructFunction(TypedStructDefinitionNode structDefinition) {
return generateEncodeFunction(
structDefinition.type(),
- structDefinition.fields().stream()
+ structDefinition.fields().orElse(List.of()).stream()
.map(field -> generateEncode(
new RustPrefixExpression(
RustPrefixOperator.BORROW,
@@ -406,24 +406,26 @@ public class RustTransient0Generator implements Generator {
return generateDecodeFunction(
structDefinition.type(),
- new RustBlockExpression(
- structDefinition.fields().stream()
- .<RustStatement>map(field -> new RustLetStatement(
- this.rustGenerator.generateFieldName(field.name()),
- false,
- generateDecode(field.type().value())
- ))
- .toList(),
- Optional.of(new RustStructExpression(
- rustType,
- structDefinition.fields().stream()
- .map(field -> new RustStructExprField(
+ structDefinition.fields().isEmpty()
+ ? new RustBlockExpression(List.of(), Optional.of(rustType))
+ : new RustBlockExpression(
+ structDefinition.fields().get().stream()
+ .<RustStatement>map(field -> new RustLetStatement(
this.rustGenerator.generateFieldName(field.name()),
- RustPath.of(this.rustGenerator.generateFieldName(field.name()))
+ false,
+ generateDecode(field.type().value())
))
- .toList()
- ))
- )
+ .toList(),
+ Optional.of(new RustStructExpression(
+ rustType,
+ structDefinition.fields().get().stream()
+ .map(field -> new RustStructExprField(
+ this.rustGenerator.generateFieldName(field.name()),
+ RustPath.of(this.rustGenerator.generateFieldName(field.name()))
+ ))
+ .toList()
+ ))
+ )
);
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java
index 99b4208..8ed9d9e 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java
@@ -127,7 +127,7 @@ public class RustTypesGenerator implements Generator {
var rustStructName = this.rustGenerator.generateTypeName(structDefinition.name());
- var rustFields = structDefinition.fields().stream()
+ var rustFields = structDefinition.fields().orElse(List.of()).stream()
.map(field -> new RustStructField(
this.rustGenerator.generateFieldName(field.name()),
generateRustTypeExpression(field.type(), context)
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
index 47a8095..e312f30 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
@@ -210,11 +210,7 @@ public class Parser {
var name = tokens.next(TokenType.IDENTIFIER);
tokens.skip(TokenType.SYMBOL_BRACE_OPEN);
- var fields = parseMany(
- () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE),
- () -> parseStructFieldDefinition(tokens),
- () -> true
- );
+ var fields = parseStructDefinitionFields(tokens);
tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
@@ -229,6 +225,21 @@ public class Parser {
);
}
+ private static Optional<List<UntypedStructFieldDefinitionNode>> parseStructDefinitionFields(TokenIterator tokens) {
+ var isSingleton = tokens.trySkip(TokenType.IDENTIFIER, "singleton");
+ if (isSingleton) {
+ tokens.skip(TokenType.SYMBOL_SEMICOLON);
+ return Optional.empty();
+ } else {
+ var fields = parseMany(
+ () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE),
+ () -> parseStructFieldDefinition(tokens),
+ () -> true
+ );
+ return Optional.of(fields);
+ }
+ }
+
private static UntypedStructFieldDefinitionNode parseStructFieldDefinition(
TokenIterator tokens
) {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java
index 55edd97..43705a1 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java
@@ -54,6 +54,16 @@ class TokenIterator {
}
}
+ public boolean trySkip(TokenType tokenType, String value) {
+ var token = peek();
+ if (token.tokenType().equals(tokenType) && value.contentEquals(token.charSequence())) {
+ this.tokenIndex++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
private Token getAbsolute(int index) {
if (index < this.tokens.size()) {
return this.tokens.get(index);
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
index d55c490..f03f979 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
@@ -8,6 +8,7 @@ import org.zwobble.hobgoblin.compiler.types.*;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import static org.zwobble.hobgoblin.compiler.typechecker.NamespaceNameResolution.resolveNamespaceName;
import static org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerSubtyping.isSubtype;
@@ -180,9 +181,13 @@ public class TypeChecker {
) {
var structType = (StructType) lookupMetaType(untyped.name(), untyped.source(), context);
- var typeCheckedFieldDefinitions = typeCheckFieldDefinitions(untyped.fields(), context);
+ var typeCheckedFieldDefinitions = untyped.fields().isPresent()
+ ? Optional.of(typeCheckFieldDefinitions(untyped.fields().get(), context))
+ : Optional.<TypeCheckFieldDefinitionsResult>empty();
+ var typedFields = typeCheckedFieldDefinitions.map(TypeCheckFieldDefinitionsResult::fields);
+ var typedFieldNodes = typeCheckedFieldDefinitions.map(TypeCheckFieldDefinitionsResult::typedFieldNodes);
- context.defineStructType(structType, typeCheckedFieldDefinitions.fields());
+ context.defineStructType(structType, typedFields);
for (var sumType : context.variantOf(structType)) {
var sumTypeFields = context.fieldsOf(sumType);
@@ -190,14 +195,14 @@ public class TypeChecker {
sumType,
sumTypeFields,
structType,
- typeCheckedFieldDefinitions.fields,
+ typedFields,
context.toTypesInfo()
);
}
return new TypedStructDefinitionNode(
structType,
- typeCheckedFieldDefinitions.typedFieldNodes(),
+ typedFieldNodes,
untyped.docComment(),
untyped.source()
);
@@ -303,13 +308,15 @@ public class TypeChecker {
SumType sumType,
List<Field> sumTypeFields,
StructType variantType,
- List<Field> variantTypeFields,
+ Optional<List<Field>> variantTypeFields,
TypesInfo typesInfo
) {
for (var sumTypeField : sumTypeFields) {
- var variantTypeField = variantTypeFields.stream()
- .filter(field -> field.name().equals(sumTypeField.name()))
- .findFirst();
+ var variantTypeField = variantTypeFields.flatMap(
+ fields -> fields.stream()
+ .filter(field -> field.name().equals(sumTypeField.name()))
+ .findFirst()
+ );
if (variantTypeField.isEmpty()) {
throw new SubtypeIsMissingFieldError(sumType, variantType, sumTypeField.name(), sumTypeField.source());
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java
index 0a61de7..5484904 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java
@@ -61,7 +61,7 @@ public class TypeCheckerNamespaceContext {
this.typesInfo.defineEnumType(enumType, enumVariants);
}
- public void defineStructType(StructType structType, List<Field> fields) {
+ public void defineStructType(StructType structType, Optional<List<Field>> fields) {
this.typesInfo.defineStructType(structType, fields);
}
@@ -69,7 +69,7 @@ public class TypeCheckerNamespaceContext {
return this.typesInfo.isDefined(type);
}
- public List<Field> fieldsOf(StructType type) {
+ public Optional<List<Field>> fieldsOf(StructType type) {
return this.typesInfo.fieldsOf(type);
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java
index 814466c..697be9b 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java
@@ -3,12 +3,13 @@ package org.zwobble.hobgoblin.compiler.typechecker;
import org.zwobble.hobgoblin.compiler.types.*;
import java.util.List;
+import java.util.Optional;
public interface TypesInfo {
TypesInfo EMPTY = TypesInfoInMemory.empty();
boolean isDefined(StructType type);
- List<Field> fieldsOf(StructType structType);
+ Optional<List<Field>> fieldsOf(StructType structType);
List<SumType> variantOf(StructType variantType);
List<Type> sumVariants(SumType type);
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java
index d9c0c85..821238b 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java
@@ -6,27 +6,32 @@ import org.zwobble.hobgoblin.compiler.util.ManyToMany;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
public class TypesInfoInMemory implements TypesInfo {
public static TypesInfoInMemory empty() {
return new TypesInfoInMemory(
new HashMap<>(),
new HashMap<>(),
+ new HashMap<>(),
new ManyToMany<>()
);
}
private final Map<EnumType, List<EnumVariant>> enumVariants;
- private final Map<Type, List<Field>> fieldsOf;
+ private final Map<Type, Optional<List<Field>>> structFields;
+ private final Map<Type, List<Field>> sumFields;
private final ManyToMany<SumType, Type> sumVariants;
public TypesInfoInMemory(
Map<EnumType, List<EnumVariant>> enumVariants,
- Map<Type, List<Field>> fieldsOf,
+ Map<Type, Optional<List<Field>>> structFields,
+ Map<Type, List<Field>> sumFields,
ManyToMany<SumType, Type> sumVariants
) {
this.enumVariants = enumVariants;
- this.fieldsOf = fieldsOf;
+ this.structFields = structFields;
+ this.sumFields = sumFields;
this.sumVariants = sumVariants;
}
@@ -38,19 +43,21 @@ public class TypesInfoInMemory implements TypesInfo {
return this.enumVariants.get(enumType);
}
- public void defineStructType(StructType structType, List<Field> fields) {
- this.fieldsOf.put(structType, fields);
+ public void defineStructType(StructType structType, Optional<List<Field>> fields) {
+ this.structFields.put(structType, fields);
}
@Override
public boolean isDefined(StructType type) {
- return this.fieldsOf.containsKey(type);
+ return this.structFields.containsKey(type);
}
- public List<Field> fieldsOf(StructType structType) {
- var fields = this.fieldsOf.get(structType);
+ @Override
+ public Optional<List<Field>> fieldsOf(StructType structType) {
+ var fields = this.structFields.get(structType);
if (fields == null) {
- return List.of();
+ // TODO: better error
+ throw new RuntimeException("struct not defined");
} else {
return fields;
}
@@ -64,7 +71,7 @@ public class TypesInfoInMemory implements TypesInfo {
for (var variantType : variantTypes) {
this.sumVariants.add(sumType, variantType);
}
- this.fieldsOf.put(sumType, fields);
+ this.sumFields.put(sumType, fields);
}
public List<SumType> variantOf(StructType variantType) {
@@ -76,7 +83,7 @@ public class TypesInfoInMemory implements TypesInfo {
}
public List<Field> fieldsOf(SumType sumType) {
- var fields = this.fieldsOf.get(sumType);
+ var fields = this.sumFields.get(sumType);
if (fields == null) {
return List.of();
} else {
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNodeMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNodeMatcher.java
index 429e438..dd66994 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNodeMatcher.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNodeMatcher.java
@@ -36,7 +36,7 @@ public class UntypedStructDefinitionNodeMatcher implements org.zwobble.precisely
return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNodeMatcher(submatchers);
}
- public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNodeMatcher withFields(org.zwobble.precisely.Matcher<? super java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields) {
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNodeMatcher withFields(org.zwobble.precisely.Matcher<? super java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>>> fields) {
var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode>>(this.submatchers);
submatchers.add(org.zwobble.precisely.Matchers.has("fields", org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode::fields, fields));
return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNodeMatcher(submatchers);
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java
index 6c90356..0b8ba5e 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java
@@ -24,7 +24,8 @@ public class ParserStructDefinitionTests {
assertThat(node, instanceOf(
UntypedStructDefinitionNode.class,
- has("name", UntypedStructDefinitionNode::name, equalTo("Point"))
+ has("name", UntypedStructDefinitionNode::name, equalTo("Point")),
+ has("fields", UntypedStructDefinitionNode::fields, isOptionalOf(isSequence()))
));
}
@@ -43,7 +44,7 @@ public class ParserStructDefinitionTests {
assertThat(node, instanceOf(
UntypedStructDefinitionNode.class,
- has("fields", UntypedStructDefinitionNode::fields, isSequence(
+ has("fields", UntypedStructDefinitionNode::fields, isOptionalOf(isSequence(
instanceOf(
UntypedStructFieldDefinitionNode.class,
has("name", UntypedStructFieldDefinitionNode::name, equalTo("x")),
@@ -68,7 +69,25 @@ public class ParserStructDefinitionTests {
)
)
)
- ))
+ )))
+ ));
+ }
+
+ @Test
+ public void singletonStruct() {
+ var source = """
+ struct Point {
+ singleton;
+ }""";
+
+ var node = parseString(
+ source,
+ Parser::parseNamespaceStatement
+ );
+
+ assertThat(node, instanceOf(
+ UntypedStructDefinitionNode.class,
+ has("fields", UntypedStructDefinitionNode::fields, isOptionalEmpty())
));
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java
index 2f7cc6b..b5814a8 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java
@@ -100,9 +100,9 @@ public class TypeCheckerNamespaceTests {
));
assertThat(
context.toTypesInfo().fieldsOf(new StructType(NamespaceName.of("a", "b"), "X")),
- isSequence(
+ isOptionalOf(isSequence(
isField("y", new SimpleNativeType(NamespaceName.of("a", "c"), "Y"))
- )
+ ))
);
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
index 0efe3b4..d86fd59 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
@@ -14,6 +14,7 @@ import org.zwobble.hobgoblin.compiler.types.SimpleNativeType;
import org.zwobble.hobgoblin.compiler.types.StructType;
import java.util.List;
+import java.util.Optional;
import static org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerTesting.typeCheckNamespaceStatement;
import static org.zwobble.hobgoblin.compiler.types.TypeMatchers.isField;
@@ -64,7 +65,7 @@ public class TypeCheckerStructDefinitionTests {
has(
"fields",
TypedStructDefinitionNode::fields,
- isSequence(
+ isOptionalOf(isSequence(
allOf(
has("name", TypedStructFieldDefinitionNode::name, equalTo("a")),
has("type", TypedStructFieldDefinitionNode::type, has(
@@ -81,16 +82,47 @@ public class TypeCheckerStructDefinitionTests {
equalTo(int64Type)
))
)
- )
+ ))
)
));
var typesInfo = globalContext.toTypesInfo();
assertThat(
typesInfo.fieldsOf(new StructType(namespaceName, "X")),
- isSequence(
+ isOptionalOf(isSequence(
isField("a", int32Type),
isField("b", int64Type)
+ ))
+ );
+ }
+
+ @Test
+ public void singletonStructHasNoFields() {
+ var int32Type = SimpleNativeType.builtin("Int32");
+ var int64Type = SimpleNativeType.builtin("Int64");
+ var untyped = UntypedStructDefinitionNode.arbitrary()
+ .withName("X")
+ .withFields(Optional.empty())
+ .build();
+ var globalContext = TypeCheckerGlobalContext.initial();
+ globalContext.addNativeType(int32Type);
+ globalContext.addNativeType(int64Type);
+ var namespaceName = NamespaceName.of("a", "b");
+ var namespaceContext = globalContext.enterNamespace(namespaceName);
+
+ var typed = typeCheckNamespaceStatement(untyped, namespaceContext);
+
+ assertThat(typed, instanceOf(
+ TypedStructDefinitionNode.class,
+ has(
+ "fields",
+ TypedStructDefinitionNode::fields,
+ isOptionalEmpty()
)
+ ));
+ var typesInfo = globalContext.toTypesInfo();
+ assertThat(
+ typesInfo.fieldsOf(new StructType(namespaceName, "X")),
+ isOptionalEmpty()
);
}
@@ -130,7 +162,7 @@ public class TypeCheckerStructDefinitionTests {
has(
"fields",
TypedStructDefinitionNode::fields,
- isSequence(
+ isOptionalOf(isSequence(
allOf(
has("name", TypedStructFieldDefinitionNode::name, equalTo("value")),
has("type", TypedStructFieldDefinitionNode::type, has(
@@ -139,7 +171,7 @@ public class TypeCheckerStructDefinitionTests {
equalTo(new StructType(namespaceName, "Y"))
))
)
- )
+ ))
)
),
instanceOf(
@@ -148,7 +180,7 @@ public class TypeCheckerStructDefinitionTests {
has(
"fields",
TypedStructDefinitionNode::fields,
- isSequence(
+ isOptionalOf(isSequence(
allOf(
has("name", TypedStructFieldDefinitionNode::name, equalTo("value")),
has("type", TypedStructFieldDefinitionNode::type, has(
@@ -157,7 +189,7 @@ public class TypeCheckerStructDefinitionTests {
equalTo(int32Type)
))
)
- )
+ ))
)
)
)
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSumDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSumDefinitionTests.java
index bfc9280..68b1b06 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSumDefinitionTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerSumDefinitionTests.java
@@ -12,6 +12,7 @@ import org.zwobble.hobgoblin.compiler.typechecker.errors.UnexpectedTypeError;
import org.zwobble.hobgoblin.compiler.types.*;
import java.util.List;
+import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerTesting.typeCheckNamespaceStatement;
@@ -159,7 +160,7 @@ public class TypeCheckerSumDefinitionTests {
.enterNamespace(namespaceName);
var variantType = new StructType(namespaceName, "Square");
namespaceContext.declare("Square", new TypeLevelValueType(variantType), NullSource.INSTANCE);
- namespaceContext.defineStructType(variantType, List.of());
+ namespaceContext.defineStructType(variantType, Optional.of(List.of()));
var error = assertThrows(
SubtypeIsMissingFieldError.class,
@@ -196,7 +197,7 @@ public class TypeCheckerSumDefinitionTests {
.enterNamespace(namespaceName);
var variantType = new StructType(namespaceName, "Square");
namespaceContext.declare("Square", new TypeLevelValueType(variantType), NullSource.INSTANCE);
- namespaceContext.defineStructType(variantType, List.of(new Field("area", int64Type, NullSource.INSTANCE)));
+ namespaceContext.defineStructType(variantType, Optional.of(List.of(new Field("area", int64Type, NullSource.INSTANCE))));
// TODO: more specific error
var error = assertThrows(
@@ -232,7 +233,7 @@ public class TypeCheckerSumDefinitionTests {
.enterNamespace(namespaceName);
var variantType = new StructType(namespaceName, "Square");
namespaceContext.declare("Square", new TypeLevelValueType(variantType), NullSource.INSTANCE);
- namespaceContext.defineStructType(variantType, List.of());
+ namespaceContext.defineStructType(variantType, Optional.of(List.of()));
assertThrows(
SubtypeIsMissingFieldError.class,