From 6f11bbeab6957974b3b30018deb46ef8ecde258f Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Wed, 11 Dec 2024 00:17:53 +0000 Subject: Move field positionality from struct field to struct --- .../ast/typed/TypedStructDefinitionNode.java | 14 ++++++++---- .../ast/typed/TypedStructFieldDefinitionNode.java | 1 - .../ast/untyped/UntypedStructDefinitionNode.java | 26 +++++++++++++++++----- .../untyped/UntypedStructFieldDefinitionNode.java | 1 - .../java/org/shedlang/compiler/parser/Parser.java | 23 ++++++++++--------- .../shedlang/compiler/typechecker/TypeChecker.java | 2 +- 6 files changed, 45 insertions(+), 22 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedStructDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedStructDefinitionNode.java index d87348a8..82379f7c 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedStructDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedStructDefinitionNode.java @@ -14,24 +14,28 @@ import java.util.List; public record TypedStructDefinitionNode( TypeOrConstructor typeOrConstructor, List fields, + boolean fieldsArePositional, Source source ) implements TypedNamespaceStatementNode { public static Builder builder() { var namespaceName = NamespaceName.of("Default", "Test", "Namespace"); return new Builder( TypeOrConstructor.type(Types.struct(namespaceName, "X")), - P.vector() + P.vector(), + false ); } public record Builder( TypeOrConstructor type, - PVector fields + PVector fields, + boolean fieldsArePositional ) { public TypedStructDefinitionNode build() { return new TypedStructDefinitionNode( this.type, this.fields, + this.fieldsArePositional, Sources.NULL ); } @@ -39,14 +43,16 @@ public record TypedStructDefinitionNode( public Builder withType(SimpleStructType type) { return new Builder( TypeOrConstructor.type(type), - this.fields + this.fields, + fieldsArePositional ); } public Builder addField(TypedStructFieldDefinitionNode field) { return new Builder( this.type, - this.fields.plus(field) + this.fields.plus(field), + fieldsArePositional ); } } diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedStructFieldDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedStructFieldDefinitionNode.java index 6dc492d2..a84517a0 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedStructFieldDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedStructFieldDefinitionNode.java @@ -6,7 +6,6 @@ import org.shedlang.compiler.types.Type; public record TypedStructFieldDefinitionNode( String name, TypedTypeLevelExpressionNode type, - boolean isPositional, Source source ) implements TypedNode { } diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructDefinitionNode.java index c1611322..f4493eb0 100644 --- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructDefinitionNode.java @@ -14,17 +14,19 @@ public record UntypedStructDefinitionNode( Visibility visibility, Optional> typeLevelParams, List fields, + boolean fieldsArePositional, Source source ) implements UntypedNamespaceStatementNode, UntypedVariableDeclarationNode { public static Builder builder() { - return new Builder("X", Visibility.PRIVATE, Optional.empty(), P.vector()); + return new Builder("X", Visibility.PRIVATE, Optional.empty(), P.vector(), false); } public record Builder( String name, Visibility visibility, Optional> typeLevelParams, - PVector fields + PVector fields, + boolean fieldsArePositional ) { public UntypedStructDefinitionNode build() { return new UntypedStructDefinitionNode( @@ -32,6 +34,7 @@ public record UntypedStructDefinitionNode( this.visibility, this.typeLevelParams, this.fields, + this.fieldsArePositional, Sources.NULL ); } @@ -41,7 +44,8 @@ public record UntypedStructDefinitionNode( name, this.visibility, this.typeLevelParams, - this.fields + this.fields, + this.fieldsArePositional ); } @@ -50,7 +54,8 @@ public record UntypedStructDefinitionNode( this.name, this.visibility, Optional.of(typeLevelParams), - this.fields + this.fields, + this.fieldsArePositional ); } @@ -59,7 +64,18 @@ public record UntypedStructDefinitionNode( this.name, this.visibility, this.typeLevelParams, - this.fields.plus(field) + this.fields.plus(field), + this.fieldsArePositional + ); + } + + public Builder withFieldsArePositional(boolean fieldsArePositional) { + return new Builder( + this.name, + this.visibility, + this.typeLevelParams, + this.fields, + fieldsArePositional ); } } diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java index 54883140..b2e69866 100644 --- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java @@ -5,7 +5,6 @@ import org.shedlang.compiler.sources.Source; public record UntypedStructFieldDefinitionNode( String name, UntypedTypeLevelExpressionNode type, - boolean isPositional, Source source ) implements UntypedNode { } diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index 2f6256d9..a4a23554 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -990,19 +990,14 @@ public class Parser { var typeLevelParams = parseTypeLevelParamsOptional(tokens); tokens.skip(TokenType.SYMBOL_PAREN_OPEN); + var structHasPositionalFields = !tokens.isNext(TokenType.SYMBOL_DOT); var fields = parseMany( () -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE), - () -> parseStructFieldDefinition(tokens), + () -> parseStructFieldDefinition(tokens, structHasPositionalFields), () -> tokens.trySkip(TokenType.SYMBOL_COMMA) ); tokens.skip(TokenType.SYMBOL_PAREN_CLOSE); - var anyPositionalFields = fields.stream().anyMatch(field -> field.isPositional()); - var anyNonPositionalFields = fields.stream().anyMatch(field -> !field.isPositional()); - if (anyPositionalFields && anyNonPositionalFields) { - throw new InconsistentStructFieldsError(fields.get(0).source()); - } - tokens.skip(TokenType.SYMBOL_BRACE_OPEN); tokens.skip(TokenType.SYMBOL_BRACE_CLOSE); @@ -1014,14 +1009,18 @@ public class Parser { visibility, typeLevelParams, fields, + structHasPositionalFields, source ); } - private static UntypedStructFieldDefinitionNode parseStructFieldDefinition(TokenIterator tokens) { + private static UntypedStructFieldDefinitionNode parseStructFieldDefinition( + TokenIterator tokens, + boolean structHasPositionalFields + ) { var start = tokens.position(); - var isPositional = !tokens.trySkip(TokenType.SYMBOL_DOT); + var fieldIsPositional = !tokens.trySkip(TokenType.SYMBOL_DOT); var name = tokens.nextValue(TokenType.IDENTIFIER); tokens.skip(TokenType.SYMBOL_COLON); @@ -1031,7 +1030,11 @@ public class Parser { var end = tokens.position(); var source = start.to(end); - return new UntypedStructFieldDefinitionNode(name, type, isPositional, source); + if (structHasPositionalFields ^ fieldIsPositional) { + throw new InconsistentStructFieldsError(source); + } + + return new UntypedStructFieldDefinitionNode(name, type, source); } static UntypedExpressionNode parseSubExpression(TokenIterator tokens, OperatorPrecedence parentPrecedence) { diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 08ce187b..528829fc 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -1661,7 +1661,6 @@ public class TypeChecker { var typedFieldNode = new TypedStructFieldDefinitionNode( untypedField.name(), typeCheckTypeExpression(untypedField.type(), context), - untypedField.isPositional(), untypedField.source() ); typedFieldNodes.add(typedFieldNode); @@ -1678,6 +1677,7 @@ public class TypeChecker { var typedNode = new TypedStructDefinitionNode( typeOrConstructor, typedFieldNodes, + untyped.fieldsArePositional(), untyped.source() ); -- cgit v1.2.3