diff --git a/effekt/shared/src/main/scala/effekt/Parser.scala b/effekt/shared/src/main/scala/effekt/Parser.scala index d73a164ed4..33362c1247 100644 --- a/effekt/shared/src/main/scala/effekt/Parser.scala +++ b/effekt/shared/src/main/scala/effekt/Parser.scala @@ -836,6 +836,10 @@ class Parser(tokens: Seq[Token], source: Source) { nonterminal: when(`at`) { Maybe.Some(captureSet(), span()) } { Maybe.None(span()) } + def maybeAtomicTypeAnnotation(): Option[AtomicType] = + nonterminal: + if peek(`:`) then Some(atomicTypeAnnotation()) else None + def maybeValueTypeAnnotation(): Option[ValueType] = nonterminal: if peek(`:`) then Some(valueTypeAnnotation()) else None @@ -852,6 +856,10 @@ class Parser(tokens: Seq[Token], source: Source) { if peek(`:`) then `:` ~> effectful() else fail("return type annotation", peek.kind) + def atomicTypeAnnotation(): AtomicType = + if peek(`:`) then `:` ~> atomicType() + else fail("a type annotation", peek.kind) + def valueTypeAnnotation(): ValueType = if peek(`:`) then `:` ~> valueType() else fail("a type annotation", peek.kind) @@ -1005,14 +1013,13 @@ class Parser(tokens: Seq[Token], source: Source) { nonterminal: peek.kind match { case `__` => skip(); IgnorePattern(span()) - case _ if isVariable => - idRef() match { + case _ if isVariable => idRef() match { case id if peek(`(`) => TagPattern(id, many(matchPattern, `(`, `,`, `)`).unspan, span()) - case IdRef(Nil, name, span) => AnyPattern(IdDef(name, span), span) + case IdRef(Nil, name, span) => + maybeAtomicTypeAnnotation() + AnyPattern(IdDef(name, span), span) case IdRef(_, name, _) => fail("Cannot use qualified names to bind a pattern variable") } - case _ if isVariable => - AnyPattern(idDef(), span()) case _ if isLiteral => LiteralPattern(literal(), span()) case `(` => some(matchPattern, `(`, `,`, `)`) match { case Many(p :: Nil , _) => fail("Pattern matching on tuples requires more than one element") diff --git a/effekt/shared/src/main/scala/effekt/source/Tree.scala b/effekt/shared/src/main/scala/effekt/source/Tree.scala index 45486e0aad..3c26ff8f4e 100644 --- a/effekt/shared/src/main/scala/effekt/source/Tree.scala +++ b/effekt/shared/src/main/scala/effekt/source/Tree.scala @@ -741,6 +741,7 @@ case class Effectful(tpe: ValueType, eff: Effects, span: Span) extends Type // These are just type aliases for documentation purposes. type BlockType = Type type ValueType = Type +type AtomicType = Type /** * Represents an annotated set of effects. Before name resolution, we cannot know diff --git a/examples/pos/patternmatching/pattern-annotations.check b/examples/pos/patternmatching/pattern-annotations.check new file mode 100644 index 0000000000..28fbb899dc --- /dev/null +++ b/examples/pos/patternmatching/pattern-annotations.check @@ -0,0 +1,19 @@ +1 +hello +--- +() +--- +0 +1 +2 +--- +test +world +--- +true +false +--- +world +test +--- +42 diff --git a/examples/pos/patternmatching/pattern-annotations.effekt b/examples/pos/patternmatching/pattern-annotations.effekt new file mode 100644 index 0000000000..352422cadc --- /dev/null +++ b/examples/pos/patternmatching/pattern-annotations.effekt @@ -0,0 +1,48 @@ +def ex1(lst: List[Int]) = lst match { + case Cons(x: Int, y) => x.show + case _ => "hello" +} + +def f { g: ((Int, String)) => Unit }: Unit = g((0, "")) + +def ex2() = f { case (x: Int, y) => () } + +def ex3() = for[(Int, String)] { [(0, "a"), (1, "b"), (2, "c")].each } { case (i: Int, s: String) => + println(i.show) +} + +def ex4(opt: Option[String]) = if (opt is Some(x: String)) x else "world" + +def ex5(opt: Option[Bool]) = { + val Some(x: Bool) = opt else false + x +} + +def ex6(str: String) = str match { + case "hello" => "world" + case s: String => s +} + +def ex7(f: Int => Int at {}) = f match { + case f: (Int => Int at {}) => f(41).show +} + +def main() = { + println(ex1([1, 2])) + println(ex1([])) + println("---") + println(ex2()) + println("---") + ex3() + println("---") + println(ex4(Some("test"))) + println(ex4(None())) + println("---") + println(ex5(Some(true))) + println(ex5(None())) + println("---") + println(ex6("hello")) + println(ex6("test")) + println("---") + println(ex7(box { x => x + 1 })) +} \ No newline at end of file