summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-04-25 10:33:55 +0100
committerMichael Williamson <mike@zwobble.org>2026-04-25 10:33:55 +0100
commit032cdc6462ad575f62b349152f31e87b187e974d (patch)
tree156f6e4170e766016f2de938e4fabe958843bdca /src
parent2a37bf78f778c2955a80f0bbf0ac7d4c14f5c55f (diff)
Generate struct type for struct definition
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java34
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContext.java19
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java2
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java37
4 files changed, 83 insertions, 9 deletions
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 cfce407..0a301c6 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
@@ -1,11 +1,8 @@
package org.zwobble.hobgoblin.compiler.typechecker;
-import org.zwobble.hobgoblin.compiler.ast.typed.TypedNamespaceNode;
-import org.zwobble.hobgoblin.compiler.ast.typed.TypedTypeLevelExpressionNode;
-import org.zwobble.hobgoblin.compiler.ast.typed.TypedTypeLevelReferenceNode;
-import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceNode;
-import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelExpressionNode;
-import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelReferenceNode;
+import org.zwobble.hobgoblin.compiler.ast.typed.*;
+import org.zwobble.hobgoblin.compiler.ast.untyped.*;
+import org.zwobble.hobgoblin.compiler.types.StructType;
import org.zwobble.hobgoblin.compiler.types.TypeLevelValue;
import org.zwobble.hobgoblin.compiler.types.TypeLevelValueType;
import org.zwobble.hobgoblin.compiler.types.TypeSet;
@@ -27,6 +24,31 @@ public class TypeChecker {
);
}
+ static TypedNamespaceStatementNode typeCheckNamespaceStatement(
+ UntypedNamespaceStatementNode untyped,
+ TypeCheckerContext context
+ ) {
+ return switch (untyped) {
+ case UntypedStructDefinitionNode untypedStructDefinition ->
+ typeCheckStructDefinition(untypedStructDefinition, context);
+ };
+ }
+
+ private static TypedStructDefinitionNode typeCheckStructDefinition(
+ UntypedStructDefinitionNode untyped,
+ TypeCheckerContext context
+ ) {
+ // TODO: better error when not in namespace
+ var namespaceName = context.namespaceName().orElseThrow();
+ var structType = new StructType(namespaceName, untyped.name());
+
+ return new TypedStructDefinitionNode(
+ structType,
+ List.of(),
+ untyped.source()
+ );
+ }
+
static TypedTypeLevelExpressionNode<? extends TypeLevelValue> typeCheckTypeLevelExpression(
UntypedTypeLevelExpressionNode untyped,
TypeCheckerContext context
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContext.java
index b80246a..e1109f9 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContext.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContext.java
@@ -1,5 +1,6 @@
package org.zwobble.hobgoblin.compiler.typechecker;
+import org.zwobble.hobgoblin.compiler.types.NamespaceName;
import org.zwobble.hobgoblin.compiler.types.Type;
import java.util.HashMap;
@@ -7,10 +8,20 @@ import java.util.Map;
import java.util.Optional;
public class TypeCheckerContext {
- private final Map<String, Variable> variables = new HashMap<>();
+ private Optional<NamespaceName> namespaceName;
+ private final Map<String, Variable> variables;
+
+ private TypeCheckerContext(Optional<NamespaceName> namespaceName, Map<String, Variable> variables) {
+ this.namespaceName = namespaceName;
+ this.variables = variables;
+ }
public static TypeCheckerContext initial() {
- return new TypeCheckerContext();
+ return new TypeCheckerContext(Optional.empty(), new HashMap<>());
+ }
+
+ public Optional<NamespaceName> namespaceName() {
+ return this.namespaceName;
}
public void declare(String name) {
@@ -26,4 +37,8 @@ public class TypeCheckerContext {
public Optional<Variable> lookup(String name) {
return Optional.ofNullable(this.variables.get(name));
}
+
+ public void enterNamespace(NamespaceName namespaceName) {
+ this.namespaceName = Optional.of(namespaceName);
+ }
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java
index 98d8064..b917ba4 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerContextArb.java
@@ -5,6 +5,6 @@ public class TypeCheckerContextArb {
}
public static TypeCheckerContext context() {
- return new TypeCheckerContext();
+ return TypeCheckerContext.initial();
}
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
new file mode 100644
index 0000000..86f78ae
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerStructDefinitionTests.java
@@ -0,0 +1,37 @@
+package org.zwobble.hobgoblin.compiler.typechecker;
+
+import org.junit.jupiter.api.Test;
+import org.zwobble.hobgoblin.compiler.ast.typed.TypedStructDefinitionNode;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode;
+import org.zwobble.hobgoblin.compiler.sources.NullSource;
+import org.zwobble.hobgoblin.compiler.types.NamespaceName;
+import org.zwobble.hobgoblin.compiler.types.StructType;
+
+import java.util.List;
+
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.*;
+
+public class TypeCheckerStructDefinitionTests {
+ @Test
+ public void structHasNamespaceFromContext() {
+ var untyped = new UntypedStructDefinitionNode(
+ "X",
+ List.of(),
+ NullSource.INSTANCE
+ );
+ var context = TypeCheckerContextArb.context();
+ context.enterNamespace(NamespaceName.of("a", "b"));
+
+ var typed = TypeChecker.typeCheckNamespaceStatement(untyped, context);
+
+ assertThat(typed, instanceOf(
+ TypedStructDefinitionNode.class,
+ has(
+ "type",
+ TypedStructDefinitionNode::type,
+ equalTo(new StructType(NamespaceName.of("a", "b"), "X"))
+ )
+ ));
+ }
+}