aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-11-02 18:59:09 +0000
committerMichael Williamson <mike@zwobble.org>2023-11-02 19:00:09 +0000
commit71544066ce3b74c18973e00348ea44faf052d5e5 (patch)
tree305635d30c993db52a75512c37704aa60424b1a3 /src
parent7f6bc2dcceb75538993af15167ca291db63107a8 (diff)
Parse try expressions
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedTryNode.java13
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Parser.java33
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java3
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java4
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedTryNodeMatcher.java50
-rw-r--r--src/test/java/org/shedlang/compiler/parser/ParserTryTests.java42
7 files changed, 145 insertions, 2 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 e8f3842d..60f80022 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, UntypedTupleNode, UntypedWhenNode {
+ permits UntypedBinaryOperationNode, UntypedBoolLiteralNode, UntypedCallNode, UntypedFieldAccessNode, UntypedFunctionExpressionNode, UntypedIfNode, UntypedIntLiteralNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTryNode, UntypedTupleNode, UntypedWhenNode {
}
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTryNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTryNode.java
new file mode 100644
index 00000000..b9146bb3
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTryNode.java
@@ -0,0 +1,13 @@
+package org.shedlang.compiler.ast.untyped;
+
+import org.shedlang.compiler.sources.Source;
+
+import java.util.List;
+
+public record UntypedTryNode(
+ UntypedBlockNode body,
+ UntypedTypeLevelExpressionNode handledEffect,
+ List<UntypedFunctionDefinitionNode> handlers,
+ 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 35efa5ab..1ed7799e 100644
--- a/src/main/java/org/shedlang/compiler/parser/Parser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Parser.java
@@ -363,7 +363,7 @@ public class Parser {
}
}
- private static UntypedNamespaceStatementNode parseFunctionDefinition(TokenIterator<TokenType> tokens) {
+ private static UntypedFunctionDefinitionNode parseFunctionDefinition(TokenIterator<TokenType> tokens) {
var start = tokens.position();
var visibility = parseVisibility(tokens);
@@ -808,6 +808,8 @@ public class Parser {
case KEYWORD_FN -> parseFunctionExpression(tokens);
+ case KEYWORD_TRY -> parseTry(tokens);
+
case KEYWORD_WHEN -> parseWhen(tokens);
case STRING -> parseStringLiteral(tokens);
@@ -1054,6 +1056,35 @@ public class Parser {
};
}
+ private static UntypedExpressionNode parseTry(
+ TokenIterator<TokenType> tokens
+ ) {
+ var start = tokens.position();
+
+ tokens.skip(TokenType.KEYWORD_TRY);
+
+ var body = parseBlock(tokens);
+
+ tokens.skip(TokenType.KEYWORD_HANDLE);
+
+ var handledEffect = parseTopLevelTypeLevelExpression(tokens);
+
+ tokens.skip(TokenType.SYMBOL_BRACE_OPEN);
+
+ var handlers = parseMany(
+ () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE),
+ () -> parseFunctionDefinition(tokens),
+ () -> true
+ );
+
+ tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
+
+ var end = tokens.position();
+ var source = start.to(end);
+
+ return new UntypedTryNode(body, handledEffect, handlers, source);
+ }
+
private static UntypedExpressionNode parseTuple(
TokenIterator<TokenType> tokens
) {
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index 3dcf8965..bdf185f8 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -424,6 +424,9 @@ public class TypeChecker {
case UntypedStringLiteralNode untypedStringLiteral ->
typeCheckStringLiteral(untypedStringLiteral, context);
+ case UntypedTryNode untypedTry ->
+ throw new UnsupportedOperationException("TODO");
+
case UntypedTupleNode untypedTuple ->
typeCheckTuple(untypedTuple, context);
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
index 517ca77a..a9befa70 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
@@ -311,6 +311,10 @@ public class UntypedNodeMatchers {
);
}
+ public static UntypedTryNodeMatcher isUntypedTryNode() {
+ return UntypedTryNodeMatcher.empty();
+ }
+
public static Matcher<UntypedExpressionNode> isUntypedTupleNode(
Matcher<Iterable<? extends UntypedExpressionNode>> elements
) {
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedTryNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedTryNodeMatcher.java
new file mode 100644
index 00000000..e8f3cfb6
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedTryNodeMatcher.java
@@ -0,0 +1,50 @@
+package org.shedlang.compiler.ast.untyped;
+
+import org.pcollections.PVector;
+import org.shedlang.compiler.testing.MatcherBuilder;
+import org.shedlang.compiler.util.P;
+import org.zwobble.precisely.Matcher;
+
+import static org.zwobble.precisely.Matchers.has;
+
+public class UntypedTryNodeMatcher extends MatcherBuilder<
+ UntypedExpressionNode,
+ UntypedTryNode,
+ UntypedTryNodeMatcher
+> {
+ public static UntypedTryNodeMatcher empty() {
+ return new UntypedTryNodeMatcher(P.vector());
+ }
+
+ public UntypedTryNodeMatcher(PVector<Matcher<? super UntypedTryNode>> submatchers) {
+ super(submatchers);
+ }
+
+ @Override
+ protected Class<UntypedTryNode> expectedType() {
+ return UntypedTryNode.class;
+ }
+
+ @Override
+ protected UntypedTryNodeMatcher create(
+ PVector<Matcher<? super UntypedTryNode>> submatchers
+ ) {
+ return new UntypedTryNodeMatcher(submatchers);
+ }
+
+ public UntypedTryNodeMatcher withBody(Matcher<UntypedBlockNode> body) {
+ return with(has("body", x -> x.body(), body));
+ }
+
+ public UntypedTryNodeMatcher withHandledEffect(
+ Matcher<UntypedTypeLevelExpressionNode> handledEffect
+ ) {
+ return with(has("handledEffect", x -> x.handledEffect(), handledEffect));
+ }
+
+ public UntypedTryNodeMatcher withHandlers(
+ Matcher<Iterable<? extends UntypedFunctionDefinitionNode>> handlers
+ ) {
+ return with(has("handlers", x -> x.handlers(), handlers));
+ }
+}
diff --git a/src/test/java/org/shedlang/compiler/parser/ParserTryTests.java b/src/test/java/org/shedlang/compiler/parser/ParserTryTests.java
new file mode 100644
index 00000000..951fd687
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/parser/ParserTryTests.java
@@ -0,0 +1,42 @@
+package org.shedlang.compiler.parser;
+
+import org.junit.jupiter.api.Test;
+
+import static org.shedlang.compiler.ast.untyped.UntypedNodeMatchers.*;
+import static org.shedlang.compiler.parser.ParserTesting.parseString;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.isSequence;
+
+public class ParserTryTests {
+ @Test
+ public void canParseTry() {
+ var source = """
+ try {
+ 1;
+ } handle State {
+ fun read() {
+ }
+
+ fun write() {
+ }
+ }
+ """;
+
+ var node = parseString(source, Parser::parseTopLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedTryNode()
+ .withBody(isUntypedBlockNode(isSequence(
+ isUntypedExpressionStatementNode(isUntypedIntLiteralNode(1))
+ )))
+ .withHandledEffect(isUntypedTypeLevelReferenceNode("State"))
+ .withHandlers(isSequence(
+ isUntypedFunctionDefinitionNode()
+ .withName("read"),
+ isUntypedFunctionDefinitionNode()
+ .withName("write")
+ ))
+ );
+ }
+}