aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-12-19 18:21:30 +0000
committerMichael Williamson <mike@zwobble.org>2024-12-19 18:21:30 +0000
commit550bdc5177fa72234a1359795615df9f80a98657 (patch)
tree0d604f4b72f2824690c575681528a0b71bd8f2a2 /src/main/java
parent7bbacfafc62ffa7f8ca5b384f29749dacfb5f86b (diff)
Rename field access to member access
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java (renamed from src/main/java/org/shedlang/compiler/ast/typed/TypedFieldAccessNode.java)4
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedMemberAccessNode.java (renamed from src/main/java/org/shedlang/compiler/ast/untyped/UntypedFieldAccessNode.java)4
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Parser.java60
-rw-r--r--src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java86
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java155
7 files changed, 156 insertions, 157 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java
index 4c8b2cfd..c31d45ac 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java
@@ -4,6 +4,6 @@ import org.shedlang.compiler.types.Type;
public sealed interface TypedExpressionNode
extends TypedNode
- permits TypedBinaryOperationNode, TypedBoolLiteralNode, TypedCallNode, TypedFieldAccessNode, TypedFunctionExpressionNode, TypedIfNode, TypedIntLiteralNode, TypedReferenceNode, TypedStringLiteralNode, TypedTryNode, TypedTupleNode, TypedUnitLiteralNode, TypedWhenNode {
+ permits TypedBinaryOperationNode, TypedBoolLiteralNode, TypedCallNode, TypedFunctionExpressionNode, TypedIfNode, TypedIntLiteralNode, TypedMemberAccessNode, TypedReferenceNode, TypedStringLiteralNode, TypedTryNode, TypedTupleNode, TypedUnitLiteralNode, TypedWhenNode {
Type type();
}
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedFieldAccessNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java
index ca088e48..481d01b6 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFieldAccessNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedMemberAccessNode.java
@@ -3,9 +3,9 @@ package org.shedlang.compiler.ast.typed;
import org.shedlang.compiler.sources.Source;
import org.shedlang.compiler.types.Type;
-public record TypedFieldAccessNode(
+public record TypedMemberAccessNode(
TypedExpressionNode receiver,
- String fieldName,
+ String memberName,
Type type,
Source source
) implements TypedExpressionNode {
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java
index a8c068e0..ba02b9db 100644
--- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java
@@ -1,5 +1,5 @@
package org.shedlang.compiler.ast.untyped;
public sealed interface UntypedExpressionNode extends UntypedNode
- permits UntypedBinaryOperationNode, UntypedBoolLiteralNode, UntypedCallNode, UntypedFieldAccessNode, UntypedFunctionExpressionNode, UntypedIfNode, UntypedIntLiteralNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTryNode, UntypedTupleNode, UntypedUnitLiteralNode, UntypedWhenNode {
+ permits UntypedBinaryOperationNode, UntypedBoolLiteralNode, UntypedCallNode, UntypedFunctionExpressionNode, UntypedIfNode, UntypedIntLiteralNode, UntypedMemberAccessNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTryNode, UntypedTupleNode, UntypedUnitLiteralNode, UntypedWhenNode {
}
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedFieldAccessNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedMemberAccessNode.java
index f99a3c3c..3472f221 100644
--- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedFieldAccessNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedMemberAccessNode.java
@@ -2,9 +2,9 @@ package org.shedlang.compiler.ast.untyped;
import org.shedlang.compiler.sources.Source;
-public record UntypedFieldAccessNode(
+public record UntypedMemberAccessNode(
UntypedExpressionNode receiver,
- String fieldName,
+ String memberName,
Source source
) implements UntypedExpressionNode {
}
diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java
index 328a1ec9..680ead15 100644
--- a/src/main/java/org/shedlang/compiler/parser/Parser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Parser.java
@@ -333,7 +333,7 @@ public class Parser {
}
private static final Map<TokenType, OperationParser<OperatorPrecedence, UntypedExpressionNode>> OPERATION_PARSERS = Stream.of(
- new FieldAccessParser(),
+ new MemberAccessParser(),
new BinaryOperationParser(TokenType.SYMBOL_EQUALS_EQUALS, OperatorPrecedence.EQUALS, UntypedBinaryOperator.EQUALS),
new BinaryOperationParser(TokenType.SYMBOL_BANG_EQUALS, OperatorPrecedence.EQUALS, UntypedBinaryOperator.NOT_EQUAL),
new BinaryOperationParser(TokenType.SYMBOL_PLUS, OperatorPrecedence.ADD, UntypedBinaryOperator.ADD),
@@ -405,35 +405,6 @@ public class Parser {
);
}
- private static class FieldAccessParser implements OperationParser<
- OperatorPrecedence,
- UntypedExpressionNode
- > {
- @Override
- public OperatorPrecedence precedence() {
- return OperatorPrecedence.CALL;
- }
-
- @Override
- public Stream<TokenType> operatorTokenTypes() {
- return Stream.of(TokenType.SYMBOL_DOT);
- }
-
- @Override
- public UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator<TokenType> tokens) {
- var start = left.source().start();
-
- tokens.skip(TokenType.SYMBOL_DOT);
-
- var fieldName = tokens.nextValue(TokenType.IDENTIFIER);
-
- var end = tokens.position();
- var source = start.to(end);
-
- return new UntypedFieldAccessNode(left, fieldName, source);
- }
- }
-
private static UntypedFunctionDefinitionNode parseFunctionDefinition(TokenIterator<TokenType> tokens) {
var start = tokens.position();
@@ -745,6 +716,35 @@ public class Parser {
}
}
+ private static class MemberAccessParser implements OperationParser<
+ OperatorPrecedence,
+ UntypedExpressionNode
+ > {
+ @Override
+ public OperatorPrecedence precedence() {
+ return OperatorPrecedence.CALL;
+ }
+
+ @Override
+ public Stream<TokenType> operatorTokenTypes() {
+ return Stream.of(TokenType.SYMBOL_DOT);
+ }
+
+ @Override
+ public UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator<TokenType> tokens) {
+ var start = left.source().start();
+
+ tokens.skip(TokenType.SYMBOL_DOT);
+
+ var memberName = tokens.nextValue(TokenType.IDENTIFIER);
+
+ var end = tokens.position();
+ var source = start.to(end);
+
+ return new UntypedMemberAccessNode(left, memberName, source);
+ }
+ }
+
public static NamespaceName parseNamespaceName(TokenIterator<TokenType> tokens) {
var namespaceNameParts = parseOneOrMoreNoTrailingSeparator(
() -> tokens.nextValue(TokenType.IDENTIFIER),
diff --git a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
index 16c1c3de..48dbbf3c 100644
--- a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
@@ -143,9 +143,6 @@ public class ShidCodeGen {
case TypedCallNode typedCallNode ->
compileCall(typedCallNode, context);
- case TypedFieldAccessNode typedFieldAccessNode ->
- compileFieldAccess(typedFieldAccessNode, context);
-
case TypedFunctionExpressionNode typedFunctionExpressionNode ->
compileFunctionExpression(typedFunctionExpressionNode, context);
@@ -155,6 +152,9 @@ public class ShidCodeGen {
case TypedIntLiteralNode typedIntLiteralNode ->
compileIntLiteral(typedIntLiteralNode, context);
+ case TypedMemberAccessNode typedMemberAccessNode ->
+ compileMemberAccess(typedMemberAccessNode, context);
+
case TypedReferenceNode typedReferenceNode ->
compileReference(typedReferenceNode, context);
@@ -184,46 +184,6 @@ public class ShidCodeGen {
return context;
}
- private static Context compileFieldAccess(
- TypedFieldAccessNode node,
- Context context
- ) {
- context = compileExpression(node.receiver(), context);
- // TODO: handle not a type with fields
- var receiverType = node.receiver().type();
- var receiver = receiverTypeToReceiver(receiverType);
-
- context = context.addInstruction(new ShidFieldLoad(
- receiver,
- node.fieldName(),
- node.source()
- ));
- return context;
- }
-
- private static ShidFieldLoad.Receiver receiverTypeToReceiver(Type receiverType) {
- return switch (receiverType) {
- case ConstructedType constructedType ->
- receiverTypeToReceiver(constructedType.genericType());
-
- case NamespaceType namespaceType ->
- new ShidFieldLoad.Receiver.Namespace(namespaceType.namespaceName());
-
- case SimpleStructType structType ->
- new ShidFieldLoad.Receiver.Struct(structType);
-
- case TypeLevelValueType typeLevelValueType -> {
- if (typeLevelValueType.value() instanceof UserDefinedEffect effect) {
- yield new ShidFieldLoad.Receiver.Effect(effect);
- } else {
- throw new RuntimeException("not a type with fields");
- }
- }
-
- default -> throw new RuntimeException("not a type with fields");
- };
- }
-
private static Context compileFunction(
String name,
TypedParamsNode params,
@@ -426,6 +386,46 @@ public class ShidCodeGen {
return context.addInstruction(new ShidPushInt(node.value(), node.source()));
}
+ private static Context compileMemberAccess(
+ TypedMemberAccessNode node,
+ Context context
+ ) {
+ context = compileExpression(node.receiver(), context);
+ // TODO: handle not a type with member
+ var receiverType = node.receiver().type();
+ var receiver = receiverTypeToReceiver(receiverType);
+
+ context = context.addInstruction(new ShidFieldLoad(
+ receiver,
+ node.memberName(),
+ node.source()
+ ));
+ return context;
+ }
+
+ private static ShidFieldLoad.Receiver receiverTypeToReceiver(Type receiverType) {
+ return switch (receiverType) {
+ case ConstructedType constructedType ->
+ receiverTypeToReceiver(constructedType.genericType());
+
+ case NamespaceType namespaceType ->
+ new ShidFieldLoad.Receiver.Namespace(namespaceType.namespaceName());
+
+ case SimpleStructType structType ->
+ new ShidFieldLoad.Receiver.Struct(structType);
+
+ case TypeLevelValueType typeLevelValueType -> {
+ if (typeLevelValueType.value() instanceof UserDefinedEffect effect) {
+ yield new ShidFieldLoad.Receiver.Effect(effect);
+ } else {
+ throw new RuntimeException("not a type with fields");
+ }
+ }
+
+ default -> throw new RuntimeException("not a type with fields");
+ };
+ }
+
public static ShidNamespace compileNamespace(TypedNamespaceNode node) {
var context = Context.EMPTY.enterBlock(node.boundVariables(), node.source());
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index 997a4607..181d41e3 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -623,9 +623,6 @@ public class TypeChecker {
case UntypedCallNode untypedCall ->
typeCheckCall(untypedCall, context);
- case UntypedFieldAccessNode untypedFieldAccess ->
- typeCheckFieldAccess(untypedFieldAccess, context);
-
case UntypedFunctionExpressionNode untypedFunctionExpression ->
typeCheckFunctionExpression(untypedFunctionExpression, hint, context);
@@ -635,6 +632,9 @@ public class TypeChecker {
case UntypedIntLiteralNode untypedIntLiteral ->
typeCheckIntLiteral(untypedIntLiteral, context);
+ case UntypedMemberAccessNode untypedMemberAccess ->
+ typeCheckMemberAccess(untypedMemberAccess, context);
+
case UntypedReferenceNode untypedReference ->
typeCheckReference(untypedReference, context);
@@ -680,81 +680,6 @@ public class TypeChecker {
});
}
- private static TypeCheckerResult<TypedFieldAccessNode> typeCheckFieldAccess(
- UntypedFieldAccessNode untyped,
- TypeCheckerContext context
- ) {
- // TODO: introduce notion of members, rename field to member where appropriate
- var typedReceiverResult = typeCheckExpression(untyped.receiver(), Optional.empty(), context);
- var typedReceiver = typedReceiverResult.value();
- context = typedReceiverResult.context();
-
- var fieldType = fieldType(
- typedReceiver.type(),
- untyped.fieldName(),
- untyped.source(),
- context
- );
-
- return context.toResult(new TypedFieldAccessNode(
- typedReceiver,
- untyped.fieldName(),
- fieldType,
- untyped.source()
- ));
- }
-
- private static Type fieldType(
- Type receiverType,
- String fieldName,
- Source source,
- TypeCheckerContext context
- ) {
- return fieldTypeOrEmpty(receiverType, fieldName, source, context)
- .orElseThrow(() -> new NoSuchFieldError(receiverType, fieldName, source));
- }
-
- private static Optional<Type> fieldTypeOrEmpty(
- Type receiverType,
- String fieldName,
- Source source,
- TypeCheckerContext context
- ) {
- switch (receiverType) {
- case ConstructedType<?> receiverTypeConstructed -> {
- return fieldTypeOrEmpty(
- receiverTypeConstructed.genericType(),
- fieldName,
- source,
- context
- ).map(genericFieldType -> TypeSubstitution.substituteType(
- genericFieldType,
- receiverTypeConstructed.typeSubstitutionMap()
- ));
- }
-
- case SimpleStructType receiverTypeStruct -> {
- var structTypeInfo = context.structTypeInfo(receiverTypeStruct, source);
- return structTypeInfo.fieldType(fieldName);
- }
-
- case NamespaceType receiverTypeNamespace -> {
- var namespaceTypeInfo = context.namespaceTypeInfo(receiverTypeNamespace, source);
- return namespaceTypeInfo.fieldType(fieldName);
- }
-
- case TypeLevelValueType receiverTypeTypeLevelValue when receiverTypeTypeLevelValue.value() instanceof UserDefinedEffect effect -> {
- var effectInfo = context.userDefinedEffectInfo(effect, source);
- return effectInfo.methodType(fieldName)
- .map(x -> x.withEffect(effect));
- }
-
- default -> {
- return Optional.empty();
- }
- }
- }
-
static TypeCheckerResult<TypedFunctionBodyNode> typeCheckFunctionBody(
UntypedBlockNode untyped,
PartialFunctionSignature signature,
@@ -1380,6 +1305,80 @@ public class TypeChecker {
));
}
+ private static TypeCheckerResult<TypedMemberAccessNode> typeCheckMemberAccess(
+ UntypedMemberAccessNode untyped,
+ TypeCheckerContext context
+ ) {
+ var typedReceiverResult = typeCheckExpression(untyped.receiver(), Optional.empty(), context);
+ var typedReceiver = typedReceiverResult.value();
+ context = typedReceiverResult.context();
+
+ var memberType = memberType(
+ typedReceiver.type(),
+ untyped.memberName(),
+ untyped.source(),
+ context
+ );
+
+ return context.toResult(new TypedMemberAccessNode(
+ typedReceiver,
+ untyped.memberName(),
+ memberType,
+ untyped.source()
+ ));
+ }
+
+ private static Type memberType(
+ Type receiverType,
+ String memberName,
+ Source source,
+ TypeCheckerContext context
+ ) {
+ return memberTypeOrEmpty(receiverType, memberName, source, context)
+ .orElseThrow(() -> new NoSuchFieldError(receiverType, memberName, source));
+ }
+
+ private static Optional<Type> memberTypeOrEmpty(
+ Type receiverType,
+ String memberName,
+ Source source,
+ TypeCheckerContext context
+ ) {
+ switch (receiverType) {
+ case ConstructedType<?> receiverTypeConstructed -> {
+ return memberTypeOrEmpty(
+ receiverTypeConstructed.genericType(),
+ memberName,
+ source,
+ context
+ ).map(genericFieldType -> TypeSubstitution.substituteType(
+ genericFieldType,
+ receiverTypeConstructed.typeSubstitutionMap()
+ ));
+ }
+
+ case SimpleStructType receiverTypeStruct -> {
+ var structTypeInfo = context.structTypeInfo(receiverTypeStruct, source);
+ return structTypeInfo.fieldType(memberName);
+ }
+
+ case NamespaceType receiverTypeNamespace -> {
+ var namespaceTypeInfo = context.namespaceTypeInfo(receiverTypeNamespace, source);
+ return namespaceTypeInfo.fieldType(memberName);
+ }
+
+ case TypeLevelValueType receiverTypeTypeLevelValue when receiverTypeTypeLevelValue.value() instanceof UserDefinedEffect effect -> {
+ var effectInfo = context.userDefinedEffectInfo(effect, source);
+ return effectInfo.methodType(memberName)
+ .map(x -> x.withEffect(effect));
+ }
+
+ default -> {
+ return Optional.empty();
+ }
+ }
+ }
+
public static TypeCheckerResult<TypedNamespaceNode> typeCheckNamespace(
UntypedNamespaceNode untyped,
TypeCheckerContext context