From 462b61579f0f4b2e71b042320d65cd2a78d77c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20Sinan=20K=C3=B6ksal?= <alisinan@gmail.com> Date: Mon, 4 Jul 2011 21:20:58 +0000 Subject: [PATCH] Generation of code for lazySolve yielding LTuples --- cp-demo/LazyVars.scala | 12 +++- src/cp/LTrees.scala | 137 ++++++++++++++++++++++++++++++++++------- src/cp/Terms.scala | 133 ++++++++++++++++++++++++++++----------- src/cp/Utils.scala | 42 ++++++++++++- 4 files changed, 263 insertions(+), 61 deletions(-) diff --git a/cp-demo/LazyVars.scala b/cp-demo/LazyVars.scala index 6e01ef2c9..1f3e6785f 100644 --- a/cp-demo/LazyVars.scala +++ b/cp-demo/LazyVars.scala @@ -7,7 +7,7 @@ object LazyVars { def chooseInt(lower: Int, upper: Int) = ((x: Int) => x >= lower && x <= upper).lazyFindAll def main(args: Array[String]): Unit = { - f3() + f4() } def f1() { @@ -44,4 +44,14 @@ object LazyVars { println("i, (a, b):" + i.value + ", " + pair.value) } } + + def f4() { + val p = ((x: Int, y: Int) => x > 0 && y == 2 * x && x <= 5).lazySolve + val other = ((z: Int) => z == p._1 + p._2).lazySolve + println("x + y: " + other.value) + val x = p._1 + val y = p._2 + println("x: " + x.value) + println("y: " + y.value) + } } diff --git a/src/cp/LTrees.scala b/src/cp/LTrees.scala index ea5b6f5c6..40f781675 100644 --- a/src/cp/LTrees.scala +++ b/src/cp/LTrees.scala @@ -13,11 +13,126 @@ import scala.collection.generic.CanBuildFrom import scala.collection.GenTraversableOnce object LTrees { + /** Handler for converting values from Expr to Scala and reporting forced + * values */ trait LHandler[T] { def convert(s: Seq[Expr]): T def enqueueAsForced(ids: Seq[Identifier], values: Seq[Expr]): Unit } + /* Symbolic variables */ + object L { + def unapply(l: L[_]): Option[Seq[Identifier]] = { + if (l == null) None else Some(l.ids) + } + } + + class L[T](handler: LHandler[T], val ids: Seq[Identifier]) extends { + import ConstraintSolving.GlobalContext + + var cache: Option[T] = None + + def value: T = cache match { + case Some(value) => value + case None => + val model = GlobalContext.findValues(ids) + val toRet = handler.convert(model) + handler.enqueueAsForced(ids, model) + cache = Some(toRet) + toRet + } + } + + trait LTuple[T] { + /* Forces this tuple to have a value */ + def value: T + } + + /** GENERATED CODE ***/ + + class LTuple1[T1](l1: L[T1]) extends LTuple[(T1)] { + def _1: L[T1] = l1 + def value: (T1) = (_1.value) + } + + class LTuple2[T1,T2](l1: L[T1],l2: L[T2]) extends LTuple[(T1,T2)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def value: (T1,T2) = (_1.value,_2.value) + } + + class LTuple3[T1,T2,T3](l1: L[T1],l2: L[T2],l3: L[T3]) extends LTuple[(T1,T2,T3)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def value: (T1,T2,T3) = (_1.value,_2.value,_3.value) + } + + class LTuple4[T1,T2,T3,T4](l1: L[T1],l2: L[T2],l3: L[T3],l4: L[T4]) extends LTuple[(T1,T2,T3,T4)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def _4: L[T4] = l4 + def value: (T1,T2,T3,T4) = (_1.value,_2.value,_3.value,_4.value) + } + + class LTuple5[T1,T2,T3,T4,T5](l1: L[T1],l2: L[T2],l3: L[T3],l4: L[T4],l5: L[T5]) extends LTuple[(T1,T2,T3,T4,T5)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def _4: L[T4] = l4 + def _5: L[T5] = l5 + def value: (T1,T2,T3,T4,T5) = (_1.value,_2.value,_3.value,_4.value,_5.value) + } + + class LTuple6[T1,T2,T3,T4,T5,T6](l1: L[T1],l2: L[T2],l3: L[T3],l4: L[T4],l5: L[T5],l6: L[T6]) extends LTuple[(T1,T2,T3,T4,T5,T6)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def _4: L[T4] = l4 + def _5: L[T5] = l5 + def _6: L[T6] = l6 + def value: (T1,T2,T3,T4,T5,T6) = (_1.value,_2.value,_3.value,_4.value,_5.value,_6.value) + } + + class LTuple7[T1,T2,T3,T4,T5,T6,T7](l1: L[T1],l2: L[T2],l3: L[T3],l4: L[T4],l5: L[T5],l6: L[T6],l7: L[T7]) extends LTuple[(T1,T2,T3,T4,T5,T6,T7)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def _4: L[T4] = l4 + def _5: L[T5] = l5 + def _6: L[T6] = l6 + def _7: L[T7] = l7 + def value: (T1,T2,T3,T4,T5,T6,T7) = (_1.value,_2.value,_3.value,_4.value,_5.value,_6.value,_7.value) + } + + class LTuple8[T1,T2,T3,T4,T5,T6,T7,T8](l1: L[T1],l2: L[T2],l3: L[T3],l4: L[T4],l5: L[T5],l6: L[T6],l7: L[T7],l8: L[T8]) extends LTuple[(T1,T2,T3,T4,T5,T6,T7,T8)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def _4: L[T4] = l4 + def _5: L[T5] = l5 + def _6: L[T6] = l6 + def _7: L[T7] = l7 + def _8: L[T8] = l8 + def value: (T1,T2,T3,T4,T5,T6,T7,T8) = (_1.value,_2.value,_3.value,_4.value,_5.value,_6.value,_7.value,_8.value) + } + + class LTuple9[T1,T2,T3,T4,T5,T6,T7,T8,T9](l1: L[T1],l2: L[T2],l3: L[T3],l4: L[T4],l5: L[T5],l6: L[T6],l7: L[T7],l8: L[T8],l9: L[T9]) extends LTuple[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] { + def _1: L[T1] = l1 + def _2: L[T2] = l2 + def _3: L[T3] = l3 + def _4: L[T4] = l4 + def _5: L[T5] = l5 + def _6: L[T6] = l6 + def _7: L[T7] = l7 + def _8: L[T8] = l8 + def _9: L[T9] = l9 + def value: (T1,T2,T3,T4,T5,T6,T7,T8,T9) = (_1.value,_2.value,_3.value,_4.value,_5.value,_6.value,_7.value,_8.value,_9.value) + } + /** END OF GENERATED CODE ***/ + + /** A stream for symbolic variables */ class LStream[T](val constraint: (L[T]) => Constraint[T]) extends scala.collection.generic.FilterMonadic[L[T], Traversable[L[T]]] { import ConstraintSolving.GlobalContext @@ -135,26 +250,4 @@ object LTrees { } } - /* L for Lazy, L for Logic */ - object L { - def unapply(l: L[_]): Option[Seq[Identifier]] = { - if (l == null) None else Some(l.ids) - } - } - - class L[T](handler: LHandler[T], val ids: Seq[Identifier]) extends { - import ConstraintSolving.GlobalContext - - var cache: Option[T] = None - - def value: T = cache match { - case Some(value) => value - case None => - val model = GlobalContext.findValues(ids) - val toRet = handler.convert(model) - handler.enqueueAsForced(ids, model) - cache = Some(toRet) - toRet - } - } } diff --git a/src/cp/Terms.scala b/src/cp/Terms.scala index f41007ca8..19c8221eb 100644 --- a/src/cp/Terms.scala +++ b/src/cp/Terms.scala @@ -35,44 +35,11 @@ object Terms { findAllExprSeq(asConstraint(this)).map(convertingFunction(_)) } - def lazySolve(implicit asConstraint: (Term[T,R]) => Constraint[T]): L[T] = { - def removeGuard(g: Identifier): Unit = { - GlobalContext.kill(g) - val noMoreLive = Not(Variable(g)) - GlobalContext.enqueueAssert(noMoreLive) - } - - val constraint = asConstraint(this) - val (newConsts, newExpr) = combineConstraint(constraint) - - GlobalContext.initializeIfNeeded(constraint.program) - - val newGuard = FreshIdentifier("live", true).setType(BooleanType) - GlobalContext.addLive(newGuard) - - val toAssert = Implies(Variable(newGuard), newExpr) - if (GlobalContext.checkAssumptions(toAssert)) { - // we can return an L value - val handler = new LHandler[T] { - def convert(s: Seq[Expr]): T = convertingFunction(s) - def enqueueAsForced(ids: Seq[Identifier], values: Seq[Expr]): Unit = { - val haveValues = And((ids zip values) map { - case (i, v) => Equals(Variable(i), v) - }) - GlobalContext.enqueueAssert(haveValues) - removeGuard(newGuard) - } - } - - new L[T](handler, newConsts) - } else { - // constraint is not satisfiable, remove guard from context - removeGuard(newGuard) - throw new UnsatisfiableConstraintException - } + def lazySolve(implicit asConstraint: (Term[T,R]) => Constraint[T]): LTuple[T] = { + throw new Exception() } - def lazyFind(implicit asConstraint: (Term[T,R]) => Term[T,Boolean]): Option[L[T]] = { + def lazyFind(implicit asConstraint: (Term[T,R]) => Term[T,Boolean]): Option[LTuple[T]] = { try { Some(this.lazySolve) } catch { @@ -86,6 +53,46 @@ object Terms { } } + def removeGuard(g: Identifier): Unit = { + GlobalContext.kill(g) + val noMoreLive = Not(Variable(g)) + GlobalContext.enqueueAssert(noMoreLive) + } + + def createL[T](constraint: Constraint[_], constant: Identifier, guard: Identifier): L[T] = { + val handler = new LHandler[T] { + def convert(s: Seq[Expr]): T = constraint.converter.exprSeq2scala1[T](s) + def enqueueAsForced(ids: Seq[Identifier], values: Seq[Expr]): Unit = { + val haveValues = And((ids zip values) map { + case (i, v) => Equals(Variable(i), v) + }) + GlobalContext.enqueueAssert(haveValues) + removeGuard(guard) + } + } + new L[T](handler, Seq(constant)) + } + + def constantsAndGuards[T](constraint: Constraint[T]): (Seq[Identifier], Seq[Identifier]) = { + val (newConsts, newExpr) = combineConstraint(constraint) + + GlobalContext.initializeIfNeeded(constraint.program) + + val newGuards = newConsts map (nc => FreshIdentifier("live", true).setType(BooleanType)) + newGuards foreach GlobalContext.addLive + + val toAssert = Implies(Or(newGuards map (ng => Variable(ng))), newExpr) + if (GlobalContext.checkAssumptions(toAssert)) { + // we can return variables and their guards + (newConsts, newGuards) + } else { + // constraint is not satisfiable, remove guard from context + newGuards foreach removeGuard + throw new UnsatisfiableConstraintException + } + } + + /** This construct represents a constraint with an expression to minimize */ abstract class MinConstraint[T](cons : Constraint[_], minFunc : IntTerm[_]) { val convertingFunction : (Seq[Expr] => T) @@ -186,6 +193,12 @@ object Terms { MinConstraint1[T1](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term1[T1,R]) => Constraint1[T1]): LTuple1[T1] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple1[T1](createL[T1](constraint, constants(0), guards(0))) + } + def compose0[A1](other : Term1[A1, T1]) : Term1[A1, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 1) Term1(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1) => this.scalaFunction(other.scalaFunction(x_0)), newTypes, this.converter) @@ -253,6 +266,12 @@ object Terms { MinConstraint2[T1,T2](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term2[T1,T2,R]) => Constraint2[T1,T2]): LTuple2[T1,T2] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple2[T1,T2](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1))) + } + def compose0[A1](other : Term1[A1, T1]) : Term2[A1, T2, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 2) Term2(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2) => this.scalaFunction(other.scalaFunction(x_0), x_1), newTypes, this.converter) @@ -355,6 +374,12 @@ object Terms { MinConstraint3[T1,T2,T3](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term3[T1,T2,T3,R]) => Constraint3[T1,T2,T3]): LTuple3[T1,T2,T3] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple3[T1,T2,T3](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2))) + } + def compose0[A1](other : Term1[A1, T1]) : Term3[A1, T2, T3, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 3) Term3(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2), newTypes, this.converter) @@ -482,6 +507,12 @@ object Terms { MinConstraint4[T1,T2,T3,T4](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term4[T1,T2,T3,T4,R]) => Constraint4[T1,T2,T3,T4]): LTuple4[T1,T2,T3,T4] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple4[T1,T2,T3,T4](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2)),createL[T4](constraint, constants(3), guards(3))) + } + def compose0[A1](other : Term1[A1, T1]) : Term4[A1, T2, T3, T4, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 4) Term4(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3, x_3 : T4) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2, x_3), newTypes, this.converter) @@ -624,6 +655,12 @@ object Terms { MinConstraint5[T1,T2,T3,T4,T5](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term5[T1,T2,T3,T4,T5,R]) => Constraint5[T1,T2,T3,T4,T5]): LTuple5[T1,T2,T3,T4,T5] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple5[T1,T2,T3,T4,T5](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2)),createL[T4](constraint, constants(3), guards(3)),createL[T5](constraint, constants(4), guards(4))) + } + def compose0[A1](other : Term1[A1, T1]) : Term5[A1, T2, T3, T4, T5, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 5) Term5(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2, x_3, x_4), newTypes, this.converter) @@ -771,6 +808,12 @@ object Terms { MinConstraint6[T1,T2,T3,T4,T5,T6](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term6[T1,T2,T3,T4,T5,T6,R]) => Constraint6[T1,T2,T3,T4,T5,T6]): LTuple6[T1,T2,T3,T4,T5,T6] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple6[T1,T2,T3,T4,T5,T6](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2)),createL[T4](constraint, constants(3), guards(3)),createL[T5](constraint, constants(4), guards(4)),createL[T6](constraint, constants(5), guards(5))) + } + def compose0[A1](other : Term1[A1, T1]) : Term6[A1, T2, T3, T4, T5, T6, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 6) Term6(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2, x_3, x_4, x_5), newTypes, this.converter) @@ -913,6 +956,12 @@ object Terms { MinConstraint7[T1,T2,T3,T4,T5,T6,T7](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term7[T1,T2,T3,T4,T5,T6,T7,R]) => Constraint7[T1,T2,T3,T4,T5,T6,T7]): LTuple7[T1,T2,T3,T4,T5,T6,T7] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple7[T1,T2,T3,T4,T5,T6,T7](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2)),createL[T4](constraint, constants(3), guards(3)),createL[T5](constraint, constants(4), guards(4)),createL[T6](constraint, constants(5), guards(5)),createL[T7](constraint, constants(6), guards(6))) + } + def compose0[A1](other : Term1[A1, T1]) : Term7[A1, T2, T3, T4, T5, T6, T7, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 7) Term7(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6, x_6 : T7) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2, x_3, x_4, x_5, x_6), newTypes, this.converter) @@ -1040,6 +1089,12 @@ object Terms { MinConstraint8[T1,T2,T3,T4,T5,T6,T7,T8](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term8[T1,T2,T3,T4,T5,T6,T7,T8,R]) => Constraint8[T1,T2,T3,T4,T5,T6,T7,T8]): LTuple8[T1,T2,T3,T4,T5,T6,T7,T8] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple8[T1,T2,T3,T4,T5,T6,T7,T8](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2)),createL[T4](constraint, constants(3), guards(3)),createL[T5](constraint, constants(4), guards(4)),createL[T6](constraint, constants(5), guards(5)),createL[T7](constraint, constants(6), guards(6)),createL[T8](constraint, constants(7), guards(7))) + } + def compose0[A1](other : Term1[A1, T1]) : Term8[A1, T2, T3, T4, T5, T6, T7, T8, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 8) Term8(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6, x_6 : T7, x_7 : T8) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2, x_3, x_4, x_5, x_6, x_7), newTypes, this.converter) @@ -1142,6 +1197,12 @@ object Terms { MinConstraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9](asConstraint(this), minFunc) } + def lazySolve(implicit asConstraint: (Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R]) => Constraint9[T1,T2,T3,T4,T5,T6,T7,T8,T9]): LTuple9[T1,T2,T3,T4,T5,T6,T7,T8,T9] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple9[T1,T2,T3,T4,T5,T6,T7,T8,T9](createL[T1](constraint, constants(0), guards(0)),createL[T2](constraint, constants(1), guards(1)),createL[T3](constraint, constants(2), guards(2)),createL[T4](constraint, constants(3), guards(3)),createL[T5](constraint, constants(4), guards(4)),createL[T6](constraint, constants(5), guards(5)),createL[T7](constraint, constants(6), guards(6)),createL[T8](constraint, constants(7), guards(7)),createL[T9](constraint, constants(8), guards(8))) + } + def compose0[A1](other : Term1[A1, T1]) : Term9[A1, T2, T3, T4, T5, T6, T7, T8, T9, R] = { val (newExpr, newTypes) = Terms.compose(other, this, 0, 1, 9) Term9(this.program, newExpr, if (this.scalaFunction == null || other.scalaFunction == null) null else (x_0 : A1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6, x_6 : T7, x_7 : T8, x_8 : T9) => this.scalaFunction(other.scalaFunction(x_0), x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8), newTypes, this.converter) diff --git a/src/cp/Utils.scala b/src/cp/Utils.scala index cf306265c..085c38dbd 100644 --- a/src/cp/Utils.scala +++ b/src/cp/Utils.scala @@ -33,6 +33,15 @@ object Utils { MinConstraint%d[%s](asConstraint(this), minFunc) }""" format (intTraitName, curriedImplicit2Constraint, arity, traitArgParamsString, arity, traitArgParamsString) + val createLCalls = (1 to arity) map (i => """createL[T%d](constraint, constants(%d), guards(%d))""" format (i, i - 1, i - 1)) + val createLCallsString = createLCalls.mkString(",") + val lazySolveMethod = +"""def lazySolve(implicit asConstraint: (%s) => Constraint%d[%s]): LTuple%d[%s] = { + val constraint = asConstraint(this) + val (constants, guards) = constantsAndGuards(constraint) + new LTuple%d[%s](%s) +}""" format (traitName, arity, traitArgParamsString, arity, traitArgParamsString, arity, traitArgParamsString, createLCallsString) + val composeMethods = (for (arityF <- 1 to (maxArity - arity + 1)) yield { for (index <- 0 until arity) yield { val fParams = (1 to arityF).map("A" + _) @@ -77,6 +86,8 @@ object Utils { %s +%s + %s }""" format (traitName, termClassParamTuple, "R", arity, traitParams.mkString(","), arity, traitArgParamsString, @@ -84,7 +95,7 @@ object Utils { termClassParamTuple, "R", evaluatorArgs.mkString(","), applyParams.mkString(", "), applyArgs.mkString(", "), - indent(orMethod), indent(andMethod), indent(notMethod), indent(minimizingMethod), indent(composeMethods)) + indent(orMethod), indent(andMethod), indent(notMethod), indent(minimizingMethod), indent(lazySolveMethod), indent(composeMethods)) termTraitString } @@ -191,7 +202,31 @@ object Utils { } } + object GenerateLTuples { + def apply(maxArity: Int): String = { + val classes = for (arity <- 1 to maxArity) yield { + val typeParams = (1 to arity) map ("T" + _) + val typeParamString = typeParams.mkString(",") + val arguments = (1 to arity) map (i => "l%d: L[T%d]" format (i, i)) + val argumentString = arguments.mkString(",") + val componentMethods = (1 to arity) map (i => "def _%d: L[T%d] = l%d" format (i, i, i)) + val componentMethodString = componentMethods.mkString("\n") + val valueMethodParams = (1 to arity) map (i => "_%d.value" format (i)) + val valueMethodParamString = valueMethodParams.mkString(",") + val valueMethod = "def value: (%s) = (%s)" format (typeParamString, valueMethodParamString) +"""class LTuple%d[%s](%s) extends LTuple[(%s)] { +%s +%s +}""" format (arity, typeParamString, argumentString, typeParamString, indent(componentMethodString), indent(valueMethod)) + } + + classes.mkString("\n\n") + } + } + def main(args: Array[String]) : Unit = { + if (args.size != 1) + throw new Exception("Enter an arity for code generation") val termTraits = GenerateTerms(args(0).toInt) val termObjects = GenerateTermObjects(args(0).toInt) val minConstraintsClasses = GenerateMinConstraintClasses(args(0).toInt) @@ -199,7 +234,10 @@ object Utils { val converterMethods = GenerateConverterMethods(args(0).toInt) + val ltupleClasses = GenerateLTuples(args(0).toInt) + val everything = Seq(typeAliases, termTraits, termObjects, minConstraintsClasses).mkString("\n\n") - println(indent(everything)) + // println(indent(everything)) + println(indent(ltupleClasses)) } } -- GitLab