From 72c84ea17a7e4b27cf9428ef23f713e32f5339d3 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 25 Apr 2026 10:56:55 +0100 Subject: Type check struct fields --- .../hobgoblin/compiler/HobgoblinCompiler.java | 3 +++ .../compiler/typechecker/TypeChecker.java | 31 +++++++++++++++++----- .../typechecker/TypeCheckerGlobalContext.java | 14 +++++++++- .../typechecker/TypeCheckerNamespaceContext.java | 15 ++++++++--- .../hobgoblin/compiler/typechecker/Variable.java | 4 +++ 5 files changed, 57 insertions(+), 10 deletions(-) (limited to 'src/main') diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java b/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java index 4f56fb1..d9f7d21 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java @@ -4,6 +4,7 @@ import org.zwobble.hobgoblin.compiler.parser.Parser; import org.zwobble.hobgoblin.compiler.typechecker.TypeChecker; import org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerGlobalContext; import org.zwobble.hobgoblin.compiler.types.NamespaceName; +import org.zwobble.hobgoblin.compiler.types.ScalarType; import org.zwobble.sourcetext.SourceText; import java.io.IOException; @@ -29,6 +30,8 @@ public class HobgoblinCompiler { var untypedNamespaceNode = Parser.parseNamespace(sourceText, namespaceName); var typeCheckerContext = TypeCheckerGlobalContext.initial(); + typeCheckerContext.addBuiltinScalarType(new ScalarType("Int32")); + var typedNamespaceNode = TypeChecker.typeCheckNamespace(untypedNamespaceNode, typeCheckerContext); } } 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 b8bdd7f..d9a37e2 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -2,13 +2,9 @@ package org.zwobble.hobgoblin.compiler.typechecker; 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; +import org.zwobble.hobgoblin.compiler.types.*; import java.util.ArrayList; -import java.util.List; public class TypeChecker { private TypeChecker() { @@ -49,13 +45,36 @@ public class TypeChecker { ) { var structType = new StructType(context.namespaceName(), untyped.name()); + var typedFields = new ArrayList(); + for (var untypedField : untyped.fields()) { + var typedField = new TypedStructFieldDefinitionNode( + untypedField.name(), + typeCheckMetaType(untypedField.type(), context), + untyped.source() + ); + typedFields.add(typedField); + } + return new TypedStructDefinitionNode( structType, - List.of(), + typedFields, untyped.source() ); } + private static TypedTypeLevelExpressionNode typeCheckMetaType( + UntypedTypeLevelExpressionNode untyped, + TypeCheckerNamespaceContext context + ) { + var typed = typeCheckTypeLevelExpression(untyped, context); + if (typed.value() instanceof Type) { + return (TypedTypeLevelExpressionNode) typed; + } else { + // TODO: better error + throw new RuntimeException("not a metatype"); + } + } + static TypedTypeLevelExpressionNode typeCheckTypeLevelExpression( UntypedTypeLevelExpressionNode untyped, TypeCheckerNamespaceContext context 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 3915767..849da2f 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerGlobalContext.java @@ -1,8 +1,16 @@ package org.zwobble.hobgoblin.compiler.typechecker; import org.zwobble.hobgoblin.compiler.types.NamespaceName; +import org.zwobble.hobgoblin.compiler.types.ScalarType; +import org.zwobble.hobgoblin.compiler.types.Type; +import org.zwobble.hobgoblin.compiler.types.TypeLevelValueType; + +import java.util.HashMap; +import java.util.Map; public class TypeCheckerGlobalContext { + private final Map builtins = new HashMap<>(); + public static TypeCheckerGlobalContext initial() { return new TypeCheckerGlobalContext(); } @@ -10,7 +18,11 @@ public class TypeCheckerGlobalContext { private TypeCheckerGlobalContext() { } + public void addBuiltinScalarType(ScalarType type) { + this.builtins.put(type.name(), new TypeLevelValueType(type)); + } + public TypeCheckerNamespaceContext enterNamespace(NamespaceName namespaceName) { - return TypeCheckerNamespaceContext.initial(namespaceName); + return TypeCheckerNamespaceContext.initial(namespaceName, this.builtins); } } 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 c1a23fd..353209b 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java @@ -3,13 +3,22 @@ package org.zwobble.hobgoblin.compiler.typechecker; import org.zwobble.hobgoblin.compiler.types.NamespaceName; import org.zwobble.hobgoblin.compiler.types.Type; -import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; public class TypeCheckerNamespaceContext { - public static TypeCheckerNamespaceContext initial(NamespaceName namespaceName) { - return new TypeCheckerNamespaceContext(namespaceName, new HashMap<>()); + public static TypeCheckerNamespaceContext initial( + NamespaceName namespaceName, + Map builtins + ) { + var variables = builtins.entrySet().stream() + .collect(Collectors.toMap( + entry -> entry.getKey(), + entry -> Variable.defined(entry.getValue()) + )); + + return new TypeCheckerNamespaceContext(namespaceName, variables); } private final NamespaceName namespaceName; diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/Variable.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/Variable.java index 1d3a4b6..e80283f 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/Variable.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/Variable.java @@ -3,6 +3,10 @@ package org.zwobble.hobgoblin.compiler.typechecker; import org.zwobble.hobgoblin.compiler.types.Type; public sealed interface Variable { + public static Variable defined(Type type) { + return new Defined(type); + } + record Declared() implements Variable { } -- cgit v1.2.3