@@ -141,115 +141,129 @@ object CodeGen {
141
141
142
142
private val initName = " $init$"
143
143
private val function1ImplClass = " scala.Function1$class"
144
- private val function2ImplClass = " scala.Function2$class"
145
144
private val copyright =
146
145
"""
147
146
|/*
148
147
| * Copyright (C) 2012-2014 Typesafe Inc. <http://www.typesafe.com>
149
148
| */""" .stripMargin.trim
150
149
151
- private def apply0MethodSpec (r : Type ): String = {
152
- val name = " apply$mc" + s " ${r.code}" + " $sp"
153
- val applyCall = s " apply(); "
154
- def body = if (r == Type .Void ) applyCall else s " return ( ${r.ref}) $applyCall"
155
- s """
156
- |default ${r.prim} $name() {
157
- | $body
158
- |}
159
- | """ .stripMargin.trim
150
+ private def function0SpecMethods = {
151
+ val apply = specialized(" apply" , function0Spec) {
152
+ case (name, List (r)) =>
153
+ val applyCall = s " apply(); "
154
+ def body = if (r == Type .Void ) applyCall else s " return ( ${r.ref}) $applyCall"
155
+ s """
156
+ |default ${r.prim} $name() {
157
+ | $body
158
+ |}
159
+ | """ .stripMargin.trim
160
+ }
161
+ indent(apply)
160
162
}
161
163
162
- private def apply0SpecMethods = {
164
+ private val function0Spec = {
163
165
val rs = List (Type .Void , Type .Byte , Type .Short , Type .Int , Type .Long , Type .Char , Type .Float , Type .Double , Type .Boolean )
164
- val methods = for (r <- rs) yield apply0MethodSpec(r)
165
- methods.map(indent).mkString(" \n\n " )
166
+ List (" R" -> rs)
166
167
}
167
-
168
- val function1SpecTs = List (Type .Int , Type .Long , Type .Float , Type .Double )
169
- val function1SpecRs = List (Type .Void , Type .Boolean , Type .Int , Type .Float , Type .Long , Type .Double )
170
-
171
- private def apply1MethodSpec (t1 : Type , r : Type ): String = {
172
- val name = " apply$mc" + s " ${r.code}${t1.code}" + " $sp"
173
- val applyCall = s " apply((T1) (( ${t1.ref}) v1)); "
174
- def body = if (r == Type .Void ) applyCall else s " return ( ${r.ref}) $applyCall"
175
-
176
- s """
177
- |default ${r.prim} $name( ${t1.prim} v1) {
178
- | $body
179
- |}
180
- | """ .stripMargin.trim
168
+ private val function1Spec = {
169
+ val ts = List (Type .Int , Type .Long , Type .Float , Type .Double )
170
+ val rs = List (Type .Void , Type .Boolean , Type .Int , Type .Float , Type .Long , Type .Double )
171
+ List (" T1" -> ts, " R" -> rs)
181
172
}
182
-
183
- private def apply1SpecMethods = {
184
- val methods = for (t1 <- function1SpecTs; r <- function1SpecRs) yield apply1MethodSpec(t1, r )
185
- methods.map(indent).mkString( " \n\n " )
173
+ private val function2Spec = {
174
+ val ts = List ( Type . Int , Type . Long , Type . Double )
175
+ val rs = List ( Type . Void , Type . Boolean , Type . Int , Type . Float , Type . Long , Type . Double )
176
+ List ( " T1 " -> ts, " T2 " -> ts, " R " -> rs )
186
177
}
187
178
188
- private def andThenComposeMethodSpec (t1 : Type , r : Type ): String = {
189
- val suffix = " $mc" + s " ${r.code}${t1.code}" + " $sp"
190
- s """
191
- |default scala.Function1 compose $suffix(scala.Function1 g) {
192
- | return compose(g);
193
- |}
194
- |default scala.Function1 andThen $suffix(scala.Function1 g) {
195
- | return andThen(g);
196
- |}
197
- | """ .stripMargin.trim
179
+ private def function1SpecMethods = {
180
+ val apply = specialized(" apply" , function1Spec) {
181
+ case (name, List (t1, r)) =>
182
+ val applyCall = s " apply((T1) (( ${t1.ref}) v1)); "
183
+ def body = if (r == Type .Void ) applyCall else s " return ( ${r.ref}) $applyCall"
184
+ s """
185
+ |default ${r.prim} $name( ${t1.prim} v1) {
186
+ | $body
187
+ |}
188
+ | """ .stripMargin.trim
189
+ }
190
+ // andThen / compose variants are no longer needed under 2.11 (@unspecialized has been fixed),
191
+ // but harmless. With them, we can use the same artifact for 2.10 and 2.11
192
+ val compose = specialized(" compose" , function1Spec) {
193
+ case (name, List (t1, r1)) =>
194
+ s """
195
+ |default scala.Function1 $name(scala.Function1 g) {
196
+ | return compose(g);
197
+ |} """ .stripMargin.trim
198
+ }
199
+ val andThen = specialized(" andThen" , function1Spec) {
200
+ case (name, List (t1, r1)) =>
201
+ s """
202
+ |default scala.Function1 $name(scala.Function1 g) {
203
+ | return andThen(g);
204
+ |} """ .stripMargin.trim
205
+ }
206
+ indent(List (apply, compose, andThen).mkString(" \n\n " ))
198
207
}
199
208
200
209
// No longer needed under 2.11 (@unspecialized has been fixed), but harmless to keep around to avoid cross-publishing this artifact.
201
- private def andThenComposeSpecMethods = {
202
- val methods = for (t1 <- function1SpecTs; r <- function1SpecRs) yield andThenComposeMethodSpec(t1, r)
203
- methods.map(indent).mkString(" \n\n " )
204
- }
205
-
206
- val function2SpecTs = List (Type .Int , Type .Long , Type .Double )
207
- val function2SpecRs = function1SpecRs
208
-
209
- private def apply2MethodSpec (t1 : Type , t2 : Type , r : Type ): String = {
210
- val name = " apply$mc" + s " ${r.code}${t1.code}${t2.code}" + " $sp"
211
- val applyCall = s " apply((T1) (( ${t1.ref}) v1), (T2) (( ${t2.ref}) v2)); "
212
- def body = if (r == Type .Void ) applyCall else s " return ( ${r.ref}) $applyCall"
213
-
214
- s """
215
- |default ${r.prim} $name( ${t1.prim} v1, ${t2.prim} v2) {
216
- | $body
217
- |}
218
- | """ .stripMargin.trim
219
- }
220
-
221
- private def apply2SpecMethods = {
222
- val methods = for (t1 <- function2SpecTs; t2 <- function2SpecTs; r <- function2SpecRs) yield apply2MethodSpec(t1, t2, r)
223
- methods.map(indent).mkString(" \n\n " )
210
+ private def function2SpecMethods = {
211
+ val apply = specialized(" apply" , function2Spec) {
212
+ case (name, List (t1, t2, r)) =>
213
+ val applyCall = s " apply((T1) (( ${t1.ref}) v1), (T2) (( ${t2.ref}) v2)); "
214
+ def body = if (r == Type .Void ) applyCall else s " return ( ${r.ref}) $applyCall"
215
+
216
+ s """
217
+ |default ${r.prim} $name( ${t1.prim} v1, ${t2.prim} v2) {
218
+ | $body
219
+ |}
220
+ | """ .stripMargin.trim
221
+ }
222
+ val curried = specialized(" curried" , function2Spec) {
223
+ case (name, List (t1, t2, r)) =>
224
+ s """
225
+ |default scala.Function1 $name() {
226
+ | return curried();
227
+ |} """ .stripMargin.trim
228
+ }
229
+ val tupled = specialized(" tupled" , function2Spec) {
230
+ case (name, List (t1, t2, r)) =>
231
+ s """
232
+ |default scala.Function1 $name() {
233
+ | return tupled();
234
+ |} """ .stripMargin.trim
235
+ }
236
+ indent(List (apply, curried, tupled).mkString(" \n\n " ))
224
237
}
225
238
226
- private def curriedTupled2MethodSpec (t1 : Type , t2 : Type , r : Type ): String = {
227
- val suffix = " $mc" + s " ${r.code}${t1.code}${t2.code}" + " $sp"
228
- s """
229
- |default scala.Function1 curried $suffix() {
230
- | return curried();
231
- |}
232
- |default scala.Function1 tupled $suffix() {
233
- | return tupled();
234
- |}
235
- | """ .stripMargin.trim
239
+ private def specialized (name : String , tps : List [(String , List [Type ])])(f : (String , List [Type ]) => String ): String = {
240
+ 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
+ val ms = for {
246
+ variantTypes <- crossProduct(tps.map(_._2))
247
+ specName = name + " $mc" + code(variantTypes) + " $sp"
248
+ } yield f(specName, variantTypes)
249
+ ms.mkString(" \n " )
236
250
}
237
251
238
- // No longer needed under 2.11 (@unspecialized has been fixed), but harmless to keep around to avoid cross-publishing this artifact.
239
- private def curriedTupled2SpecMethods = {
240
- val methods = for (t1 <- function2SpecTs; t2 <- function2SpecTs; r <- function2SpecRs) yield curriedTupled2MethodSpec(t1, t2, r )
241
- methods.map(indent).mkString( " \n\n " )
252
+ def crossProduct [ A ]( input : List [ List [ A ]]) : List [ List [ A ]] = input match {
253
+ case Nil => Nil
254
+ case head :: Nil => head.map(_ :: Nil )
255
+ case head :: tail => for (elem <- head; sub <- crossProduct(tail)) yield elem :: sub
242
256
}
243
257
244
258
def fN (n : Int ) = {
245
259
val header = arity(n).fHeader
246
260
val specializedVariants = n match {
247
- case 0 => apply0SpecMethods
248
- case 1 => apply1SpecMethods + " \n\n " + andThenComposeSpecMethods
249
- case 2 => apply2SpecMethods + " \n\n " + curriedTupled2SpecMethods
261
+ case 0 => function0SpecMethods
262
+ case 1 => function1SpecMethods
263
+ case 2 => function2SpecMethods
250
264
case x => " "
251
265
}
252
- val trailer = " }\n "
266
+ val trailer = " \n }\n "
253
267
List (header, specializedVariants, trailer).mkString
254
268
}
255
269
0 commit comments