/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // $Id$ /**

* This program generates the ProductN, TupleN FunctionN classes, where * 0 <= N <+ MAXWIDTH. *

*

* usage: scala -classpath ... genprod PATH * where PATH is the desired output directory *

* * @author Burak Emir, Stephane Micheloud, Geoffrey Washburn * @version 1.1 */ object genprod { /** The biggest ?? has Sup?? - 1 components/arguments */ val SUP_PRODUCT_ARITY = 23 val SUP_TUPLE_ARITY = 23 val SUP_FUNCTION_ARITY = 23 def productClassname(i: Int) = "Product"+i def productFilename(i: Int) = productClassname(i)+".scala" def tupleClassname(i: Int) = "Tuple"+i def tupleFilename(i: Int) = tupleClassname(i)+".scala" def functionClassname(i: Int) = "Function"+i def functionFilename(i: Int) = functionClassname(i)+".scala" def join(sep: String, xs: Seq[String]): String = if (xs.length == 0) "" else xs.drop(1).foldLeft(xs.first) { (acc, x) => acc + sep + x } def targs(i: Int) = for (j <- List.range(1, i+1)) yield "T" + j def covariantArgs(i: Int) = for (t <- targs(i)) yield "+" + t def contraCoArgs(i: Int) = (for (t <- targs(i)) yield "-" + t) ::: List("+R") def vdefs(i: Int) = for (j <- List.range(1, i+1)) yield "v" + j def mdefs(i: Int) = for (j <- List.range(1, i+1)) yield "_" + j def zippedAndCommaSeparated(left: List[String], right: List[String]): String = { val sb = new StringBuilder val it = (left zip right).elements def append1 = { val p = it.next sb.append(p._1).append(':').append(p._2) } if (it.hasNext) { append1 while(it.hasNext) { sb.append(", "); append1 } } sb.toString } def fields(i: Int) = zippedAndCommaSeparated(mdefs(i), targs(i)) def funArgs(i: Int) = zippedAndCommaSeparated(vdefs(i), targs(i)) def productFiles = for (i <- List.range(1, SUP_PRODUCT_ARITY)) yield ProductFile.make(i) def tupleFiles = for (i <- List.range(1, SUP_TUPLE_ARITY)) yield TupleFile.make(i) def functionFiles = for (i <- List.range(0, SUP_FUNCTION_ARITY)) yield FunctionFile.make(i) def allfiles = productFiles ::: tupleFiles ::: functionFiles def main(args: Array[String]) { if (args.length != 1) { println("please give path of output directory") exit(-1) } import java.io.{File, FileOutputStream} import java.nio.channels.Channels val out = args(0) for (node <- allfiles) { val f = new File(out + File.separator + node.attributes("name")) try { f.createNewFile val fos = new FileOutputStream(f) val c = fos.getChannel val w = Channels.newWriter(c, "utf-8") w.write(node.text) w.close } catch { case e: java.io.IOException => println(e.getMessage() + ": " + out) exit(-1) } } } } /* zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz F U N C T I O N zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */ object FunctionFile { import genprod._ def make(i: Int) = { val __typeArgs__ = contraCoArgs(i).mkString("[",", ","]") val __funArgs__ = funArgs(i) /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // {"$Id$"} // generated by genprod on {new java.util.Date().toString()} {if(descriptiveComment(i).length > 0) "(with fancy comment)" else ""} {if(moreMethods(i).length > 0) "(with extra methods)" else ""} package scala /** <p> * Function with {i} parameters. * </p> * {descriptiveComment(i)} */ trait {functionClassname(i)}{__typeArgs__} extends AnyRef {{ def apply({__funArgs__}): R override def toString() = "<function>" {moreMethods(i)} }} } def moreMethods(i:Int) = i match { case 1 => """ /** (f compose g)(x) == f(g(x)) */ def compose[A](g: A => T1): A => R = { x => apply(g(x)) } /** (f andThen g)(x) == g(f(x)) */ def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) } """ case _ if (i > 1) && (i < 9) => """ /** f(""" + join(",", (1 to i).map(i => "x" + i)) + """) == (f.curry)""" + join("", (1 to i).map(i => "(x" + i + ")")) + """ */ def curry: """ + join(" => ", (1 to i).map(i => "T" + i)) + """ => R = { """ + join(" => ", (1 to i).map(i => "(x" + i + ": T" + i + ")")) + """ => apply(""" + join(",", (1 to i).map(i => "x" + i)) + """) } """ case _ => """ """ } def descriptiveComment(i: Int) = i match { case 0 => """

In the following example the definition of * currentSeconds is a shorthand for the anonymous class * definition anonfun0: *

*
 *  object Main extends Application {
 *
 *    val currentSeconds = () => System.currentTimeMillis() / 1000L
 *
 *    val anonfun0 = new Function0[Long] {
 *      def apply(): Long = System.currentTimeMillis() / 1000L
 *    }
 *
 *    println(currentSeconds())
 *    println(anonfun0())
 *  }
""" case 1 => """

In the following example the definition of * succ is a shorthand for the anonymous class definition * anonfun1: *

*
 *  object Main extends Application {
 *
 *    val succ = (x: Int) => x + 1
 *
 *    val anonfun1 = new Function1[Int, Int] {
 *      def apply(x: Int): Int = x + 1
 *    }
 *
 *    println(succ(0))
 *    println(anonfun1(0))
 *  }
""" case 2 => """

In the following example the definition of * max is a shorthand for the anonymous class definition * anonfun2: *

*
 *  object Main extends Application {
 *
 *    val max = (x: Int, y: Int) => if (x < y) y else x
 *
 *    val anonfun2 = new Function2[Int, Int, Int] {
 *      def apply(x: Int, y: Int): Int = if (x < y) y else x
 *    }
 *
 *    println(max(0, 1))
 *    println(anonfun2(0, 1))
 *  }
""" case _ => "" } } // object FunctionFile /* zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz T U P L E zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */ object TupleFile { import genprod._ def make(i: Int) = { val __typeArgs__ = covariantArgs(i).mkString("[",", ","]") val __typeArgRefs__ = targs(i).mkString("[",", ","]") val __fields__ = fields(i) /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // {"$Id$"} // generated by genprod on {new java.util.Date().toString()} {if(descriptiveComment(i).length > 0) "(with fancy comment)" else ""} {if(moreMethods(i).length > 0) "(with extra methods)" else ""} package scala /** {tupleClassname(i)} is the canonical representation of a @see {productClassname(i)} * {descriptiveComment(i)} */ case class {tupleClassname(i)}{__typeArgs__}({ __fields__ }) extends {productClassname(i)}{__typeArgRefs__} {{ override def toString() = {{ val sb = new StringBuilder { if ({i} == 1) "sb.append('(').append(_" + {i} + ").append(\",)\")" else { val xs = (1 to i).map(i => ".append(_" + i + ")") xs.mkString("sb.append('(')", ".append(',')",".append(')')") } } sb.toString }} {moreMethods(i)} }} } def moreMethods(i:Int) = i match { case 2 => """ /** Swap the elements of the tuple */ def swap: Tuple2[T2,T1] = Tuple2(_2, _1) """ case _ => "" } def descriptiveComment(i: Int) = i match { case _ => "" } } // object TupleFile /* zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz P R O D U C T zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */ object ProductFile { import genprod._ def make(i:Int) = { val __typeArgs__ = if (i==0) Nil else covariantArgs(i).mkString("[",", ","]") val __refArgs__ = if (i==0) Nil else targs(i).mkString("[",", ","]") /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // {"$Id$"} // generated by genprod on {new java.util.Date().toString()} {if(descriptiveComment(i).length > 0) "(with fancy comment)" else ""} {if(moreMethods(i).length > 0) "(with extra methods)" else ""} package scala import Predef._ object {productClassname(i)} {{ def unapply{__refArgs__}(x: {productClassname(i)}{__refArgs__}): Option[{productClassname(i)}{__refArgs__}] = Some(x) }} /** {productClassname(i)} is a cartesian product of {i} components * {descriptiveComment(i)} */ trait {productClassname(i)}{__typeArgs__} extends Product {{ /** * The arity of this product. * @return {i} */ override def productArity = {i} /** * Returns the n-th projection of this product if 0&lt;=n&lt;arity, * otherwise null. * * @param n number of the projection to be returned * @return same as _(n+1) * @throws IndexOutOfBoundsException */ @throws(classOf[IndexOutOfBoundsException]) override def productElement(n: Int) = n match {{ {for ((m, j) <- mdefs(i).zip(List.range(0, i))) yield "case "+j+" => "+m+"\n "}case _ => throw new IndexOutOfBoundsException(n.toString()) }} {for ((m, t) <- mdefs(i) zip targs(i)) yield "/** projection of this product */\n def " + m + ": " + t + "\n\n" } {moreMethods(i)} }} } def moreMethods(i:Int) = i match { case _ => "" } def descriptiveComment(i: Int) = i match { case _ => "" } };