summaryrefslogtreecommitdiff
path: root/src/test/java/org/zwobble
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-04-26 21:31:44 +0100
committerMichael Williamson <mike@zwobble.org>2026-04-26 21:31:44 +0100
commit92708742a18a1a3de5eb59a2e7c12788aa199d9a (patch)
treec50d46c56b5a80df00046f3cad244794056f05eb /src/test/java/org/zwobble
parent9f6c9b42073373b18c8a92a9428f35986effc77b (diff)
Declare types ahead of defining them
Diffstat (limited to 'src/test/java/org/zwobble')
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java80
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTesting.java17
2 files changed, 95 insertions, 2 deletions
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 f13731f..aec039b 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
@@ -1,10 +1,12 @@
package org.zwobble.hobgoblin.compiler.typechecker;
import org.junit.jupiter.api.Test;
+import org.zwobble.hobgoblin.compiler.ast.typed.TypedNamespaceNode;
import org.zwobble.hobgoblin.compiler.ast.typed.TypedStructDefinitionNode;
import org.zwobble.hobgoblin.compiler.ast.typed.TypedStructFieldDefinitionNode;
import org.zwobble.hobgoblin.compiler.ast.typed.TypedTypeLevelExpressionNode;
import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedArb;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceNode;
import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode;
import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode;
import org.zwobble.hobgoblin.compiler.sources.NullSource;
@@ -15,6 +17,7 @@ import org.zwobble.hobgoblin.compiler.types.TypeLevelValueType;
import java.util.List;
+import static org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerTesting.typeCheckNamespaceStatement;
import static org.zwobble.precisely.AssertThat.assertThat;
import static org.zwobble.precisely.Matchers.*;
@@ -28,7 +31,7 @@ public class TypeCheckerStructDefinitionTests {
);
var context = TypeCheckerContextArb.namespaceContext(NamespaceName.of("a", "b"));
- var typed = TypeChecker.typeCheckNamespaceStatement(untyped, context);
+ var typed = typeCheckNamespaceStatement(untyped, context);
assertThat(typed, instanceOf(
TypedStructDefinitionNode.class,
@@ -58,7 +61,7 @@ public class TypeCheckerStructDefinitionTests {
context.declare(int64Type.name());
context.define(int64Type.name(), new TypeLevelValueType(int64Type));
- var typed = TypeChecker.typeCheckNamespaceStatement(untyped, context);
+ var typed = typeCheckNamespaceStatement(untyped, context);
assertThat(typed, instanceOf(
TypedStructDefinitionNode.class,
@@ -86,4 +89,77 @@ public class TypeCheckerStructDefinitionTests {
)
));
}
+
+ @Test
+ public void structCanUseTypeDefinedLater() {
+ var int32Type = new ScalarType("Int32");
+ var namespaceName = NamespaceName.of("a", "b");
+ var untyped = new UntypedNamespaceNode(
+ namespaceName,
+ List.of(
+ new UntypedStructDefinitionNode(
+ "X",
+ List.of(
+ new UntypedStructFieldDefinitionNode("value", UntypedArb.typeLevelReference("Y"), NullSource.INSTANCE)
+ ),
+ NullSource.INSTANCE
+ ),
+ new UntypedStructDefinitionNode(
+ "Y",
+ List.of(
+ new UntypedStructFieldDefinitionNode("value", UntypedArb.typeLevelReference("Int32"), NullSource.INSTANCE)
+ ),
+ NullSource.INSTANCE
+ )
+ ),
+ NullSource.INSTANCE
+ );
+ var context = TypeCheckerContextArb.globalContext();
+ context.addBuiltinScalarType(int32Type);
+
+ var typed = TypeChecker.typeCheckNamespace(untyped, context);
+
+ assertThat(typed, has(
+ "body",
+ TypedNamespaceNode::body,
+ isSequence(
+ instanceOf(
+ TypedStructDefinitionNode.class,
+ has("name", TypedStructDefinitionNode::name, equalTo("X")),
+ has(
+ "fields",
+ TypedStructDefinitionNode::fields,
+ isSequence(
+ allOf(
+ has("name", TypedStructFieldDefinitionNode::name, equalTo("value")),
+ has("type", TypedStructFieldDefinitionNode::type, has(
+ "value",
+ TypedTypeLevelExpressionNode::value,
+ equalTo(new StructType(namespaceName, "Y"))
+ ))
+ )
+ )
+ )
+ ),
+ instanceOf(
+ TypedStructDefinitionNode.class,
+ has("name", TypedStructDefinitionNode::name, equalTo("Y")),
+ has(
+ "fields",
+ TypedStructDefinitionNode::fields,
+ isSequence(
+ allOf(
+ has("name", TypedStructFieldDefinitionNode::name, equalTo("value")),
+ has("type", TypedStructFieldDefinitionNode::type, has(
+ "value",
+ TypedTypeLevelExpressionNode::value,
+ equalTo(int32Type)
+ ))
+ )
+ )
+ )
+ )
+ )
+ ));
+ }
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTesting.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTesting.java
new file mode 100644
index 0000000..b0c21ec
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerTesting.java
@@ -0,0 +1,17 @@
+package org.zwobble.hobgoblin.compiler.typechecker;
+
+import org.zwobble.hobgoblin.compiler.ast.typed.TypedNamespaceStatementNode;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode;
+
+public class TypeCheckerTesting {
+ private TypeCheckerTesting() {
+ }
+
+ public static TypedNamespaceStatementNode typeCheckNamespaceStatement(
+ UntypedNamespaceStatementNode untyped,
+ TypeCheckerNamespaceContext context
+ ) {
+ TypeChecker.declareNamespaceStatement(untyped, context);
+ return TypeChecker.defineNamespaceStatement(untyped, context);
+ }
+}