diff --git a/cache/Cache.scala b/cache/Cache.scala index 011d35211..2f35d2c96 100644 --- a/cache/Cache.scala +++ b/cache/Cache.scala @@ -23,18 +23,23 @@ object Cache extends BasicCacheImplicits with SBinaryFormats with HListCacheImpl def wrapOutputCache[O,DO](implicit convert: O => DO, reverse: DO => O, base: OutputCache[DO]): OutputCache[O] = new WrappedOutputCache[O,DO](convert, reverse, base) - /* Note: Task[O] { type Input = I } is written out because ITask[I,O] did not work (type could not be inferred properly) with a task - * with an HList input.*/ - def apply[I,O](task: Task[O] { type Input = I }, file: File)(implicit cache: Cache[I,O]): Task[O] { type Input = I } = - task match { case m: M[I,O,_] => - new M[I,O,Result[O]](None)(m.dependencies)(m.extract)(computeWithCache(m, cache, file)) - } - private def computeWithCache[I,O](m: M[I,O,_], cache: Cache[I,O], file: File)(in: I): Result[O] = - cache(file)(in) match - { - case Left(value) => Value(value) - case Right(store) => m.map { out => store(out); out } - } + def apply[I,O](file: File)(f: I => Task[O])(implicit cache: Cache[I,O]): I => Task[O] = + in => + cache(file)(in) match + { + case Left(value) => Task(value) + case Right(store) => f(in) map { out => store(out); out } + } + def cached[I,O](file: File)(f: I => O)(implicit cache: Cache[I,O]): I => O = + in => + cache(file)(in) match + { + case Left(value) => value + case Right(store) => + val out = f(in) + store(out) + out + } } trait BasicCacheImplicits extends NotNull { diff --git a/cache/HListCache.scala b/cache/HListCache.scala index eb3affd13..90f00f47d 100644 --- a/cache/HListCache.scala +++ b/cache/HListCache.scala @@ -1,18 +1,18 @@ package xsbt import java.io.{InputStream,OutputStream} -import metascala.HLists.{HCons,HList,HNil} +import HLists._ class HNilInputCache extends NoInputCache[HNil] class HConsInputCache[H,T <: HList](val headCache: InputCache[H], val tailCache: InputCache[T]) extends InputCache[HCons[H,T]] { def uptodate(in: HCons[H,T])(cacheStream: InputStream) = { - lazy val headResult = headCache.uptodate(in.head)(cacheStream) - lazy val tailResult = tailCache.uptodate(in.tail)(cacheStream) + val headResult = headCache.uptodate(in.head)(cacheStream) + val tailResult = tailCache.uptodate(in.tail)(cacheStream) new CacheResult { - lazy val uptodate = headResult.uptodate && tailResult.uptodate + val uptodate = headResult.uptodate && tailResult.uptodate def update(outputStream: OutputStream) = { headResult.update(outputStream) diff --git a/cache/src/test/scala/CacheTest.scala b/cache/src/test/scala/CacheTest.scala index f0cf919aa..7bba6ec79 100644 --- a/cache/src/test/scala/CacheTest.scala +++ b/cache/src/test/scala/CacheTest.scala @@ -4,19 +4,25 @@ import java.io.File object CacheTest// extends Properties("Cache test") { + val lengthCache = new File("/tmp/length-cache") + val cCache = new File("/tmp/c-cache") + import Task._ import Cache._ import FileInfo.hash._ - def checkFormattable(file: File) + def test { val createTask = Task { new File("test") } - val lengthTask = createTask map { f => println("File length: " + f.length); f.length } - val cached = Cache(lengthTask, new File("/tmp/length-cache")) - val cTask = (createTask :: cached :: TNil) map { case (file :: len :: HNil) => println("File: " + file + " length: " + len); len :: file :: HNil } - val cachedC = Cache(cTask, new File("/tmp/c-cache")) + val length = (f: File) => { println("File length: " + f.length); f.length } + val cachedLength = cached(lengthCache) ( length ) - try { TaskRunner(cachedC) } + val lengthTask = createTask map cachedLength + + val c = (file: File, len: Long) => { println("File: " + file + ", length: " + len); len :: file :: HNil } + val cTask = (createTask :: lengthTask :: TNil) map cached(cCache) { case (file :: len :: HNil) => c(file, len) } + + try { TaskRunner(cTask) } catch { case TasksFailed(failures) => failures.foreach(_.exception.printStackTrace) } } } \ No newline at end of file diff --git a/cache/tracking/Tracked.scala b/cache/tracking/Tracked.scala index 7eba581a0..72be00ac6 100644 --- a/cache/tracking/Tracked.scala +++ b/cache/tracking/Tracked.scala @@ -24,7 +24,7 @@ class Changed[O](val task: Task[O], val cacheFile: File)(implicit input: InputCa { val clean = Clean(cacheFile) def clear = Task.empty - def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): Task[O2] { type Input = O } = + def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): Task[O2] = task map { value => val cache = try { OpenResource.fileInputStream(cacheFile)(input.uptodate(value)) } diff --git a/licenses/LICENSE_MetaScala b/licenses/LICENSE_MetaScala new file mode 100644 index 000000000..8c3025bcc --- /dev/null +++ b/licenses/LICENSE_MetaScala @@ -0,0 +1,27 @@ +Copyright (c) 2009, Jesper Nordenberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the author nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY JESPER NORDENBERG ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL JESPER NORDENBERG BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tasks/TList.scala b/tasks/TList.scala new file mode 100644 index 000000000..58cecfeb2 --- /dev/null +++ b/tasks/TList.scala @@ -0,0 +1,37 @@ +package xsbt + +import Task.{bindTask, mapTask} + +sealed trait TList +{ + type Head + type Tail <: TList + type HListType <: HList + private[xsbt] def tasks: List[Task[_]] + private[xsbt] def get(results: Results): HListType +} +sealed class TNil extends TList +{ + type Head = Nothing + type Tail = TNil + type HListType = HNil + def ::[A](t: Task[A]) = TCons[A,HNil,TNil](t, this) + private[xsbt] def tasks = Nil + private[xsbt] def get(results: Results) = HNil +} +final case class TCons[H, HL <: HList, T <: TList { type HListType = HL}](head: Task[H], tail: T) extends TList +{ + type Head = H + type Tail = T + type HListType = HCons[H,HL] + type This = TCons[H, HL, T] + def ::[A](t: Task[A]) = TCons[A,HListType,This](t, this) + private[xsbt] def tasks = head :: tail.tasks + private[xsbt] def get(results: Results) = HCons(results(head), tail.get(results)) + private def getF = get _ + + def map[X](f: HListType => X): Task[X] = mapTask(tasks: _*)(f compose getF) + def bind[X](f: HListType => Result[X]): Task[X] = bindTask(tasks: _*)(f compose getF) + def join: Task[HListType] = map(identity[HListType]) +} +object TNil extends TNil \ No newline at end of file diff --git a/tasks/Task.scala b/tasks/Task.scala index a601a1e34..322b76ec2 100644 --- a/tasks/Task.scala +++ b/tasks/Task.scala @@ -1,36 +1,35 @@ package xsbt -import Task.{mapTask,bindTask, ITask} +import Task.{mapTask,bindTask} import scala.collection.{mutable,immutable} sealed trait Result[O] extends NotNull final case class Value[O](t: O) extends Result[O] sealed abstract class Task[O] extends Identity with Result[O] { - type Input def dependencies: TreeHashSet[Task[_]] // IMPORTANT!! immutable.HashSet is NOT suitable. It has issues with multi-threaded access - def map[N](f: O => N): ITask[O,N] - def bind[N](f: O => Result[N]): ITask[O,N] - def dependsOn(addDependencies: Task[_]*): ITask[Input,O] - def named(s: String): ITask[Input,O] + def map[N](f: O => N): Task[N] + def bind[N](f: O => Result[N]): Task[N] + def dependsOn(addDependencies: Task[_]*): Task[O] + def named(s: String): Task[O] } -private final class M[I,O,R <: Result[O]](name: Option[String]) - (val dependencies: TreeHashSet[Task[_]])(val extract: Results => I)(val compute: I => R) extends Task[O] +private final class M[O,R <: Result[O]](name: Option[String])(val dependencies: TreeHashSet[Task[_]])(val compute: Results => R) extends Task[O] { - type Input = I - def this(dependencies: Task[_]*)(extract: Results => I)(compute: I => R) = - this(None)(TreeHashSet(dependencies: _*))(extract)(compute) + def this(dependencies: Task[_]*)(compute: Results => R) = + this(None)(TreeHashSet(dependencies: _*))(compute) - final def dependsOn(addDependencies: Task[_]*) = new M(name)(dependencies ++ addDependencies)(extract)(compute) - final def map[N](f: O => N) = mapTask(this)(_(this))(f) - final def bind[N](f: O => Result[N]) = bindTask(this)(_(this))(f) + final def dependsOn(addDependencies: Task[_]*) = new M(name)(dependencies ++ addDependencies)(compute) + final def map[N](f: O => N) = mapTask(this)(f compose get) + final def bind[N](f: O => Result[N]) = bindTask(this)(f compose get) final def named(s: String) = name match { case Some(n) => error("Cannot rename task already named '" + n + "'. (Tried to rename it to '" + s + "')") - case None => new M(Some(s))(dependencies)(extract)(compute) + case None => new M(Some(s))(dependencies)(compute) } - final override def toString = "Task " + name.getOrElse("") + final override def toString = "Task " + name.getOrElse("") + + private def get: (Results => O) = _(this) } abstract class Identity extends NotNull { @@ -49,22 +48,19 @@ object Task { val empty = Task(()) - type ITask[I,O] = Task[O] { type Input = I } import Function.tupled - def apply[O](o: => O): ITask[Unit,O] = - new M[Unit,O,Value[O]]()(r => ())( u => Value(o) ) - def bindTask[I,O](dependencies: Task[_]*)(extract: Results => I)(compute: I => Result[O]): ITask[I,O] = - new M[I,O,Result[O]](dependencies : _*)(extract)(compute) - def mapTask[I,O](dependencies: Task[_]*)(extract: Results => I)(compute: I => O): ITask[I,O] = - new M[I,O,Value[O]](dependencies : _*)(extract)(in => Value(compute(in))) + def apply[O](o: => O): Task[O] = mapTask()( _ => o ) + def mapTask[O](dependencies: Task[_]*)(compute: Results => O): Task[O] = + bindTask(dependencies : _*)(in => Value(compute(in))) + def bindTask[O](dependencies: Task[_]*)(compute: Results => Result[O]): Task[O] = + new M[O,Result[O]](dependencies : _*)(compute) - private[xsbt] def extract[I,O](t: ITask[I,O], results: Results): I = t match { case m: M[I,O,_] => m.extract(results) } - private[xsbt] def compute[I,O](t: ITask[I,O], input: I): Result[O] = t match { case m: M[I,O,_] => m.compute(input) } + private[xsbt] def compute[O](t: Task[O], results: Results): Result[O] = t match { case m: M[O,_] => m.compute(results) } implicit def iterableToForkBuilder[A](t: Iterable[A]): ForkBuilderIterable[A] = new ForkBuilderIterable(t) final class ForkBuilderIterable[A] private[Task](a: Iterable[A]) extends NotNull { - def fork[X](f: A => X): Iterable[ITask[Unit,X]] = a.map(x => Task(f(x))) + def fork[X](f: A => X): Iterable[Task[X]] = forkTasks(x => Task(f(x)) ) def forkTasks[X](f: A => Task[X]): Iterable[Task[X]] = a.map(x => f(x)) def reduce(f: (A,A) => A): Task[A] = fork(x => x) reduce(f) } @@ -72,11 +68,11 @@ object Task implicit def iterableToBuilder[O](t: Iterable[Task[O]]): BuilderIterable[O] = new BuilderIterable(t) final class BuilderIterable[O] private[Task](a: Iterable[Task[O]]) extends NotNull { - //def mapBind[X](f: O => Task[_,X]): Iterable[Task[O,XO]] = a.map(_.bind(f)) + //def mapBind[X](f: O => Task[X]): Iterable[Task[XO]] = a.map(_.bind(f)) def join: Task[Iterable[O]] = join(identity[O]) - def joinIgnore: Task[Unit] = join.map(i => ()) - def join[X](f: O => X): Task[Iterable[X]] = mapTask(a.toSeq: _*)( r => a.map(t => r(t)) )(_.map(f)) - //def bindJoin[X](f: O => Task[_,X]): Task[Iterable[X],Iterable[X]] = mapBind(f).join + def joinIgnore: Task[Unit] = join.map(_ => ()) + def join[X](f: O => X): Task[Iterable[X]] = mapTask(a.toSeq: _*)( r => a map (f compose r.apply[O]) ) + //def bindJoin[X](f: O => Task[X]): Task[Iterable[X]] = mapBind(f).join def reduce(f: (O,O) => O): Task[O] = { def reduce2(list: List[Task[O]], accumulate: List[Task[O]]): List[Task[O]] = @@ -97,59 +93,31 @@ object Task } } - import metascala.HLists.{HList,HNil,HCons} - sealed trait TList - { - type Head - type Tail <: TList - type HListType <: HList - def tasks: List[Task[_]] - def get(results: Results): HListType - } - final class TNil extends TList - { - type Head = Nothing - type Tail = TNil - type HListType = HNil - def ::[A](t: Task[A]) = TCons[A,HNil,TNil](t, this) - def tasks = Nil - def get(results: Results) = HNil - } - final case class TCons[H, HL <: HList, T <: TList { type HListType = HL}](head: Task[H], tail: T) extends TList - { - type Head = H - type Tail = T - type This = TCons[H,HL,T] - type HListType = HCons[H,HL] - def ::[A](t: Task[A]) = TCons[A,HListType,This](t, this) - def tasks = head :: tail.tasks - def get(results: Results) = HCons(results(head), tail.get(results)) - - def map[X](f: HListType => X): ITask[HListType,X] = mapTask(tasks: _*)(get)(f) - def bind[X](f: HListType => Result[X]): ITask[HListType,X] = bindTask(tasks: _*)(get)(f) - def join: ITask[HListType,HListType] = map(identity[HListType]) - } - val TNil = new TNil - implicit def twoToBuilder[A,B](t: (Task[A], Task[B]) ): Builder2[A,B] = t match { case (a,b) => new Builder2(a,b) } final class Builder2[A,B] private[Task](a: Task[A], b: Task[B]) extends NotNull { - def map[X](f: (A,B) => X): ITask[(A,B),X] = mapTask(a,b)(r => (r(a), r(b)))(tupled(f)) - def bind[X](f: (A,B) => Result[X]): ITask[(A,B),X] = bindTask(a,b)( r => (r(a), r(b)) )(tupled(f)) + private def extract = (r: Results) => (r(a), r(b)) + private def compute[T](f: (A,B) => T) = tupled(f) compose extract + def map[X](f: (A,B) => X): Task[X] = mapTask(a,b)(compute(f)) + def bind[X](f: (A,B) => Result[X]): Task[X] = bindTask(a,b)(compute(f)) } implicit def threeToBuilder[A,B,C](t: (Task[A], Task[B], Task[C])): Builder3[A,B,C] = t match { case (a,b,c) => new Builder3(a,b,c) } final class Builder3[A,B,C] private[Task](a: Task[A], b: Task[B], c: Task[C]) extends NotNull { - def map[X](f: (A,B,C) => X): ITask[(A,B,C),X] = mapTask(a,b,c)( r => (r(a), r(b), r(c)) )(tupled(f)) - def bind[X](f: (A,B,C) => Result[X]): ITask[(A,B,C),X] = bindTask(a,b,c)( r => (r(a), r(b), r(c)) )(tupled(f)) + private def extract = (r: Results) => (r(a), r(b), r(c)) + private def compute[T](f: (A,B,C) => T) = tupled(f) compose extract + def map[X](f: (A,B,C) => X): Task[X] = mapTask(a,b,c)(compute(f)) + def bind[X](f: (A,B,C) => Result[X]): Task[X] = bindTask(a,b,c)(compute(f)) } implicit def fourToBuilder[A,B,C,D](t: (Task[A], Task[B], Task[C], Task[D])): Builder4[A,B,C,D] = t match { case (a,b,c,d) => new Builder4(a,b,c,d) } final class Builder4[A,B,C,D] private[Task](a: Task[A], b: Task[B], c: Task[C], d: Task[D]) extends NotNull { - def map[X](f: (A,B,C,D) => X): ITask[(A,B,C,D),X] = mapTask(a,b,c,d)( r => (r(a), r(b), r(c), r(d)) )(tupled(f)) - def bind[X](f: (A,B,C,D) => Result[X]): ITask[(A,B,C,D),X] = bindTask(a,b,c,d)( r => (r(a), r(b), r(c),r(d)) )(tupled(f)) + private def extract = (r: Results) => (r(a), r(b), r(c), r(d)) + private def compute[T](f: (A,B,C,D) => T) = tupled(f) compose extract + def map[X](f: (A,B,C,D) => X): Task[X] = mapTask(a,b,c,d)( compute(f) ) + def bind[X](f: (A,B,C,D) => Result[X]): Task[X] = bindTask(a,b,c,d)( compute(f) ) } } diff --git a/tasks/TaskRunner.scala b/tasks/TaskRunner.scala index ad1df0e6e..552e7fda1 100644 --- a/tasks/TaskRunner.scala +++ b/tasks/TaskRunner.scala @@ -8,10 +8,10 @@ object TaskRunner def apply[T](node: Task[T], maximumTasks: Int): T = { require(maximumTasks > 0) - val compute = new Compute[Work.Job, Result] { def apply[A](w: Work.Job[A]) = w.apply } - val strategy = new SimpleStrategy[Work[_,_]] + val compute = new Compute[Work, Result] { def apply[A](w: Work[A]) = w.apply } + val strategy = new SimpleStrategy[Work[_]] val scheduler = new TaskScheduler(node, strategy, new BasicTaskListener) - val distributor = new Distributor[ Either[ List[WorkFailure[Task[_]]], T ] , Work.Job, Result](scheduler, compute, maximumTasks) + val distributor = new Distributor[ Either[ List[WorkFailure[Task[_]]], T ] , Work, Result](scheduler, compute, maximumTasks) distributor.run().fold(failures => throw new TasksFailed(failures), identity[T]) } } diff --git a/tasks/TaskScheduler.scala b/tasks/TaskScheduler.scala index 8810cfd48..1bef32616 100644 --- a/tasks/TaskScheduler.scala +++ b/tasks/TaskScheduler.scala @@ -1,14 +1,13 @@ package xsbt import scala.collection.{immutable,mutable} -import Task.ITask final case class WorkFailure[D](work: D, exception: Throwable) extends NotNull { def map[C](f: D => C) = WorkFailure(f(work), exception) } -private final class TaskScheduler[O](root: Task[O], strategy: ScheduleStrategy[Work[_,_]], newListener: => TaskListener) - extends Scheduler[ Either[ List[WorkFailure[Task[_]]], O ], Work.Job, Result] +private final class TaskScheduler[O](root: Task[O], strategy: ScheduleStrategy[Work[_]], newListener: => TaskListener) + extends Scheduler[ Either[ List[WorkFailure[Task[_]]], O ], Work, Result] { def run = new Run { @@ -32,7 +31,7 @@ private final class TaskScheduler[O](root: Task[O], strategy: ScheduleStrategy[W } def isComplete = reverseDeps.isEmpty def hasPending = strategyRun.hasReady || !forwardDeps.isEmpty - def complete[A](work: Work.Job[A], result: Either[Throwable,Result[A]]): Unit = + def complete[A](work: Work[A], result: Either[Throwable,Result[A]]): Unit = { val task = work.source result match @@ -66,19 +65,14 @@ private final class TaskScheduler[O](root: Task[O], strategy: ScheduleStrategy[W private def addReady[O](m: Task[O]) { - def add[I](m: ITask[I,O]) - { - val input = Task.extract(m, completed) - strategyRun.workReady(new Work(m, input)) - listener.runnable(m) - } - assert(!forwardDeps.contains(m), m) assert(reverseDeps.contains(m), m) assert(!completed.contains(m), m) assert(!calls.isCalling(m), m) assert(m.dependencies.forall(completed.contains), "Could not find result for dependency of ready task " + m) - add(m: ITask[_,O]) + + strategyRun.workReady(new Work(m, completed)) + listener.runnable(m) } // context called node private def addGraph(node: Task[_], context: Task[_]): Boolean = @@ -230,19 +224,16 @@ private final class CalledByMap extends NotNull caller.asInstanceOf[Task[O]] } } -private final class ResultMap(private val map: mutable.HashMap[Task[_], Any]) extends Results +import java.util.concurrent.{ConcurrentHashMap => HashMap} +private final class ResultMap(private val map: HashMap[Task[_], Any]) extends Results { - def this() = this(new mutable.HashMap) - def update[O](task: Task[O], value: O) { map(task) = value } - def apply[O](task: Task[O]): O = map(task).asInstanceOf[O] - def contains(task: Task[_]) = map.contains(task) + def this() = this(new HashMap) + def update[O](task: Task[O], value: O) { map.put(task, value) } + def apply[O](task: Task[O]): O = map.get(task).asInstanceOf[O] + def contains(task: Task[_]) = map.containsKey(task) } -private final class Work[I,O](val source: ITask[I,O], input: I) extends Identity with NotNull +private final class Work[O](val source: Task[O], results: Results) extends Identity with NotNull { - final def apply = Task.compute(source, input) -} -private object Work -{ - type Job[A] = Work[_,A] + final def apply = Task.compute(source, results) } \ No newline at end of file diff --git a/tasks/src/test/scala/TListCompileTest.scala b/tasks/src/test/scala/TListCompileTest.scala index b559fb200..068ec2ca0 100644 --- a/tasks/src/test/scala/TListCompileTest.scala +++ b/tasks/src/test/scala/TListCompileTest.scala @@ -1,5 +1,5 @@ -//import metascala.HLists._ -import xsbt.{HLists,Task} +package xsbt + import HLists._ import Task._ diff --git a/tasks/src/test/scala/TestRunnerSort.scala b/tasks/src/test/scala/TestRunnerSort.scala index 8ea0c4e75..b7d0daf8c 100644 --- a/tasks/src/test/scala/TestRunnerSort.scala +++ b/tasks/src/test/scala/TestRunnerSort.scala @@ -12,7 +12,7 @@ object TaskRunnerSortTest extends Properties("TaskRunnerSort") java.util.Arrays.sort(sorted) ("Workers: " + workers) |: ("Array: " + a.toList) |: { - def result = TaskRunner( sort(a.toArray), workers) + def result = TaskRunner( sort(a.toArray), if(workers > 0) workers else 1) checkResult(result.toList, sorted.toList) } } @@ -29,8 +29,8 @@ object TaskRunnerSortTest extends Properties("TaskRunnerSort") } final def sort(a: RandomAccessSeq[Int]): Task[RandomAccessSeq[Int]] = { - if(a.length < 2) - Task(a) + if(a.length < 200) + Task(sortDirect(a)) else { Task(a) bind { a => diff --git a/util/collection/HLists.scala b/util/collection/HLists.scala index 4d4a00caa..f376ee4fd 100644 --- a/util/collection/HLists.scala +++ b/util/collection/HLists.scala @@ -1,15 +1,29 @@ package xsbt -import metascala.HLists.{HCons => metaHCons, HList => metaHList, HNil => metaHNil} +// stripped down version of http://trac.assembla.com/metascala/browser/src/metascala/HLists.scala +// Copyright (c) 2009, Jesper Nordenberg +// new BSD license, see licenses/MetaScala object HLists extends HLists -// add an extractor to metascala.HLists and define aliases to the HList classes in the xsbt namespace -trait HLists extends NotNull +trait HLists { object :: { def unapply[H,T<:HList](list: HCons[H,T]) = Some((list.head,list.tail)) } - final val HNil = metaHNil - final type ::[H, T <: HList] = metaHCons[H, T] - final type HNil = metaHNil - final type HList = metaHList - final type HCons[H, T <: HList] = metaHCons[H, T] + type ::[H, T <: HList] = HCons[H, T] +} + +object HNil extends HNil +sealed trait HList { + type Head + type Tail <: HList +} +sealed class HNil extends HList { + type Head = Nothing + type Tail = HNil + def ::[T](v : T) = HCons(v, this) +} + +final case class HCons[H, T <: HList](head : H, tail : T) extends HList { + type Head = H + type Tail = T + def ::[T](v : T) = HCons(v, this) } \ No newline at end of file diff --git a/util/collection/lib/metascala-0.1.jar b/util/collection/lib/metascala-0.1.jar deleted file mode 100644 index ea1d3a62b..000000000 Binary files a/util/collection/lib/metascala-0.1.jar and /dev/null differ