From 1fa10b3463575aa49196e827d5b90406970dd56d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ali=20Sinan=20K=C3=B6ksal?= <alisinan@gmail.com>
Date: Mon, 9 May 2011 11:52:02 +0000
Subject: [PATCH] Automatically generate all code depending on a specific arity
 of terms

---
 src/cp/Converter.scala   |   31 +-
 src/cp/Definitions.scala |    7 +
 src/cp/Terms.scala       | 1453 ++++++++++++++++++++++++++++++++++----
 src/cp/Utils.scala       |  213 +++++-
 4 files changed, 1555 insertions(+), 149 deletions(-)

diff --git a/src/cp/Converter.scala b/src/cp/Converter.scala
index 559308e34..05c14b73a 100644
--- a/src/cp/Converter.scala
+++ b/src/cp/Converter.scala
@@ -5,12 +5,31 @@ import purescala.Trees._
 /** A converter has functions for converting FunCheck expressions into Scala
  * values */
 class Converter(expr2scala : (Expr => Any)) {
-  def exprSeq2scala1[A](exprs: Seq[Expr]) : A =
-    expr2scala(exprs(0)).asInstanceOf[A]
+  def exprSeq2scala1[T1](exprs : Seq[Expr]) : (T1) =
+    (expr2scala(exprs(0)).asInstanceOf[T1])
 
-  def exprSeq2scala2[A,B](exprs: Seq[Expr]) : (A,B) =
-    (expr2scala(exprs(0)).asInstanceOf[A], expr2scala(exprs(1)).asInstanceOf[B])
+  def exprSeq2scala2[T1,T2](exprs : Seq[Expr]) : (T1,T2) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2])
+
+  def exprSeq2scala3[T1,T2,T3](exprs : Seq[Expr]) : (T1,T2,T3) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3])
+
+  def exprSeq2scala4[T1,T2,T3,T4](exprs : Seq[Expr]) : (T1,T2,T3,T4) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3],expr2scala(exprs(3)).asInstanceOf[T4])
+
+  def exprSeq2scala5[T1,T2,T3,T4,T5](exprs : Seq[Expr]) : (T1,T2,T3,T4,T5) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3],expr2scala(exprs(3)).asInstanceOf[T4],expr2scala(exprs(4)).asInstanceOf[T5])
+
+  def exprSeq2scala6[T1,T2,T3,T4,T5,T6](exprs : Seq[Expr]) : (T1,T2,T3,T4,T5,T6) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3],expr2scala(exprs(3)).asInstanceOf[T4],expr2scala(exprs(4)).asInstanceOf[T5],expr2scala(exprs(5)).asInstanceOf[T6])
+
+  def exprSeq2scala7[T1,T2,T3,T4,T5,T6,T7](exprs : Seq[Expr]) : (T1,T2,T3,T4,T5,T6,T7) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3],expr2scala(exprs(3)).asInstanceOf[T4],expr2scala(exprs(4)).asInstanceOf[T5],expr2scala(exprs(5)).asInstanceOf[T6],expr2scala(exprs(6)).asInstanceOf[T7])
+
+  def exprSeq2scala8[T1,T2,T3,T4,T5,T6,T7,T8](exprs : Seq[Expr]) : (T1,T2,T3,T4,T5,T6,T7,T8) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3],expr2scala(exprs(3)).asInstanceOf[T4],expr2scala(exprs(4)).asInstanceOf[T5],expr2scala(exprs(5)).asInstanceOf[T6],expr2scala(exprs(6)).asInstanceOf[T7],expr2scala(exprs(7)).asInstanceOf[T8])
+
+  def exprSeq2scala9[T1,T2,T3,T4,T5,T6,T7,T8,T9](exprs : Seq[Expr]) : (T1,T2,T3,T4,T5,T6,T7,T8,T9) =
+    (expr2scala(exprs(0)).asInstanceOf[T1],expr2scala(exprs(1)).asInstanceOf[T2],expr2scala(exprs(2)).asInstanceOf[T3],expr2scala(exprs(3)).asInstanceOf[T4],expr2scala(exprs(4)).asInstanceOf[T5],expr2scala(exprs(5)).asInstanceOf[T6],expr2scala(exprs(6)).asInstanceOf[T7],expr2scala(exprs(7)).asInstanceOf[T8],expr2scala(exprs(8)).asInstanceOf[T9])
 
-  def exprSeq2scala3[A,B,C](exprs: Seq[Expr]) : (A,B,C) =
-    (expr2scala(exprs(0)).asInstanceOf[A], expr2scala(exprs(1)).asInstanceOf[B], expr2scala(exprs(2)).asInstanceOf[C])
 }
diff --git a/src/cp/Definitions.scala b/src/cp/Definitions.scala
index 3ed534056..0210fa093 100644
--- a/src/cp/Definitions.scala
+++ b/src/cp/Definitions.scala
@@ -12,6 +12,13 @@ object Definitions {
 
   implicit def func2term1[T1,R](func : T1 => R) : Term1[T1,R] = throw new NotImplementedException
   implicit def func2term2[T1,T2,R](func : (T1,T2) => R) : Term2[T1,T2,R] = throw new NotImplementedException
+  implicit def func2term3[T1,T2,T3,R](func : (T1,T2,T3) => R) : Term3[T1,T2,T3,R] = throw new NotImplementedException
+  implicit def func2term4[T1,T2,T3,T4,R](func : (T1,T2,T3,T4) => R) : Term4[T1,T2,T3,T4,R] = throw new NotImplementedException
+  implicit def func2term5[T1,T2,T3,T4,T5,R](func : (T1,T2,T3,T4,T5) => R) : Term5[T1,T2,T3,T4,T5,R] = throw new NotImplementedException
+  implicit def func2term6[T1,T2,T3,T4,T5,T6,R](func : (T1,T2,T3,T4,T5,T6) => R) : Term6[T1,T2,T3,T4,T5,T6,R] = throw new NotImplementedException
+  implicit def func2term7[T1,T2,T3,T4,T5,T6,T7,R](func : (T1,T2,T3,T4,T5,T6,T7) => R) : Term7[T1,T2,T3,T4,T5,T6,T7,R] = throw new NotImplementedException
+  implicit def func2term8[T1,T2,T3,T4,T5,T6,T7,T8,R](func : (T1,T2,T3,T4,T5,T6,T7,T8) => R) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,R] = throw new NotImplementedException
+  implicit def func2term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R](func : (T1,T2,T3,T4,T5,T6,T7,T8,T9) => R) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R] = throw new NotImplementedException
 
   def distinct[A](args: A*) : Boolean = {
     args.toList.distinct.size == args.size
diff --git a/src/cp/Terms.scala b/src/cp/Terms.scala
index 3bcc32d94..5faf87ddb 100644
--- a/src/cp/Terms.scala
+++ b/src/cp/Terms.scala
@@ -35,211 +35,621 @@ object Terms {
     }
   }
 
-  /** Terms with one argument */
-  sealed trait Term1[T1,R] extends Term[T1,R] {
+  /** Contains helper methods for constructing base terms */
+  object Term {
+    def processArgs(converter : Converter, serializedProg : Serialized, serializedInputVars : Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) : (Converter,Program,Expr,Seq[TypeTree]) = {
+      val program : Program             = deserialize[Program](serializedProg)
+      val inputVars : Seq[Variable]     = deserialize[Seq[Variable]](serializedInputVars)
+      val outputVars : Seq[Identifier]  = deserialize[Seq[Identifier]](serializedOutputVars)
+      val initialExpr : Expr            = deserialize[Expr](serializedExpr)
+
+      val env : Map[Expr,Expr]                 = (inputVars zip inputVarValues).toMap
+      val deBruijnIndices: Seq[DeBruijnIndex]  = outputVars.zipWithIndex.map{ case (v, idx) => DeBruijnIndex(idx).setType(v.getType) }
+      val exprWithIndices: Expr                = replace(((outputVars map (Variable(_))) zip deBruijnIndices).toMap, initialExpr)
+
+      val expr : Expr                          = replace(env, exprWithIndices)
+      val types : Seq[TypeTree]                = outputVars.map(_.getType)
+      (converter, program, expr, types)
+    }
+  }
+
+  /*  this is for Constraint2[A,B]
+  def proj0 : Constraint1[A] = this.asInstanceOf[Constraint] match {
+    case BaseTerm(conv,pr,ex,ts) => {
+      val deBruijnIndices = ts.zipWithIndex.map{ case (t,idx) => DeBruijnIndex(idx).setType(t) }
+      val freshIDs = deBruijnIndices.tail.zipWithIndex.map{ case (dbi, i) => FreshIdentifier("x" + i).setType(dbi.getType) }
+      val subst = deBruijnIndices.tail.zip(freshIDs map (Variable)).toMap[Expr,Expr]
+      new BaseTerm[Boolean](conv, pr, replace(subst, ex), ts.take(1)) with Constraint1[A]
+    }
+    case NotConstraint2(c) => NotConstraint1[A](c.asInstanceOf[Constraint2[A,B]].proj0)
+    case OrConstraint2(cs) => OrConstraint1[A](cs map (c => c.asInstanceOf[Constraint2[A,B]].proj0))
+    case AndConstraint2(cs) => AndConstraint1[A](cs map (c => c.asInstanceOf[Constraint2[A,B]].proj0))
+    case _ => error("Cannot reach this")
+  }
+  */
+
+  /** A constraint is just a term with Boolean range */
+  type Constraint[T] = Term[T,Boolean]
+  type Constraint1[T1] = Term1[T1,Boolean]
+  type Constraint2[T1,T2] = Term2[T1,T2,Boolean]
+  type Constraint3[T1,T2,T3] = Term3[T1,T2,T3,Boolean]
+  type Constraint4[T1,T2,T3,T4] = Term4[T1,T2,T3,T4,Boolean]
+  type Constraint5[T1,T2,T3,T4,T5] = Term5[T1,T2,T3,T4,T5,Boolean]
+  type Constraint6[T1,T2,T3,T4,T5,T6] = Term6[T1,T2,T3,T4,T5,T6,Boolean]
+  type Constraint7[T1,T2,T3,T4,T5,T6,T7] = Term7[T1,T2,T3,T4,T5,T6,T7,Boolean]
+  type Constraint8[T1,T2,T3,T4,T5,T6,T7,T8] = Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean]
+  type Constraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9] = Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean]
+  type IntTerm[T] = Term[T,Int]
+  type IntTerm1[T1] = Term1[T1,Int]
+  type IntTerm2[T1,T2] = Term2[T1,T2,Int]
+  type IntTerm3[T1,T2,T3] = Term3[T1,T2,T3,Int]
+  type IntTerm4[T1,T2,T3,T4] = Term4[T1,T2,T3,T4,Int]
+  type IntTerm5[T1,T2,T3,T4,T5] = Term5[T1,T2,T3,T4,T5,Int]
+  type IntTerm6[T1,T2,T3,T4,T5,T6] = Term6[T1,T2,T3,T4,T5,T6,Int]
+  type IntTerm7[T1,T2,T3,T4,T5,T6,T7] = Term7[T1,T2,T3,T4,T5,T6,T7,Int]
+  type IntTerm8[T1,T2,T3,T4,T5,T6,T7,T8] = Term8[T1,T2,T3,T4,T5,T6,T7,T8,Int]
+  type IntTerm9[T1,T2,T3,T4,T5,T6,T7,T8,T9] = Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Int]
+
+  sealed trait Term1[T1,R] extends Term[(T1),R] {
     val convertingFunction = converterOf(this).exprSeq2scala1[T1] _
     type t2c = (Term1[T1,R]) => Term1[T1,Boolean]
+    
+    def ||(other : Term1[T1,Boolean])(implicit asConstraint : t2c) : Term1[T1,Boolean] = OrConstraint1[T1](this, other)
 
-    def minimizing(minFunc : IntTerm1[T1])(implicit asConstraint: t2c) : MinConstraint1[T1] = {
-      MinConstraint1[T1](asConstraint(this), minFunc)
-    }
-      
-    def ||(other : Constraint1[T1])(implicit asConstraint: t2c) : Constraint1[T1] = OrConstraint1[T1](asConstraint(this), other)
+    def &&(other : Term1[T1,Boolean])(implicit asConstraint : t2c) : Term1[T1,Boolean] = AndConstraint1[T1](this, other)
 
-    def &&(other : Constraint1[T1])(implicit asConstraint: t2c) : Constraint1[T1] = AndConstraint1[T1](asConstraint(this), other)
+    def unary_!(implicit asConstraint : t2c) : Term1[T1,Boolean] = NotConstraint1[T1](this)
 
-    def unary_!(implicit asConstraint: t2c) : Constraint1[T1] = NotConstraint1[T1](asConstraint(this))
+    def minimizing(minFunc : Term1[T1,Int])(implicit asConstraint : t2c) : MinConstraint1[T1] = {
+      MinConstraint1[T1](asConstraint(this), minFunc)
+    }
 
-    /** function composition this ∘ other */
-    def compose0[A](other : Term1[A,T1]) : Term1[A,R]       = compose_0_1_1(other, this)
-    def compose0[A,B](other : Term2[A,B,T1]) : Term2[A,B,R] = compose_0_2_1(other, this)
+    def compose0[A1](other : Term1[A1,T1]) : Term1[A1,R] = compose_0_1_1(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term2[A1,A2,R] = compose_0_2_1(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term3[A1,A2,A3,R] = compose_0_3_1(other, this)
+    def compose0[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T1]) : Term4[A1,A2,A3,A4,R] = compose_0_4_1(other, this)
+    def compose0[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T1]) : Term5[A1,A2,A3,A4,A5,R] = compose_0_5_1(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T1]) : Term6[A1,A2,A3,A4,A5,A6,R] = compose_0_6_1(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6,A7](other : Term7[A1,A2,A3,A4,A5,A6,A7,T1]) : Term7[A1,A2,A3,A4,A5,A6,A7,R] = compose_0_7_1(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6,A7,A8](other : Term8[A1,A2,A3,A4,A5,A6,A7,A8,T1]) : Term8[A1,A2,A3,A4,A5,A6,A7,A8,R] = compose_0_8_1(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6,A7,A8,A9](other : Term9[A1,A2,A3,A4,A5,A6,A7,A8,A9,T1]) : Term9[A1,A2,A3,A4,A5,A6,A7,A8,A9,R] = compose_0_9_1(other, this)
   }
 
