diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-06-16 21:21:59 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-06-16 21:21:59 +0100 |
| commit | 124e712c8ca3738ec17db34151fb081efa36b214 (patch) | |
| tree | 0abc0a111745567612f6f24060c50b88ddc3b1ec | |
| parent | 6465a06977c79ccb3c328d3c97d6873066e46b11 (diff) | |
Store namespace fields
8 files changed, 80 insertions, 20 deletions
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<Field>(); 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<TypedNamespaceStatementNode>(); 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<String, Type> nativeTypes = new HashMap<>(); - private final Map<StructType, List<Field>> fieldsOf = new HashMap<>(); + private final Map<StructType, List<Field>> structFieldsOf = new HashMap<>(); + private final Map<NamespaceName, Fields> namespaceFieldsOf = new HashMap<>(); private final ManyToMany<SumType, Type> 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<Field> 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<StructType, List<Field>> fieldsOf; + private final Map<StructType, List<Field>> structFieldsOf; private final ManyToMany<SumType, Type> variants; public TypesInfo( - Map<StructType, List<Field>> fieldsOf, + Map<StructType, List<Field>> structFieldsOf, ManyToMany<SumType, Type> variants ) { - this.fieldsOf = fieldsOf; + this.structFieldsOf = structFieldsOf; this.variants = variants; } public List<Field> 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<SumType> 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<Field> fields; + + public Fields(List<Field> 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<Type> isMetaType(Type type) { + return equalTo(new TypeLevelValueType(type)); + } +} |
