From abfae536a732ba3a7299aaf3811de701ed73799b Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 20 Dec 2024 10:36:49 +0000 Subject: Store member kind in type member access nodes --- .../compiler/ast/typed/TypedMemberAccessNode.java | 2 ++ .../shedlang/compiler/typechecker/TypeChecker.java | 30 +++++++++++++--------- .../org/shedlang/compiler/types/MemberAccess.java | 11 ++++++++ .../org/shedlang/compiler/types/MemberKind.java | 6 +++++ .../shedlang/compiler/types/StructTypeInfo.java | 17 +++++++----- 5 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/types/MemberAccess.java create mode 100644 src/main/java/org/shedlang/compiler/types/MemberKind.java (limited to 'src/main/java') 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 memberTypeOrEmpty( + private static Optional 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 memberType(String memberName) { - return fields.fieldType(memberName).or(() -> - methods.stream() - .filter(method -> method.name().equals(memberName)) - .findFirst() - .map(method -> method.type()) - ); + public Optional 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) { -- cgit v1.2.3