aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-12-20 10:36:49 +0000
committerMichael Williamson <mike@zwobble.org>2024-12-20 10:36:57 +0000
commitabfae536a732ba3a7299aaf3811de701ed73799b (patch)
treef5b10b3c8a9b43998f75b8046dfcc56c16342449 /src/main/java
parentfd8ec8d57f27a669e657d80c4534dd09dc922b4f (diff)
Store member kind in type member access nodes
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java30
-rw-r--r--src/main/java/org/shedlang/compiler/types/MemberAccess.java11
-rw-r--r--src/main/java/org/shedlang/compiler/types/MemberKind.java6
-rw-r--r--src/main/java/org/shedlang/compiler/types/StructTypeInfo.java17
5 files changed, 47 insertions, 19 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java
index 481d01b6..b2c34050 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java
@@ -1,11 +1,13 @@
package org.shedlang.compiler.ast.typed;
import org.shedlang.compiler.sources.Source;
+import org.shedlang.compiler.types.MemberKind;
import org.shedlang.compiler.types.Type;
public record TypedMemberAccessNode(
TypedExpressionNode receiver,
String memberName,
+ MemberKind memberKind,
Type type,
Source source
) implements TypedExpressionNode {
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index d6b8b813..daee11c4 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -1316,7 +1316,7 @@ public class TypeChecker {
var typedReceiver = typedReceiverResult.value();
context = typedReceiverResult.context();
- var memberType = memberType(
+ var memberAccess = memberAccess(
typedReceiver.type(),
untyped.memberName(),
untyped.source(),
@@ -1326,22 +1326,23 @@ public class TypeChecker {
return context.toResult(new TypedMemberAccessNode(
typedReceiver,
untyped.memberName(),
- memberType,
+ memberAccess.memberKind(),
+ memberAccess.type(),
untyped.source()
));
}
- private static Type memberType(
+ private static MemberAccess memberAccess(
Type receiverType,
String memberName,
Source source,
TypeCheckerContext context
) {
- return memberTypeOrEmpty(receiverType, memberName, source, context)
+ return memberAccessOrEmpty(receiverType, memberName, source, context)
.orElseThrow(() -> new NoSuchMemberError(receiverType, memberName, source));
}
- private static Optional<Type> memberTypeOrEmpty(
+ private static Optional<MemberAccess> memberAccessOrEmpty(
Type receiverType,
String memberName,
Source source,
@@ -1349,32 +1350,37 @@ public class TypeChecker {
) {
switch (receiverType) {
case ConstructedType<?> receiverTypeConstructed -> {
- return memberTypeOrEmpty(
+ return memberAccessOrEmpty(
receiverTypeConstructed.genericType(),
memberName,
source,
context
- ).map(genericFieldType -> TypeSubstitution.substituteType(
- genericFieldType,
- receiverTypeConstructed.typeSubstitutionMap()
+ ).map(genericFieldMemberAccess -> new MemberAccess(
+ TypeSubstitution.substituteType(
+ genericFieldMemberAccess.type(),
+ receiverTypeConstructed.typeSubstitutionMap()
+ ),
+ genericFieldMemberAccess.memberKind()
));
}
case SimpleStructType receiverTypeStruct -> {
// TODO: handle ambiguity
var structTypeInfo = context.structTypeInfo(receiverTypeStruct, source);
- return structTypeInfo.memberType(memberName);
+ return structTypeInfo.memberAccess(memberName);
}
case NamespaceType receiverTypeNamespace -> {
var namespaceTypeInfo = context.namespaceTypeInfo(receiverTypeNamespace, source);
- return namespaceTypeInfo.fieldType(memberName);
+ var fieldType = namespaceTypeInfo.fieldType(memberName);
+ return fieldType.map(MemberAccess::field);
}
case TypeLevelValueType receiverTypeTypeLevelValue when receiverTypeTypeLevelValue.value() instanceof UserDefinedEffect effect -> {
var effectInfo = context.userDefinedEffectInfo(effect, source);
- return effectInfo.methodType(memberName)
+ var methodType = effectInfo.methodType(memberName)
.map(x -> x.withEffect(effect));
+ return methodType.map(MemberAccess::field);
}
default -> {
diff --git a/src/main/java/org/shedlang/compiler/types/MemberAccess.java b/src/main/java/org/shedlang/compiler/types/MemberAccess.java
new file mode 100644
index 00000000..00799349
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/types/MemberAccess.java
@@ -0,0 +1,11 @@
+package org.shedlang.compiler.types;
+
+public record MemberAccess(Type type, MemberKind memberKind) {
+ public static MemberAccess field(Type type) {
+ return new MemberAccess(type, MemberKind.FIELD);
+ }
+
+ public static MemberAccess method(Type type) {
+ return new MemberAccess(type, MemberKind.METHOD);
+ }
+}
diff --git a/src/main/java/org/shedlang/compiler/types/MemberKind.java b/src/main/java/org/shedlang/compiler/types/MemberKind.java
new file mode 100644
index 00000000..8bc6d9fd
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/types/MemberKind.java
@@ -0,0 +1,6 @@
+package org.shedlang.compiler.types;
+
+public enum MemberKind {
+ FIELD,
+ METHOD
+}
diff --git a/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java b/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java
index d90a5f6b..026d9f1e 100644
--- a/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java
+++ b/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java
@@ -15,13 +15,16 @@ public record StructTypeInfo(
return fields().fieldCount();
}
- public Optional<Type> memberType(String memberName) {
- return fields.fieldType(memberName).or(() ->
- methods.stream()
- .filter(method -> method.name().equals(memberName))
- .findFirst()
- .map(method -> method.type())
- );
+ public Optional<MemberAccess> memberAccess(String memberName) {
+ // TODO: handle ambiguity
+ return fields.fieldType(memberName)
+ .map(MemberAccess::field)
+ .or(() ->
+ methods.stream()
+ .filter(method -> method.name().equals(memberName))
+ .findFirst()
+ .map(method -> MemberAccess.method(method.type()))
+ );
}
public int fieldIndex(String fieldName) {