@@ -76,19 +76,25 @@ trait VersionSpecificRepeated {
76
76
* @param ifZero the Expr to use when combining zero items together.
77
77
* If None, `newAccumulator.result()` will be used.
78
78
* If Some, should ideally be equivalent to but more efficient than the None expr.
79
- * @param ifOne the Expr to use when combining one scalar item together.
80
- * If None, `newAccumulator.+=(item).result()` will be used.
81
- * If Some, should ideally be equivalent to but more efficient than the None expr.
79
+ * @param ifOneScalar the Expr to use when combining one scalar item together.
80
+ * When not defined, `'{$newAccumulator.addOne($item).result()}` will be used.
81
+ * The definition should be equivalent to but more efficient than the undefined expr.
82
+ * @param ifOneSplice the Expr to use when combining one splice item together.
83
+ * When not defined, `'{$newAccumulator.addAll($item).result()}` will be used.
84
+ * The definition should be equivalent to but more efficient than the undefined expr.
82
85
* @version 0.1.1
83
86
*/
84
87
def forContextFromSplicesUsingBuilder [A , Z ](c: Context )(
85
88
newAccumulator : c.Expr [Builder [A , Z ]],
86
89
ifZero : Option [() => c.Expr [Z ]],
87
- ifOne : Option [(c.Expr [A ]) => c.Expr [Z ]],
90
+ ifOneScalar : PartialFunction [c.Expr [A ], c.Expr [Z ]],
91
+ ifOneSplice : PartialFunction [c.Expr [Iterable [A ]], c.Expr [Z ]],
88
92
)(implicit
89
93
accumulatorType : c.universe.TypeTag [Builder [A , Z ]],
90
94
zType : c.universe.TypeTag [Z ],
91
95
): Repeated [SplicePiece [c.Expr , A ], c.Expr [Z ]] = {
96
+ // using default arguments confuses the typechecker (found `c.Expr` required `x$1.Expr`), so don't provide default arguments
97
+
92
98
import c .universe .Tree
93
99
import c .universe .Quasiquote
94
100
@@ -107,7 +113,8 @@ trait VersionSpecificRepeated {
107
113
108
114
sealed trait Acc
109
115
final object AccZero extends Acc
110
- final class AccOne (val elem : c.Expr [A ]) extends Acc
116
+ final class AccOneScalar (val elem : c.Expr [A ]) extends Acc
117
+ final class AccOneSplice (val iter : c.Expr [Iterable [A ]]) extends Acc
111
118
final class AccMany extends Acc {
112
119
val builder : Builder [Tree , c.Expr [Z ]] = List .newBuilder.mapResult(stat =>
113
120
c.Expr [Z ](
@@ -124,27 +131,39 @@ trait VersionSpecificRepeated {
124
131
case AccZero =>
125
132
elem match {
126
133
case _ : SplicePiece .Zero [c.Expr ] => AccZero
127
- case elemOne : SplicePiece .One [c.Expr , A ] => new AccOne (elemOne.elem)
128
- case elemMany : SplicePiece .Many [c.Expr , A ] => {
134
+ case elemOne : SplicePiece .One [c.Expr , A ] => new AccOneScalar (elemOne.elem)
135
+ case elemMany : SplicePiece .Many [c.Expr , A ] => new AccOneSplice (elemMany.iter)
136
+ }
137
+ case accOne : AccOneScalar => {
138
+ elem match {
139
+ case _ : SplicePiece .Zero [c.Expr ] => accOne
140
+ case elemOne : SplicePiece .One [c.Expr , A ] =>
129
141
val retval = new AccMany ()
130
142
retval.builder += accumulatorValDef
143
+ retval.builder += q " $accumulatorIdent.+=( ${accOne.elem}) "
144
+ retval.builder += q " $accumulatorIdent.+=( ${elemOne.elem}) "
145
+ retval
146
+ case elemMany : SplicePiece .Many [c.Expr , A ] =>
147
+ val retval = new AccMany ()
148
+ retval.builder += accumulatorValDef
149
+ retval.builder += q " $accumulatorIdent.+=( ${accOne.elem}) "
131
150
retval.builder += q " $accumulatorIdent.++=( ${elemMany.iter}) "
132
151
retval
133
- }
134
152
}
135
- case accOne : AccOne => {
153
+ }
154
+ case accOne : AccOneSplice => {
136
155
elem match {
137
156
case _ : SplicePiece .Zero [c.Expr ] => accOne
138
157
case elemOne : SplicePiece .One [c.Expr , A ] =>
139
158
val retval = new AccMany ()
140
159
retval.builder += accumulatorValDef
141
- retval.builder += q " $accumulatorIdent.+=( ${accOne.elem }) "
160
+ retval.builder += q " $accumulatorIdent.++ =( ${accOne.iter }) "
142
161
retval.builder += q " $accumulatorIdent.+=( ${elemOne.elem}) "
143
162
retval
144
163
case elemMany : SplicePiece .Many [c.Expr , A ] =>
145
164
val retval = new AccMany ()
146
165
retval.builder += accumulatorValDef
147
- retval.builder += q " $accumulatorIdent.+=( ${accOne.elem }) "
166
+ retval.builder += q " $accumulatorIdent.++ =( ${accOne.iter }) "
148
167
retval.builder += q " $accumulatorIdent.++=( ${elemMany.iter}) "
149
168
retval
150
169
}
@@ -165,7 +184,8 @@ trait VersionSpecificRepeated {
165
184
def result (acc: Acc ): c.Expr [Z ] = {
166
185
acc match {
167
186
case AccZero => ifZero.map(_.apply()).getOrElse(c.Expr [Z ](q " $newAccumulator.result() " ))
168
- case accOne : AccOne => ifOne.map(_.apply(accOne.elem)).getOrElse(c.Expr [Z ](q " $newAccumulator.+=( ${accOne.elem}).result() " ))
187
+ case accOne : AccOneScalar => ifOneScalar.applyOrElse(accOne.elem, (e : c.Expr [A ]) => c.Expr [Z ](q " $newAccumulator.+=( ${e}).result() " ))
188
+ case accOne : AccOneSplice => ifOneSplice.applyOrElse(accOne.iter, (es : c.Expr [Iterable [A ]]) => c.Expr [Z ](q " $newAccumulator.++=( ${es}).result() " ))
169
189
case accMany : AccMany => accMany.builder.result()
170
190
}
171
191
}
@@ -185,7 +205,8 @@ trait VersionSpecificRepeated {
185
205
forContextFromSplicesUsingBuilder[A , List [A ]](c)(
186
206
c.universe.reify(List .newBuilder),
187
207
Option (() => c.universe.reify(List .empty)),
188
- Option ((a : c.Expr [A ]) => c.universe.reify(List (a.splice))),
208
+ {case (a : c.Expr [A ]) => c.universe.reify(List (a.splice))},
209
+ {case (a : c.Expr [_]) if a.staticType <:< zType.tpe => c.Expr [List [A ]](a.tree)},
189
210
)
190
211
}
191
212
}
0 commit comments