-  /** Terms with two arguments */
   sealed trait Term2[T1,T2,R] extends Term[(T1,T2),R] {
     val convertingFunction = converterOf(this).exprSeq2scala2[T1,T2] _
     type t2c = (Term2[T1,T2,R]) => Term2[T1,T2,Boolean]
+    
+    def ||(other : Term2[T1,T2,Boolean])(implicit asConstraint : t2c) : Term2[T1,T2,Boolean] = OrConstraint2[T1,T2](this, other)
 
-    def minimizing(minFunc : IntTerm2[T1,T2])(implicit asConstraint: t2c) : MinConstraint2[T1,T2] =
-      MinConstraint2[T1,T2](asConstraint(this), minFunc)
-      
-    def ||(other : Constraint2[T1,T2])(implicit asConstraint: t2c) : Constraint2[T1,T2] = OrConstraint2[T1,T2](this, other)
+    def &&(other : Term2[T1,T2,Boolean])(implicit asConstraint : t2c) : Term2[T1,T2,Boolean] = AndConstraint2[T1,T2](this, other)
 
-    def &&(other : Constraint2[T1,T2])(implicit asConstraint: t2c) : Constraint2[T1,T2] = AndConstraint2[T1,T2](this, other)
+    def unary_!(implicit asConstraint : t2c) : Term2[T1,T2,Boolean] = NotConstraint2[T1,T2](this)
 
-    def unary_!(implicit asConstraint: t2c) : Constraint2[T1,T2] = NotConstraint2[T1,T2](this)
+    def minimizing(minFunc : Term2[T1,T2,Int])(implicit asConstraint : t2c) : MinConstraint2[T1,T2] = {
+      MinConstraint2[T1,T2](asConstraint(this), minFunc)
+    }
 
-    def compose0[A](other : Term1[A, T1]) : Term2[A,T2,R] = compose_0_1_2(other, this)
-    def compose1[A](other : Term1[A, T2]) : Term2[T1,A,R] = compose_1_1_2(other, this)
+    def compose0[A1](other : Term1[A1,T1]) : Term2[A1,T2,R] = compose_0_1_2(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term2[T1,A1,R] = compose_1_1_2(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term3[A1,A2,T2,R] = compose_0_2_2(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term3[T1,A1,A2,R] = compose_1_2_2(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term4[A1,A2,A3,T2,R] = compose_0_3_2(other, this)
+    def compose1[A1,A2,A3](other : Term3[A1,A2,A3,T2]) : Term4[T1,A1,A2,A3,R] = compose_1_3_2(other, this)
+    def compose0[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T1]) : Term5[A1,A2,A3,A4,T2,R] = compose_0_4_2(other, this)
+    def compose1[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T2]) : Term5[T1,A1,A2,A3,A4,R] = compose_1_4_2(other, this)
+    def compose0[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T1]) : Term6[A1,A2,A3,A4,A5,T2,R] = compose_0_5_2(other, this)
+    def compose1[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T2]) : Term6[T1,A1,A2,A3,A4,A5,R] = compose_1_5_2(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T1]) : Term7[A1,A2,A3,A4,A5,A6,T2,R] = compose_0_6_2(other, this)
+    def compose1[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T2]) : Term7[T1,A1,A2,A3,A4,A5,A6,R] = compose_1_6_2(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6,A7](other : Term7[A1,A2,A3,A4,A5,A6,A7,T1]) : Term8[A1,A2,A3,A4,A5,A6,A7,T2,R] = compose_0_7_2(other, this)
+    def compose1[A1,A2,A3,A4,A5,A6,A7](other : Term7[A1,A2,A3,A4,A5,A6,A7,T2]) : Term8[T1,A1,A2,A3,A4,A5,A6,A7,R] = compose_1_7_2(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6,A7,A8](other : Term8[A1,A2,A3,A4,A5,A6,A7,A8,T1]) : Term9[A1,A2,A3,A4,A5,A6,A7,A8,T2,R] = compose_0_8_2(other, this)
+    def compose1[A1,A2,A3,A4,A5,A6,A7,A8](other : Term8[A1,A2,A3,A4,A5,A6,A7,A8,T2]) : Term9[T1,A1,A2,A3,A4,A5,A6,A7,A8,R] = compose_1_8_2(other, this)
   }
 
-  /** Terms with three arguments */
   sealed trait Term3[T1,T2,T3,R] extends Term[(T1,T2,T3),R] {
     val convertingFunction = converterOf(this).exprSeq2scala3[T1,T2,T3] _
     type t2c = (Term3[T1,T2,T3,R]) => Term3[T1,T2,T3,Boolean]
+    
+    def ||(other : Term3[T1,T2,T3,Boolean])(implicit asConstraint : t2c) : Term3[T1,T2,T3,Boolean] = OrConstraint3[T1,T2,T3](this, other)
 
-    def minimizing(minFunc : IntTerm3[T1,T2,T3])(implicit asConstraint: t2c) : MinConstraint3[T1,T2,T3] =
+    def &&(other : Term3[T1,T2,T3,Boolean])(implicit asConstraint : t2c) : Term3[T1,T2,T3,Boolean] = AndConstraint3[T1,T2,T3](this, other)
+
+    def unary_!(implicit asConstraint : t2c) : Term3[T1,T2,T3,Boolean] = NotConstraint3[T1,T2,T3](this)
+
+    def minimizing(minFunc : Term3[T1,T2,T3,Int])(implicit asConstraint : t2c) : MinConstraint3[T1,T2,T3] = {
       MinConstraint3[T1,T2,T3](asConstraint(this), minFunc)
-      
-    def ||(other : Constraint3[T1,T2,T3])(implicit asConstraint: t2c) : Constraint3[T1,T2,T3] = OrConstraint3[T1,T2,T3](this, other)
+    }
+
+    def compose0[A1](other : Term1[A1,T1]) : Term3[A1,T2,T3,R] = compose_0_1_3(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term3[T1,A1,T3,R] = compose_1_1_3(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term3[T1,T2,A1,R] = compose_2_1_3(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term4[A1,A2,T2,T3,R] = compose_0_2_3(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term4[T1,A1,A2,T3,R] = compose_1_2_3(other, this)
+    def compose2[A1,A2](other : Term2[A1,A2,T3]) : Term4[T1,T2,A1,A2,R] = compose_2_2_3(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term5[A1,A2,A3,T2,T3,R] = compose_0_3_3(other, this)
+    def compose1[A1,A2,A3](other : Term3[A1,A2,A3,T2]) : Term5[T1,A1,A2,A3,T3,R] = compose_1_3_3(other, this)
+    def compose2[A1,A2,A3](other : Term3[A1,A2,A3,T3]) : Term5[T1,T2,A1,A2,A3,R] = compose_2_3_3(other, this)
+    def compose0[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T1]) : Term6[A1,A2,A3,A4,T2,T3,R] = compose_0_4_3(other, this)
+    def compose1[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T2]) : Term6[T1,A1,A2,A3,A4,T3,R] = compose_1_4_3(other, this)
+    def compose2[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T3]) : Term6[T1,T2,A1,A2,A3,A4,R] = compose_2_4_3(other, this)
+    def compose0[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T1]) : Term7[A1,A2,A3,A4,A5,T2,T3,R] = compose_0_5_3(other, this)
+    def compose1[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T2]) : Term7[T1,A1,A2,A3,A4,A5,T3,R] = compose_1_5_3(other, this)
+    def compose2[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T3]) : Term7[T1,T2,A1,A2,A3,A4,A5,R] = compose_2_5_3(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T1]) : Term8[A1,A2,A3,A4,A5,A6,T2,T3,R] = compose_0_6_3(other, this)
+    def compose1[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T2]) : Term8[T1,A1,A2,A3,A4,A5,A6,T3,R] = compose_1_6_3(other, this)
+    def compose2[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T3]) : Term8[T1,T2,A1,A2,A3,A4,A5,A6,R] = compose_2_6_3(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6,A7](other : Term7[A1,A2,A3,A4,A5,A6,A7,T1]) : Term9[A1,A2,A3,A4,A5,A6,A7,T2,T3,R] = compose_0_7_3(other, this)
+    def compose1[A1,A2,A3,A4,A5,A6,A7](other : Term7[A1,A2,A3,A4,A5,A6,A7,T2]) : Term9[T1,A1,A2,A3,A4,A5,A6,A7,T3,R] = compose_1_7_3(other, this)
+    def compose2[A1,A2,A3,A4,A5,A6,A7](other : Term7[A1,A2,A3,A4,A5,A6,A7,T3]) : Term9[T1,T2,A1,A2,A3,A4,A5,A6,A7,R] = compose_2_7_3(other, this)
+  }
+
+  sealed trait Term4[T1,T2,T3,T4,R] extends Term[(T1,T2,T3,T4),R] {
+    val convertingFunction = converterOf(this).exprSeq2scala4[T1,T2,T3,T4] _
+    type t2c = (Term4[T1,T2,T3,T4,R]) => Term4[T1,T2,T3,T4,Boolean]
+    
+    def ||(other : Term4[T1,T2,T3,T4,Boolean])(implicit asConstraint : t2c) : Term4[T1,T2,T3,T4,Boolean] = OrConstraint4[T1,T2,T3,T4](this, other)
+
+    def &&(other : Term4[T1,T2,T3,T4,Boolean])(implicit asConstraint : t2c) : Term4[T1,T2,T3,T4,Boolean] = AndConstraint4[T1,T2,T3,T4](this, other)
 
-    def &&(other : Constraint3[T1,T2,T3])(implicit asConstraint: t2c) : Constraint3[T1,T2,T3] = AndConstraint3[T1,T2,T3](this, other)
+    def unary_!(implicit asConstraint : t2c) : Term4[T1,T2,T3,T4,Boolean] = NotConstraint4[T1,T2,T3,T4](this)
 
-    def unary_!(implicit asConstraint: t2c) : Constraint3[T1,T2,T3] = NotConstraint3[T1,T2,T3](this)
+    def minimizing(minFunc : Term4[T1,T2,T3,T4,Int])(implicit asConstraint : t2c) : MinConstraint4[T1,T2,T3,T4] = {
+      MinConstraint4[T1,T2,T3,T4](asConstraint(this), minFunc)
+    }
+
+    def compose0[A1](other : Term1[A1,T1]) : Term4[A1,T2,T3,T4,R] = compose_0_1_4(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term4[T1,A1,T3,T4,R] = compose_1_1_4(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term4[T1,T2,A1,T4,R] = compose_2_1_4(other, this)
+    def compose3[A1](other : Term1[A1,T4]) : Term4[T1,T2,T3,A1,R] = compose_3_1_4(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term5[A1,A2,T2,T3,T4,R] = compose_0_2_4(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term5[T1,A1,A2,T3,T4,R] = compose_1_2_4(other, this)
+    def compose2[A1,A2](other : Term2[A1,A2,T3]) : Term5[T1,T2,A1,A2,T4,R] = compose_2_2_4(other, this)
+    def compose3[A1,A2](other : Term2[A1,A2,T4]) : Term5[T1,T2,T3,A1,A2,R] = compose_3_2_4(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term6[A1,A2,A3,T2,T3,T4,R] = compose_0_3_4(other, this)
+    def compose1[A1,A2,A3](other : Term3[A1,A2,A3,T2]) : Term6[T1,A1,A2,A3,T3,T4,R] = compose_1_3_4(other, this)
+    def compose2[A1,A2,A3](other : Term3[A1,A2,A3,T3]) : Term6[T1,T2,A1,A2,A3,T4,R] = compose_2_3_4(other, this)
+    def compose3[A1,A2,A3](other : Term3[A1,A2,A3,T4]) : Term6[T1,T2,T3,A1,A2,A3,R] = compose_3_3_4(other, this)
+    def compose0[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T1]) : Term7[A1,A2,A3,A4,T2,T3,T4,R] = compose_0_4_4(other, this)
+    def compose1[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T2]) : Term7[T1,A1,A2,A3,A4,T3,T4,R] = compose_1_4_4(other, this)
+    def compose2[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T3]) : Term7[T1,T2,A1,A2,A3,A4,T4,R] = compose_2_4_4(other, this)
+    def compose3[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T4]) : Term7[T1,T2,T3,A1,A2,A3,A4,R] = compose_3_4_4(other, this)
+    def compose0[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T1]) : Term8[A1,A2,A3,A4,A5,T2,T3,T4,R] = compose_0_5_4(other, this)
+    def compose1[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T2]) : Term8[T1,A1,A2,A3,A4,A5,T3,T4,R] = compose_1_5_4(other, this)
+    def compose2[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T3]) : Term8[T1,T2,A1,A2,A3,A4,A5,T4,R] = compose_2_5_4(other, this)
+    def compose3[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T4]) : Term8[T1,T2,T3,A1,A2,A3,A4,A5,R] = compose_3_5_4(other, this)
+    def compose0[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T1]) : Term9[A1,A2,A3,A4,A5,A6,T2,T3,T4,R] = compose_0_6_4(other, this)
+    def compose1[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T2]) : Term9[T1,A1,A2,A3,A4,A5,A6,T3,T4,R] = compose_1_6_4(other, this)
+    def compose2[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T3]) : Term9[T1,T2,A1,A2,A3,A4,A5,A6,T4,R] = compose_2_6_4(other, this)
+    def compose3[A1,A2,A3,A4,A5,A6](other : Term6[A1,A2,A3,A4,A5,A6,T4]) : Term9[T1,T2,T3,A1,A2,A3,A4,A5,A6,R] = compose_3_6_4(other, this)
   }
 
