aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-21 00:10:50 +0100
committerMichael Williamson <mike@zwobble.org>2023-10-21 00:10:50 +0100
commit51f3d868199b411a4b0a010c0a26585b5718e0fb (patch)
tree10337877d31a4ee89920805f1315d45647fe07e6 /src/main/java
parent8c9b4c92c1493d96d4bb2a5b88bf9e98e3a584e2 (diff)
Support type checking field access on namespace
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java30
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java5
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/errors/MissingNamespaceTypeInfoError.java18
-rw-r--r--src/main/java/org/shedlang/compiler/types/NamespaceTypeInfo.java6
-rw-r--r--src/main/java/org/shedlang/compiler/types/Types.java2
5 files changed, 52 insertions, 9 deletions
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<TypedFunctionDefinitionNode> 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<String, Type> fields) {
return new NamespaceTypeInfo(new FieldsInfo(fields));
@@ -11,6 +13,10 @@ public record NamespaceTypeInfo(FieldsInfo fields) {
return fields.fieldCount();
}
+ public <T> Optional<Type> 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);
}