@@ -43,64 +43,65 @@ Let's define some abstractions on the possible results of this pattern matching
4343type Matching = Option [Tuple ]
4444type Env
4545
46- def noMatch = None
47- def emptyMatch = Some (()) // aka Some(Tuple0())
48- def match [T ](x : T ) = Some (Tuple1 (x))
49- def (x : Matching ) ++ (y : Matching ) = if (x == None || y == None ) None else Some (x.get ++ y.get)
50- def fold [T ](m : Mattching * ) given Env : Matching = m.fold(emptyMatch )(_ ++ _)
46+ def notMatched = None
47+ def matched = Some (()) // aka Some(Tuple0())
48+ def matched [T ](x : T ) = Some (Tuple1 (x))
49+ def (x : Matching ) && (y : Matching ) = if (x == None || y == None ) None else Some (x.get ++ y.get)
50+ def fold [T ](m : Mattching * ) given Env : Matching = m.fold(matched )(_ && _)
5151
52- def matches (scrutinee : Tree , pattern : Tree ) given Env : Matching // described by cases in the tables below
52+ // `a =#= b` stands for `a` matches `b`
53+ def (scrutinee : Tree ) =#= pattern : Tree ) given Env : Matching // described by cases in the tables below
5354
5455def envWith (equiv : (Symbol , Symbol )* ) given Env : Env // Adds to the current environment the fact that s1 from the scrutinee is equivalent to s2 in the pattern
5556
5657def equivalent (s1 : Symbol , s2 : Symbol ) given Env : Env
5758```
5859
59- The implementation of ` matches `
60+ The implementation of ` =#= `
6061
6162| Tree | Pattern | Returns |
6263| :-----------------------: | :-------------------------: | :---------- |
6364| Term ` a ` | ` patternHole[X] ` | ` match(quoted.Expr[X]('a)) ` if type of ` a ` is a subtype of ` X `
64- | ` val a: A ` | ` @patternBindHole val x: X ` | ` match(quoted.Bind[X](a.sym)) ++ matches( '{val a: A}, '{val x: X}) `
65- | Literal ` a ` | Literal ` x ` | ` emptyMatch ` if value of ` a ` is equal to the value of ` x `
66- | ` a ` | ` x ` | ` emptyMatch ` if ` equivalent(a.sym, x.sym) `
67- | ` a.b ` | ` x.y ` | ` matches('a, 'x) ` if ` equivalent(b.sym, y.sym) `
68- | ` a: A ` | ` x: X ` | ` matches('a, 'x) ++ matches( '[A], '[X]) `
69- | ` fa(.. ai ..) ` | ` fx(.. xi ..) ` | ` matches( 'fa, 'fx) ++ fold(.. matches( 'ai, 'xi) ..)`
70- | ` fa[.. Ai ..] ` | ` fx[.. Xi ..] ` | ` matches( 'fa, 'fx) ++ fold(.. matches( '[Ai], '[Xi]) ..)`
71- | ` {.. ai ..} ` | ` {.. xi ..} ` | ` fold(.. matches( 'ai, 'xi) ..) `
72- | ` if (a) b else c ` | ` if (x) y else z ` | ` matches('a, 'x) ++ matches('b, 'y) ++ matches('c, 'z) `
73- | ` while (a) b ` | ` while (x) y ` | ` matches('a, 'x) ++ matches('b, 'y) `
74- | Assignment ` a = b ` | Assignment ` x = y ` | ` matches('b, 'y) ` if ` matches('a, 'x) .nonEmpty`
75- | Named argument<br >` n = a ` | Named argument<br >` m = x ` | ` matches('a, 'x) `
76- | ` Seq(.. ai ..): _* ` | ` Seq(.. xi ..): _* ` | ` fold(.. matches( 'ai, 'xi) ..) `
77- | ` new A ` | ` new X ` | ` matches( '[A], '[X]) `
78- | ` this ` | ` this ` | ` emptyMatch ` if both refer to the same symbol
79- | ` a.super[B] ` | ` x.super[Y] ` | ` matches('a, 'x) ` if ` B ` equals ` Y `
80- | ` val a: A = b ` <br >` lazy val a: A = b ` <br >` var a: A = b ` | ` val x: X = y ` <br >` lazy val x: X = y ` <br >` var x: X = y ` | ` matches( '[A], '[X]) ++ matches('b, 'y) given envWith(a.sym -> b.sym)`
81- | ` def a[..Ai..](.. bij: Bij ..): A = c ` | ` def x[..Xi..](.. yij: Yij ..): X = z ` | ` fold(..matches( '[Ai], '[Xi]) ..) ++ fold(.. matches( 'bij, 'yij) ++ matches( '[Bij], '[Yij]) ..) ++ matches( '[A], '[X]) ++ matches('c, 'z) given envWith(a.sym -> b.sym, .. bij.sym -> yij.sym ..) `
82- | ` (.. ai: Ai ..) => b ` | ` (.. xi: Xi ..) => y ` | ` fold(.. matches( 'ai, 'xi) ++ matches( '[Ai], '[Xi]) ..) ++ matches('b, 'y) given envWith(.. ai.sym -> xi.sym ..) `
83- | ` a match { .. bi .. } ` | ` x match { .. yi .. } ` | ` matches('a, 'x) ++ fold(.. matches( 'bi, 'yi) ..)`
84- | ` try a catch { .. bi .. } finally ci ` | ` try x catch { .. yi .. } finally z ` | ` matches('a, 'x) ++ fold(.. matches( 'bi, 'yi) ..) ++ matches('c, 'z) `
65+ | ` val a: A ` | ` @patternBindHole val x: X ` | ` match(quoted.Bind[X](a.sym)) && '{val a: A} =#= '{val x: X} `
66+ | Literal ` a ` | Literal ` x ` | ` matched ` if value of ` a ` is equal to the value of ` x `
67+ | ` a ` | ` x ` | ` matched ` if ` equivalent(a.sym, x.sym) `
68+ | ` a.b ` | ` x.y ` | ` 'a =#= 'x ` if ` equivalent(b.sym, y.sym) `
69+ | ` a: A ` | ` x: X ` | ` 'a =#= 'x && '[A] =#= '[X]`
70+ | ` fa(.. ai ..) ` | ` fx(.. xi ..) ` | ` 'fa =#= 'fx && fold(.. 'ai =#= 'xi) ..) `
71+ | ` fa[.. Ai ..] ` | ` fx[.. Xi ..] ` | ` 'fa =#= 'fx && fold(.. '[Ai] =#= '[Xi] ..) `
72+ | ` {.. ai ..} ` | ` {.. xi ..} ` | ` fold(.. 'ai =#= 'xi ..) `
73+ | ` if (a) b else c ` | ` if (x) y else z ` | ` 'a =#= 'x && 'b =#= 'y && 'c =#= 'z `
74+ | ` while (a) b ` | ` while (x) y ` | ` 'a =#= 'x && 'b =#= 'y `
75+ | Assignment ` a = b ` | Assignment ` x = y ` | ` 'b =#= 'y ` if ` 'a =#= 'x .nonEmpty`
76+ | Named argument<br >` n = a ` | Named argument<br >` m = x ` | ` 'a =#= 'x `
77+ | ` Seq(.. ai ..): _* ` | ` Seq(.. xi ..): _* ` | ` fold(.. 'ai =#= 'xi ..) `
78+ | ` new A ` | ` new X ` | ` '[A] =#= '[X] `
79+ | ` this ` | ` this ` | ` matched ` if both refer to the same symbol
80+ | ` a.super[B] ` | ` x.super[Y] ` | ` 'a =#= 'x ` if ` B ` equals ` Y `
81+ | ` val a: A = b ` <br >` lazy val a: A = b ` <br >` var a: A = b ` | ` val x: X = y ` <br >` lazy val x: X = y ` <br >` var x: X = y ` | ` '[A] =#= '[X] && 'b =#= 'y given envWith(a.sym -> b.sym) `
82+ | ` def a[..Ai..](.. bij: Bij ..): A = c ` | ` def x[..Xi..](.. yij: Yij ..): X = z ` | ` fold(..'[Ai] =#= '[Xi]..) && fold(.. 'bij =#= 'yij && '[Bij] =#= '[Yij] ..) && '[A] =#= '[X] && 'c =#= 'z given envWith(a.sym -> b.sym, .. bij.sym -> yij.sym ..) `
83+ | ` (.. ai: Ai ..) => b ` | ` (.. xi: Xi ..) => y ` | ` fold(.. 'ai =#= 'xi && '[Ai] =#= '[Xi] ..) && 'b =#= 'y given envWith(.. ai.sym -> xi.sym ..) `
84+ | ` a match { .. bi .. } ` | ` x match { .. yi .. } ` | ` 'a =#= 'x && fold(.. 'bi =#= 'yi ..)`
85+ | ` try a catch { .. bi .. } finally ci ` | ` try x catch { .. yi .. } finally z ` | ` 'a =#= 'x && fold(.. 'bi =#= 'yi ..) && 'c =#= 'z `
8586| | |
86- | ` case a if b => c ` | ` case x if y => z ` | ` matches('a, 'x) ++ matches('b, 'y) ++ matches(c, z) `
87+ | ` case a if b => c ` | ` case x if y => z ` | ` 'a =#= 'x && 'b =#= 'y && c =#= z `
8788| | |
88- | Inferred ` A ` | Inferred ` X ` | ` emptyMatch ` if ` A <:< X `
89- | ` A[.. Bi ..] ` | ` X[.. Yi ..] ` | ` emptyMatch ` if ` (matches( '[A], '[X]) ++ fold(.. matches( '[Bi], '[Yi]) ..)).nonEmpty `
90- | ` A @annot ` | ` X ` | ` matches( '[A], '[X]) `
91- | ` A ` | ` X @annot ` | ` matches( '[A], '[X]) `
92- | | | ` noMatch `
89+ | Inferred ` A ` | Inferred ` X ` | ` matched ` if ` A <:< X `
90+ | ` A[.. Bi ..] ` | ` X[.. Yi ..] ` | ` matched ` if ` ('[A] && '[X] && fold(.. '[Bi] =#= '[Yi] ..)).nonEmpty `
91+ | ` A @annot ` | ` X ` | ` '[A] =#= '[X] `
92+ | ` A ` | ` X @annot ` | ` '[A] && '[X] `
93+ | | | ` notMatched `
9394
9495
9596| Pattern inside the quote | Pattern | Returns |
9697| :-------------------------: | :--------------------------: | :------------- |
97- | Value ` a ` | Value ` x ` | ` matches('a, 'x) `
98- | ` a: A ` | ` x: X ` | ` matches( '[A], '[X]) `
99- | ` a @ b ` | ` x @ y ` | ` matches('b, 'y) given envWith(a.sym -> b.sym)`
100- | Unapply ` a(..bi..)(..ci..) ` | Unapply ` x(..yi..)(..zi..) ` | ` matches('a, 'x) ++ fold(.. matches( 'bi, 'yi) ..) ++ fold(.. matches( 'ci, 'zi) ..)`
101- | ` .. | ai | .. ` | ` .. | xi | .. ` | ` fold(.. matches( 'ai, 'xi) ..) `
102- | ` _ ` | ` _ ` | ` emptyMatch `
103- | | | ` noMatch `
98+ | Value ` a ` | Value ` x ` | ` 'a =#= 'x `
99+ | ` a: A ` | ` x: X ` | ` '[A] && '[X] `
100+ | ` a @ b ` | ` x @ y ` | ` 'b =#= 'y given envWith(a.sym -> b.sym)`
101+ | Unapply ` a(..bi..)(..ci..) ` | Unapply ` x(..yi..)(..zi..) ` | ` 'a =#= 'x && fold(.. 'bi =#= 'yi ..) && fold(.. 'ci =#= 'zi ..)`
102+ | ` .. | ai | .. ` | ` .. | xi | .. ` | ` fold(.. 'ai =#= 'xi ..) `
103+ | ` _ ` | ` _ ` | ` matched `
104+ | | | ` notMatched `
104105
105106<!-- TODO spec for the environment from patterns propagated to the result -->
106107
0 commit comments