-    /*  this is for Constraint2[A,B]
-    def proj0 : Constraint1[A] = this.asInstanceOf[Constraint] match {
-      case BaseTerm(conv,pr,ex,ts) => {
-        val deBruijnIndices = ts.zipWithIndex.map{ case (t,idx) => DeBruijnIndex(idx).setType(t) }
-        val freshIDs = deBruijnIndices.tail.zipWithIndex.map{ case (dbi, i) => FreshIdentifier("x" + i).setType(dbi.getType) }
-        val subst = deBruijnIndices.tail.zip(freshIDs map (Variable)).toMap[Expr,Expr]
-        new BaseTerm[Boolean](conv, pr, replace(subst, ex), ts.take(1)) with Constraint1[A]
-      }
-      case NotConstraint2(c) => NotConstraint1[A](c.asInstanceOf[Constraint2[A,B]].proj0)
-      case OrConstraint2(cs) => OrConstraint1[A](cs map (c => c.asInstanceOf[Constraint2[A,B]].proj0))
-      case AndConstraint2(cs) => AndConstraint1[A](cs map (c => c.asInstanceOf[Constraint2[A,B]].proj0))
-      case _ => error("Cannot reach this")
+  sealed trait Term5[T1,T2,T3,T4,T5,R] extends Term[(T1,T2,T3,T4,T5),R] {
+    val convertingFunction = converterOf(this).exprSeq2scala5[T1,T2,T3,T4,T5] _
+    type t2c = (Term5[T1,T2,T3,T4,T5,R]) => Term5[T1,T2,T3,T4,T5,Boolean]
+    
+    def ||(other : Term5[T1,T2,T3,T4,T5,Boolean])(implicit asConstraint : t2c) : Term5[T1,T2,T3,T4,T5,Boolean] = OrConstraint5[T1,T2,T3,T4,T5](this, other)
+
+    def &&(other : Term5[T1,T2,T3,T4,T5,Boolean])(implicit asConstraint : t2c) : Term5[T1,T2,T3,T4,T5,Boolean] = AndConstraint5[T1,T2,T3,T4,T5](this, other)
+
+    def unary_!(implicit asConstraint : t2c) : Term5[T1,T2,T3,T4,T5,Boolean] = NotConstraint5[T1,T2,T3,T4,T5](this)
+
+    def minimizing(minFunc : Term5[T1,T2,T3,T4,T5,Int])(implicit asConstraint : t2c) : MinConstraint5[T1,T2,T3,T4,T5] = {
+      MinConstraint5[T1,T2,T3,T4,T5](asConstraint(this), minFunc)
     }
-    */
 
-  /** Contains helper methods for constructing base terms */
-  object Term {
-    def processArgs(converter : Converter, serializedProg : Serialized, serializedInputVars : Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) : (Converter,Program,Expr,Seq[TypeTree]) = {
-      val program : Program             = deserialize[Program](serializedProg)
-      val inputVars : Seq[Variable]     = deserialize[Seq[Variable]](serializedInputVars)
-      val outputVars : Seq[Identifier]  = deserialize[Seq[Identifier]](serializedOutputVars)
-      val initialExpr : Expr            = deserialize[Expr](serializedExpr)
+    def compose0[A1](other : Term1[A1,T1]) : Term5[A1,T2,T3,T4,T5,R] = compose_0_1_5(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term5[T1,A1,T3,T4,T5,R] = compose_1_1_5(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term5[T1,T2,A1,T4,T5,R] = compose_2_1_5(other, this)
+    def compose3[A1](other : Term1[A1,T4]) : Term5[T1,T2,T3,A1,T5,R] = compose_3_1_5(other, this)
+    def compose4[A1](other : Term1[A1,T5]) : Term5[T1,T2,T3,T4,A1,R] = compose_4_1_5(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term6[A1,A2,T2,T3,T4,T5,R] = compose_0_2_5(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term6[T1,A1,A2,T3,T4,T5,R] = compose_1_2_5(other, this)
+    def compose2[A1,A2](other : Term2[A1,A2,T3]) : Term6[T1,T2,A1,A2,T4,T5,R] = compose_2_2_5(other, this)
+    def compose3[A1,A2](other : Term2[A1,A2,T4]) : Term6[T1,T2,T3,A1,A2,T5,R] = compose_3_2_5(other, this)
+    def compose4[A1,A2](other : Term2[A1,A2,T5]) : Term6[T1,T2,T3,T4,A1,A2,R] = compose_4_2_5(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term7[A1,A2,A3,T2,T3,T4,T5,R] = compose_0_3_5(other, this)
+    def compose1[A1,A2,A3](other : Term3[A1,A2,A3,T2]) : Term7[T1,A1,A2,A3,T3,T4,T5,R] = compose_1_3_5(other, this)
+    def compose2[A1,A2,A3](other : Term3[A1,A2,A3,T3]) : Term7[T1,T2,A1,A2,A3,T4,T5,R] = compose_2_3_5(other, this)
+    def compose3[A1,A2,A3](other : Term3[A1,A2,A3,T4]) : Term7[T1,T2,T3,A1,A2,A3,T5,R] = compose_3_3_5(other, this)
+    def compose4[A1,A2,A3](other : Term3[A1,A2,A3,T5]) : Term7[T1,T2,T3,T4,A1,A2,A3,R] = compose_4_3_5(other, this)
+    def compose0[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T1]) : Term8[A1,A2,A3,A4,T2,T3,T4,T5,R] = compose_0_4_5(other, this)
+    def compose1[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T2]) : Term8[T1,A1,A2,A3,A4,T3,T4,T5,R] = compose_1_4_5(other, this)
+    def compose2[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T3]) : Term8[T1,T2,A1,A2,A3,A4,T4,T5,R] = compose_2_4_5(other, this)
+    def compose3[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T4]) : Term8[T1,T2,T3,A1,A2,A3,A4,T5,R] = compose_3_4_5(other, this)
+    def compose4[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T5]) : Term8[T1,T2,T3,T4,A1,A2,A3,A4,R] = compose_4_4_5(other, this)
+    def compose0[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T1]) : Term9[A1,A2,A3,A4,A5,T2,T3,T4,T5,R] = compose_0_5_5(other, this)
+    def compose1[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T2]) : Term9[T1,A1,A2,A3,A4,A5,T3,T4,T5,R] = compose_1_5_5(other, this)
+    def compose2[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T3]) : Term9[T1,T2,A1,A2,A3,A4,A5,T4,T5,R] = compose_2_5_5(other, this)
+    def compose3[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T4]) : Term9[T1,T2,T3,A1,A2,A3,A4,A5,T5,R] = compose_3_5_5(other, this)
+    def compose4[A1,A2,A3,A4,A5](other : Term5[A1,A2,A3,A4,A5,T5]) : Term9[T1,T2,T3,T4,A1,A2,A3,A4,A5,R] = compose_4_5_5(other, this)
+  }
 
-      val env : Map[Expr,Expr]                 = (inputVars zip inputVarValues).toMap
-      val deBruijnIndices: Seq[DeBruijnIndex]  = outputVars.zipWithIndex.map{ case (v, idx) => DeBruijnIndex(idx).setType(v.getType) }
-      val exprWithIndices: Expr                = replace(((outputVars map (Variable(_))) zip deBruijnIndices).toMap, initialExpr)
+  sealed trait Term6[T1,T2,T3,T4,T5,T6,R] extends Term[(T1,T2,T3,T4,T5,T6),R] {
+    val convertingFunction = converterOf(this).exprSeq2scala6[T1,T2,T3,T4,T5,T6] _
+    type t2c = (Term6[T1,T2,T3,T4,T5,T6,R]) => Term6[T1,T2,T3,T4,T5,T6,Boolean]
+    
+    def ||(other : Term6[T1,T2,T3,T4,T5,T6,Boolean])(implicit asConstraint : t2c) : Term6[T1,T2,T3,T4,T5,T6,Boolean] = OrConstraint6[T1,T2,T3,T4,T5,T6](this, other)
 
-      val expr : Expr                          = replace(env, exprWithIndices)
-      val types : Seq[TypeTree]                = outputVars.map(_.getType)
-      (converter, program, expr, types)
+    def &&(other : Term6[T1,T2,T3,T4,T5,T6,Boolean])(implicit asConstraint : t2c) : Term6[T1,T2,T3,T4,T5,T6,Boolean] = AndConstraint6[T1,T2,T3,T4,T5,T6](this, other)
+
+    def unary_!(implicit asConstraint : t2c) : Term6[T1,T2,T3,T4,T5,T6,Boolean] = NotConstraint6[T1,T2,T3,T4,T5,T6](this)
+
+    def minimizing(minFunc : Term6[T1,T2,T3,T4,T5,T6,Int])(implicit asConstraint : t2c) : MinConstraint6[T1,T2,T3,T4,T5,T6] = {
+      MinConstraint6[T1,T2,T3,T4,T5,T6](asConstraint(this), minFunc)
+    }
+
+    def compose0[A1](other : Term1[A1,T1]) : Term6[A1,T2,T3,T4,T5,T6,R] = compose_0_1_6(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term6[T1,A1,T3,T4,T5,T6,R] = compose_1_1_6(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term6[T1,T2,A1,T4,T5,T6,R] = compose_2_1_6(other, this)
+    def compose3[A1](other : Term1[A1,T4]) : Term6[T1,T2,T3,A1,T5,T6,R] = compose_3_1_6(other, this)
+    def compose4[A1](other : Term1[A1,T5]) : Term6[T1,T2,T3,T4,A1,T6,R] = compose_4_1_6(other, this)
+    def compose5[A1](other : Term1[A1,T6]) : Term6[T1,T2,T3,T4,T5,A1,R] = compose_5_1_6(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term7[A1,A2,T2,T3,T4,T5,T6,R] = compose_0_2_6(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term7[T1,A1,A2,T3,T4,T5,T6,R] = compose_1_2_6(other, this)
+    def compose2[A1,A2](other : Term2[A1,A2,T3]) : Term7[T1,T2,A1,A2,T4,T5,T6,R] = compose_2_2_6(other, this)
+    def compose3[A1,A2](other : Term2[A1,A2,T4]) : Term7[T1,T2,T3,A1,A2,T5,T6,R] = compose_3_2_6(other, this)
+    def compose4[A1,A2](other : Term2[A1,A2,T5]) : Term7[T1,T2,T3,T4,A1,A2,T6,R] = compose_4_2_6(other, this)
+    def compose5[A1,A2](other : Term2[A1,A2,T6]) : Term7[T1,T2,T3,T4,T5,A1,A2,R] = compose_5_2_6(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term8[A1,A2,A3,T2,T3,T4,T5,T6,R] = compose_0_3_6(other, this)
+    def compose1[A1,A2,A3](other : Term3[A1,A2,A3,T2]) : Term8[T1,A1,A2,A3,T3,T4,T5,T6,R] = compose_1_3_6(other, this)
+    def compose2[A1,A2,A3](other : Term3[A1,A2,A3,T3]) : Term8[T1,T2,A1,A2,A3,T4,T5,T6,R] = compose_2_3_6(other, this)
+    def compose3[A1,A2,A3](other : Term3[A1,A2,A3,T4]) : Term8[T1,T2,T3,A1,A2,A3,T5,T6,R] = compose_3_3_6(other, this)
+    def compose4[A1,A2,A3](other : Term3[A1,A2,A3,T5]) : Term8[T1,T2,T3,T4,A1,A2,A3,T6,R] = compose_4_3_6(other, this)
+    def compose5[A1,A2,A3](other : Term3[A1,A2,A3,T6]) : Term8[T1,T2,T3,T4,T5,A1,A2,A3,R] = compose_5_3_6(other, this)
+    def compose0[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T1]) : Term9[A1,A2,A3,A4,T2,T3,T4,T5,T6,R] = compose_0_4_6(other, this)
+    def compose1[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T2]) : Term9[T1,A1,A2,A3,A4,T3,T4,T5,T6,R] = compose_1_4_6(other, this)
+    def compose2[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T3]) : Term9[T1,T2,A1,A2,A3,A4,T4,T5,T6,R] = compose_2_4_6(other, this)
+    def compose3[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T4]) : Term9[T1,T2,T3,A1,A2,A3,A4,T5,T6,R] = compose_3_4_6(other, this)
+    def compose4[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T5]) : Term9[T1,T2,T3,T4,A1,A2,A3,A4,T6,R] = compose_4_4_6(other, this)
+    def compose5[A1,A2,A3,A4](other : Term4[A1,A2,A3,A4,T6]) : Term9[T1,T2,T3,T4,T5,A1,A2,A3,A4,R] = compose_5_4_6(other, this)
+  }
+
+  sealed trait Term7[T1,T2,T3,T4,T5,T6,T7,R] extends Term[(T1,T2,T3,T4,T5,T6,T7),R] {
+    val convertingFunction = converterOf(this).exprSeq2scala7[T1,T2,T3,T4,T5,T6,T7] _
+    type t2c = (Term7[T1,T2,T3,T4,T5,T6,T7,R]) => Term7[T1,T2,T3,T4,T5,T6,T7,Boolean]
+    
+    def ||(other : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean])(implicit asConstraint : t2c) : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] = OrConstraint7[T1,T2,T3,T4,T5,T6,T7](this, other)
+
+    def &&(other : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean])(implicit asConstraint : t2c) : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] = AndConstraint7[T1,T2,T3,T4,T5,T6,T7](this, other)
+
+    def unary_!(implicit asConstraint : t2c) : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] = NotConstraint7[T1,T2,T3,T4,T5,T6,T7](this)
+
+    def minimizing(minFunc : Term7[T1,T2,T3,T4,T5,T6,T7,Int])(implicit asConstraint : t2c) : MinConstraint7[T1,T2,T3,T4,T5,T6,T7] = {
+      MinConstraint7[T1,T2,T3,T4,T5,T6,T7](asConstraint(this), minFunc)
+    }
+
+    def compose0[A1](other : Term1[A1,T1]) : Term7[A1,T2,T3,T4,T5,T6,T7,R] = compose_0_1_7(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term7[T1,A1,T3,T4,T5,T6,T7,R] = compose_1_1_7(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term7[T1,T2,A1,T4,T5,T6,T7,R] = compose_2_1_7(other, this)
+    def compose3[A1](other : Term1[A1,T4]) : Term7[T1,T2,T3,A1,T5,T6,T7,R] = compose_3_1_7(other, this)
+    def compose4[A1](other : Term1[A1,T5]) : Term7[T1,T2,T3,T4,A1,T6,T7,R] = compose_4_1_7(other, this)
+    def compose5[A1](other : Term1[A1,T6]) : Term7[T1,T2,T3,T4,T5,A1,T7,R] = compose_5_1_7(other, this)
+    def compose6[A1](other : Term1[A1,T7]) : Term7[T1,T2,T3,T4,T5,T6,A1,R] = compose_6_1_7(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term8[A1,A2,T2,T3,T4,T5,T6,T7,R] = compose_0_2_7(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term8[T1,A1,A2,T3,T4,T5,T6,T7,R] = compose_1_2_7(other, this)
+    def compose2[A1,A2](other : Term2[A1,A2,T3]) : Term8[T1,T2,A1,A2,T4,T5,T6,T7,R] = compose_2_2_7(other, this)
+    def compose3[A1,A2](other : Term2[A1,A2,T4]) : Term8[T1,T2,T3,A1,A2,T5,T6,T7,R] = compose_3_2_7(other, this)
+    def compose4[A1,A2](other : Term2[A1,A2,T5]) : Term8[T1,T2,T3,T4,A1,A2,T6,T7,R] = compose_4_2_7(other, this)
+    def compose5[A1,A2](other : Term2[A1,A2,T6]) : Term8[T1,T2,T3,T4,T5,A1,A2,T7,R] = compose_5_2_7(other, this)
+    def compose6[A1,A2](other : Term2[A1,A2,T7]) : Term8[T1,T2,T3,T4,T5,T6,A1,A2,R] = compose_6_2_7(other, this)
+    def compose0[A1,A2,A3](other : Term3[A1,A2,A3,T1]) : Term9[A1,A2,A3,T2,T3,T4,T5,T6,T7,R] = compose_0_3_7(other, this)
+    def compose1[A1,A2,A3](other : Term3[A1,A2,A3,T2]) : Term9[T1,A1,A2,A3,T3,T4,T5,T6,T7,R] = compose_1_3_7(other, this)
+    def compose2[A1,A2,A3](other : Term3[A1,A2,A3,T3]) : Term9[T1,T2,A1,A2,A3,T4,T5,T6,T7,R] = compose_2_3_7(other, this)
+    def compose3[A1,A2,A3](other : Term3[A1,A2,A3,T4]) : Term9[T1,T2,T3,A1,A2,A3,T5,T6,T7,R] = compose_3_3_7(other, this)
+    def compose4[A1,A2,A3](other : Term3[A1,A2,A3,T5]) : Term9[T1,T2,T3,T4,A1,A2,A3,T6,T7,R] = compose_4_3_7(other, this)
+    def compose5[A1,A2,A3](other : Term3[A1,A2,A3,T6]) : Term9[T1,T2,T3,T4,T5,A1,A2,A3,T7,R] = compose_5_3_7(other, this)
+    def compose6[A1,A2,A3](other : Term3[A1,A2,A3,T7]) : Term9[T1,T2,T3,T4,T5,T6,A1,A2,A3,R] = compose_6_3_7(other, this)
+  }
+
+  sealed trait Term8[T1,T2,T3,T4,T5,T6,T7,T8,R] extends Term[(T1,T2,T3,T4,T5,T6,T7,T8),R] {
+    val convertingFunction = converterOf(this).exprSeq2scala8[T1,T2,T3,T4,T5,T6,T7,T8] _
+    type t2c = (Term8[T1,T2,T3,T4,T5,T6,T7,T8,R]) => Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean]
+    
+    def ||(other : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean])(implicit asConstraint : t2c) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] = OrConstraint8[T1,T2,T3,T4,T5,T6,T7,T8](this, other)
+
+    def &&(other : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean])(implicit asConstraint : t2c) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] = AndConstraint8[T1,T2,T3,T4,T5,T6,T7,T8](this, other)
+
+    def unary_!(implicit asConstraint : t2c) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] = NotConstraint8[T1,T2,T3,T4,T5,T6,T7,T8](this)
+
+    def minimizing(minFunc : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Int])(implicit asConstraint : t2c) : MinConstraint8[T1,T2,T3,T4,T5,T6,T7,T8] = {
+      MinConstraint8[T1,T2,T3,T4,T5,T6,T7,T8](asConstraint(this), minFunc)
+    }
+
+    def compose0[A1](other : Term1[A1,T1]) : Term8[A1,T2,T3,T4,T5,T6,T7,T8,R] = compose_0_1_8(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term8[T1,A1,T3,T4,T5,T6,T7,T8,R] = compose_1_1_8(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term8[T1,T2,A1,T4,T5,T6,T7,T8,R] = compose_2_1_8(other, this)
+    def compose3[A1](other : Term1[A1,T4]) : Term8[T1,T2,T3,A1,T5,T6,T7,T8,R] = compose_3_1_8(other, this)
+    def compose4[A1](other : Term1[A1,T5]) : Term8[T1,T2,T3,T4,A1,T6,T7,T8,R] = compose_4_1_8(other, this)
+    def compose5[A1](other : Term1[A1,T6]) : Term8[T1,T2,T3,T4,T5,A1,T7,T8,R] = compose_5_1_8(other, this)
+    def compose6[A1](other : Term1[A1,T7]) : Term8[T1,T2,T3,T4,T5,T6,A1,T8,R] = compose_6_1_8(other, this)
+    def compose7[A1](other : Term1[A1,T8]) : Term8[T1,T2,T3,T4,T5,T6,T7,A1,R] = compose_7_1_8(other, this)
+    def compose0[A1,A2](other : Term2[A1,A2,T1]) : Term9[A1,A2,T2,T3,T4,T5,T6,T7,T8,R] = compose_0_2_8(other, this)
+    def compose1[A1,A2](other : Term2[A1,A2,T2]) : Term9[T1,A1,A2,T3,T4,T5,T6,T7,T8,R] = compose_1_2_8(other, this)
+    def compose2[A1,A2](other : Term2[A1,A2,T3]) : Term9[T1,T2,A1,A2,T4,T5,T6,T7,T8,R] = compose_2_2_8(other, this)
+    def compose3[A1,A2](other : Term2[A1,A2,T4]) : Term9[T1,T2,T3,A1,A2,T5,T6,T7,T8,R] = compose_3_2_8(other, this)
+    def compose4[A1,A2](other : Term2[A1,A2,T5]) : Term9[T1,T2,T3,T4,A1,A2,T6,T7,T8,R] = compose_4_2_8(other, this)
+    def compose5[A1,A2](other : Term2[A1,A2,T6]) : Term9[T1,T2,T3,T4,T5,A1,A2,T7,T8,R] = compose_5_2_8(other, this)
+    def compose6[A1,A2](other : Term2[A1,A2,T7]) : Term9[T1,T2,T3,T4,T5,T6,A1,A2,T8,R] = compose_6_2_8(other, this)
+    def compose7[A1,A2](other : Term2[A1,A2,T8]) : Term9[T1,T2,T3,T4,T5,T6,T7,A1,A2,R] = compose_7_2_8(other, this)
+  }
+
+  sealed trait Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R] extends Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),R] {
+    val convertingFunction = converterOf(this).exprSeq2scala9[T1,T2,T3,T4,T5,T6,T7,T8,T9] _
+    type t2c = (Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R]) => Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean]
+    
+    def ||(other : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean])(implicit asConstraint : t2c) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] = OrConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9](this, other)
+
+    def &&(other : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean])(implicit asConstraint : t2c) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] = AndConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9](this, other)
+
+    def unary_!(implicit asConstraint : t2c) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] = NotConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9](this)
+
+    def minimizing(minFunc : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Int])(implicit asConstraint : t2c) : MinConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9] = {
+      MinConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9](asConstraint(this), minFunc)
     }
