aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/org/shedlang/compiler/parser
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-22 22:23:01 +0100
committerMichael Williamson <mike@zwobble.org>2023-10-22 22:23:01 +0100
commitd1d0984bc8a157a2f001d3c991dae5c9498cd790 (patch)
tree89056dc50059c60c4ce1bf9aa18a8045fb282036 /src/test/java/org/shedlang/compiler/parser
parentbc94a020433c8b7dc0adaa2a6adf235da9c9b4e9 (diff)
Parse function types
Diffstat (limited to 'src/test/java/org/shedlang/compiler/parser')
-rw-r--r--src/test/java/org/shedlang/compiler/parser/ParserFunctionTypeTests.java168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/test/java/org/shedlang/compiler/parser/ParserFunctionTypeTests.java b/src/test/java/org/shedlang/compiler/parser/ParserFunctionTypeTests.java
new file mode 100644
index 00000000..467930a3
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/parser/ParserFunctionTypeTests.java
@@ -0,0 +1,168 @@
+package org.shedlang.compiler.parser;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+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.*;
+
+public class ParserFunctionTypeTests {
+ @Test
+ public void canParseFunctionTypeWithNoParamsAndNoEffect() {
+ var source = "fn () -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withParams(isUntypedParamTypesNode(
+ isSequence(),
+ isSequence()
+ ))
+ .withEffect(isOptionalEmpty())
+ .withReturnType(isUntypedTypeLevelReferenceNode("Unit"))
+ );
+ }
+
+ @Test
+ public void canParseFunctionWithSinglePositionalParam() {
+ var source = "fn (Int) -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withParams(isUntypedParamTypesNode(
+ isSequence(
+ isUntypedTypeLevelReferenceNode("Int")
+ ),
+ isSequence()
+ ))
+ );
+ }
+
+ @Test
+ public void canParseFunctionWithManyPositionalParams() {
+ var source = "fn (Int, String, Bool) -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withParams(isUntypedParamTypesNode(
+ isSequence(
+ isUntypedTypeLevelReferenceNode("Int"),
+ isUntypedTypeLevelReferenceNode("String"),
+ isUntypedTypeLevelReferenceNode("Bool")
+ ),
+ isSequence()
+ ))
+ );
+ }
+
+ @Test
+ public void canParseFunctionWithSingleNamedParam() {
+ var source = "fn (.a: Int) -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withParams(isUntypedParamTypesNode(
+ isSequence(),
+ isSequence(
+ isUntypedParamNode("a", isUntypedTypeLevelReferenceNode("Int"))
+ )
+ ))
+ );
+ }
+
+ @Test
+ public void canParseFunctionWithManyNamedParams() {
+ var source = "fn (.a: Int, .b: String, .c: Bool) -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withParams(isUntypedParamTypesNode(
+ isSequence(),
+ isSequence(
+ isUntypedParamNode("a", isUntypedTypeLevelReferenceNode("Int")),
+ isUntypedParamNode("b", isUntypedTypeLevelReferenceNode("String")),
+ isUntypedParamNode("c", isUntypedTypeLevelReferenceNode("Bool"))
+ )
+ ))
+ );
+ }
+
+ @Test
+ public void canParseNamedParamAfterPositionalParam() {
+ var source = "fn (Int, .b: String) -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withParams(isUntypedParamTypesNode(
+ isSequence(
+ isUntypedTypeLevelReferenceNode("Int")
+ ),
+ isSequence(
+ isUntypedParamNode("b", isUntypedTypeLevelReferenceNode("String"))
+ )
+ ))
+ );
+ }
+
+ @Test
+ public void cannotParsePositionalParamAfterNamedParam() {
+ var source = "fn (.a: Int, String) -> Unit";
+
+ assertThrows(
+ PositionalParamAfterNamedParamError.class,
+ () -> parseString(source, Parser::parseTopLevelTypeLevelExpression)
+ );
+ }
+
+ @Test
+ public void paramsCanHaveTrailingComma() {
+ var source = """
+ fun f(a: Int, ) -> Unit {
+ }""";
+
+ var node = parseString(source, Parser::parseNamespaceStatement);
+
+ assertThat(
+ node,
+ isUntypedFunctionDefinitionNode()
+ .withParams(isUntypedParamsNode(
+ isSequence(
+ isUntypedParamNode("a", isUntypedTypeLevelReferenceNode("Int"))
+ ),
+ isSequence()
+ ))
+ );
+ }
+
+ @Test
+ public void canParseFunctionTypeWithEffect() {
+ var source = "fn () ! Io -> Unit";
+
+ var node = parseString(source, Parser::parseTopLevelTypeLevelExpression);
+
+ assertThat(
+ node,
+ isUntypedFunctionTypeNode()
+ .withEffect(isOptionalOf(isUntypedTypeLevelReferenceNode("Io")))
+ );
+ }
+}