mirror of https://github.com/sbt/sbt.git
graph evaluator, rewrite, general updates
This commit is contained in:
parent
b1bb6ce5ec
commit
1144fb5a27
|
|
@ -0,0 +1,45 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
/** A mutable set interface that uses object identity to test for set membership.*/
|
||||
trait IDSet[T]
|
||||
{
|
||||
def apply(t: T): Boolean
|
||||
def contains(t: T): Boolean
|
||||
def += (t: T): Unit
|
||||
def ++=(t: Iterable[T]): Unit
|
||||
def -= (t: T): Boolean
|
||||
def all: collection.Iterable[T]
|
||||
def isEmpty: Boolean
|
||||
def foreach(f: T => Unit): Unit
|
||||
def process[S](t: T)(ifSeen: S)(ifNew: => S): S
|
||||
}
|
||||
|
||||
object IDSet
|
||||
{
|
||||
implicit def toTraversable[T]: IDSet[T] => Traversable[T] = _.all
|
||||
def apply[T](values: T*): IDSet[T] = apply(values)
|
||||
def apply[T](values: Iterable[T]): IDSet[T] =
|
||||
{
|
||||
val s = create[T]
|
||||
s ++= values
|
||||
s
|
||||
}
|
||||
def create[T]: IDSet[T] = new IDSet[T] {
|
||||
private[this] val backing = new java.util.IdentityHashMap[T, AnyRef]
|
||||
private[this] val Dummy: AnyRef = ""
|
||||
|
||||
def apply(t: T) = contains(t)
|
||||
def contains(t: T) = backing.containsKey(t)
|
||||
def foreach(f: T => Unit) = all foreach f
|
||||
def += (t: T) = backing.put(t, Dummy)
|
||||
def ++=(t: Iterable[T]) = t foreach +=
|
||||
def -= (t:T) = if(backing.remove(t) eq null) false else true
|
||||
def all = collection.JavaConversions.asIterable(backing.keySet)
|
||||
def isEmpty = backing.isEmpty
|
||||
def process[S](t: T)(ifSeen: S)(ifNew: => S) = if(contains(t)) ifSeen else { this += t ; ifNew }
|
||||
override def toString = backing.toString
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,11 @@ import Types._
|
|||
|
||||
sealed trait MList[+M[_]]
|
||||
{
|
||||
// For converting MList[Id] to an HList
|
||||
// This is useful because type inference doesn't work well with Id
|
||||
type Raw <: HList
|
||||
def down(implicit ev: M ~> Id): Raw
|
||||
|
||||
type Map[N[_]] <: MList[N]
|
||||
def map[N[_]](f: M ~> N): Map[N]
|
||||
|
||||
|
|
@ -14,6 +19,9 @@ sealed trait MList[+M[_]]
|
|||
}
|
||||
final case class MCons[H, +T <: MList[M], +M[_]](head: M[H], tail: T) extends MList[M]
|
||||
{
|
||||
type Raw = H :+: tail.Raw
|
||||
def down(implicit f: M ~> Id): Raw = HCons(f(head), tail.down(f))
|
||||
|
||||
type Map[N[_]] = MCons[H, tail.Map[N], N]
|
||||
def map[N[_]](f: M ~> N) = MCons( f(head), tail.map(f) )
|
||||
|
||||
|
|
@ -23,6 +31,9 @@ final case class MCons[H, +T <: MList[M], +M[_]](head: M[H], tail: T) extends ML
|
|||
}
|
||||
sealed class MNil extends MList[Nothing]
|
||||
{
|
||||
type Raw = HNil
|
||||
def down(implicit f: Nothing ~> Id) = HNil
|
||||
|
||||
type Map[N[_]] = MNil
|
||||
def map[N[_]](f: Nothing ~> N) = MNil
|
||||
|
||||
|
|
@ -30,4 +41,4 @@ sealed class MNil extends MList[Nothing]
|
|||
|
||||
def toList = Nil
|
||||
}
|
||||
object MNil extends MNil
|
||||
object MNil extends MNil
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
trait PMap[K[_], V[_]] extends (K ~> V)
|
||||
{
|
||||
def apply[T](k: K[T]): V[T]
|
||||
def get[T](k: K[T]): Option[V[T]]
|
||||
def update[T](k: K[T], v: V[T]): Unit
|
||||
def contains[T](k: K[T]): Boolean
|
||||
def remove[T](k: K[T]): Option[V[T]]
|
||||
def getOrUpdate[T](k: K[T], make: => V[T]): V[T]
|
||||
}
|
||||
object PMap
|
||||
{
|
||||
implicit def toFunction[K[_], V[_]](map: PMap[K,V]): K[_] => V[_] = k => map(k)
|
||||
}
|
||||
|
||||
abstract class AbstractPMap[K[_], V[_]] extends PMap[K,V]
|
||||
{
|
||||
def apply[T](k: K[T]): V[T] = get(k).get
|
||||
def contains[T](k: K[T]): Boolean = get(k).isDefined
|
||||
}
|
||||
|
||||
import collection.mutable.Map
|
||||
|
||||
/** Only suitable for K that is invariant in its parameter.
|
||||
* Option and List keys are not, for example, because None <:< Option[String] and None <: Option[Int].*/
|
||||
class DelegatingPMap[K[_], V[_]](backing: Map[K[_], V[_]]) extends AbstractPMap[K,V]
|
||||
{
|
||||
def get[T](k: K[T]): Option[V[T]] = cast[T]( backing.get(k) )
|
||||
def update[T](k: K[T], v: V[T]) { backing(k) = v }
|
||||
def remove[T](k: K[T]) = cast( backing.remove(k) )
|
||||
def getOrUpdate[T](k: K[T], make: => V[T]) = cast[T]( backing.getOrElseUpdate(k, make) )
|
||||
|
||||
private[this] def cast[T](v: V[_]): V[T] = v.asInstanceOf[V[T]]
|
||||
private[this] def cast[T](o: Option[V[_]]): Option[V[T]] = o map cast[T]
|
||||
|
||||
override def toString = backing.toString
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
// Used to emulate ~> literals
|
||||
trait Param[A[_], B[_]]
|
||||
{
|
||||
type T
|
||||
def in: A[T]
|
||||
def ret(out: B[T])
|
||||
def ret: B[T]
|
||||
}
|
||||
|
||||
object Param
|
||||
{
|
||||
implicit def pToT[A[_], B[_]](p: Param[A,B] => Unit): A~>B = new (A ~> B) {
|
||||
def apply[s](a: A[s]): B[s] = {
|
||||
val v: Param[A,B] { type T = s} = new Param[A,B] { type T = s
|
||||
def in = a
|
||||
private var r: B[T] = _
|
||||
def ret(b: B[T]) {r = b}
|
||||
def ret: B[T] = r
|
||||
}
|
||||
p(v)
|
||||
v.ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
trait Rewrite[A[_]]
|
||||
{
|
||||
def apply[T](node: A[T], rewrite: Rewrite[A]): A[T]
|
||||
}
|
||||
object Rewrite
|
||||
{
|
||||
def Id[A[_]]: Rewrite[A] = new Rewrite[A] { def apply[T](node: A[T], rewrite: Rewrite[A]) = node }
|
||||
|
||||
implicit def specificF[T](f: T => T): Rewrite[Const[T]#Apply] = new Rewrite[Const[T]#Apply] {
|
||||
def apply[S](node:T, rewrite: Rewrite[Const[T]#Apply]): T = f(node)
|
||||
}
|
||||
implicit def pToRewrite[A[_]](p: Param[A,A] => Unit): Rewrite[A] = toRewrite(Param.pToT(p))
|
||||
implicit def toRewrite[A[_]](f: A ~> A): Rewrite[A] = new Rewrite[A] {
|
||||
def apply[T](node: A[T], rewrite:Rewrite[A]) = f(node)
|
||||
}
|
||||
def compose[A[_]](a: Rewrite[A], b: Rewrite[A]): Rewrite[A] =
|
||||
new Rewrite[A] {
|
||||
def apply[T](node: A[T], rewrite: Rewrite[A]) =
|
||||
a(b(node, rewrite), rewrite)
|
||||
}
|
||||
implicit def rewriteOps[A[_]](outer: Rewrite[A]): RewriteOps[A] =
|
||||
new RewriteOps[A] {
|
||||
def ∙(g: A ~> A): Rewrite[A] = compose(outer, g)
|
||||
def andThen(g: A ~> A): Rewrite[A] = compose(g, outer)
|
||||
def ∙(g: Rewrite[A]): Rewrite[A] = compose(outer, g)
|
||||
def andThen(g: Rewrite[A]): Rewrite[A] = compose(g, outer)
|
||||
}
|
||||
def apply[A[_], T](value: A[T])(implicit rewrite: Rewrite[A]): A[T] = rewrite(value, rewrite)
|
||||
}
|
||||
trait RewriteOps[A[_]]
|
||||
{
|
||||
def andThen(g: A ~> A): Rewrite[A]
|
||||
def ∙(g: A ~> A): Rewrite[A]
|
||||
def ∙(g: Rewrite[A]): Rewrite[A]
|
||||
}
|
||||
|
|
@ -7,14 +7,26 @@ trait TypeFunctions
|
|||
{
|
||||
type Id[X] = X
|
||||
trait Const[A] { type Apply[B] = A }
|
||||
trait P1of2[M[_,_], A] { type Apply[B] = M[A,B] }
|
||||
trait Down[M[_]] { type Apply[B] = Id[M[B]] }
|
||||
trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
|
||||
trait P1of2[M[_,_], A] { type Apply[B] = M[A,B]; type Flip[B] = M[B, A] }
|
||||
|
||||
trait ~>[-A[_], +B[_]]
|
||||
{
|
||||
def apply[T](a: A[T]): B[T]
|
||||
}
|
||||
def Id: Id ~> Id =
|
||||
new (Id ~> Id) { def apply[T](a: T): T = a }
|
||||
final val left = new (Id ~> P1of2[Left, Nothing]#Flip) { def apply[T](t: T) = Left(t) }
|
||||
final val right = new (Id ~> P1of2[Right, Nothing]#Apply) { def apply[T](t: T) = Right(t) }
|
||||
final val some = new (Id ~> Some) { def apply[T](t: T) = Some(t) }
|
||||
}
|
||||
object TypeFunctions extends TypeFunctions
|
||||
object TypeFunctions extends TypeFunctions
|
||||
|
||||
trait ~>[-A[_], +B[_]]
|
||||
{ outer =>
|
||||
def apply[T](a: A[T]): B[T]
|
||||
// directly on ~> because of type inference limitations
|
||||
final def ∙[C[_]](g: C ~> A): C ~> B = new (C ~> B) { def apply[T](c: C[T]) = outer.apply(g(c)) }
|
||||
final def ∙[C,D](g: C => D)(implicit ev: D <:< A[D]): C => B[D] = i => apply(ev(g(i)) )
|
||||
final def fn[T] = (t: A[T]) => apply[T](t)
|
||||
}
|
||||
object ~>
|
||||
{
|
||||
import TypeFunctions._
|
||||
val Id: Id ~> Id = new (Id ~> Id) { def apply[T](a: T): T = a }
|
||||
implicit def tcIdEquals: (Id ~> Id) = Id
|
||||
}
|
||||
|
|
@ -8,4 +8,4 @@ object Types extends TypeFunctions
|
|||
val :^: = MCons
|
||||
val :+: = HCons
|
||||
type :+:[H, T <: HList] = HCons[H,T]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
// compilation test
|
||||
object LiteralTest {
|
||||
def x[A[_],B[_]](f: A ~> B) = f
|
||||
|
||||
import Param._
|
||||
val f = x { (p: Param[Option,List]) => p.ret( p.in.toList ) }
|
||||
|
||||
val a: List[Int] = f( Some(3) )
|
||||
val b: List[String] = f( Some("aa") )
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
object MTest {
|
||||
val f = new (Option ~> List) { def apply[T](o: Option[T]): List[T] = o.toList }
|
||||
|
||||
val x = Some(3) :^: Some("asdf") :^: MNil
|
||||
val y = x map f
|
||||
val m1a = y match { case List(3) :^: List("asdf") :^: MNil => println("true") }
|
||||
val m1b = (List(3) :^: MNil) match { case yy :^: MNil => println("true") }
|
||||
|
||||
val head = new (List ~> Id) { def apply[T](xs: List[T]): T = xs.head }
|
||||
val z = y.map[Id](head).down
|
||||
val m2 = z match { case 3 :+: "asdf" :+: HNil => println("true") }
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
// compilation test
|
||||
object PMapTest
|
||||
{
|
||||
val mp = new DelegatingPMap[Some, Id](new collection.mutable.HashMap)
|
||||
mp(Some("asdf")) = "a"
|
||||
mp(Some(3)) = 9
|
||||
val x = Some(3) :^: Some("asdf") :^: MNil
|
||||
val y = x.map[Id](mp)
|
||||
val z = y.down
|
||||
z match { case 9 :+: "a" :+: HNil => println("true") }
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
|
||||
object RewriteTest
|
||||
{
|
||||
// dist and add0 show the awkwardness when not just manipulating superstructure:
|
||||
// would have to constrain the parameters to Term to be instances of Zero/Eq somehow
|
||||
val dist: Rewrite[Term] = (p: Param[Term, Term]) => p.ret( p.in match {
|
||||
case Add(Mult(a,b),Mult(c,d)) if a == c=> Mult(a, Add(b,d))
|
||||
case x => x
|
||||
})
|
||||
val add0: Rewrite[Term] = (p: Param[Term, Term]) => p.ret( p.in match {
|
||||
case Add(V(0), y) => y
|
||||
case Add(x, V(0)) => x
|
||||
case x => x
|
||||
})
|
||||
val rewriteBU= new Rewrite[Term] {
|
||||
def apply[T](node: Term[T], rewrite: Rewrite[Term]) = {
|
||||
def r[T](node: Term[T]) = rewrite(node, rewrite)
|
||||
node match {
|
||||
case Add(x, y) => Add(r(x), r(y))
|
||||
case Mult(x, y) => Mult(r(x), r(y))
|
||||
case x => x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val d2 = dist ∙ add0 ∙ rewriteBU
|
||||
|
||||
implicit def toV(t: Int): V[Int] = V(t)
|
||||
implicit def toVar(s: String): Var[Int] = Var[Int](s)
|
||||
|
||||
val t1: Term[Int] = Add(Mult(3,4), Mult(4, 5))
|
||||
val t2: Term[Int] = Add(Mult(4,4), Mult(4, 5))
|
||||
val t3: Term[Int] = Add(Mult(Add("x", 0),4), Mult("x", 5))
|
||||
|
||||
println( Rewrite(t1)(d2) )
|
||||
println( Rewrite(t2)(d2) )
|
||||
println( Rewrite(t3)(d2) )
|
||||
}
|
||||
|
||||
sealed trait Term[T]
|
||||
final case class Add[T](a: Term[T], b: Term[T]) extends Term[T]
|
||||
final case class Mult[T](a: Term[T], b: Term[T]) extends Term[T]
|
||||
final case class V[T](v: T) extends Term[T]
|
||||
final case class Var[T](name: String) extends Term[T]
|
||||
Loading…
Reference in New Issue