+
+    def compose0[A1](other : Term1[A1,T1]) : Term9[A1,T2,T3,T4,T5,T6,T7,T8,T9,R] = compose_0_1_9(other, this)
+    def compose1[A1](other : Term1[A1,T2]) : Term9[T1,A1,T3,T4,T5,T6,T7,T8,T9,R] = compose_1_1_9(other, this)
+    def compose2[A1](other : Term1[A1,T3]) : Term9[T1,T2,A1,T4,T5,T6,T7,T8,T9,R] = compose_2_1_9(other, this)
+    def compose3[A1](other : Term1[A1,T4]) : Term9[T1,T2,T3,A1,T5,T6,T7,T8,T9,R] = compose_3_1_9(other, this)
+    def compose4[A1](other : Term1[A1,T5]) : Term9[T1,T2,T3,T4,A1,T6,T7,T8,T9,R] = compose_4_1_9(other, this)
+    def compose5[A1](other : Term1[A1,T6]) : Term9[T1,T2,T3,T4,T5,A1,T7,T8,T9,R] = compose_5_1_9(other, this)
+    def compose6[A1](other : Term1[A1,T7]) : Term9[T1,T2,T3,T4,T5,T6,A1,T8,T9,R] = compose_6_1_9(other, this)
+    def compose7[A1](other : Term1[A1,T8]) : Term9[T1,T2,T3,T4,T5,T6,T7,A1,T9,R] = compose_7_1_9(other, this)
+    def compose8[A1](other : Term1[A1,T9]) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,A1,R] = compose_8_1_9(other, this)
   }
 
   object Term1 {
-    def apply[T1,R](conv : Converter, serializedProg : Serialized, serializedInputVars : Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+    def apply[T1,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
       val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
-      new Term[T1,R](program, expr, types, converter) with Term1[T1,R]
+      new Term[(T1),R](program, expr, types, converter) with Term1[T1,R]
     }
-
+    
     def apply[T1,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
-      new Term[T1,R](program, expr, types, converter) with Term1[T1,R]
+      new Term[(T1),R](program, expr, types, converter) with Term1[T1,R]
+  }
+
+  object OrConstraint1 {
+    def apply[T1](l : Term[(T1),Boolean], r : Term[(T1),Boolean]) : Term1[T1,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term1(p1,Or(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object AndConstraint1 {
+    def apply[T1](l : Term[(T1),Boolean], r : Term[(T1),Boolean]) : Term1[T1,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term1(p1,And(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object NotConstraint1 {
+    def apply[T1](c : Term[(T1),Boolean]) : Term1[T1,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term1(p,Not(ex),ts,conv)
+    }
   }
 
   object Term2 {
-    def apply[T1,T2,R](conv : Converter, serializedProg : Serialized, serializedInputVars : Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+    def apply[T1,T2,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
       val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
       new Term[(T1,T2),R](program, expr, types, converter) with Term2[T1,T2,R]
     }
-
+    
     def apply[T1,T2,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
       new Term[(T1,T2),R](program, expr, types, converter) with Term2[T1,T2,R]
   }
 
+  object OrConstraint2 {
+    def apply[T1,T2](l : Term[(T1,T2),Boolean], r : Term[(T1,T2),Boolean]) : Term2[T1,T2,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term2(p1,Or(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object AndConstraint2 {
+    def apply[T1,T2](l : Term[(T1,T2),Boolean], r : Term[(T1,T2),Boolean]) : Term2[T1,T2,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term2(p1,And(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object NotConstraint2 {
+    def apply[T1,T2](c : Term[(T1,T2),Boolean]) : Term2[T1,T2,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term2(p,Not(ex),ts,conv)
+    }
+  }
+
   object Term3 {
-    def apply[T1,T2,T3,R](conv : Converter, serializedProg : Serialized, serializedInputVars : Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+    def apply[T1,T2,T3,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
       val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
       new Term[(T1,T2,T3),R](program, expr, types, converter) with Term3[T1,T2,T3,R]
     }
-
+    
     def apply[T1,T2,T3,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
       new Term[(T1,T2,T3),R](program, expr, types, converter) with Term3[T1,T2,T3,R]
   }
 
-  /** A constraint is just a term with Boolean range */
-  type Constraint[T] = Term[T,Boolean]
-  type Constraint1[T1] = Term1[T1,Boolean]
-  type Constraint2[T1,T2] = Term2[T1,T2,Boolean]
-  type Constraint3[T1,T2,T3] = Term3[T1,T2,T3,Boolean]
+  object OrConstraint3 {
+    def apply[T1,T2,T3](l : Term[(T1,T2,T3),Boolean], r : Term[(T1,T2,T3),Boolean]) : Term3[T1,T2,T3,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term3(p1,Or(ex1,ex2),ts1,conv1)
+    }
+  }
 
-  object OrConstraint1 {
-    def apply[A](l : Constraint[A], r : Constraint[A]) : Constraint1[A] = (l, r) match {
-      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term1(p1,Or(ex1,ex2),ts1,conv1)
+  object AndConstraint3 {
+    def apply[T1,T2,T3](l : Term[(T1,T2,T3),Boolean], r : Term[(T1,T2,T3),Boolean]) : Term3[T1,T2,T3,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term3(p1,And(ex1,ex2),ts1,conv1)
     }
+  }
 
-    def apply[A](cs : Seq[Constraint[A]]) : Constraint1[A] = cs match {
-      case s @ Seq(Term(p,ex,ts,conv), _*) => Term1(p, Or(s.map(_.expr)), ts, conv)
+  object NotConstraint3 {
+    def apply[T1,T2,T3](c : Term[(T1,T2,T3),Boolean]) : Term3[T1,T2,T3,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term3(p,Not(ex),ts,conv)
     }
   }
 
-  object OrConstraint2 {
-    def apply[A,B](l : Constraint[(A,B)], r : Constraint[(A,B)]) : Constraint2[A,B] = (l, r) match {
-      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term2(p1,Or(ex1,ex2),ts1,conv1)
+  object Term4 {
+    def apply[T1,T2,T3,T4,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+      val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+      new Term[(T1,T2,T3,T4),R](program, expr, types, converter) with Term4[T1,T2,T3,T4,R]
     }
+    
+    def apply[T1,T2,T3,T4,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+      new Term[(T1,T2,T3,T4),R](program, expr, types, converter) with Term4[T1,T2,T3,T4,R]
+  }
 
-    def apply[A,B](cs : Seq[Constraint[(A,B)]]) : Constraint2[A,B] = cs match {
-      case s @ Seq(Term(p,ex,ts,conv), _*) => Term2(p, Or(s.map(_.expr)), ts, conv)
+  object OrConstraint4 {
+    def apply[T1,T2,T3,T4](l : Term[(T1,T2,T3,T4),Boolean], r : Term[(T1,T2,T3,T4),Boolean]) : Term4[T1,T2,T3,T4,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term4(p1,Or(ex1,ex2),ts1,conv1)
     }
   }
 
-  object OrConstraint3 {
-    def apply[A,B,C](l : Constraint[(A,B,C)], r : Constraint[(A,B,C)]) : Constraint3[A,B,C] = (l, r) match {
-      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term3(p1,Or(ex1,ex2),ts1,conv1)
+  object AndConstraint4 {
+    def apply[T1,T2,T3,T4](l : Term[(T1,T2,T3,T4),Boolean], r : Term[(T1,T2,T3,T4),Boolean]) : Term4[T1,T2,T3,T4,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term4(p1,And(ex1,ex2),ts1,conv1)
     }
+  }
 
-    def apply[A,B,C](cs : Seq[Constraint[(A,B,C)]]) : Constraint3[A,B,C] = cs match {
-      case s @ Seq(Term(p,ex,ts,conv), _*) => Term3(p, Or(s.map(_.expr)), ts, conv)
+  object NotConstraint4 {
+    def apply[T1,T2,T3,T4](c : Term[(T1,T2,T3,T4),Boolean]) : Term4[T1,T2,T3,T4,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term4(p,Not(ex),ts,conv)
     }
   }
 
-  object AndConstraint1 {
-    def apply[A](l : Constraint[A], r : Constraint[A]) : Constraint1[A] = (l, r) match {
-      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term1(p1,And(ex1,ex2),ts1,conv1)
+  object Term5 {
+    def apply[T1,T2,T3,T4,T5,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+      val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+      new Term[(T1,T2,T3,T4,T5),R](program, expr, types, converter) with Term5[T1,T2,T3,T4,T5,R]
     }
+    
+    def apply[T1,T2,T3,T4,T5,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+      new Term[(T1,T2,T3,T4,T5),R](program, expr, types, converter) with Term5[T1,T2,T3,T4,T5,R]
+  }
 
-    def apply[A](cs : Seq[Constraint[A]]) : Constraint1[A] = cs match {
-      case s @ Seq(Term(p,ex,ts,conv), _*) => Term1(p, And(s.map(_.expr)), ts, conv)
+  object OrConstraint5 {
+    def apply[T1,T2,T3,T4,T5](l : Term[(T1,T2,T3,T4,T5),Boolean], r : Term[(T1,T2,T3,T4,T5),Boolean]) : Term5[T1,T2,T3,T4,T5,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term5(p1,Or(ex1,ex2),ts1,conv1)
     }
   }
 
-  object AndConstraint2 {
-    def apply[A,B](l : Constraint[(A,B)], r : Constraint[(A,B)]) : Constraint2[A,B] = (l, r) match {
-      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term2(p1,And(ex1,ex2),ts1,conv1)
+  object AndConstraint5 {
+    def apply[T1,T2,T3,T4,T5](l : Term[(T1,T2,T3,T4,T5),Boolean], r : Term[(T1,T2,T3,T4,T5),Boolean]) : Term5[T1,T2,T3,T4,T5,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term5(p1,And(ex1,ex2),ts1,conv1)
     }
+  }
 
-    def apply[A,B](cs : Seq[Constraint[(A,B)]]) : Constraint2[A,B] = cs match {
-      case s @ Seq(Term(p,ex,ts,conv), _*) => Term2(p, And(s.map(_.expr)), ts, conv)
+  object NotConstraint5 {
+    def apply[T1,T2,T3,T4,T5](c : Term[(T1,T2,T3,T4,T5),Boolean]) : Term5[T1,T2,T3,T4,T5,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term5(p,Not(ex),ts,conv)
     }
   }
 
-  object AndConstraint3 {
-    def apply[A,B,C](l : Constraint[(A,B,C)], r : Constraint[(A,B,C)]) : Constraint3[A,B,C] = (l, r) match {
-      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term3(p1,And(ex1,ex2),ts1,conv1)
+  object Term6 {
+    def apply[T1,T2,T3,T4,T5,T6,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+      val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+      new Term[(T1,T2,T3,T4,T5,T6),R](program, expr, types, converter) with Term6[T1,T2,T3,T4,T5,T6,R]
     }
+    
+    def apply[T1,T2,T3,T4,T5,T6,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+      new Term[(T1,T2,T3,T4,T5,T6),R](program, expr, types, converter) with Term6[T1,T2,T3,T4,T5,T6,R]
+  }
 
-    def apply[A,B,C](cs : Seq[Constraint[(A,B,C)]]) : Constraint3[A,B,C] = cs match {
-      case s @ Seq(Term(p,ex,ts,conv), _*) => Term3(p, And(s.map(_.expr)), ts, conv)
+  object OrConstraint6 {
+    def apply[T1,T2,T3,T4,T5,T6](l : Term[(T1,T2,T3,T4,T5,T6),Boolean], r : Term[(T1,T2,T3,T4,T5,T6),Boolean]) : Term6[T1,T2,T3,T4,T5,T6,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term6(p1,Or(ex1,ex2),ts1,conv1)
     }
   }
 
-  object NotConstraint1 {
-    def apply[A](c : Constraint[A]) : Constraint1[A] = c match {
-      case Term(p,ex,ts,conv) => Term1(p,Not(ex),ts,conv)
+  object AndConstraint6 {
+    def apply[T1,T2,T3,T4,T5,T6](l : Term[(T1,T2,T3,T4,T5,T6),Boolean], r : Term[(T1,T2,T3,T4,T5,T6),Boolean]) : Term6[T1,T2,T3,T4,T5,T6,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term6(p1,And(ex1,ex2),ts1,conv1)
     }
   }
 
-  object NotConstraint2 {
-    def apply[A,B](c : Constraint[(A,B)]) : Constraint2[A,B] = c match {
-      case Term(p,ex,ts,conv) => Term2(p,Not(ex),ts,conv)
+  object NotConstraint6 {
+    def apply[T1,T2,T3,T4,T5,T6](c : Term[(T1,T2,T3,T4,T5,T6),Boolean]) : Term6[T1,T2,T3,T4,T5,T6,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term6(p,Not(ex),ts,conv)
     }
   }
 
-  object NotConstraint3 {
-    def apply[A,B,C](c : Constraint[(A,B,C)]) : Constraint3[A,B,C] = c match {
-      case Term(p,ex,ts,conv) => Term3(p,Not(ex),ts,conv)
+  object Term7 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+      val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+      new Term[(T1,T2,T3,T4,T5,T6,T7),R](program, expr, types, converter) with Term7[T1,T2,T3,T4,T5,T6,T7,R]
     }
+    
+    def apply[T1,T2,T3,T4,T5,T6,T7,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+      new Term[(T1,T2,T3,T4,T5,T6,T7),R](program, expr, types, converter) with Term7[T1,T2,T3,T4,T5,T6,T7,R]
   }
 
-  type IntTerm[T] = Term[T,Int]
-  type IntTerm1[T1] = Term1[T1,Int]
-  type IntTerm2[T1,T2] = Term2[T1,T2,Int]
-  type IntTerm3[T1,T2,T3] = Term3[T1,T2,T3,Int]
+  object OrConstraint7 {
+    def apply[T1,T2,T3,T4,T5,T6,T7](l : Term[(T1,T2,T3,T4,T5,T6,T7),Boolean], r : Term[(T1,T2,T3,T4,T5,T6,T7),Boolean]) : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term7(p1,Or(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object AndConstraint7 {
+    def apply[T1,T2,T3,T4,T5,T6,T7](l : Term[(T1,T2,T3,T4,T5,T6,T7),Boolean], r : Term[(T1,T2,T3,T4,T5,T6,T7),Boolean]) : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term7(p1,And(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object NotConstraint7 {
+    def apply[T1,T2,T3,T4,T5,T6,T7](c : Term[(T1,T2,T3,T4,T5,T6,T7),Boolean]) : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term7(p,Not(ex),ts,conv)
+    }
+  }
+
+  object Term8 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+      val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+      new Term[(T1,T2,T3,T4,T5,T6,T7,T8),R](program, expr, types, converter) with Term8[T1,T2,T3,T4,T5,T6,T7,T8,R]
+    }
+    
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+      new Term[(T1,T2,T3,T4,T5,T6,T7,T8),R](program, expr, types, converter) with Term8[T1,T2,T3,T4,T5,T6,T7,T8,R]
+  }
+
+  object OrConstraint8 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8](l : Term[(T1,T2,T3,T4,T5,T6,T7,T8),Boolean], r : Term[(T1,T2,T3,T4,T5,T6,T7,T8),Boolean]) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term8(p1,Or(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object AndConstraint8 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8](l : Term[(T1,T2,T3,T4,T5,T6,T7,T8),Boolean], r : Term[(T1,T2,T3,T4,T5,T6,T7,T8),Boolean]) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term8(p1,And(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object NotConstraint8 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8](c : Term[(T1,T2,T3,T4,T5,T6,T7,T8),Boolean]) : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term8(p,Not(ex),ts,conv)
+    }
+  }
+
+  object Term9 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,T9,R](conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+      val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+      new Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),R](program, expr, types, converter) with Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R]
+    }
+    
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,T9,R](program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+      new Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),R](program, expr, types, converter) with Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R]
+  }
+
+  object OrConstraint9 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,T9](l : Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),Boolean], r : Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),Boolean]) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term9(p1,Or(ex1,ex2),ts1,conv1)
+    }
+  }
 
+  object AndConstraint9 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,T9](l : Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),Boolean], r : Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),Boolean]) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] = (l, r) match {
+      case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term9(p1,And(ex1,ex2),ts1,conv1)
+    }
+  }
+
+  object NotConstraint9 {
+    def apply[T1,T2,T3,T4,T5,T6,T7,T8,T9](c : Term[(T1,T2,T3,T4,T5,T6,T7,T8,T9),Boolean]) : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] = c match {
+      case Term(p,ex,ts,conv) => Term9(p,Not(ex),ts,conv)
+    }
+  }
   /** This construct represents a constraint with an expression to minimize */
   abstract class MinConstraint[T](cons : Constraint[_], minFunc : IntTerm[_]) {
     val convertingFunction : (Seq[Expr] => T)
@@ -262,18 +672,42 @@ object Terms {
     } 
   }
 
-  case class MinConstraint1[T](cons : Constraint1[T], minFunc : IntTerm1[T]) extends MinConstraint[T](cons, minFunc) {
-    val convertingFunction = converterOf(cons).exprSeq2scala1[T] _
+  case class MinConstraint1[T1](cons : Term1[T1,Boolean], minFunc : Term1[T1,Int]) extends MinConstraint[(T1)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala1[T1] _
   }
 
-  case class MinConstraint2[T1,T2](cons : Constraint2[T1,T2], minFunc : IntTerm2[T1,T2]) extends MinConstraint[(T1,T2)](cons, minFunc) {
+  case class MinConstraint2[T1,T2](cons : Term2[T1,T2,Boolean], minFunc : Term2[T1,T2,Int]) extends MinConstraint[(T1,T2)](cons, minFunc) {
     val convertingFunction = converterOf(cons).exprSeq2scala2[T1,T2] _
   }
 
-  case class MinConstraint3[T1,T2,T3](cons : Constraint3[T1,T2,T3], minFunc : IntTerm3[T1,T2,T3]) extends MinConstraint[(T1,T2,T3)](cons, minFunc) {
+  case class MinConstraint3[T1,T2,T3](cons : Term3[T1,T2,T3,Boolean], minFunc : Term3[T1,T2,T3,Int]) extends MinConstraint[(T1,T2,T3)](cons, minFunc) {
     val convertingFunction = converterOf(cons).exprSeq2scala3[T1,T2,T3] _
   }
 
+  case class MinConstraint4[T1,T2,T3,T4](cons : Term4[T1,T2,T3,T4,Boolean], minFunc : Term4[T1,T2,T3,T4,Int]) extends MinConstraint[(T1,T2,T3,T4)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala4[T1,T2,T3,T4] _
+  }
+
+  case class MinConstraint5[T1,T2,T3,T4,T5](cons : Term5[T1,T2,T3,T4,T5,Boolean], minFunc : Term5[T1,T2,T3,T4,T5,Int]) extends MinConstraint[(T1,T2,T3,T4,T5)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala5[T1,T2,T3,T4,T5] _
+  }
+
+  case class MinConstraint6[T1,T2,T3,T4,T5,T6](cons : Term6[T1,T2,T3,T4,T5,T6,Boolean], minFunc : Term6[T1,T2,T3,T4,T5,T6,Int]) extends MinConstraint[(T1,T2,T3,T4,T5,T6)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala6[T1,T2,T3,T4,T5,T6] _
+  }
+
+  case class MinConstraint7[T1,T2,T3,T4,T5,T6,T7](cons : Term7[T1,T2,T3,T4,T5,T6,T7,Boolean], minFunc : Term7[T1,T2,T3,T4,T5,T6,T7,Int]) extends MinConstraint[(T1,T2,T3,T4,T5,T6,T7)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala7[T1,T2,T3,T4,T5,T6,T7] _
+  }
+
+  case class MinConstraint8[T1,T2,T3,T4,T5,T6,T7,T8](cons : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean], minFunc : Term8[T1,T2,T3,T4,T5,T6,T7,T8,Int]) extends MinConstraint[(T1,T2,T3,T4,T5,T6,T7,T8)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala8[T1,T2,T3,T4,T5,T6,T7,T8] _
+  }
+
+  case class MinConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9](cons : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean], minFunc : Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Int]) extends MinConstraint[(T1,T2,T3,T4,T5,T6,T7,T8,T9)](cons, minFunc) {
+    val convertingFunction = converterOf(cons).exprSeq2scala9[T1,T2,T3,T4,T5,T6,T7,T8,T9] _
+  }
+
   /********** TERM METHODS **********/
   /** compose_i_j_k will compose f (of arity j) and g (of arity k) as "g∘f" by
    * inserting arguments of f in place of argument i of g */
@@ -292,6 +726,36 @@ object Terms {
     Term3(f.program, newExpr, newTypes, f.converter)
   }
 
+  private def compose_0_4_1[A1,A2,A3,A4,R1,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(R1),R2]) : Term4[A1,A2,A3,A4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 4, 1)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_5_1[A1,A2,A3,A4,A5,R1,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(R1),R2]) : Term5[A1,A2,A3,A4,A5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 5, 1)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_6_1[A1,A2,A3,A4,A5,A6,R1,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(R1),R2]) : Term6[A1,A2,A3,A4,A5,A6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 6, 1)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_7_1[A1,A2,A3,A4,A5,A6,A7,R1,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7),R1], g : Term[(R1),R2]) : Term7[A1,A2,A3,A4,A5,A6,A7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 7, 1)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_8_1[A1,A2,A3,A4,A5,A6,A7,A8,R1,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7,A8),R1], g : Term[(R1),R2]) : Term8[A1,A2,A3,A4,A5,A6,A7,A8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 8, 1)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_9_1[A1,A2,A3,A4,A5,A6,A7,A8,A9,R1,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7,A8,A9),R1], g : Term[(R1),R2]) : Term9[A1,A2,A3,A4,A5,A6,A7,A8,A9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 9, 1)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
   private def compose_0_1_2[A1,R1,B2,R2](f : Term[(A1),R1], g : Term[(R1,B2),R2]) : Term2[A1,B2,R2] = {
     val (newExpr, newTypes) = compose(f, g, 0, 1, 2)
     Term2(f.program, newExpr, newTypes, f.converter)
@@ -312,19 +776,764 @@ object Terms {
     Term3(f.program, newExpr, newTypes, f.converter)
   }
 
-  private def compose_0_1_3[A1,R1,B2,B3,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3),R2]) : Term3[A1,B2,B3,R2] = {
-    val (newExpr, newTypes) = compose(f, g, 0, 1, 3)
-    Term3(f.program, newExpr, newTypes, f.converter)
+  private def compose_0_3_2[A1,A2,A3,R1,B2,R2](f : Term[(A1,A2,A3),R1], g : Term[(R1,B2),R2]) : Term4[A1,A2,A3,B2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 3, 2)
+    Term4(f.program, newExpr, newTypes, f.converter)
   }
 
-  private def compose_1_1_3[A1,R1,B1,B3,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3),R2]) : Term3[B1,A1,B3,R2] = {
-    val (newExpr, newTypes) = compose(f, g, 1, 1, 3)
-    Term3(f.program, newExpr, newTypes, f.converter)
+  private def compose_1_3_2[A1,A2,A3,R1,B1,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,R1),R2]) : Term4[B1,A1,A2,A3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 3, 2)
+    Term4(f.program, newExpr, newTypes, f.converter)
   }
 
-  private def compose_2_1_3[A1,R1,B1,B2,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1),R2]) : Term3[B1,B2,A1,R2] = {
-    val (newExpr, newTypes) = compose(f, g, 2, 1, 3)
-    Term3(f.program, newExpr, newTypes, f.converter)
+  private def compose_0_4_2[A1,A2,A3,A4,R1,B2,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(R1,B2),R2]) : Term5[A1,A2,A3,A4,B2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 4, 2)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_4_2[A1,A2,A3,A4,R1,B1,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,R1),R2]) : Term5[B1,A1,A2,A3,A4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 4, 2)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_5_2[A1,A2,A3,A4,A5,R1,B2,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(R1,B2),R2]) : Term6[A1,A2,A3,A4,A5,B2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 5, 2)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_5_2[A1,A2,A3,A4,A5,R1,B1,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,R1),R2]) : Term6[B1,A1,A2,A3,A4,A5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 5, 2)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_6_2[A1,A2,A3,A4,A5,A6,R1,B2,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(R1,B2),R2]) : Term7[A1,A2,A3,A4,A5,A6,B2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 6, 2)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_6_2[A1,A2,A3,A4,A5,A6,R1,B1,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(B1,R1),R2]) : Term7[B1,A1,A2,A3,A4,A5,A6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 6, 2)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_7_2[A1,A2,A3,A4,A5,A6,A7,R1,B2,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7),R1], g : Term[(R1,B2),R2]) : Term8[A1,A2,A3,A4,A5,A6,A7,B2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 7, 2)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_7_2[A1,A2,A3,A4,A5,A6,A7,R1,B1,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7),R1], g : Term[(B1,R1),R2]) : Term8[B1,A1,A2,A3,A4,A5,A6,A7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 7, 2)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_8_2[A1,A2,A3,A4,A5,A6,A7,A8,R1,B2,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7,A8),R1], g : Term[(R1,B2),R2]) : Term9[A1,A2,A3,A4,A5,A6,A7,A8,B2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 8, 2)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_8_2[A1,A2,A3,A4,A5,A6,A7,A8,R1,B1,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7,A8),R1], g : Term[(B1,R1),R2]) : Term9[B1,A1,A2,A3,A4,A5,A6,A7,A8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 8, 2)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_3[A1,R1,B2,B3,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3),R2]) : Term3[A1,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 3)
+    Term3(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_3[A1,R1,B1,B3,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3),R2]) : Term3[B1,A1,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 3)
+    Term3(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_3[A1,R1,B1,B2,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1),R2]) : Term3[B1,B2,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 3)
+    Term3(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_2_3[A1,A2,R1,B2,B3,R2](f : Term[(A1,A2),R1], g : Term[(R1,B2,B3),R2]) : Term4[A1,A2,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 2, 3)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_2_3[A1,A2,R1,B1,B3,R2](f : Term[(A1,A2),R1], g : Term[(B1,R1,B3),R2]) : Term4[B1,A1,A2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 2, 3)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_2_3[A1,A2,R1,B1,B2,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,R1),R2]) : Term4[B1,B2,A1,A2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 2, 3)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_3_3[A1,A2,A3,R1,B2,B3,R2](f : Term[(A1,A2,A3),R1], g : Term[(R1,B2,B3),R2]) : Term5[A1,A2,A3,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 3, 3)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_3_3[A1,A2,A3,R1,B1,B3,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,R1,B3),R2]) : Term5[B1,A1,A2,A3,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 3, 3)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_3_3[A1,A2,A3,R1,B1,B2,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,R1),R2]) : Term5[B1,B2,A1,A2,A3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 3, 3)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_4_3[A1,A2,A3,A4,R1,B2,B3,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(R1,B2,B3),R2]) : Term6[A1,A2,A3,A4,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 4, 3)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_4_3[A1,A2,A3,A4,R1,B1,B3,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,R1,B3),R2]) : Term6[B1,A1,A2,A3,A4,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 4, 3)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_4_3[A1,A2,A3,A4,R1,B1,B2,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,R1),R2]) : Term6[B1,B2,A1,A2,A3,A4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 4, 3)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_5_3[A1,A2,A3,A4,A5,R1,B2,B3,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(R1,B2,B3),R2]) : Term7[A1,A2,A3,A4,A5,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 5, 3)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_5_3[A1,A2,A3,A4,A5,R1,B1,B3,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,R1,B3),R2]) : Term7[B1,A1,A2,A3,A4,A5,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 5, 3)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_5_3[A1,A2,A3,A4,A5,R1,B1,B2,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,B2,R1),R2]) : Term7[B1,B2,A1,A2,A3,A4,A5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 5, 3)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_6_3[A1,A2,A3,A4,A5,A6,R1,B2,B3,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(R1,B2,B3),R2]) : Term8[A1,A2,A3,A4,A5,A6,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 6, 3)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_6_3[A1,A2,A3,A4,A5,A6,R1,B1,B3,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(B1,R1,B3),R2]) : Term8[B1,A1,A2,A3,A4,A5,A6,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 6, 3)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_6_3[A1,A2,A3,A4,A5,A6,R1,B1,B2,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(B1,B2,R1),R2]) : Term8[B1,B2,A1,A2,A3,A4,A5,A6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 6, 3)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_7_3[A1,A2,A3,A4,A5,A6,A7,R1,B2,B3,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7),R1], g : Term[(R1,B2,B3),R2]) : Term9[A1,A2,A3,A4,A5,A6,A7,B2,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 7, 3)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_7_3[A1,A2,A3,A4,A5,A6,A7,R1,B1,B3,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7),R1], g : Term[(B1,R1,B3),R2]) : Term9[B1,A1,A2,A3,A4,A5,A6,A7,B3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 7, 3)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_7_3[A1,A2,A3,A4,A5,A6,A7,R1,B1,B2,R2](f : Term[(A1,A2,A3,A4,A5,A6,A7),R1], g : Term[(B1,B2,R1),R2]) : Term9[B1,B2,A1,A2,A3,A4,A5,A6,A7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 7, 3)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_4[A1,R1,B2,B3,B4,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3,B4),R2]) : Term4[A1,B2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 4)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_4[A1,R1,B1,B3,B4,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3,B4),R2]) : Term4[B1,A1,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 4)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_4[A1,R1,B1,B2,B4,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1,B4),R2]) : Term4[B1,B2,A1,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 4)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_1_4[A1,R1,B1,B2,B3,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,R1),R2]) : Term4[B1,B2,B3,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 1, 4)
+    Term4(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_2_4[A1,A2,R1,B2,B3,B4,R2](f : Term[(A1,A2),R1], g : Term[(R1,B2,B3,B4),R2]) : Term5[A1,A2,B2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 2, 4)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_2_4[A1,A2,R1,B1,B3,B4,R2](f : Term[(A1,A2),R1], g : Term[(B1,R1,B3,B4),R2]) : Term5[B1,A1,A2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 2, 4)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_2_4[A1,A2,R1,B1,B2,B4,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,R1,B4),R2]) : Term5[B1,B2,A1,A2,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 2, 4)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_2_4[A1,A2,R1,B1,B2,B3,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,R1),R2]) : Term5[B1,B2,B3,A1,A2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 2, 4)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_3_4[A1,A2,A3,R1,B2,B3,B4,R2](f : Term[(A1,A2,A3),R1], g : Term[(R1,B2,B3,B4),R2]) : Term6[A1,A2,A3,B2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 3, 4)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_3_4[A1,A2,A3,R1,B1,B3,B4,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,R1,B3,B4),R2]) : Term6[B1,A1,A2,A3,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 3, 4)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_3_4[A1,A2,A3,R1,B1,B2,B4,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,R1,B4),R2]) : Term6[B1,B2,A1,A2,A3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 3, 4)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_3_4[A1,A2,A3,R1,B1,B2,B3,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,R1),R2]) : Term6[B1,B2,B3,A1,A2,A3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 3, 4)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_4_4[A1,A2,A3,A4,R1,B2,B3,B4,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(R1,B2,B3,B4),R2]) : Term7[A1,A2,A3,A4,B2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 4, 4)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_4_4[A1,A2,A3,A4,R1,B1,B3,B4,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,R1,B3,B4),R2]) : Term7[B1,A1,A2,A3,A4,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 4, 4)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_4_4[A1,A2,A3,A4,R1,B1,B2,B4,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,R1,B4),R2]) : Term7[B1,B2,A1,A2,A3,A4,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 4, 4)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_4_4[A1,A2,A3,A4,R1,B1,B2,B3,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,B3,R1),R2]) : Term7[B1,B2,B3,A1,A2,A3,A4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 4, 4)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_5_4[A1,A2,A3,A4,A5,R1,B2,B3,B4,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(R1,B2,B3,B4),R2]) : Term8[A1,A2,A3,A4,A5,B2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 5, 4)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_5_4[A1,A2,A3,A4,A5,R1,B1,B3,B4,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,R1,B3,B4),R2]) : Term8[B1,A1,A2,A3,A4,A5,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 5, 4)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_5_4[A1,A2,A3,A4,A5,R1,B1,B2,B4,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,B2,R1,B4),R2]) : Term8[B1,B2,A1,A2,A3,A4,A5,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 5, 4)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_5_4[A1,A2,A3,A4,A5,R1,B1,B2,B3,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,B2,B3,R1),R2]) : Term8[B1,B2,B3,A1,A2,A3,A4,A5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 5, 4)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_6_4[A1,A2,A3,A4,A5,A6,R1,B2,B3,B4,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(R1,B2,B3,B4),R2]) : Term9[A1,A2,A3,A4,A5,A6,B2,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 6, 4)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_6_4[A1,A2,A3,A4,A5,A6,R1,B1,B3,B4,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(B1,R1,B3,B4),R2]) : Term9[B1,A1,A2,A3,A4,A5,A6,B3,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 6, 4)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_6_4[A1,A2,A3,A4,A5,A6,R1,B1,B2,B4,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(B1,B2,R1,B4),R2]) : Term9[B1,B2,A1,A2,A3,A4,A5,A6,B4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 6, 4)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_6_4[A1,A2,A3,A4,A5,A6,R1,B1,B2,B3,R2](f : Term[(A1,A2,A3,A4,A5,A6),R1], g : Term[(B1,B2,B3,R1),R2]) : Term9[B1,B2,B3,A1,A2,A3,A4,A5,A6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 6, 4)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_5[A1,R1,B2,B3,B4,B5,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3,B4,B5),R2]) : Term5[A1,B2,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 5)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_5[A1,R1,B1,B3,B4,B5,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3,B4,B5),R2]) : Term5[B1,A1,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 5)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_5[A1,R1,B1,B2,B4,B5,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1,B4,B5),R2]) : Term5[B1,B2,A1,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 5)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_1_5[A1,R1,B1,B2,B3,B5,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,R1,B5),R2]) : Term5[B1,B2,B3,A1,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 1, 5)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_1_5[A1,R1,B1,B2,B3,B4,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,R1),R2]) : Term5[B1,B2,B3,B4,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 1, 5)
+    Term5(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_2_5[A1,A2,R1,B2,B3,B4,B5,R2](f : Term[(A1,A2),R1], g : Term[(R1,B2,B3,B4,B5),R2]) : Term6[A1,A2,B2,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 2, 5)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_2_5[A1,A2,R1,B1,B3,B4,B5,R2](f : Term[(A1,A2),R1], g : Term[(B1,R1,B3,B4,B5),R2]) : Term6[B1,A1,A2,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 2, 5)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_2_5[A1,A2,R1,B1,B2,B4,B5,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,R1,B4,B5),R2]) : Term6[B1,B2,A1,A2,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 2, 5)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_2_5[A1,A2,R1,B1,B2,B3,B5,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,R1,B5),R2]) : Term6[B1,B2,B3,A1,A2,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 2, 5)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_2_5[A1,A2,R1,B1,B2,B3,B4,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,R1),R2]) : Term6[B1,B2,B3,B4,A1,A2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 2, 5)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_3_5[A1,A2,A3,R1,B2,B3,B4,B5,R2](f : Term[(A1,A2,A3),R1], g : Term[(R1,B2,B3,B4,B5),R2]) : Term7[A1,A2,A3,B2,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 3, 5)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_3_5[A1,A2,A3,R1,B1,B3,B4,B5,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,R1,B3,B4,B5),R2]) : Term7[B1,A1,A2,A3,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 3, 5)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_3_5[A1,A2,A3,R1,B1,B2,B4,B5,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,R1,B4,B5),R2]) : Term7[B1,B2,A1,A2,A3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 3, 5)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_3_5[A1,A2,A3,R1,B1,B2,B3,B5,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,R1,B5),R2]) : Term7[B1,B2,B3,A1,A2,A3,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 3, 5)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_3_5[A1,A2,A3,R1,B1,B2,B3,B4,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,B4,R1),R2]) : Term7[B1,B2,B3,B4,A1,A2,A3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 3, 5)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_4_5[A1,A2,A3,A4,R1,B2,B3,B4,B5,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(R1,B2,B3,B4,B5),R2]) : Term8[A1,A2,A3,A4,B2,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 4, 5)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_4_5[A1,A2,A3,A4,R1,B1,B3,B4,B5,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,R1,B3,B4,B5),R2]) : Term8[B1,A1,A2,A3,A4,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 4, 5)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_4_5[A1,A2,A3,A4,R1,B1,B2,B4,B5,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,R1,B4,B5),R2]) : Term8[B1,B2,A1,A2,A3,A4,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 4, 5)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_4_5[A1,A2,A3,A4,R1,B1,B2,B3,B5,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,B3,R1,B5),R2]) : Term8[B1,B2,B3,A1,A2,A3,A4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 4, 5)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_4_5[A1,A2,A3,A4,R1,B1,B2,B3,B4,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,B3,B4,R1),R2]) : Term8[B1,B2,B3,B4,A1,A2,A3,A4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 4, 5)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_5_5[A1,A2,A3,A4,A5,R1,B2,B3,B4,B5,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(R1,B2,B3,B4,B5),R2]) : Term9[A1,A2,A3,A4,A5,B2,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 5, 5)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_5_5[A1,A2,A3,A4,A5,R1,B1,B3,B4,B5,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,R1,B3,B4,B5),R2]) : Term9[B1,A1,A2,A3,A4,A5,B3,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 5, 5)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_5_5[A1,A2,A3,A4,A5,R1,B1,B2,B4,B5,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,B2,R1,B4,B5),R2]) : Term9[B1,B2,A1,A2,A3,A4,A5,B4,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 5, 5)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_5_5[A1,A2,A3,A4,A5,R1,B1,B2,B3,B5,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,B2,B3,R1,B5),R2]) : Term9[B1,B2,B3,A1,A2,A3,A4,A5,B5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 5, 5)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_5_5[A1,A2,A3,A4,A5,R1,B1,B2,B3,B4,R2](f : Term[(A1,A2,A3,A4,A5),R1], g : Term[(B1,B2,B3,B4,R1),R2]) : Term9[B1,B2,B3,B4,A1,A2,A3,A4,A5,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 5, 5)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_6[A1,R1,B2,B3,B4,B5,B6,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3,B4,B5,B6),R2]) : Term6[A1,B2,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 6)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_6[A1,R1,B1,B3,B4,B5,B6,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3,B4,B5,B6),R2]) : Term6[B1,A1,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 6)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_6[A1,R1,B1,B2,B4,B5,B6,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1,B4,B5,B6),R2]) : Term6[B1,B2,A1,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 6)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_1_6[A1,R1,B1,B2,B3,B5,B6,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,R1,B5,B6),R2]) : Term6[B1,B2,B3,A1,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 1, 6)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_1_6[A1,R1,B1,B2,B3,B4,B6,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,R1,B6),R2]) : Term6[B1,B2,B3,B4,A1,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 1, 6)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_1_6[A1,R1,B1,B2,B3,B4,B5,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,R1),R2]) : Term6[B1,B2,B3,B4,B5,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 1, 6)
+    Term6(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_2_6[A1,A2,R1,B2,B3,B4,B5,B6,R2](f : Term[(A1,A2),R1], g : Term[(R1,B2,B3,B4,B5,B6),R2]) : Term7[A1,A2,B2,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 2, 6)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_2_6[A1,A2,R1,B1,B3,B4,B5,B6,R2](f : Term[(A1,A2),R1], g : Term[(B1,R1,B3,B4,B5,B6),R2]) : Term7[B1,A1,A2,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 2, 6)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_2_6[A1,A2,R1,B1,B2,B4,B5,B6,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,R1,B4,B5,B6),R2]) : Term7[B1,B2,A1,A2,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 2, 6)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_2_6[A1,A2,R1,B1,B2,B3,B5,B6,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,R1,B5,B6),R2]) : Term7[B1,B2,B3,A1,A2,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 2, 6)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_2_6[A1,A2,R1,B1,B2,B3,B4,B6,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,R1,B6),R2]) : Term7[B1,B2,B3,B4,A1,A2,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 2, 6)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_2_6[A1,A2,R1,B1,B2,B3,B4,B5,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,B5,R1),R2]) : Term7[B1,B2,B3,B4,B5,A1,A2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 2, 6)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_3_6[A1,A2,A3,R1,B2,B3,B4,B5,B6,R2](f : Term[(A1,A2,A3),R1], g : Term[(R1,B2,B3,B4,B5,B6),R2]) : Term8[A1,A2,A3,B2,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 3, 6)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_3_6[A1,A2,A3,R1,B1,B3,B4,B5,B6,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,R1,B3,B4,B5,B6),R2]) : Term8[B1,A1,A2,A3,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 3, 6)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_3_6[A1,A2,A3,R1,B1,B2,B4,B5,B6,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,R1,B4,B5,B6),R2]) : Term8[B1,B2,A1,A2,A3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 3, 6)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_3_6[A1,A2,A3,R1,B1,B2,B3,B5,B6,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,R1,B5,B6),R2]) : Term8[B1,B2,B3,A1,A2,A3,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 3, 6)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_3_6[A1,A2,A3,R1,B1,B2,B3,B4,B6,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,B4,R1,B6),R2]) : Term8[B1,B2,B3,B4,A1,A2,A3,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 3, 6)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_3_6[A1,A2,A3,R1,B1,B2,B3,B4,B5,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,B4,B5,R1),R2]) : Term8[B1,B2,B3,B4,B5,A1,A2,A3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 3, 6)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_4_6[A1,A2,A3,A4,R1,B2,B3,B4,B5,B6,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(R1,B2,B3,B4,B5,B6),R2]) : Term9[A1,A2,A3,A4,B2,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 4, 6)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_4_6[A1,A2,A3,A4,R1,B1,B3,B4,B5,B6,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,R1,B3,B4,B5,B6),R2]) : Term9[B1,A1,A2,A3,A4,B3,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 4, 6)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_4_6[A1,A2,A3,A4,R1,B1,B2,B4,B5,B6,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,R1,B4,B5,B6),R2]) : Term9[B1,B2,A1,A2,A3,A4,B4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 4, 6)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_4_6[A1,A2,A3,A4,R1,B1,B2,B3,B5,B6,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,B3,R1,B5,B6),R2]) : Term9[B1,B2,B3,A1,A2,A3,A4,B5,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 4, 6)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_4_6[A1,A2,A3,A4,R1,B1,B2,B3,B4,B6,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,B3,B4,R1,B6),R2]) : Term9[B1,B2,B3,B4,A1,A2,A3,A4,B6,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 4, 6)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_4_6[A1,A2,A3,A4,R1,B1,B2,B3,B4,B5,R2](f : Term[(A1,A2,A3,A4),R1], g : Term[(B1,B2,B3,B4,B5,R1),R2]) : Term9[B1,B2,B3,B4,B5,A1,A2,A3,A4,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 4, 6)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_7[A1,R1,B2,B3,B4,B5,B6,B7,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3,B4,B5,B6,B7),R2]) : Term7[A1,B2,B3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_7[A1,R1,B1,B3,B4,B5,B6,B7,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3,B4,B5,B6,B7),R2]) : Term7[B1,A1,B3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_7[A1,R1,B1,B2,B4,B5,B6,B7,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1,B4,B5,B6,B7),R2]) : Term7[B1,B2,A1,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_1_7[A1,R1,B1,B2,B3,B5,B6,B7,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,R1,B5,B6,B7),R2]) : Term7[B1,B2,B3,A1,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_1_7[A1,R1,B1,B2,B3,B4,B6,B7,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,R1,B6,B7),R2]) : Term7[B1,B2,B3,B4,A1,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_1_7[A1,R1,B1,B2,B3,B4,B5,B7,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,R1,B7),R2]) : Term7[B1,B2,B3,B4,B5,A1,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_6_1_7[A1,R1,B1,B2,B3,B4,B5,B6,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,B6,R1),R2]) : Term7[B1,B2,B3,B4,B5,B6,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 6, 1, 7)
+    Term7(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_2_7[A1,A2,R1,B2,B3,B4,B5,B6,B7,R2](f : Term[(A1,A2),R1], g : Term[(R1,B2,B3,B4,B5,B6,B7),R2]) : Term8[A1,A2,B2,B3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_2_7[A1,A2,R1,B1,B3,B4,B5,B6,B7,R2](f : Term[(A1,A2),R1], g : Term[(B1,R1,B3,B4,B5,B6,B7),R2]) : Term8[B1,A1,A2,B3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_2_7[A1,A2,R1,B1,B2,B4,B5,B6,B7,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,R1,B4,B5,B6,B7),R2]) : Term8[B1,B2,A1,A2,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_2_7[A1,A2,R1,B1,B2,B3,B5,B6,B7,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,R1,B5,B6,B7),R2]) : Term8[B1,B2,B3,A1,A2,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_2_7[A1,A2,R1,B1,B2,B3,B4,B6,B7,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,R1,B6,B7),R2]) : Term8[B1,B2,B3,B4,A1,A2,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_2_7[A1,A2,R1,B1,B2,B3,B4,B5,B7,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,B5,R1,B7),R2]) : Term8[B1,B2,B3,B4,B5,A1,A2,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_6_2_7[A1,A2,R1,B1,B2,B3,B4,B5,B6,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,B5,B6,R1),R2]) : Term8[B1,B2,B3,B4,B5,B6,A1,A2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 6, 2, 7)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_3_7[A1,A2,A3,R1,B2,B3,B4,B5,B6,B7,R2](f : Term[(A1,A2,A3),R1], g : Term[(R1,B2,B3,B4,B5,B6,B7),R2]) : Term9[A1,A2,A3,B2,B3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_3_7[A1,A2,A3,R1,B1,B3,B4,B5,B6,B7,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,R1,B3,B4,B5,B6,B7),R2]) : Term9[B1,A1,A2,A3,B3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_3_7[A1,A2,A3,R1,B1,B2,B4,B5,B6,B7,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,R1,B4,B5,B6,B7),R2]) : Term9[B1,B2,A1,A2,A3,B4,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_3_7[A1,A2,A3,R1,B1,B2,B3,B5,B6,B7,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,R1,B5,B6,B7),R2]) : Term9[B1,B2,B3,A1,A2,A3,B5,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_3_7[A1,A2,A3,R1,B1,B2,B3,B4,B6,B7,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,B4,R1,B6,B7),R2]) : Term9[B1,B2,B3,B4,A1,A2,A3,B6,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_3_7[A1,A2,A3,R1,B1,B2,B3,B4,B5,B7,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,B4,B5,R1,B7),R2]) : Term9[B1,B2,B3,B4,B5,A1,A2,A3,B7,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_6_3_7[A1,A2,A3,R1,B1,B2,B3,B4,B5,B6,R2](f : Term[(A1,A2,A3),R1], g : Term[(B1,B2,B3,B4,B5,B6,R1),R2]) : Term9[B1,B2,B3,B4,B5,B6,A1,A2,A3,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 6, 3, 7)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_8[A1,R1,B2,B3,B4,B5,B6,B7,B8,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3,B4,B5,B6,B7,B8),R2]) : Term8[A1,B2,B3,B4,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_8[A1,R1,B1,B3,B4,B5,B6,B7,B8,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3,B4,B5,B6,B7,B8),R2]) : Term8[B1,A1,B3,B4,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_8[A1,R1,B1,B2,B4,B5,B6,B7,B8,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1,B4,B5,B6,B7,B8),R2]) : Term8[B1,B2,A1,B4,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_1_8[A1,R1,B1,B2,B3,B5,B6,B7,B8,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,R1,B5,B6,B7,B8),R2]) : Term8[B1,B2,B3,A1,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_1_8[A1,R1,B1,B2,B3,B4,B6,B7,B8,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,R1,B6,B7,B8),R2]) : Term8[B1,B2,B3,B4,A1,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_1_8[A1,R1,B1,B2,B3,B4,B5,B7,B8,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,R1,B7,B8),R2]) : Term8[B1,B2,B3,B4,B5,A1,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_6_1_8[A1,R1,B1,B2,B3,B4,B5,B6,B8,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,B6,R1,B8),R2]) : Term8[B1,B2,B3,B4,B5,B6,A1,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 6, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_7_1_8[A1,R1,B1,B2,B3,B4,B5,B6,B7,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,B6,B7,R1),R2]) : Term8[B1,B2,B3,B4,B5,B6,B7,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 7, 1, 8)
+    Term8(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_2_8[A1,A2,R1,B2,B3,B4,B5,B6,B7,B8,R2](f : Term[(A1,A2),R1], g : Term[(R1,B2,B3,B4,B5,B6,B7,B8),R2]) : Term9[A1,A2,B2,B3,B4,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_2_8[A1,A2,R1,B1,B3,B4,B5,B6,B7,B8,R2](f : Term[(A1,A2),R1], g : Term[(B1,R1,B3,B4,B5,B6,B7,B8),R2]) : Term9[B1,A1,A2,B3,B4,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_2_8[A1,A2,R1,B1,B2,B4,B5,B6,B7,B8,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,R1,B4,B5,B6,B7,B8),R2]) : Term9[B1,B2,A1,A2,B4,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_2_8[A1,A2,R1,B1,B2,B3,B5,B6,B7,B8,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,R1,B5,B6,B7,B8),R2]) : Term9[B1,B2,B3,A1,A2,B5,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_2_8[A1,A2,R1,B1,B2,B3,B4,B6,B7,B8,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,R1,B6,B7,B8),R2]) : Term9[B1,B2,B3,B4,A1,A2,B6,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_2_8[A1,A2,R1,B1,B2,B3,B4,B5,B7,B8,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,B5,R1,B7,B8),R2]) : Term9[B1,B2,B3,B4,B5,A1,A2,B7,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_6_2_8[A1,A2,R1,B1,B2,B3,B4,B5,B6,B8,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,B5,B6,R1,B8),R2]) : Term9[B1,B2,B3,B4,B5,B6,A1,A2,B8,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 6, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_7_2_8[A1,A2,R1,B1,B2,B3,B4,B5,B6,B7,R2](f : Term[(A1,A2),R1], g : Term[(B1,B2,B3,B4,B5,B6,B7,R1),R2]) : Term9[B1,B2,B3,B4,B5,B6,B7,A1,A2,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 7, 2, 8)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_0_1_9[A1,R1,B2,B3,B4,B5,B6,B7,B8,B9,R2](f : Term[(A1),R1], g : Term[(R1,B2,B3,B4,B5,B6,B7,B8,B9),R2]) : Term9[A1,B2,B3,B4,B5,B6,B7,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 0, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_1_1_9[A1,R1,B1,B3,B4,B5,B6,B7,B8,B9,R2](f : Term[(A1),R1], g : Term[(B1,R1,B3,B4,B5,B6,B7,B8,B9),R2]) : Term9[B1,A1,B3,B4,B5,B6,B7,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 1, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_2_1_9[A1,R1,B1,B2,B4,B5,B6,B7,B8,B9,R2](f : Term[(A1),R1], g : Term[(B1,B2,R1,B4,B5,B6,B7,B8,B9),R2]) : Term9[B1,B2,A1,B4,B5,B6,B7,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 2, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_3_1_9[A1,R1,B1,B2,B3,B5,B6,B7,B8,B9,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,R1,B5,B6,B7,B8,B9),R2]) : Term9[B1,B2,B3,A1,B5,B6,B7,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 3, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_4_1_9[A1,R1,B1,B2,B3,B4,B6,B7,B8,B9,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,R1,B6,B7,B8,B9),R2]) : Term9[B1,B2,B3,B4,A1,B6,B7,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 4, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_5_1_9[A1,R1,B1,B2,B3,B4,B5,B7,B8,B9,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,R1,B7,B8,B9),R2]) : Term9[B1,B2,B3,B4,B5,A1,B7,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 5, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_6_1_9[A1,R1,B1,B2,B3,B4,B5,B6,B8,B9,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,B6,R1,B8,B9),R2]) : Term9[B1,B2,B3,B4,B5,B6,A1,B8,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 6, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_7_1_9[A1,R1,B1,B2,B3,B4,B5,B6,B7,B9,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,B6,B7,R1,B9),R2]) : Term9[B1,B2,B3,B4,B5,B6,B7,A1,B9,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 7, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
+  }
+
+  private def compose_8_1_9[A1,R1,B1,B2,B3,B4,B5,B6,B7,B8,R2](f : Term[(A1),R1], g : Term[(B1,B2,B3,B4,B5,B6,B7,B8,R1),R2]) : Term9[B1,B2,B3,B4,B5,B6,B7,B8,A1,R2] = {
+    val (newExpr, newTypes) = compose(f, g, 8, 1, 9)
+    Term9(f.program, newExpr, newTypes, f.converter)
   }
 
   /** Compute composed expression for g∘f */
