From 51f3d868199b411a4b0a010c0a26585b5718e0fb Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 21 Oct 2023 00:10:50 +0100 Subject: Support type checking field access on namespace --- .../shedlang/compiler/typechecker/TypeChecker.java | 30 ++++++++++++++++------ .../compiler/typechecker/TypeCheckerContext.java | 5 ++++ .../errors/MissingNamespaceTypeInfoError.java | 18 +++++++++++++ .../shedlang/compiler/types/NamespaceTypeInfo.java | 6 +++++ .../java/org/shedlang/compiler/types/Types.java | 2 +- 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/typechecker/errors/MissingNamespaceTypeInfoError.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 9157356d..30121611 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -430,14 +430,12 @@ public class TypeChecker { var typedReceiver = typedReceiverResult.value(); context = typedReceiverResult.context(); - if (!(typedReceiver.type() instanceof StructType receiverType)) { - throw new NoSuchFieldError(typedReceiver.type(), untyped.fieldName(), untyped.source()); - } - - var structTypeInfo = context.structTypeInfo(receiverType, untyped.source()); - - var fieldType = structTypeInfo.fieldType(untyped.fieldName()) - .orElseThrow(() -> new NoSuchFieldError(receiverType, untyped.fieldName(), untyped.source())); + var fieldType = fieldType( + typedReceiver.type(), + untyped.fieldName(), + untyped.source(), + context + ); return context.toResult(new TypedFieldAccessNode( typedReceiver, @@ -447,6 +445,22 @@ public class TypeChecker { )); } + private static Type fieldType(Type receiverType, String fieldName, Source source, TypeCheckerContext context) { + if (receiverType instanceof StructType receiverTypeStruct) { + var structTypeInfo = context.structTypeInfo(receiverTypeStruct, source); + + return structTypeInfo.fieldType(fieldName) + .orElseThrow(() -> new NoSuchFieldError(receiverTypeStruct, fieldName, source)); + } else if (receiverType instanceof NamespaceType receiverTypeNamespace) { + var namespaceTypeInfo = context.namespaceTypeInfo(receiverTypeNamespace, source); + + return namespaceTypeInfo.fieldType(fieldName) + .orElseThrow(() -> new NoSuchFieldError(receiverTypeNamespace, fieldName, source)); + } else { + throw new NoSuchFieldError(receiverType, fieldName, source); + } + } + private static TypeCheckSteps typeCheckStepsFunctionDefinition( UntypedFunctionDefinitionNode untyped ) { diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java index 2fc19b80..8787be9a 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java @@ -357,6 +357,11 @@ public class TypeCheckerContext { ); } + public NamespaceTypeInfo namespaceTypeInfo(NamespaceType type, Source source) { + return this.typeInfos.namespaceTypeInfo(type.namespaceName()) + .orElseThrow(() -> new MissingNamespaceTypeInfoError(type, source)); + } + public TypeCheckerContext addStructTypeInfo( StructType structType, StructTypeInfo structTypeInfo diff --git a/src/main/java/org/shedlang/compiler/typechecker/errors/MissingNamespaceTypeInfoError.java b/src/main/java/org/shedlang/compiler/typechecker/errors/MissingNamespaceTypeInfoError.java new file mode 100644 index 00000000..922b08f9 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/errors/MissingNamespaceTypeInfoError.java @@ -0,0 +1,18 @@ +package org.shedlang.compiler.typechecker.errors; + +import org.shedlang.compiler.errors.InternalCompilerError; +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.types.NamespaceType; + +public class MissingNamespaceTypeInfoError extends InternalCompilerError { + private final NamespaceType type; + + public MissingNamespaceTypeInfoError(NamespaceType type, Source source) { + super("Missing type info for namespace " + type, source); + this.type = type; + } + + public NamespaceType type() { + return type; + } +} diff --git a/src/main/java/org/shedlang/compiler/types/NamespaceTypeInfo.java b/src/main/java/org/shedlang/compiler/types/NamespaceTypeInfo.java index d821f411..3e2b9ab0 100644 --- a/src/main/java/org/shedlang/compiler/types/NamespaceTypeInfo.java +++ b/src/main/java/org/shedlang/compiler/types/NamespaceTypeInfo.java @@ -2,6 +2,8 @@ package org.shedlang.compiler.types; import org.shedlang.compiler.util.POrderedMap; +import java.util.Optional; + public record NamespaceTypeInfo(FieldsInfo fields) { public static NamespaceTypeInfo fromFields(POrderedMap fields) { return new NamespaceTypeInfo(new FieldsInfo(fields)); @@ -11,6 +13,10 @@ public record NamespaceTypeInfo(FieldsInfo fields) { return fields.fieldCount(); } + public Optional fieldType(String fieldName) { + return fields.fieldType(fieldName); + } + public int fieldIndex(String fieldName) { return fields.fieldIndex(fieldName); } diff --git a/src/main/java/org/shedlang/compiler/types/Types.java b/src/main/java/org/shedlang/compiler/types/Types.java index c349e27e..71c931b3 100644 --- a/src/main/java/org/shedlang/compiler/types/Types.java +++ b/src/main/java/org/shedlang/compiler/types/Types.java @@ -14,7 +14,7 @@ public class Types { public static final Type TOP = TopType.INSTANCE; public static final Type UNIT = UnitType.INSTANCE; - public static Type namespace(NamespaceName namespaceName) { + public static NamespaceType namespace(NamespaceName namespaceName) { return new NamespaceType(namespaceName); } -- cgit v1.2.3