Skip to content

Commit 5c11511

Browse files
committed
Add spec for quoted patterns
1 parent 58d5dca commit 5c11511

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
layout: doc-page
3+
title: "Pattern Matching on Quoted Code"
4+
---
5+
6+
7+
8+
## Overview
9+
10+
```scala
11+
def foo(x: Expr[Int]) given tasty.Reflect: Expr[Int] = x match {
12+
case '{ val $a = $x; (${Bind(`a`)}: Int) + ($y: Int) } => '{ $x + $y } // TODO needs fix for #6328, `a` is currently not in scope while typing
13+
}
14+
```
15+
16+
```scala
17+
def foo(x: Expr[Int]) given tasty.Reflect: Expr[Int] = x match {
18+
case scala.internal.quoted.Matcher.unapply[Tuple3[Bind[Int], Expr[Int], Expr[Int]]](Tuple3(a, x, Bind(`a`), y))('{ @patternBindHole val a: Int = patternHole[Int]; patternHole[Int] + patternHole[Int] }) =>
19+
}
20+
```
21+
22+
23+
## Matcher
24+
25+
At runtime to a `quoted.Expr` can be matched to another using `scala.internal.quoted.Matcher.unapply`.
26+
27+
```scala
28+
def unapply[Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup]
29+
```
30+
31+
The `scrutineeExpr` is a normal quoted expression while `patternExpr` may contain holes representing splices.
32+
The result of pattern matching is `None` if the expressions are not equivalent, otherwise it returns `Some` (some tuple) containing the contents of the matched holes.
33+
34+
35+
| Expression | Pattern | |
36+
| :-----------------------: |:-----------------------: | -------------------------------------------------------------------------: |
37+
| Literal `a` | Literal `x` | matches if `a == x` |
38+
| `a` | `x` | matches if `a` and `x` refer to the same symbol |
39+
| `a.b` | `x.y` | matches if `b` and `y` refer to the same symbol and `a` matches `x` |
40+
| `a: A` | `x: X` | matches if `a` matches `x` and `A` matches `X` |
41+
| `fa(.. bi ..)` | `fx(.. xi ..)` | matches if `fa` matches `fx` and for all `i` `ai` matches `xi` |
42+
| `fa[.. Ai ..]` | `fx[.. Xi ..]` | matches if `fa` matches `fx` and for all `i` `Ai` matches `Xi` |
43+
| `{.. ai ..}` | `{.. xi ..}` | matches if all `i` `ai` matches `xi` |
44+
| `if (a) b else c` | `if (x) y else z` | matches if `a` matches `x`, `b` matches `y` and `c` matches `z` |
45+
| `while (a) b` | `while (x) y` | matches if `a` matches `x` and `b` matches `y` |
46+
| Assignment `a = b` | Assignment `x = y` | matches if `a` matches `x`, `b` matches `y` |
47+
| Named argument `n = a` | Named argument `m = x | matches if `c1` matches `c2`, `t1` matches `t2` and `e1` matches `e2` |
48+
| `new A` | `new X` | matches if `A` matches `B` |
49+
| `this` | `this` | matches if both refer to the same symbol |
50+
| `a.super[B]` | `x.super[Y]` | matches if `a` matches `x` and `A` equals `Y` |
51+
| Repeated `ai` | Repeated `xi` | matches if for all `i` `ai` matches `xi` |
52+
> ValDef
53+
> DefDef
54+
> Lambda
55+
> Match
56+
> Try
57+
58+
| Type | Pattern | |
59+
| :-----------------------: |:-----------------------: | -------------------------------------------------------------------------: |
60+
| Inferred `A` | Inferred `X` | matches if `A <:< B` |
61+
> Applied Type
62+
> Annotated
63+
64+
65+
| Pattern inside the quote | Pattern | |
66+
| :-------------------------: |:--------------------------: | ---------------------------------------------------------------------------------: |
67+
| Value `a` | Value `x` | matches if `a` matches `x` |
68+
| `a: A` | `x: X` | matches if `A` matches `X` |
69+
| `a @ b` | `x @ y` | makes symbols of `a` and `x` equivalent and matches if `b` matches `y` |
70+
| Unapply `a(..bi..)(..ci..)` | Unapply `x(..yi..)(..zi..)` | matches if `a` matches `x` and for all `i` `bi` matches `yi` and `ci` matches `zi` |
71+
| `.. | ai | ..` | `.. | xi | ..` | matches if for all `i` `ai` matches `xi` |
72+
| `_` | `_` | always matches |
73+
74+
75+
## Quoted Patterns
76+
77+

0 commit comments

Comments
 (0)