diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-04-26 21:31:44 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-04-26 21:31:44 +0100 |
| commit | 92708742a18a1a3de5eb59a2e7c12788aa199d9a (patch) | |
| tree | c50d46c56b5a80df00046f3cad244794056f05eb /src/main/java/org | |
| parent | 9f6c9b42073373b18c8a92a9428f35986effc77b (diff) | |
Declare types ahead of defining them
Diffstat (limited to 'src/main/java/org')
| -rw-r--r-- | src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java | 15 | ||||
| -rw-r--r-- | src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java | 70 |
2 files changed, 69 insertions, 16 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java index 54796e2..c638763 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java @@ -11,6 +11,8 @@ import org.zwobble.hobgoblin.compiler.output.java.ast.JavaRecordComponent; import org.zwobble.hobgoblin.compiler.output.java.ast.JavaRecordDeclaration; import org.zwobble.hobgoblin.compiler.output.java.ast.JavaCompilationUnit; import org.zwobble.hobgoblin.compiler.output.java.ast.JavaTypeRef; +import org.zwobble.hobgoblin.compiler.types.NamespaceName; +import org.zwobble.hobgoblin.compiler.types.StructType; import org.zwobble.hobgoblin.compiler.types.Type; import java.io.File; @@ -36,8 +38,7 @@ public class JavaTypesGenerator implements Generator { } private void generateNamespace(TypedNamespaceNode namespace) throws IOException { - var packageParts = new ArrayList<>(this.packageName); - packageParts.addAll(namespace.namespaceName().parts()); + var packageParts = namespaceToJavaPackageParts(namespace.namespaceName()); for (var statement : namespace.body()) { switch (statement) { @@ -69,10 +70,18 @@ public class JavaTypesGenerator implements Generator { } } + private ArrayList<String> namespaceToJavaPackageParts(NamespaceName namespaceName) { + var packageParts = new ArrayList<>(this.packageName); + packageParts.addAll(namespaceName.parts()); + return packageParts; + } + private JavaTypeRef generateTypeRef(TypedTypeLevelExpressionNode<Type> typeNode) { var type = typeNode.value(); - if (type.equals(BuiltinTypes.INT_32)) { + if (type instanceof StructType structType) { + return new JavaTypeRef(namespaceToJavaPackageParts(structType.namespaceName()), structType.name()); + } else if (type.equals(BuiltinTypes.INT_32)) { return new JavaTypeRef(List.of(), "int"); } else { throw new UnsupportedOperationException("TODO"); 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 d9a37e2..7678f94 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -2,6 +2,7 @@ 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.sources.Source; import org.zwobble.hobgoblin.compiler.types.*; import java.util.ArrayList; @@ -16,9 +17,13 @@ public class TypeChecker { ) { var namespaceContext = context.enterNamespace(untyped.namespaceName()); + for (var untypedStatement : untyped.body()) { + declareNamespaceStatement(untypedStatement, namespaceContext); + } + var typedBody = new ArrayList<TypedNamespaceStatementNode>(); for (var untypedStatement : untyped.body()) { - var typedStatement = typeCheckNamespaceStatement(untypedStatement, namespaceContext); + var typedStatement = defineNamespaceStatement(untypedStatement, namespaceContext); typedBody.add(typedStatement); } @@ -29,21 +34,41 @@ public class TypeChecker { ); } - static TypedNamespaceStatementNode typeCheckNamespaceStatement( + static void declareNamespaceStatement( + UntypedNamespaceStatementNode untyped, + TypeCheckerNamespaceContext context + ) { + switch (untyped) { + case UntypedStructDefinitionNode untypedStructDefinition -> + declareStructDefinition(untypedStructDefinition, context); + } + } + + static TypedNamespaceStatementNode defineNamespaceStatement( UntypedNamespaceStatementNode untyped, TypeCheckerNamespaceContext context ) { return switch (untyped) { case UntypedStructDefinitionNode untypedStructDefinition -> - typeCheckStructDefinition(untypedStructDefinition, context); + defineStructDefinition(untypedStructDefinition, context); }; } - private static TypedStructDefinitionNode typeCheckStructDefinition( + private static void 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)); + } + + private static TypedStructDefinitionNode defineStructDefinition( + UntypedStructDefinitionNode untyped, + TypeCheckerNamespaceContext context + ) { + var structType = (StructType) lookupMetaType(untyped.name(), untyped.source(), context); var typedFields = new ArrayList<TypedStructFieldDefinitionNode>(); for (var untypedField : untyped.fields()) { @@ -89,12 +114,35 @@ public class TypeChecker { UntypedTypeLevelReferenceNode untyped, TypeCheckerNamespaceContext context ) { - var variable = context.lookup(untyped.name()) - .orElseThrow(() -> new UndeclaredVariableError(untyped.name(), untyped.source())); + var value = lookupTypeLevelValue(untyped.name(), untyped.source(), context); + + return new TypedTypeLevelReferenceNode<>( + untyped.name(), + value, + untyped.source() + ); + } + + private static Type lookupMetaType( + String name, + Source source, + TypeCheckerNamespaceContext context + ) { + // TODO: handle not a type properly + return (Type) lookupTypeLevelValue(name, source, context); + } + + private static TypeLevelValue lookupTypeLevelValue( + String name, + Source source, + TypeCheckerNamespaceContext context + ) { + var variable = context.lookup(name) + .orElseThrow(() -> new UndeclaredVariableError(name, source)); var type = switch (variable) { case Variable.Declared declared -> - throw new UndefinedVariableError(untyped.name(), untyped.source()); + throw new UndefinedVariableError(name, source); case Variable.Defined defined -> defined.type(); @@ -102,13 +150,9 @@ public class TypeChecker { // TODO: handle not a type-level value if (!(type instanceof TypeLevelValueType(TypeLevelValue value))) { - throw new UnexpectedTypeError(new TypeSet.MetaType(), type, untyped.source()); + throw new UnexpectedTypeError(new TypeSet.MetaType(), type, source); } - return new TypedTypeLevelReferenceNode<>( - untyped.name(), - value, - untyped.source() - ); + return value; } } |