diff --git a/src/cp/Utils.scala b/src/cp/Utils.scala
index 39eb23dd7..335cc062e 100644
--- a/src/cp/Utils.scala
+++ b/src/cp/Utils.scala
@@ -2,45 +2,211 @@ package cp
 
 object Utils {
 
+  val composeMethods = scala.collection.mutable.Map[Int,Seq[String]]()
+  private def indent(s : String) : String = s.split("\n").mkString("  ", "\n  ", "")
+
   /** Generate `compose' methods for terms */
   object GenerateCompose {
-    private def indent(s : String) : String = s.split("\n").mkString("  ", "\n  ", "")
-
     def apply(maxArity : Int) : String = {
       val methods : Seq[String] = (for (arityG <- 1 to maxArity) yield {
         for (arityF <- 1 to (maxArity - arityG + 1)) yield {
           for (index <- 0 until arityG) yield {
-            val sb = new scala.collection.mutable.StringBuilder
-            sb.append("private def compose_")
-            sb.append(index + "_" + arityF + "_" + arityG)
+            val methodName = "compose_%d_%d_%d" format (index, arityF, arityG)
             val fParams = (1 to arityF).map("A" + _)
             val gParams = (1 to arityG).map("B" + _)
 
             val replacedGParams = gParams.take(index) ++ Seq("R1") ++ gParams.drop(index + 1)
             val allParams = fParams ++ Seq("R1") ++ (gParams.take(index) ++ gParams.drop(index + 1)) ++ Seq("R2")
 
-            sb.append(allParams.mkString("[", ",", "]"))
+            val methodParams = allParams.mkString("[", ",", "]")
 
-            sb.append("(f : Term[")
-            sb.append(fParams.mkString("(", ",", ")"))
-            sb.append(",R1], g : Term[")
-            sb.append(replacedGParams.mkString("(", ",", ")"))
-            sb.append(",R2]) : Term")
+            val fParamsTuple = fParams.mkString("(", ",", ")")
+            val replacedGParamsTuple = replacedGParams.mkString("(", ",", ")")
 
             val newTermSize = arityG + arityF - 1
-            val resultParams = gParams.take(index) ++ fParams ++ gParams.drop(index + 1) ++ Seq("R2")
-
-            sb.append(resultParams.mkString(newTermSize + "[", ",", "]"))
-            sb.append(" = {\n")
-            sb.append(indent("val (newExpr, newTypes) = compose(f, g, " + index + ", " + arityF + ", " + arityG + ")"))
-            sb.append("\n")
-            sb.append(indent("Term" + newTermSize + "(f.program, newExpr, newTypes, f.converter)"))
-            sb.append("\n")
-            sb.append("}")
-            sb.toString
+            val resultParams = (gParams.take(index) ++ fParams ++ gParams.drop(index + 1) ++ Seq("R2")).mkString("[", ",", "]")
+
+            val fParamsBrackets = fParams.mkString("[", ",", "]")
+            val rangeType = "T" + (index + 1)
+            val otherTypeParams = (fParams ++ Seq(rangeType)).mkString("[", ",", "]")
+            val resultTermArity = arityG + arityF - 1
+            val classParams = (1 to arityG) map ("T" + _)
+            val resultTermParams = (classParams.take(index) ++ fParams ++ classParams.drop(index + 1) ++ Seq("R")).mkString("[", ",", "]")
+
+            val s1 =
+"""private def %s%s(f : Term[%s,%s], g : Term[%s,%s]) : Term%d%s = {
+  val (newExpr, newTypes) = compose(f, g, %d, %d, %d)
+  Term%d(f.program, newExpr, newTypes, f.converter)
+}""" format (methodName, methodParams, fParamsTuple, "R1", replacedGParamsTuple, "R2", newTermSize, resultParams, index, arityF, arityG, newTermSize)
+
+            val s2 =
+"""def compose%d%s(other : Term%d%s) : Term%d%s = %s(other, this)""" format (index, fParamsBrackets, arityF, otherTypeParams, resultTermArity, resultTermParams, methodName)
+            composeMethods(arityG) = s2 +: composeMethods.getOrElse(arityG,Nil)
+
+            s1
           }
         }
       }).flatten.flatten
+        
+      methods.mkString("\n\n")
+    }
+  }
+
+  object GenerateTerms {
+    def apply(maxArity : Int) : String = {
+      val termTraits = for (arity <- 1 to maxArity) yield {
+        val traitArgParams = (1 to arity) map ("T" + _)
+        val traitArgParamsString = traitArgParams.mkString("[", ",", "]")
+        val traitParams = traitArgParams ++ Seq("R")
+        val traitParamsString = traitParams.mkString("[", ",", "]")
+        val termClassParamTuple = traitArgParams.mkString("(", ",", ")")
+        val traitName = "Term%d%s" format (arity, traitParamsString)
+        val booleanTraitName = "Term%d%s" format (arity, (traitArgParams ++ Seq("Boolean")).mkString("[", ",", "]"))
+        val orConstraintName = "OrConstraint%d%s" format (arity, traitArgParamsString)
+        val andConstraintName = "AndConstraint%d%s" format (arity, traitArgParamsString)
+        val notConstraintName = "NotConstraint%d%s" format (arity, traitArgParamsString)
+        val curriedImplicit2Boolean = "(implicit asConstraint : t2c)"
+        val orMethod = "def ||(other : %s)%s : %s = %s(this, other)" format (booleanTraitName, curriedImplicit2Boolean, booleanTraitName, orConstraintName)
+        val andMethod = "def &&(other : %s)%s : %s = %s(this, other)" format (booleanTraitName, curriedImplicit2Boolean, booleanTraitName, andConstraintName)
+        val notMethod = "def unary_!%s : %s = %s(this)" format (curriedImplicit2Boolean, booleanTraitName, notConstraintName)
+        
+        val intTraitName = "Term%d%s" format (arity, (traitArgParams ++ Seq("Int")).mkString("[", ",", "]"))
+        val minimizingMethod = 
+"""def minimizing(minFunc : %s)%s : MinConstraint%d%s = {
+  MinConstraint%d%s(asConstraint(this), minFunc)
+}""" format (intTraitName, curriedImplicit2Boolean, arity, traitArgParamsString, arity, traitArgParamsString)
+
+        val composeMethodsString = composeMethods.getOrElse(arity, Nil).reverse.mkString("\n")
+
+        val termTraitString =
+"""sealed trait %s extends Term[%s,%s] {
+  val convertingFunction = converterOf(this).exprSeq2scala%d%s _
+  type t2c = (%s) => %s
+  
+%s
+
+%s
+
+%s
+
+%s
+
+%s
+}""" format (traitName, termClassParamTuple, "R", arity, traitArgParamsString, traitName, booleanTraitName, indent(orMethod), indent(andMethod), indent(notMethod), indent(minimizingMethod), indent(composeMethodsString))
+        
+        termTraitString
+      }
+
+      termTraits.mkString("\n\n")
+    }
+  }
+
+  object GenerateTermObjects {
+    def apply(maxArity : Int) : String = {
+      val objectStrings = for (arity <- 1 to maxArity) yield {
+        val argParams = (1 to arity) map ("T" + _)
+        val argParamsString = argParams.mkString("[", ",", "]")
+        val applyParamString = (argParams ++ Seq("R")).mkString("[", ",", "]")
+        val argParamTuple = argParams.mkString("(", ",", ")")
+        val termClassName = "Term[%s,%s]" format (argParamTuple, "R")
+        val booleanTermClassName = "Term[%s,%s]" format (argParamTuple, "Boolean")
+        val termTraitName = "Term%d%s" format (arity, applyParamString)
+        val booleanTermTraitName = "Term%d%s" format (arity, (argParams ++ Seq("Boolean")).mkString("[", ",", "]"))
+        val objectString =
+"""object Term%d {
+  def apply%s(conv : Converter, serializedProg : Serialized, serializedInputVars: Serialized, serializedOutputVars : Serialized, serializedExpr : Serialized, inputVarValues : Seq[Expr]) = {
+    val (converter, program, expr, types) = Term.processArgs(conv, serializedProg, serializedInputVars, serializedOutputVars, serializedExpr, inputVarValues)
+    new %s(program, expr, types, converter) with %s
+  }
+  
+  def apply%s(program : Program, expr : Expr, types : Seq[TypeTree], converter : Converter) =
+    new %s(program, expr, types, converter) with %s
+}""" format (arity, applyParamString, termClassName, termTraitName, applyParamString, termClassName, termTraitName)
+
+        val binaryOpObjectString =
+"""object %sConstraint%d {
+  def apply%s(l : %s, r : %s) : %s = (l, r) match {
+    case (Term(p1,ex1,ts1,conv1), Term(p2,ex2,ts2,conv2)) => Term%d(p1,%s(ex1,ex2),ts1,conv1)
+  }
+}""" 
+        val orObjectString = binaryOpObjectString format ("Or", arity, argParamsString, booleanTermClassName, booleanTermClassName, booleanTermTraitName, arity, "Or")
+        val andObjectString = binaryOpObjectString format ("And", arity, argParamsString, booleanTermClassName, booleanTermClassName, booleanTermTraitName, arity, "And")
+
+        val unaryOpObjectString =
+"""object %sConstraint%d {
+  def apply%s(c : %s) : %s = c match {
+    case Term(p,ex,ts,conv) => Term%d(p,%s(ex),ts,conv)
+  }
+}"""
+
+        val notObjectString = unaryOpObjectString format ("Not", arity, argParamsString, booleanTermClassName, booleanTermTraitName, arity, "Not")
+
+        List(objectString, orObjectString, andObjectString, notObjectString).mkString("\n\n")
+      }
+
+      objectStrings.mkString("\n\n")
+    }
+  }
+
+  object GenerateMinConstraintClasses {
+    def apply(maxArity : Int) : String = {
+      val classes = for (arity <- 1 to maxArity) yield {
+        val params = (1 to arity) map ("T" + _)
+        val paramString = params.mkString("[", ",", "]")
+        val paramTupleString = params.mkString("(", ",", ")")
+        val booleanTermParams = (params ++ Seq("Boolean")).mkString("[", ",", "]")
+        val intTermParams = (params ++ Seq("Int")).mkString("[", ",", "]")
+        val booleanTermName = "Term%d%s" format (arity, booleanTermParams)
+        val intTermName = "Term%d%s" format (arity, intTermParams)
+        val classString =
+"""case class MinConstraint%d%s(cons : %s, minFunc : %s) extends MinConstraint[%s](cons, minFunc) {
+  val convertingFunction = converterOf(cons).exprSeq2scala%d%s _
+}""" format (arity, paramString, booleanTermName, intTermName, paramTupleString, arity, paramString)
+
+        classString
+      }
+
+      classes.mkString("\n\n")
+    }
+  }
+
+  object GenerateTypeAliases {
+    def apply(maxArity : Int) : String = {
+      var booleanTerms = List[String]()
+      var intTerms = List[String]()
+
+      booleanTerms = "type Constraint[T] = Term[T,Boolean]" :: booleanTerms
+      intTerms = "type IntTerm[T] = Term[T,Int]" :: intTerms
+
+      for (arity <- 1 to maxArity) {
+        val params = (1 to arity) map ("T" + _)
+        val paramWithBooleanString = (params ++ Seq("Boolean")).mkString("[", ",", "]")
+        val paramWithIntString = (params ++ Seq("Int")).mkString("[", ",", "]")
+        val paramString = params.mkString("[", ",", "]")
+        val boolType = "type Constraint%d%s = Term%d%s" format (arity, paramString, arity, paramWithBooleanString)
+        val intType = "type IntTerm%d%s = Term%d%s" format (arity, paramString, arity, paramWithIntString)
+
+        booleanTerms = boolType :: booleanTerms
+        intTerms = intType :: intTerms
+      }
+
+      (booleanTerms.reverse ++ intTerms.reverse).mkString("\n")
+    }
+  }
+
+  object GenerateConverterMethods {
+    def apply(maxArity : Int) : String = {
+      val methods = for (arity <- 1 to maxArity) yield {
+        val params = (1 to arity) map ("T" + _)
+        val paramsBrackets = params.mkString("[", ",", "]")
+        val paramsParen    = params.mkString("(", ",", ")")
+        val tuple = params.zipWithIndex.map{ case (p, i) => "expr2scala(exprs(%d)).asInstanceOf[%s]" format (i, p) }.mkString("(", ",", ")")
+        val methodString =
+"""def exprSeq2scala%d%s(exprs : Seq[Expr]) : %s =
+  %s""" format (arity, paramsBrackets, paramsParen, tuple)
+
+        methodString
+      }
 
       methods.mkString("\n\n")
     }
@@ -48,5 +214,10 @@ object Utils {
 
   def main(args: Array[String]) : Unit = {
     println(GenerateCompose(args(0).toInt))
+    println(GenerateTerms(args(0).toInt))
+    println(GenerateTermObjects(args(0).toInt))
+    println(GenerateMinConstraintClasses(args(0).toInt))
+    println(GenerateTypeAliases(args(0).toInt))
+    println(GenerateConverterMethods(args(0).toInt))
   }
 }
-- 
GitLab