aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-24 21:02:07 +0100
committerMichael Williamson <mike@zwobble.org>2023-10-24 21:02:07 +0100
commit0dccc0cdf7813c3c5571a79186a73bfd239a66d6 (patch)
treebc313d4336b83fe774ea1d8f14064bef2d09a97b /src/main/java
parent192cb27a8d8bc78211897c9f9325eb898390dbc4 (diff)
Parse function expressions
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedFunctionExpressionNode.java94
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Parser.java32
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);