@@ -29,69 +29,100 @@ object FromExpr {
29
29
* - Unlifts `'{false}` into `Some(false)`
30
30
* - Otherwise unlifts to `None`
31
31
*/
32
- given BooleanFromExpr [T <: Boolean ]: FromExpr [T ] = new PrimitiveFromExpr
32
+ given BooleanFromExpr [T <: Boolean ]: FromExpr [T ] with
33
+ def unapply (expr : Expr [T ])(using Quotes ) =
34
+ import quotes .reflect ._
35
+ for BooleanConstant (v) <- nestedConstant(expr.asTerm)
36
+ yield v.asInstanceOf [T ]
33
37
34
38
/** Default implementation of `FromExpr[Byte]`
35
39
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Byte`
36
40
* - Otherwise unlifts to `None`
37
41
*/
38
- given ByteFromExpr [T <: Byte ]: FromExpr [T ] = new PrimitiveFromExpr
42
+ given ByteFromExpr [T <: Byte ]: FromExpr [T ] with
43
+ def unapply (expr : Expr [T ])(using Quotes ) =
44
+ import quotes .reflect ._
45
+ for ByteConstant (v) <- nestedConstant(expr.asTerm)
46
+ yield v.asInstanceOf [T ]
39
47
40
48
/** Default implementation of `FromExpr[Short]`
41
49
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Short`
42
50
* - Otherwise unlifts to `None`
43
51
*/
44
- given ShortFromExpr [T <: Short ]: FromExpr [T ] = new PrimitiveFromExpr
52
+ given ShortFromExpr [T <: Short ]: FromExpr [T ] with
53
+ def unapply (expr : Expr [T ])(using Quotes ) =
54
+ import quotes .reflect ._
55
+ for ShortConstant (v) <- nestedConstant(expr.asTerm)
56
+ yield v.asInstanceOf [T ]
45
57
46
58
/** Default implementation of `FromExpr[Int]`
47
59
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Int`
48
60
* - Otherwise unlifts to `None`
49
61
*/
50
- given IntFromExpr [T <: Int ]: FromExpr [T ] = new PrimitiveFromExpr
62
+ given IntFromExpr [T <: Int ]: FromExpr [T ] with
63
+ def unapply (expr : Expr [T ])(using Quotes ) =
64
+ import quotes .reflect ._
65
+ for IntConstant (v) <- nestedConstant(expr.asTerm)
66
+ yield v.asInstanceOf [T ]
51
67
52
68
/** Default implementation of `FromExpr[Long]`
53
69
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Long`
54
70
* - Otherwise unlifts to `None`
55
71
*/
56
- given LongFromExpr [T <: Long ]: FromExpr [T ] = new PrimitiveFromExpr
72
+ given LongFromExpr [T <: Long ]: FromExpr [T ] with
73
+ def unapply (expr : Expr [T ])(using Quotes ) =
74
+ import quotes .reflect ._
75
+ for LongConstant (v) <- nestedConstant(expr.asTerm)
76
+ yield v.asInstanceOf [T ]
57
77
58
78
/** Default implementation of `FromExpr[Float]`
59
79
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Float`
60
80
* - Otherwise unlifts to `None`
61
81
*/
62
- given FloatFromExpr [T <: Float ]: FromExpr [T ] = new PrimitiveFromExpr
82
+ given FloatFromExpr [T <: Float ]: FromExpr [T ] with
83
+ def unapply (expr : Expr [T ])(using Quotes ) =
84
+ import quotes .reflect ._
85
+ for FloatConstant (v) <- nestedConstant(expr.asTerm)
86
+ yield v.asInstanceOf [T ]
63
87
64
88
/** Default implementation of `FromExpr[Double]`
65
89
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Double`
66
90
* - Otherwise unlifts to `None`
67
91
*/
68
- given DoubleFromExpr [T <: Double ]: FromExpr [T ] = new PrimitiveFromExpr
92
+ given DoubleFromExpr [T <: Double ]: FromExpr [T ] with
93
+ def unapply (expr : Expr [T ])(using Quotes ) =
94
+ import quotes .reflect ._
95
+ for DoubleConstant (v) <- nestedConstant(expr.asTerm)
96
+ yield v.asInstanceOf [T ]
69
97
70
98
/** Default implementation of `FromExpr[Char]`
71
99
* - Unlifts `'{c}` into `Some(c)` for a literal `c` of type `Char`
72
100
* - Otherwise unlifts to `None`
73
101
*/
74
- given CharFromExpr [T <: Char ]: FromExpr [T ] = new PrimitiveFromExpr
102
+ given CharFromExpr [T <: Char ]: FromExpr [T ] with
103
+ def unapply (expr : Expr [T ])(using Quotes ) =
104
+ import quotes .reflect ._
105
+ for CharConstant (v) <- nestedConstant(expr.asTerm)
106
+ yield v.asInstanceOf [T ]
75
107
76
108
/** Default implementation of `FromExpr[String]`
77
109
* - Unlifts `'{str}` into `Some(str)` for a literal `str` of type `String`
78
110
* - Otherwise unlifts to `None`
79
111
*/
80
- given StringFromExpr [T <: String ]: FromExpr [T ] = new PrimitiveFromExpr
81
-
82
- /** Lift a quoted primitive value `'{ x }` into `x` */
83
- private class PrimitiveFromExpr [T <: Boolean | Byte | Short | Int | Long | Float | Double | Char | String ] extends FromExpr [T ] {
112
+ given StringFromExpr [T <: String ]: FromExpr [T ] with
84
113
def unapply (expr : Expr [T ])(using Quotes ) =
85
114
import quotes .reflect ._
86
- def rec (tree : Term ): Option [T ] = tree match {
87
- case Literal (c) if c.value != null => Some (c.value.asInstanceOf [T ])
88
- case Block (Nil , e) => rec(e)
89
- case Typed (e, _) => rec(e)
90
- case Inlined (_, Nil , e) => rec(e)
91
- case _ => None
92
- }
93
- rec(expr.asTerm)
94
- }
115
+ for StringConstant (v) <- nestedConstant(expr.asTerm)
116
+ yield v.asInstanceOf [T ]
117
+
118
+ private def nestedConstant (using Quotes )(tree : quotes.reflect.Term ): Option [quotes.reflect.Constant ] =
119
+ import quotes .reflect ._
120
+ tree match
121
+ case Literal (c) => Some (c)
122
+ case Block (Nil , e) => nestedConstant(e)
123
+ case Typed (e, _) => nestedConstant(e)
124
+ case Inlined (_, Nil , e) => nestedConstant(e)
125
+ case _ => None
95
126
96
127
/** Default implementation of `FromExpr[Option]`
97
128
* - Unlifts `'{Some(x)}` into `Some(Some(x))` if `x` is unliftable
0 commit comments