diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-10-24 21:02:07 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-10-24 21:02:07 +0100 |
| commit | 0dccc0cdf7813c3c5571a79186a73bfd239a66d6 (patch) | |
| tree | bc313d4336b83fe774ea1d8f14064bef2d09a97b /src/main/java | |
| parent | 192cb27a8d8bc78211897c9f9325eb898390dbc4 (diff) | |
Parse function expressions
Diffstat (limited to 'src/main/java')
3 files changed, 127 insertions, 1 deletions
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 107bc20b..e8f3842d 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, UntypedIfNode, UntypedIntLiteralNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTupleNode, UntypedWhenNode { + permits UntypedBinaryOperationNode, UntypedBoolLiteralNode, UntypedCallNode, UntypedFieldAccessNode, UntypedFunctionExpressionNode, UntypedIfNode, UntypedIntLiteralNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTupleNode, UntypedWhenNode { } diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedFunctionExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedFunctionExpressionNode.java new file mode 100644 index 00000000..bc931a5a --- /dev/null +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedFunctionExpressionNode.java @@ -0,0 +1,94 @@ +package org.shedlang.compiler.ast.untyped; + +import org.pcollections.Empty; +import org.pcollections.PVector; +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.sources.Sources; + +import java.util.Optional; + +public record UntypedFunctionExpressionNode( + UntypedParamsNode params, + Optional<UntypedTypeLevelExpressionNode> effect, + UntypedTypeLevelExpressionNode returnType, + UntypedBlockNode body, + Source source +) implements UntypedExpressionNode { + public static Builder builder() { + return new Builder( + Empty.vector(), + Empty.vector(), + Optional.empty(), + new UntypedTypeLevelReferenceNode("Unit", Sources.NULL), + Empty.vector() + ); + } + + public record Builder( + PVector<UntypedParamNode> positionalParams, + PVector<UntypedParamNode> namedParams, + Optional<UntypedTypeLevelExpressionNode> effect, + UntypedTypeLevelExpressionNode returnType, + PVector<UntypedFunctionStatementNode> body + ) { + public UntypedFunctionExpressionNode build() { + return new UntypedFunctionExpressionNode( + new UntypedParamsNode(positionalParams, namedParams, Sources.NULL), + effect, + returnType, + new UntypedBlockNode(body, Sources.NULL), + Sources.NULL + ); + } + + public Builder addPositionalParam(String name, UntypedTypeLevelExpressionNode type) { + return new Builder( + this.positionalParams.plus(new UntypedParamNode(name, type, Sources.NULL)), + this.namedParams, + this.effect, + this.returnType, + this.body + ); + } + + public Builder addNamedParam(String name, UntypedTypeLevelExpressionNode type) { + return new Builder( + this.positionalParams, + this.namedParams.plus(new UntypedParamNode(name, type, Sources.NULL)), + this.effect, + this.returnType, + this.body + ); + } + + public Builder withEffect(UntypedTypeLevelExpressionNode effect) { + return new Builder( + this.positionalParams, + this.namedParams, + Optional.of(effect), + this.returnType, + this.body + ); + } + + public Builder withReturnType(UntypedTypeLevelExpressionNode returnType) { + return new Builder( + this.positionalParams, + this.namedParams, + this.effect, + returnType, + this.body + ); + } + + public Builder addStatement(UntypedFunctionStatementNode statement) { + return new Builder( + this.positionalParams, + this.namedParams, + this.effect, + this.returnType, + this.body.plus(statement) + ); + } + } +} diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index 13b62323..fefd6d62 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -314,6 +314,36 @@ public class Parser { ); } + private static UntypedExpressionNode parseFunctionExpression( + TokenIterator<TokenType> tokens + ) { + var start = tokens.position(); + + tokens.skip(TokenType.KEYWORD_FN); + + tokens.skip(TokenType.SYMBOL_PAREN_OPEN); + var params = parseParams(tokens); + tokens.skip(TokenType.SYMBOL_PAREN_CLOSE); + + var effect = parseFunctionTypeEffect(tokens); + + tokens.skip(TokenType.SYMBOL_THIN_ARROW); + var returnType = parseTopLevelTypeLevelExpression(tokens); + + var body = parseBlock(tokens); + + var end = tokens.position(); + var source = start.to(end); + + return new UntypedFunctionExpressionNode( + params, + effect, + returnType, + body, + source + ); + } + private static UntypedFunctionStatementNode parseFunctionReturn(TokenIterator<TokenType> tokens) { var start = tokens.position(); @@ -670,6 +700,8 @@ public class Parser { case KEYWORD_FALSE, KEYWORD_TRUE -> parseBoolLiteral(tokens); + case KEYWORD_FN -> parseFunctionExpression(tokens); + case KEYWORD_WHEN -> parseWhen(tokens); case STRING -> parseStringLiteral(tokens); |
