summaryrefslogblamecommitdiff
path: root/src/build/genprod.scala
blob: 9e05ab6299977edbd96a9b0e0825d0140a341d28 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                                          
                                                                          
                                                                          


                                                                          

       

       

                                                                                                                



                                                             
        
  
                                                              
                
   


                                                          
                             
                             
                             
 
                                            
                                                            
 
                                        
                                                        
 
                                              
                                                              
 




                                                                      
                     
                                               
 
                             
                                     
 
                            
                                                       

                     
                                               

                     
                                               
 

                                                                                  
                                      



                                              
                     




                                                    
 


                                                                   

                    
                                                                         

                  
                                                                     

                     
                                                                           



                                                 
                                 
                           

                                                     
     

                                           
                     
                            
                                                                      








                                              

                                              
       















                                                                              
                                                                          
                                                                          



                                                                          
           
 

                                                                                                                                                                                                 


             



                                   
   
                                                                    








                                           
                                  
     
                                                           
 
                                  
     
                                                           
   
                            
                                                                                                                                
     






                                                                                                                                                                      


                 
   
                                            






                                                                        
  
                                                                          
  


                                                                     
  

                               







                                                                         
  
                                         
  


                                                            
  

                          







                                                                        
  
                                                                            
  


                                                                                 
  

                             
              










                                                                              

                                                                 
                              


                                                                          
                                                                          
                                                                          



                                                                          
           
 
                                                                                                                                                                                                 

             
 


                                                                                       
                                                            
                                                    
 
                               
                               
                    
                                                             
             
                                                          
                                                                     


                
     
                  
  










                                            






                                                                              
 


                     

                                                                                 


                                                                          
                                                                          
                                                                          



                                                                          
           
 
                                                                                                                                                                                                 
 



               
                               
                                                                                                               
           

  
                                                                  
                           
   
                                                            




                                









                                                                              
                                             
                                                  
                                                   


                                                                                                  
                                              
                                                                         

                  
  


                                    
   



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

// $Id$

/** <p>
 *   This program generates the <code>ProductN</code>, <code>TupleN</code> <code>FunctionN</code> classes, where
 *   <code>0 &lt;= N &lt;+ MAXWIDTH</code>.
 *  </p>
 *  <p>
 *    usage: <code>scala -classpath ... genprod PATH</code>
 *    where <code>PATH</code> is the desired output directory
 *  </p>
 *
 *  @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).iterator
    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)
<file name={functionFilename(i)}>
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2009, 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


/** &lt;p&gt;
 *    Function with {i} parameters.
 *  &lt;/p&gt;
 *  {descriptiveComment(i)}
 */
trait {functionClassname(i)}{__typeArgs__} extends AnyRef {{ self =>
  def apply({__funArgs__}): R
  override def toString() = "&lt;function>"
  {moreMethods(i)}
}}
</file>
}

  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) => """
  /** 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 = {
""" +
  (if (i < 5) {
    "      " + join(" => ", (1 to i).map(i => "(x" + i + ": T" + i + ")")) + """ => apply(""" + join(",", (1 to i).map(i => "x" + i)) + ")\n  }"
  } else {
    """      (x1: T1) => ((""" + join(", ", (2 to i).map(i => "x" + i + ": T" + i)) + """) => self.apply(""" + join(",", (1 to i).map(i => "x" + i)) + ")).curry\n  }"
  })
    case _ => """
"""

  }
  def descriptiveComment(i: Int) = i match {
    case 0 => """<p>
      In the following example the definition of
 *    <code>currentSeconds</code> is a shorthand for the anonymous class
 *    definition <code>anonfun0</code>:
 *  </p>
 *  <pre>
 *  <b>object</b> Main <b>extends</b> Application {
 *
 *    <b>val</b> currentSeconds = () => System.currentTimeMillis() / 1000L
 *
 *    <b>val</b> anonfun0 = <b>new</b> Function0[Long] {
 *      <b>def</b> apply(): Long = System.currentTimeMillis() / 1000L
 *    }
 *
 *    println(currentSeconds())
 *    println(anonfun0())
 *  }</pre>"""
    case 1 => """<p>
      In the following example the definition of
 *    <code>succ</code> is a shorthand for the anonymous class definition
 *    <code>anonfun1</code>:
 *  </p>
 *  <pre>
 *  <b>object</b> Main <b>extends</b> Application {
 *
 *    <b>val</b> succ = (x: Int) => x + 1
 *
 *    <b>val</b> anonfun1 = <b>new</b> Function1[Int, Int] {
 *      <b>def</b> apply(x: Int): Int = x + 1
 *    }
 *
 *    println(succ(0))
 *    println(anonfun1(0))
 *  }</pre>"""
    case 2 => """<p>
      In the following example the definition of
 *    <code>max</code> is a shorthand for the anonymous class definition
 *    <code>anonfun2</code>:
 *  </p>
 *  <pre>
 *  <b>object</b> Main <b>extends</b> Application {
 *
 *    <b>val</b> max = (x: Int, y: Int) => <b>if</b> (x < y) y <b>else</b> x
 *
 *    <b>val</b> anonfun2 = <b>new</b> Function2[Int, Int, Int] {
 *      <b>def</b> apply(x: Int, y: Int): Int = <b>if</b> (x < y) y <b>else</b> x
 *    }
 *
 *    println(max(0, 1))
 *    println(anonfun2(0, 1))
 *  }</pre>"""
    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)
<file name={tupleFilename(i)}>
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2009, 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)}
}}
</file>}
  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("[",", ","]")
<file name={productFilename(i)}>
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2009, 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&amp;lt;=n&amp;lt;arity,
   *  otherwise <code>null</code>.
   *
   *  @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)}
}}
</file>}
  def moreMethods(i:Int) = i match {
    case _ => ""
  }
  def descriptiveComment(i: Int) = i match {
    case _ => ""
  }
};