From 124e712c8ca3738ec17db34151fb081efa36b214 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 16 Jun 2026 21:21:59 +0100 Subject: Store namespace fields --- hobgoblin/src/ast/untyped.hob | 2 ++ .../ast/untyped/UntypedNamespaceStatementNode.java | 2 ++ .../compiler/typechecker/TypeChecker.java | 30 ++++++++++++++-------- .../typechecker/TypeCheckerGlobalContext.java | 20 ++++++++++----- .../hobgoblin/compiler/typechecker/TypesInfo.java | 8 +++--- .../zwobble/hobgoblin/compiler/types/Fields.java | 20 +++++++++++++++ .../typechecker/TypeCheckerNamespaceTests.java | 5 ++++ .../hobgoblin/compiler/types/TypeMatchers.java | 13 ++++++++++ 8 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/types/Fields.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/types/TypeMatchers.java diff --git a/hobgoblin/src/ast/untyped.hob b/hobgoblin/src/ast/untyped.hob index c761ffe..c4036a6 100644 --- a/hobgoblin/src/ast/untyped.hob +++ b/hobgoblin/src/ast/untyped.hob @@ -24,6 +24,8 @@ sum UntypedNamespaceStatementNode { variant UntypedNativeTypeDefinitionNode; variant UntypedStructDefinitionNode; variant UntypedSumDefinitionNode; + + field name: String; } struct UntypedNativeTypeDefinitionNode { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedNamespaceStatementNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedNamespaceStatementNode.java index a7be931..a2d3171 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedNamespaceStatementNode.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedNamespaceStatementNode.java @@ -10,6 +10,8 @@ public sealed interface UntypedNamespaceStatementNode permits org.zwobble.hobgob // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode.Builder body } + public String name(); + // Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode body // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode body } 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 650cecd..4b718a2 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -19,9 +19,13 @@ public class TypeChecker { ) { var namespaceContext = context.enterNamespace(untyped.namespaceName()); + var fields = new ArrayList(); for (var untypedStatement : untyped.body()) { - declareNamespaceStatement(untypedStatement, namespaceContext); + var type = declareNamespaceStatement(untypedStatement, namespaceContext); + var field = new Field(untypedStatement.name(), type); + fields.add(field); } + context.defineNamespace(untyped.namespaceName(), fields); var typedBody = new ArrayList(); for (var untypedStatement : untyped.body()) { @@ -36,11 +40,11 @@ public class TypeChecker { ); } - static void declareNamespaceStatement( + static Type declareNamespaceStatement( UntypedNamespaceStatementNode untyped, TypeCheckerNamespaceContext context ) { - switch (untyped) { + return switch (untyped) { case UntypedNativeTypeDefinitionNode untypedNativeTypeDefinition -> declareNativeTypeDefinition(untypedNativeTypeDefinition, context); @@ -49,7 +53,7 @@ public class TypeChecker { case UntypedSumDefinitionNode untypedSumDefinition -> declareSumDefinition(untypedSumDefinition, context); - } + }; } static TypedNamespaceStatementNode defineNamespaceStatement( @@ -68,14 +72,16 @@ public class TypeChecker { }; } - private static void declareNativeTypeDefinition( + private static Type declareNativeTypeDefinition( UntypedNativeTypeDefinitionNode untyped, TypeCheckerNamespaceContext context ) { var nativeType = new SimpleNativeType(context.namespaceName(), untyped.name()); // TODO: tidy up declare vs define context.declare(untyped.name()); - context.define(untyped.name(), new TypeLevelValueType(nativeType)); + var metaType = new TypeLevelValueType(nativeType); + context.define(untyped.name(), metaType); + return metaType; } private static TypedNativeTypeDefinitionNode defineNativeTypeDefinition( @@ -91,14 +97,16 @@ public class TypeChecker { ); } - private static void declareStructDefinition( + private static Type declareStructDefinition( UntypedStructDefinitionNode untyped, TypeCheckerNamespaceContext context ) { var structType = new StructType(context.namespaceName(), untyped.name()); // TODO: tidy up declare vs define context.declare(untyped.name()); - context.define(untyped.name(), new TypeLevelValueType(structType)); + var metaType = new TypeLevelValueType(structType); + context.define(untyped.name(), metaType); + return metaType; } private static TypedStructDefinitionNode defineStructDefinition( @@ -145,14 +153,16 @@ public class TypeChecker { return new TypeCheckFieldDefinitionsResult(typedFields, fields); } - private static void declareSumDefinition( + private static Type declareSumDefinition( UntypedSumDefinitionNode untyped, TypeCheckerNamespaceContext context ) { var sumType = new SumType(context.namespaceName(), untyped.name()); // TODO: tidy up declare vs define context.declare(untyped.name()); - context.define(untyped.name(), new TypeLevelValueType(sumType)); + var metaType = new TypeLevelValueType(sumType); + context.define(untyped.name(), metaType); + return metaType; } private static TypedNamespaceStatementNode defineSumDefinition( diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java index 9bc0efb..e50e424 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java @@ -3,13 +3,12 @@ package org.zwobble.hobgoblin.compiler.typechecker; import org.zwobble.hobgoblin.compiler.types.*; import org.zwobble.hobgoblin.compiler.util.ManyToMany; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class TypeCheckerGlobalContext { private final Map nativeTypes = new HashMap<>(); - private final Map> fieldsOf = new HashMap<>(); + private final Map> structFieldsOf = new HashMap<>(); + private final Map namespaceFieldsOf = new HashMap<>(); private final ManyToMany variants = new ManyToMany<>(); public static TypeCheckerGlobalContext initial() { @@ -20,7 +19,7 @@ public class TypeCheckerGlobalContext { } public TypesInfo toTypesInfo() { - return new TypesInfo(this.fieldsOf, this.variants); + return new TypesInfo(this.structFieldsOf, this.variants); } public void addNativeType(SimpleNativeType type) { @@ -35,8 +34,17 @@ public class TypeCheckerGlobalContext { return TypeCheckerNamespaceContext.initial( namespaceName, this.nativeTypes, - this.fieldsOf, + this.structFieldsOf, this.variants ); } + + public void defineNamespace(NamespaceName namespaceName, List fields) { + this.namespaceFieldsOf.put(namespaceName, new Fields(fields)); + } + + public Fields namespaceFields(NamespaceName namespaceName) { + // TODO: better error handling + return Optional.ofNullable(namespaceFieldsOf.get(namespaceName)).orElseThrow(); + } } 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 649ded0..e64a4b8 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java @@ -11,20 +11,20 @@ import java.util.Map; import java.util.Optional; public class TypesInfo { - private final Map> fieldsOf; + private final Map> structFieldsOf; private final ManyToMany variants; public TypesInfo( - Map> fieldsOf, + Map> structFieldsOf, ManyToMany variants ) { - this.fieldsOf = fieldsOf; + this.structFieldsOf = structFieldsOf; this.variants = variants; } public List fieldsOf(StructType structType) { // TODO: handle error better - return Optional.ofNullable(this.fieldsOf.get(structType)).orElseThrow(); + return Optional.ofNullable(this.structFieldsOf.get(structType)).orElseThrow(); } public List variantOf(StructType variantType) { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/Fields.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/Fields.java new file mode 100644 index 0000000..4fc364e --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/Fields.java @@ -0,0 +1,20 @@ +package org.zwobble.hobgoblin.compiler.types; + +import java.util.List; + +public class Fields { + private final List fields; + + public Fields(List fields) { + this.fields = fields; + } + + public Type get(String name) { + return fields.stream() + .filter(field -> field.name().equals(name)) + .findFirst() + // TODO: better error handling + .orElseThrow() + .type(); + } +} 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 5a2f7cb..cfe52c3 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceTests.java @@ -10,6 +10,7 @@ import org.zwobble.hobgoblin.compiler.types.StructType; import java.util.List; +import static org.zwobble.hobgoblin.compiler.types.TypeMatchers.isMetaType; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.*; @@ -41,5 +42,9 @@ public class TypeCheckerNamespaceTests { ) )) )); + assertThat( + context.namespaceFields(NamespaceName.of("a", "b")).get("X"), + isMetaType(new StructType(NamespaceName.of("a", "b"), "X")) + ); } } diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/types/TypeMatchers.java b/src/test/java/org/zwobble/hobgoblin/compiler/types/TypeMatchers.java new file mode 100644 index 0000000..d676d89 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/types/TypeMatchers.java @@ -0,0 +1,13 @@ +package org.zwobble.hobgoblin.compiler.types; + +import org.zwobble.precisely.Matcher; + +import static org.zwobble.precisely.Matchers.equalTo; + +public class TypeMatchers { + private TypeMatchers() {} + + public static Matcher isMetaType(Type type) { + return equalTo(new TypeLevelValueType(type)); + } +} -- cgit v1.2.3