From 5b21bae2449174609c6ec279cb786b03578cd366 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sat, 21 Aug 2010 22:55:42 -0400 Subject: [PATCH] task system cleanup KList.map -> transform can now drop trailing 'H' from multi-Task 'mapH' compressed Action hierarchy by merging (Flat)Map{ped,All,Failure} into (Flat)Mapped moved most information in Info into attributes: AttributeMap to allow future changes --- util/collection/Attributes.scala | 34 +++++++++++++++++++ util/collection/KList.scala | 17 ++++++---- util/collection/Types.scala | 4 +++ .../collection/src/test/scala/KListTest.scala | 2 +- 4 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 util/collection/Attributes.scala diff --git a/util/collection/Attributes.scala b/util/collection/Attributes.scala new file mode 100644 index 000000000..231cda300 --- /dev/null +++ b/util/collection/Attributes.scala @@ -0,0 +1,34 @@ +/* sbt -- Simple Build Tool + * Copyright 2010 Mark Harrah + */ +package sbt + +import Types._ + +// T must be invariant to work properly. +// Because it is sealed and the only instances go through make, +// a single AttributeKey instance cannot conform to AttributeKey[T] for different Ts +sealed trait AttributeKey[T] +object AttributeKey +{ + def make[T]: AttributeKey[T] = new AttributeKey[T] {} +} + +trait AttributeMap +{ + def apply[T](k: AttributeKey[T]): T + def get[T](k: AttributeKey[T]): Option[T] + def contains[T](k: AttributeKey[T]): Boolean + def put[T](k: AttributeKey[T], value: T): AttributeMap +} +object AttributeMap +{ + def empty: AttributeMap = new BasicAttributeMap(Map.empty) +} +private class BasicAttributeMap(backing: Map[AttributeKey[_], Any]) extends AttributeMap +{ + def apply[T](k: AttributeKey[T]) = backing(k).asInstanceOf[T] + def get[T](k: AttributeKey[T]) = backing.get(k).asInstanceOf[Option[T]] + def contains[T](k: AttributeKey[T]) = backing.contains(k) + def put[T](k: AttributeKey[T], value: T): AttributeMap = new BasicAttributeMap( backing.updated(k, value) ) +} \ No newline at end of file diff --git a/util/collection/KList.scala b/util/collection/KList.scala index b2ad40859..81ef6afcd 100644 --- a/util/collection/KList.scala +++ b/util/collection/KList.scala @@ -9,21 +9,23 @@ import Types._ * type parameters HL. The underlying data is M applied to each type parameter. * Explicitly tracking M[_] allows performing natural transformations or ensuring * all data conforms to some common type. */ -sealed trait KList[+M[_], +HL <: HList] { +sealed trait KList[+M[_], +HL <: HList] +{ type Raw = HL /** Transform to the underlying HList type.*/ def down(implicit ev: M ~> Id): HL /** Apply a natural transformation. */ - def map[N[_]](f: M ~> N): KList[N, HL] + def transform[N[_]](f: M ~> N): KList[N, HL] /** Convert to a List. */ def toList: List[M[_]] /** Convert to an HList. */ def combine[N[X] >: M[X]]: HL#Wrap[N] } -final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) extends KList[M, H :+: T] { - def down(implicit f: M ~> Id) = HCons(f(head), tail.down(f)) - def map[N[_]](f: M ~> N) = KCons( f(head), tail.map(f) ) +final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) extends KList[M, H :+: T] +{ + def down(implicit f: M ~> Id) = HCons(f(head), tail down f) + def transform[N[_]](f: M ~> N) = KCons( f(head), tail transform f ) // prepend def :^: [N[X] >: M[X], G](g: N[G]) = KCons(g, this) def toList = head :: tail.toList @@ -31,9 +33,10 @@ final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) exten def combine[N[X] >: M[X]]: (H :+: T)#Wrap[N] = HCons(head, tail.combine) } -sealed class KNil extends KList[Nothing, HNil] { +sealed class KNil extends KList[Nothing, HNil] +{ def down(implicit f: Nothing ~> Id) = HNil - def map[N[_]](f: Nothing ~> N) = KNil + def transform[N[_]](f: Nothing ~> N) = KNil def :^: [M[_], H](h: M[H]) = KCons(h, this) def toList = Nil def combine[N[X]] = HNil diff --git a/util/collection/Types.scala b/util/collection/Types.scala index c5d484c51..abd9ee06b 100644 --- a/util/collection/Types.scala +++ b/util/collection/Types.scala @@ -8,4 +8,8 @@ object Types extends TypeFunctions val :^: = KCons val :+: = HCons type :+:[H, T <: HList] = HCons[H,T] + + implicit def hconsToK[M[_], H, T <: HList](h: M[H] :+: T)(implicit mt: T => KList[M, T]): KList[M, H :+: T] = + KCons[H, T, M](h.head, mt(h.tail) ) + implicit def hnilToK(hnil: HNil): KNil = KNil } diff --git a/util/collection/src/test/scala/KListTest.scala b/util/collection/src/test/scala/KListTest.scala index 210084fb1..2ca25a31a 100644 --- a/util/collection/src/test/scala/KListTest.scala +++ b/util/collection/src/test/scala/KListTest.scala @@ -9,7 +9,7 @@ object KTest { val f = new (Option ~> List) { def apply[T](o: Option[T]): List[T] = o.toList } val x = Some(3) :^: Some("asdf") :^: KNil - val y = x map f + val y = x transform f val m1a = y match { case List(3) :^: List("asdf") :^: KNil => println("true") } val m1b = (List(3) :^: KNil) match { case yy :^: KNil => println("true") }