22 * Copyright (C) 2012-2014 Typesafe Inc. <http://www.typesafe.com>
33 */
44
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+ }
68object Type {
79 case object Boolean extends Type ('Z' , " boolean" , " Boolean" )
810 case object Byte extends Type ('B' , " byte" , " Byte" )
@@ -12,7 +14,7 @@ object Type {
1214 case object Float extends Type ('F' , " float" , " Float" )
1315 case object Double extends Type ('D' , " double" , " Double" )
1416 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 " )
1618 case object Object extends Type ('L' , " Object" , " Object" )
1719}
1820
@@ -95,33 +97,106 @@ object CodeGen {
9597 val vparams = csv(n => s " T $n t $n" )
9698 val vparamRefs = csv(n => s " t $n" )
9799 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
118142 }
119143
120144 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
125200 }
126201
127202 def accept : String = {
@@ -138,6 +213,69 @@ object CodeGen {
138213 }
139214 }
140215
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+ }
141279
142280 private val initName = " $init$"
143281 private val function1ImplClass = " scala.Function1$class"
@@ -236,15 +374,17 @@ object CodeGen {
236374 indent(List (apply, curried, tupled).mkString(" \n\n " ))
237375 }
238376
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+
239383 private def specialized (name : String , tps : List [(String , List [Type ])])(f : (String , List [Type ]) => String ): String = {
240384 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- }
245385 val ms = for {
246386 variantTypes <- crossProduct(tps.map(_._2))
247- specName = name + " $mc " + code( variantTypes) + " $sp "
387+ specName = name + specializedSuffix(tparamNames, variantTypes)
248388 } yield f(specName, variantTypes)
249389 ms.mkString(" \n " )
250390 }
@@ -267,10 +407,29 @@ object CodeGen {
267407 List (header, specializedVariants, trailer).mkString
268408 }
269409
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+
270429 def pN (n : Int ) = arity(n).pN
271430
272431 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 " )
274433 s """
275434 | $copyright
276435 |
@@ -280,7 +439,6 @@ object CodeGen {
280439 |
281440 |public final class JFunction {
282441 | private JFunction() {}
283- | public static <R> scala.Function0<R> func(JFunction0<R> f) { return f; }
284442 | ${indent(ms)}
285443 |}
286444 |
0 commit comments