2
2
* Copyright (C) 2012-2014 Typesafe Inc. <http://www.typesafe.com>
3
3
*/
4
4
5
- sealed abstract class Type (val code : Char , val prim : String , val ref : String )
5
+ sealed abstract class Type (val code : Char , val prim : String , val ref : String ) {
6
+ def boxed : String = ref
7
+ }
6
8
object Type {
7
9
case object Boolean extends Type ('Z' , " boolean" , " Boolean" )
8
10
case object Byte extends Type ('B' , " byte" , " Byte" )
@@ -12,7 +14,7 @@ object Type {
12
14
case object Float extends Type ('F' , " float" , " Float" )
13
15
case object Double extends Type ('D' , " double" , " Double" )
14
16
case object Long extends Type ('J' , " long" , " Long" )
15
- case object Void extends Type ('V' , " void" , " Void " )
17
+ case object Void extends Type ('V' , " void" , " BoxedUnit " )
16
18
case object Object extends Type ('L' , " Object" , " Object" )
17
19
}
18
20
@@ -95,33 +97,106 @@ object CodeGen {
95
97
val vparams = csv(n => s " T $n t $n" )
96
98
val vparamRefs = csv(n => s " t $n" )
97
99
val parent = " JFunction" + n
98
- s """
99
- | $copyright
100
- |
101
- | $packaging
102
- |
103
- |import scala.runtime.BoxedUnit;
104
- |
105
- |@FunctionalInterface
106
- |public interface JProcedure ${n}< ${tparams}> extends ${parent}< $tparams, BoxedUnit> {
107
- | default void $initName() {
108
- | }
109
- |
110
- | void applyVoid( $vparams);
111
- |
112
- | default BoxedUnit apply( $vparams) {
113
- | applyVoid( $vparamRefs);
114
- | return BoxedUnit.UNIT;
115
- | }
116
- |}
117
- | """ .stripMargin
100
+ if (n == 0 )
101
+ s """
102
+ | $copyright
103
+ |
104
+ | $packaging
105
+ |
106
+ |import scala.runtime.BoxedUnit;
107
+ |
108
+ |@FunctionalInterface
109
+ |public interface JProcedure0 extends ${parent}<BoxedUnit> {
110
+ | default void $initName() {
111
+ | }
112
+ |
113
+ | void applyVoid();
114
+ |
115
+ | default BoxedUnit apply() {
116
+ | applyVoid();
117
+ | return BoxedUnit.UNIT;
118
+ | }
119
+ |}
120
+ | """ .stripMargin
121
+ else
122
+ s """
123
+ | $copyright
124
+ |
125
+ | $packaging
126
+ |
127
+ |import scala.runtime.BoxedUnit;
128
+ |
129
+ |@FunctionalInterface
130
+ |public interface JProcedure ${n}< ${tparams}> extends ${parent}< $tparams, BoxedUnit> {
131
+ | default void $initName() {
132
+ | }
133
+ |
134
+ | void applyVoid( $vparams);
135
+ |
136
+ | default BoxedUnit apply( $vparams) {
137
+ | applyVoid( $vparamRefs);
138
+ | return BoxedUnit.UNIT;
139
+ | }
140
+ |}
141
+ | """ .stripMargin
118
142
}
119
143
120
144
def factory : String = {
121
- s """
122
- |public static < $tparams, R> scala.Function $n< $tparams, R> func(JFunction $n< $tparams, R> f) { return f; }
123
- |public static < $tparams> scala.Function $n< $tparams, BoxedUnit> proc(JProcedure $n< $tparams> p) { return p; }
124
- | """ .stripMargin.trim
145
+ val specializedFactories = this .n match {
146
+ case 0 =>
147
+ val tparamNames = function0Spec.map(_._1)
148
+
149
+ def specFactory (tps : List [Type ]) = {
150
+ val List (r) = tps
151
+ val suffix = specializedSuffix(tparamNames, tps)
152
+ val name = (if (r == Type .Void ) " proc" else " func" ) + " Specialized"
153
+ s " public static scala.Function0< ${r.ref}> $name(JFunction0 $suffix f) { return f; } "
154
+ }
155
+
156
+ for {
157
+ variantTypes <- crossProduct(function0Spec.map(_._2))
158
+ } yield specFactory(variantTypes)
159
+ case 1 =>
160
+ val tparamNames = function1Spec.map(_._1)
161
+
162
+ def specFactory (tps : List [Type ]) = {
163
+ val List (t, r) = tps
164
+ val suffix = specializedSuffix(tparamNames, tps)
165
+ val name = (if (r == Type .Void ) " proc" else " func" ) + " Specialized"
166
+ s " public static scala.Function1< ${t.ref}, ${r.ref}> $name(JFunction1 $suffix f) { return f; } "
167
+ }
168
+
169
+ for {
170
+ variantTypes <- crossProduct(function1Spec.map(_._2))
171
+ } yield specFactory(variantTypes)
172
+ case 2 =>
173
+ val tparamNames = function2Spec.map(_._1)
174
+
175
+ def specFactory (tps : List [Type ]) = {
176
+ val List (t1, t2, r) = tps
177
+ val suffix = specializedSuffix(tparamNames, tps)
178
+ val name = (if (r == Type .Void ) " proc" else " func" ) + " Specialized"
179
+ s " public static scala.Function2< ${t1.ref}, ${t2.ref}, ${r.ref}> $name(JFunction2 $suffix f) { return f; } "
180
+ }
181
+
182
+ for {
183
+ variantTypes <- crossProduct(function2Spec.map(_._2))
184
+ } yield specFactory(variantTypes)
185
+ case _ =>
186
+ Nil
187
+ }
188
+ if (n == 0 )
189
+ s """
190
+ |public static <R> scala.Function $n<R> func(JFunction $n<R> f) { return f; }
191
+ |public static scala.Function $n<BoxedUnit> proc(JProcedure $n p) { return p; }
192
+ | ${specializedFactories.mkString(" \n " )}
193
+ | """ .stripMargin.trim
194
+ else
195
+ s """
196
+ |public static < $tparams, R> scala.Function $n< $tparams, R> func(JFunction $n< $tparams, R> f) { return f; }
197
+ |public static < $tparams> scala.Function $n< $tparams, BoxedUnit> proc(JProcedure $n< $tparams> p) { return p; }
198
+ | ${specializedFactories.mkString(" \n " )}
199
+ | """ .stripMargin.trim
125
200
}
126
201
127
202
def accept : String = {
@@ -138,6 +213,69 @@ object CodeGen {
138
213
}
139
214
}
140
215
216
+ def f0Specialized (tps : List [Type ]): (String , String ) = {
217
+ val tparamNames = function0Spec.map(_._1)
218
+ val suffix = specializedSuffix(tparamNames, tps)
219
+ val List (r) = tps
220
+ val applyMethodBody = if (r == Type .Void ) s " apply $suffix(); return scala.runtime.BoxedUnit.UNIT; "
221
+ else s " return ( ${r.ref}) apply $suffix(); "
222
+ val code = s """
223
+ | $copyright
224
+ |
225
+ | $packaging
226
+ |
227
+ |@FunctionalInterface
228
+ |public interface JFunction0 $suffix extends JFunction0 {
229
+ | abstract ${r.prim} apply $suffix();
230
+ |
231
+ | default Object apply() { $applyMethodBody }
232
+ |}
233
+ | """ .stripMargin
234
+ (s " JFunction0 $suffix" , code)
235
+ }
236
+
237
+
238
+ def f1Specialized (tps : List [Type ]): (String , String ) = {
239
+ val tparamNames = function1Spec.map(_._1)
240
+ val suffix = specializedSuffix(tparamNames, tps)
241
+ val List (t, r) = tps
242
+ val applyMethodBody = if (r == Type .Void ) s " apply $suffix(( ${t.ref}) t); return scala.runtime.BoxedUnit.UNIT; "
243
+ else s " return ( ${r.ref}) apply $suffix(( ${t.ref}) t); "
244
+ val code = s """
245
+ | $copyright
246
+ |
247
+ | $packaging
248
+ |
249
+ |@FunctionalInterface
250
+ |public interface JFunction1 $suffix extends JFunction1 {
251
+ | abstract ${r.prim} apply $suffix( ${t.prim} v1);
252
+ |
253
+ | default Object apply(Object t) { $applyMethodBody }
254
+ |}
255
+ | """ .stripMargin
256
+ (s " JFunction1 $suffix" , code)
257
+ }
258
+
259
+ def f2Specialized (tps : List [Type ]): (String , String ) = {
260
+ val tparamNames = function2Spec.map(_._1)
261
+ val suffix = specializedSuffix(tparamNames, tps)
262
+ val List (t1, t2, r) = tps
263
+ val applyMethodBody = if (r == Type .Void ) s " apply $suffix(( ${t1.ref}) v1, ( ${t2.ref}) v2); return scala.runtime.BoxedUnit.UNIT; "
264
+ else s " return ( ${r.ref}) apply $suffix(( ${t1.ref}) v1, ( ${t2.ref}) v2); "
265
+ val code = s """
266
+ | $copyright
267
+ |
268
+ | $packaging
269
+ |
270
+ |@FunctionalInterface
271
+ |public interface JFunction2 $suffix extends JFunction2 {
272
+ | abstract ${r.prim} apply $suffix( ${t1.prim} v1, ${t2.prim} v2);
273
+ |
274
+ | default Object apply(Object v1, Object v2) { $applyMethodBody }
275
+ |}
276
+ | """ .stripMargin
277
+ (s " JFunction2 $suffix" , code)
278
+ }
141
279
142
280
private val initName = " $init$"
143
281
private val function1ImplClass = " scala.Function1$class"
@@ -236,15 +374,17 @@ object CodeGen {
236
374
indent(List (apply, curried, tupled).mkString(" \n\n " ))
237
375
}
238
376
377
+ def specializedSuffix (tparamNames : List [String ], tps : List [Type ]): String = {
378
+ val sorted = (tps zip tparamNames).sortBy(_._2).map(_._1) // as per scalac, sort by tparam name before assembling the code
379
+ val code = sorted.map(_.code).mkString
380
+ " $mc" + code + " $sp"
381
+ }
382
+
239
383
private def specialized (name : String , tps : List [(String , List [Type ])])(f : (String , List [Type ]) => String ): String = {
240
384
val tparamNames = tps.map(_._1)
241
- def code (tps : List [Type ]) = {
242
- val sorted = (tps zip tparamNames).sortBy(_._2).map(_._1) // as per scalac, sort by tparam name before assembling the code
243
- sorted.map(_.code).mkString
244
- }
245
385
val ms = for {
246
386
variantTypes <- crossProduct(tps.map(_._2))
247
- specName = name + " $mc " + code( variantTypes) + " $sp "
387
+ specName = name + specializedSuffix(tparamNames, variantTypes)
248
388
} yield f(specName, variantTypes)
249
389
ms.mkString(" \n " )
250
390
}
@@ -267,10 +407,29 @@ object CodeGen {
267
407
List (header, specializedVariants, trailer).mkString
268
408
}
269
409
410
+ def specializedF0 : List [(String , String )] = {
411
+ val tparamNames = function0Spec.map(_._1)
412
+ for {
413
+ variantTypes <- crossProduct(function0Spec.map(_._2))
414
+ } yield f0Specialized(variantTypes)
415
+ }
416
+ def specializedF1 : List [(String , String )] = {
417
+ val tparamNames = function1Spec.map(_._1)
418
+ for {
419
+ variantTypes <- crossProduct(function1Spec.map(_._2))
420
+ } yield f1Specialized(variantTypes)
421
+ }
422
+ def specializedF2 : List [(String , String )] = {
423
+ val tparamNames = function2Spec.map(_._1)
424
+ for {
425
+ variantTypes <- crossProduct(function2Spec.map(_._2))
426
+ } yield f2Specialized(variantTypes)
427
+ }
428
+
270
429
def pN (n : Int ) = arity(n).pN
271
430
272
431
def factory : String = {
273
- val ms = (1 to 22 ).map(n => arity(n).factory).mkString(" \n " )
432
+ val ms = (0 to 22 ).map(n => arity(n).factory).mkString(" \n " )
274
433
s """
275
434
| $copyright
276
435
|
@@ -280,7 +439,6 @@ object CodeGen {
280
439
|
281
440
|public final class JFunction {
282
441
| private JFunction() {}
283
- | public static <R> scala.Function0<R> func(JFunction0<R> f) { return f; }
284
442
| ${indent(ms)}
285
443
|}
286
444
|
0 commit comments