diff --git a/main/Append.scala b/main/Append.scala new file mode 100644 index 000000000..c9a0e7e61 --- /dev/null +++ b/main/Append.scala @@ -0,0 +1,41 @@ +package sbt + + import java.io.File + import Keys.Classpath + import scala.annotation.implicitNotFound + +object Append +{ + @implicitNotFound(msg = "No implicit for Append.Value[${A}, ${B}] found,\n so ${B} cannot be appended to ${A}") + sealed trait Value[A,B] + { + def appendValue(a: A, b: B): A + } + @implicitNotFound(msg = "No implicit for Append.Values[${A}, ${B}] found,\n so ${B} cannot be appended to ${A}") + sealed trait Values[A,B] + { + def appendValues(a: A, b: B): A + } + sealed trait Sequence[A,B,T] extends Value[A,T] with Values[A,B] + + implicit def appendSeq[T, V <: T]: Sequence[Seq[T], Seq[V], V] = new Sequence[Seq[T], Seq[V], V] { + def appendValues(a: Seq[T], b: Seq[V]): Seq[T] = a ++ b + def appendValue(a: Seq[T], b: V): Seq[T] = a :+ b + } + implicit def appendString: Value[String, String] = new Value[String, String] { + def appendValue(a: String, b: String) = a + b + } + implicit def appendInt = new Value[Int, Int] { + def appendValue(a: Int, b: Int) = a + b + } + implicit def appendLong = new Value[Long, Long] { + def appendValue(a: Long, b: Long) = a + b + } + implicit def appendDouble = new Value[Double, Double] { + def appendValue(a: Double, b: Double) = a + b + } + implicit def appendClasspath: Sequence[Classpath, Seq[File], File] = new Sequence[Classpath, Seq[File], File] { + def appendValues(a: Classpath, b: Seq[File]): Classpath = a ++ Attributed.blankSeq(b) + def appendValue(a: Classpath, b: File): Classpath = a :+ Attributed.blank(b) + } +} \ No newline at end of file diff --git a/main/CommandSupport.scala b/main/CommandSupport.scala index 142b88dc7..18f677d81 100644 --- a/main/CommandSupport.scala +++ b/main/CommandSupport.scala @@ -193,7 +193,7 @@ Multi + " command1 " + Multi + """ command2 ... Runs the specified commands. """ - def Append = "append" + def AppendCommand = "append" def AppendLastBrief = (Append + " command", AppendLastDetailed) def AppendLastDetailed = "Appends `command` to list of commands to run." diff --git a/main/Defaults.scala b/main/Defaults.scala index d499f4e4c..1d54191f3 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -456,7 +456,7 @@ object Defaults extends BuildCommon } def sbtPluginExtra(m: ModuleID, sbtV: String, scalaV: String): ModuleID = m.extra(CustomPomParser.SbtVersionKey -> sbtV, CustomPomParser.ScalaVersionKey -> scalaV).copy(crossVersion = false) - def writePluginsDescriptor(plugins: Set[String], dir: File): List[File] = + def writePluginsDescriptor(plugins: Set[String], dir: File): Seq[File] = { val descriptor: File = dir / "sbt" / "sbt.plugins" if(plugins.isEmpty) @@ -528,7 +528,7 @@ object Defaults extends BuildCommon val CompletionsID = "completions" - def noAggregation = Seq(run, console, consoleQuick, consoleProject) + def noAggregation: Seq[Scoped] = Seq(run, console, consoleQuick, consoleProject) lazy val disableAggregation = noAggregation map disableAggregate def disableAggregate(k: Scoped) = aggregate in Scope.GlobalScope.copy(task = Select(k.key)) :== false @@ -582,7 +582,7 @@ object Classpaths lazy val defaultArtifactTasks: Seq[ScopedTask[File]] = makePom +: defaultPackages def packaged(pkgTasks: Seq[ScopedTask[File]]): Initialize[Task[Map[Artifact, File]]] = - enabledOnly(packagedArtifact.task, pkgTasks).map(_.join.map(_.toMap)) + enabledOnly(packagedArtifact.task, pkgTasks) apply (_.join.map(_.toMap)) def artifactDefs(pkgTasks: Seq[ScopedTask[File]]): Initialize[Seq[Artifact]] = enabledOnly(artifact, pkgTasks) @@ -617,7 +617,7 @@ object Classpaths organizationHomepage in GlobalScope <<= organizationHomepage or homepage.identity, projectInfo <<= (name, description, homepage, licenses, organizationName, organizationHomepage) apply ModuleInfo, classpathFilter in GlobalScope :== "*.jar" | "*.so" | "*.dll", - externalResolvers <<= (externalResolvers.task.? zipWith resolvers.identity) { + externalResolvers <<= (externalResolvers.task.?, resolvers) { case (Some(delegated), Seq()) => delegated case (_, rs) => task { Resolver.withDefaultResolvers(rs) } }, @@ -1046,14 +1046,14 @@ trait BuildExtra extends BuildCommon def fullRunInputTask(scoped: ScopedInput[Unit], config: Configuration, mainClass: String, baseArguments: String*): Setting[InputTask[Unit]] = scoped <<= inputTask { result => - ( initScoped(scoped.scoped, runnerInit) zipWith (fullClasspath in config, streams, result).identityMap) { (rTask, t) => + ( initScoped(scoped.scopedKey, runnerInit) zipWith (fullClasspath in config, streams, result).identityMap) { (rTask, t) => (t :^: rTask :^: KNil) map { case (cp, s, args) :+: r :+: HNil => toError(r.run(mainClass, data(cp), baseArguments ++ args, s.log)) } } } def fullRunTask(scoped: ScopedTask[Unit], config: Configuration, mainClass: String, arguments: String*): Setting[Task[Unit]] = - scoped <<= ( initScoped(scoped.scoped, runnerInit) zipWith (fullClasspath in config, streams).identityMap ) { case (rTask, t) => + scoped <<= ( initScoped(scoped.scopedKey, runnerInit) zipWith (fullClasspath in config, streams).identityMap ) { case (rTask, t) => (t :^: rTask :^: KNil) map { case (cp, s) :+: r :+: HNil => toError(r.run(mainClass, data(cp), arguments, s.log)) } diff --git a/main/GlobalPlugin.scala b/main/GlobalPlugin.scala index 40db7ce6b..c7557a0ec 100644 --- a/main/GlobalPlugin.scala +++ b/main/GlobalPlugin.scala @@ -43,7 +43,7 @@ object GlobalPlugin val depMap = pdescs + mod.dependencyMapping(log(state)) GlobalPluginData(pid, pdeps, depMap, cp, prods ++ intcp) } - val task = taskInit mapReferenced Project.mapScope(Scope replaceThis p) get data + val task = taskInit mapReferenced Project.mapScope(Scope replaceThis p) evaluate data evaluate(state, structure, task) } def evaluate[T](state: State, structure: BuildStructure, t: Task[T]): T = diff --git a/main/Main.scala b/main/Main.scala index 36f152aa5..cd6ea2920 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -216,7 +216,7 @@ object BuiltinCommands def ifLast = Command(IfLast, IfLastBrief, IfLastDetailed)(otherCommandParser) { (s, arg) => if(s.remainingCommands.isEmpty) arg :: s else s } - def append = Command(Append, AppendLastBrief, AppendLastDetailed)(otherCommandParser) { (s, arg) => + def append = Command(AppendCommand, AppendLastBrief, AppendLastDetailed)(otherCommandParser) { (s, arg) => s.copy(remainingCommands = s.remainingCommands :+ arg) } diff --git a/main/Project.scala b/main/Project.scala index 219a614b1..9f12c025f 100644 --- a/main/Project.scala +++ b/main/Project.scala @@ -75,8 +75,8 @@ final case class Extracted(structure: BuildStructure, session: SessionSettings, { import EvaluateTask._ val extracted = Project.extract(state) - val rkey = Project.mapScope(Scope.resolveScope(GlobalScope, extracted.currentRef.build, rootProject) )( key ) - val value: Option[Result[T]] = evaluateTask(structure, key.task.scoped, state, currentRef) + val rkey = Project.mapScope(Scope.resolveScope(GlobalScope, extracted.currentRef.build, rootProject) )( key.scopedKey ) + val value: Option[Result[T]] = evaluateTask(structure, key.task.scopedKey, state, currentRef) val result = getOrError(rkey.scope, rkey.key, value) processResult(result, ConsoleLogger()) } @@ -330,6 +330,7 @@ object Project extends Init[Scope] with ProjectExtra } // this is here instead of Scoped so that it is considered without need for import (because of Project.Initialize) implicit def richInitializeTask[T](init: Initialize[Task[T]]): Scoped.RichInitializeTask[T] = new Scoped.RichInitializeTask(init) + implicit def richInitialize[T](i: Initialize[T]): Scoped.RichInitialize[T] = new Scoped.RichInitialize[T](i) } trait ProjectExtra diff --git a/main/Structure.scala b/main/Structure.scala index 26c48886d..bd390e2ef 100644 --- a/main/Structure.scala +++ b/main/Structure.scala @@ -8,7 +8,7 @@ package sbt import Types._ import std.TaskExtra.{task => mktask, _} import Task._ - import Project.{Initialize, ScopedKey, Setting, setting} + import Project.{Initialize, KeyedInitialize, ScopedKey, Setting, setting} import complete.Parser import java.io.File import java.net.URI @@ -56,7 +56,7 @@ object InputTask def apply[I,T](p: Initialize[State => Parser[I]])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] = { val key: TaskKey[I] = Keys.parseResult.asInstanceOf[TaskKey[I]] - (p zip Keys.resolvedScoped.identity zipWith action(key)) { case ((parserF, scoped), act) => + (p zip Keys.resolvedScoped zipWith action(key)) { case ((parserF, scoped), act) => new InputDynamic[T] { type Result = I @@ -72,47 +72,45 @@ object InputTask sealed trait Scoped { def scope: Scope; def key: AttributeKey[_] } sealed trait ScopedTaskable[T] extends Scoped -sealed trait ScopedSetting[T] extends ScopedTaskable[T] { def key: AttributeKey[T] } -sealed trait ScopedTask[T] extends ScopedTaskable[T] { def key: AttributeKey[Task[T]] } -sealed trait ScopedInput[T] extends Scoped { def key: AttributeKey[InputTask[T]] } +sealed trait ScopedSetting[T] extends ScopedTaskable[T] with KeyedInitialize[T] with Scoped.ScopingSetting[ScopedSetting[T]] with Scoped.DefinableSetting[T] with Scoped.ListSetting[T, Id] +{ + def key: AttributeKey[T] + def scopedKey: ScopedKey[T] = ScopedKey(scope, key) + def in(scope: Scope): ScopedSetting[T] = Scoped.scopedSetting(Scope.replaceThis(this.scope)(scope), this.key) -sealed trait Key[T] extends Scoped { final def scope: Scope = Scope(This,This,This,This) } + protected[this] def make[S](other: Initialize[S])(f: (T, S) => T): Setting[T] = this <<= (this, other)(f) +} +sealed trait ScopedTask[T] extends ScopedTaskable[T] with KeyedInitialize[Task[T]] with Scoped.ScopingSetting[ScopedTask[T]] with Scoped.ListSetting[T, Task] with Scoped.DefinableTask[T] +{ + def key: AttributeKey[Task[T]] + def scopedKey: ScopedKey[Task[T]] = ScopedKey(scope, key) + def in(scope: Scope): ScopedTask[T] = Scoped.scopedTask(Scope.replaceThis(this.scope)(scope), this.key) + + protected[this] def make[S](other: Initialize[Task[S]])(f: (T, S) => T): Setting[Task[T]] = this <<= (this, other) { (a,b) => (a,b) map f } +} +sealed trait ScopedInput[T] extends Scoped with KeyedInitialize[InputTask[T]] with Scoped.ScopingSetting[ScopedInput[T]] with Scoped.DefinableSetting[InputTask[T]] +{ + def key: AttributeKey[InputTask[T]] + def scopedKey: ScopedKey[InputTask[T]] = ScopedKey(scope, key) + def in(scope: Scope): ScopedInput[T] = Scoped.scopedInput(Scope.replaceThis(this.scope)(scope), this.key) +} + +sealed trait Key[T] extends Scoped { final def scope: Scope = Scope.ThisScope } final class SettingKey[T] private(val key: AttributeKey[T]) extends Key[T] with ScopedSetting[T] final class TaskKey[T] private(val key: AttributeKey[Task[T]]) extends Key[T] with ScopedTask[T] final class InputKey[T] private(val key: AttributeKey[InputTask[T]]) extends Key[InputTask[T]] with ScopedInput[T] object Scoped { - implicit def richSettingScoped[T](s: ScopedSetting[T]): RichSettingScoped[T] = new RichSettingScoped[T](s.scope, s.key) - implicit def richTaskScoped[T](s: ScopedTask[T]): RichTaskScoped[T] = new RichTaskScoped[T](s.scope, s.key) - implicit def richInputScoped[T](s: ScopedInput[T]): RichInputScoped[T] = new RichInputScoped[T](s.scope, s.key) - implicit def richSettingListScoped[T](s: ScopedSetting[Seq[T]]): RichSettingList[T] = new RichSettingList[T](s.scope, s.key) - implicit def richListTaskScoped[T](s: ScopedTask[Seq[T]]): RichListTask[T] = new RichListTask[T](s.scope, s.key) - + @deprecated("Implicit conversion from ScopedTask[T] to ScopedKey[Task[T]] is deprecated. Use the scopedKey method of ScopedTask.") implicit def taskScopedToKey[T](s: ScopedTask[T]): ScopedKey[Task[T]] = ScopedKey(s.scope, s.key) + + @deprecated("Implicit conversion from ScopedInput[T] to ScopedKey[InputTask[T]] is deprecated. Use the scopedKey method of ScopedInput.") implicit def inputScopedToKey[T](s: ScopedInput[T]): ScopedKey[InputTask[T]] = ScopedKey(s.scope, s.key) - implicit def scopedSettingScoping[T](s: ScopedSetting[T]): ScopingSetting[ScopedSetting[T]] = - new ScopingSetting(scope => scopedSetting(Scope.replaceThis(s.scope)(scope), s.key)) - - implicit def scopedTaskScoping[T](s: ScopedTask[T]): ScopingSetting[ScopedTask[T]] = - new ScopingSetting(scope => scopedTask(Scope.replaceThis(s.scope)(scope), s.key)) - - implicit def scopedInputScoping[T](s: ScopedInput[T]): ScopingSetting[ScopedInput[T]] = - new ScopingSetting(scope => scopedInput(Scope.replaceThis(s.scope)(scope), s.key)) - - implicit def settingScoping[T](s: SettingKey[T]): ScopingSetting[ScopedSetting[T]] = - new ScopingSetting(scope => scopedSetting(scope, s.key)) - - implicit def inputScoping[T](s: InputKey[T]): ScopingSetting[ScopedInput[T]] = - new ScopingSetting(scope => scopedInput(scope, s.key)) - - implicit def taskScoping[T](s: TaskKey[T]): ScopingSetting[ScopedTask[T]] = - new ScopingSetting(scope => scopedTask(scope, s.key)) - - final class ScopingSetting[Result](app0: Scope => Result) + sealed trait ScopingSetting[Result] { - def in(s: Scope): Result = app0(s) + def in(s: Scope): Result def in(p: Reference): Result = in(Select(p), This, This) def in(t: Scoped): Result = in(This, This, Select(t.key)) @@ -124,127 +122,94 @@ object Scoped def in(p: ScopeAxis[Reference], c: ScopeAxis[ConfigKey], t: ScopeAxis[AttributeKey[_]]): Result = in( Scope(p, c, t, This) ) } - private[this] def scopedSetting[T](s: Scope, k: AttributeKey[T]): ScopedSetting[T] = new ScopedSetting[T] { val scope = s; val key = k } - private[this] def scopedInput[T](s: Scope, k: AttributeKey[InputTask[T]]): ScopedInput[T] = new ScopedInput[T] { val scope = s; val key = k } - private[this] def scopedTask[T](s: Scope, k: AttributeKey[Task[T]]): ScopedTask[T] = new ScopedTask[T] { val scope = s; val key = k } + def scopedSetting[T](s: Scope, k: AttributeKey[T]): ScopedSetting[T] = new ScopedSetting[T] { val scope = s; val key = k} + def scopedInput[T](s: Scope, k: AttributeKey[InputTask[T]]): ScopedInput[T] = new ScopedInput[T] { val scope = s; val key = k } + def scopedTask[T](s: Scope, k: AttributeKey[Task[T]]): ScopedTask[T] = new ScopedTask[T] { val scope = s; val key = k } - sealed abstract class RichXList[S, M[_]] + sealed trait ListSetting[S, M[_]] { - protected[this] def make[T](other: Initialize[M[T]])(f: (Seq[S], T) => Seq[S]): Setting[M[Seq[S]]] - protected[this] def update(f: Seq[S] => Seq[S]): Setting[M[Seq[S]]] - def <+= (value: Initialize[M[S]]): Setting[M[Seq[S]]] = make(value) {_ :+ _ } - def <++=(values: Initialize[M[Seq[S]]]): Setting[M[Seq[S]]] = make(values) {_ ++ _ } - def += (value: => S): Setting[M[Seq[S]]] = update(_ :+ value) - def ++=(values: => Seq[S]): Setting[M[Seq[S]]] = update(_ ++ values) - } - final class RichSettingList[S](scope: Scope, key: AttributeKey[Seq[S]]) extends RichXList[S, Id] - { - private[this] val base = new RichSettingScoped(scope, key) - protected[this] def make[T](other: Initialize[T])(f: (Seq[S], T) => Seq[S]): Setting[Seq[S]] = base <<= (base.identity zipWith other)(f) - protected[this] def update(f: Seq[S] => Seq[S]): Setting[Seq[S]] = base ~= f - } - final class RichListTask[S](scope: Scope, key: AttributeKey[Task[Seq[S]]]) extends RichXList[S, Task] - { - private[this] val base = new RichTaskScoped(scope, key) - protected[this] def make[T](other: Initialize[Task[T]])(f: (Seq[S], T) => Seq[S]): Setting[Task[Seq[S]]] = base <<= (base.identity zipWith other) { (a,b) => (a,b) map f } - protected[this] def update(f: Seq[S] => Seq[S]): Setting[Task[Seq[S]]] = base ~= f - } - sealed abstract class RichBaseScoped[S] - { - def scope: Scope - def key: AttributeKey[S] - final val scoped = ScopedKey(scope, key) - - final def :==(value: S): Setting[S] = :=(value) - final def := (value: => S): Setting[S] = setting(scoped, Project.value(value)) - final def ~= (f: S => S): Setting[S] = Project.update(scoped)(f) - final def <<= (app: Initialize[S]): Setting[S] = setting(scoped, app) + protected[this] def make[T](other: Initialize[M[T]])(f: (S, T) => S): Setting[M[S]] + protected[this] def ~=(f: S => S): Setting[M[S]] - final def apply[T](f: S => T): Initialize[T] = Apply.single(scoped)(f) - final def identity: Initialize[S] = apply(idFun) - final def ? : Initialize[Option[S]] = Project.optional(scoped)(idFun) - final def or[T >: S](i: Initialize[T]): Initialize[T] = (this.? zipWith i)(_ getOrElse _ ) - final def ??[T >: S](or: => T): Initialize[T] = Project.optional(scoped)(_ getOrElse or ) - - final def get(settings: Settings[Scope]): Option[S] = settings.get(scope, key) + def <+= [V](value: Initialize[M[V]])(implicit a: Append.Value[S, V]): Setting[M[S]] = make(value)(a.appendValue) + def <++= [V](values: Initialize[M[V]])(implicit a: Append.Values[S, V]): Setting[M[S]] = make(values)(a.appendValues) + def += [U](value: => U)(implicit a: Append.Value[S, U]): Setting[M[S]] = this ~= ( v => a.appendValue(v, value) ) + def ++=[U](values: => U)(implicit a: Append.Values[S, U]): Setting[M[S]] = this ~= ( v => a.appendValues(v, values) ) } - final class RichInputScoped[T](val scope: Scope, val key: AttributeKey[InputTask[T]]) extends RichBaseScoped[InputTask[T]] - final class RichSettingScoped[S](val scope: Scope, val key: AttributeKey[S]) extends RichBaseScoped[S] + sealed trait DefinableSetting[S] { - def map[T](f: S => T): Initialize[Task[T]] = flatMap(s => mktask(f(s)) ) - def flatMap[T](f: S => Task[T]): Initialize[Task[T]] = Apply.single(scoped)(f) - } - final class RichTaskScoped[S](scope: Scope, key: AttributeKey[Task[S]]) - { - type ScS = Setting[Task[S]] - def :==(value: S): ScS = :=(value) - def ::=(value: Task[S]): ScS = Project.setting(scoped, Project.value( value )) - def := (value: => S): ScS = ::=(mktask(value)) - def :== (v: ScopedSetting[S]): ScS = <<=( v(constant)) - def ~= (f: S => S): ScS = Project.update(scoped)( _ map f ) + def scopedKey: ScopedKey[S] - def <<= (app: App[S]): ScS = Project.setting(scoped, app) + private[sbt] final def :==(value: S): Setting[S] = :=(value) + final def := (value: => S): Setting[S] = setting(scopedKey, Project.value(value)) + final def ~= (f: S => S): Setting[S] = Project.update(scopedKey)(f) + final def <<= (app: Initialize[S]): Setting[S] = setting(scopedKey, app) + final def get(settings: Settings[Scope]): Option[S] = settings.get(scopedKey.scope, scopedKey.key) + final def ? : Initialize[Option[S]] = Project.optional(scopedKey)(idFun) + final def or[T >: S](i: Initialize[T]): Initialize[T] = (this.?, i)(_ getOrElse _ ) + final def ??[T >: S](or: => T): Initialize[T] = Project.optional(scopedKey)(_ getOrElse or ) + } + final class RichInitialize[S](init: Initialize[S]) + { + @deprecated("A call to 'identity' is no longer necessary and can be removed.") + final def identity: Initialize[S] = init + def map[T](f: S => T): Initialize[Task[T]] = init(s => mktask(f(s)) ) + def flatMap[T](f: S => Task[T]): Initialize[Task[T]] = init(f) + } + sealed trait DefinableTask[S] + { self: ScopedTask[S] => + + private[sbt] def :==(value: S): Setting[Task[S]] = :=(value) + private[sbt] def ::=(value: Task[S]): Setting[Task[S]] = Project.setting(scopedKey, Project.value( value )) + def := (value: => S): Setting[Task[S]] = ::=(mktask(value)) + private[sbt] def :== (v: ScopedSetting[S]): Setting[Task[S]] = <<=( v(constant)) + def ~= (f: S => S): Setting[Task[S]] = Project.update(scopedKey)( _ map f ) + + def <<= (app: Initialize[Task[S]]): Setting[Task[S]] = Project.setting(scopedKey, app) def task: ScopedSetting[Task[S]] = scopedSetting(scope, key) def get(settings: Settings[Scope]): Option[Task[S]] = settings.get(scope, key) - type App[T] = Initialize[Task[T]] - def scoped = ScopedKey(scope, key) - private[this] def mk[T](onTask: Task[S] => Task[T]): App[T] = Apply.single(scoped)(onTask) - - def flatMapR[T](f: Result[S] => Task[T]): App[T] = mk(_ flatMapR f) - def flatMap[T](f: S => Task[T]): App[T] = flatMapR(f compose successM) - def map[T](f: S => T): App[T] = mapR(f compose successM) - def mapR[T](f: Result[S] => T): App[T] = mk(_ mapR f) - def flatFailure[T](f: Incomplete => Task[T]): App[T] = flatMapR(f compose failM) - def mapFailure[T](f: Incomplete => T): App[T] = mapR(f compose failM) - def andFinally(fin: => Unit): App[S] = mk(_ andFinally fin) - def doFinally(t: Task[Unit]): App[S] = mk(_ doFinally t) - def identity: App[S] = mk(idFun) - def ? : Initialize[Task[Option[S]]] = Project.optional(scoped) { case None => mktask { None }; case Some(t) => t map some.fn } - def ??[T >: S](or: => T): Initialize[Task[T]] = Project.optional(scoped)( _ getOrElse mktask(or) ) - def or[T >: S](i: Initialize[Task[T]]): Initialize[Task[T]] = (this.? zipWith i)( (x,y) => (x :^: y :^: KNil) map hf2( _ getOrElse _ )) + @deprecated("A call to 'identity' is no longer necessary and can be removed.") + def identity: Initialize[Task[S]] = this - def || [T >: S](alt: Task[T]): App[T] = mk(_ || alt) - def && [T](alt: Task[T]): App[T] = mk(_ && alt) + def ? : Initialize[Task[Option[S]]] = Project.optional(scopedKey) { case None => mktask { None }; case Some(t) => t map some.fn } + def ??[T >: S](or: => T): Initialize[Task[T]] = Project.optional(scopedKey)( _ getOrElse mktask(or) ) + def or[T >: S](i: Initialize[Task[T]]): Initialize[Task[T]] = (this.? zipWith scopedKey)( (x,y) => (x :^: y :^: KNil) map hf2( _ getOrElse _ )) + } + final class RichInitializeTask[S](i: Initialize[Task[S]]) + { + def flatMapR[T](f: Result[S] => Task[T]): Initialize[Task[T]] = i(_ flatMapR f) + def flatMap[T](f: S => Task[T]): Initialize[Task[T]] = flatMapR(f compose successM) + def map[T](f: S => T): Initialize[Task[T]] = mapR(f compose successM) + def mapR[T](f: Result[S] => T): Initialize[Task[T]] = i(_ mapR f) + def flatFailure[T](f: Incomplete => Task[T]): Initialize[Task[T]] = flatMapR(f compose failM) + def mapFailure[T](f: Incomplete => T): Initialize[Task[T]] = mapR(f compose failM) + def andFinally(fin: => Unit): Initialize[Task[S]] = i(_ andFinally fin) + def doFinally(t: Task[Unit]): Initialize[Task[S]] = i(_ doFinally t) - def dependsOn(tasks: ScopedTask[_]*): App[S] = - { - val in = KCons(scopedTask(scope, key), KList.fromList(tasks)) - Apply.tasks(in) { kl => - kl.head.dependsOn(kl.tail.toList :_*) - } - } - } + def || [T >: S](alt: Task[T]): Initialize[Task[T]] = i(_ || alt) + def && [T](alt: Task[T]): Initialize[Task[T]] = i(_ && alt) - implicit def richSettingSeq[T](in: Seq[ScopedSetting[T]]): RichSettingSeq[T] = new RichSettingSeq(in) - final class RichSettingSeq[T](keys: Seq[ScopedSetting[T]]) - { - def join: Initialize[Seq[T]] = joinWith(idFun) - def joinWith[S](f: Seq[T] => S): Initialize[S] = Apply.uniform(keys)(f) - } - implicit def richTaskSeq[T](in: Seq[ScopedTask[T]]): RichTaskSeq[T] = new RichTaskSeq(in) - final class RichTaskSeq[T](keys: Seq[ScopedTask[T]]) - { - def join: Initialize[Task[Seq[T]]] = Apply.uniformTasks(keys) - } - implicit def richAnyTaskSeq(in: Seq[ScopedTask[_]]): RichAnyTaskSeq = new RichAnyTaskSeq(in) - final class RichAnyTaskSeq(keys: Seq[ScopedTask[_]]) - { - def dependOn: Initialize[Task[Unit]] = Apply.tasks(KList.fromList(keys)) { kl => nop.dependsOn(kl.toList :_*) } - } + def dependsOn(tasks: AnyInitTask*): Initialize[Task[S]] = (i, Initialize.joinAny(tasks)) { (thisTask, deps) => thisTask.dependsOn(deps : _*) } - final class RichInitializeTask[T](init: Initialize[Task[T]]) + def triggeredBy(tasks: AnyInitTask*): Initialize[Task[S]] = nonLocal(tasks, Keys.triggeredBy) + def runBefore(tasks: AnyInitTask*): Initialize[Task[S]] = nonLocal(tasks, Keys.runBefore) + private[this] def nonLocal(tasks: Seq[AnyInitTask], key: AttributeKey[Seq[Task[_]]]): Initialize[Task[S]] = + (Initialize.joinAny(tasks), i) { (ts, i) => i.copy(info = i.info.set(key, ts)) } + } + type AnyInitTask = Initialize[Task[T]] forSome { type T } + + implicit def richTaskSeq[T](in: Seq[Initialize[Task[T]]]): RichTaskSeq[T] = new RichTaskSeq(in) + final class RichTaskSeq[T](keys: Seq[Initialize[Task[T]]]) { - def triggeredBy(tasks: ScopedTask[_]*): Initialize[Task[T]] = nonLocal(tasks, Keys.triggeredBy) - def runBefore(tasks: ScopedTask[_]*): Initialize[Task[T]] = nonLocal(tasks, Keys.runBefore) - private[this] def nonLocal(tasks: Seq[ScopedTask[_]], key: AttributeKey[Seq[Task[_]]]): Initialize[Task[T]] = - { - val getTasks = Apply.tasks(KList.fromList(tasks))(idFun) - (getTasks zipWith init) { (tasks, i) => - i.copy(info = i.info.set(key, tasks.toList)) - } - } + def join: Initialize[Task[Seq[T]]] = tasks(_.join) + def tasks: Initialize[Seq[Task[T]]] = Initialize.join(keys) + } + implicit def richAnyTaskSeq(in: Seq[AnyInitTask]): RichAnyTaskSeq = new RichAnyTaskSeq(in) + final class RichAnyTaskSeq(keys: Seq[AnyInitTask]) + { + def dependOn: Initialize[Task[Unit]] = Initialize.joinAny(keys).apply(deps => nop.dependsOn(deps : _*) ) } @@ -433,36 +398,22 @@ object Scoped def mapFailure[T](f: Seq[Incomplete] => T): App[T] = mapR(f compose anyFailM) } - implicit def t2ToApp2[A,B](t2: (ScopedSetting[A], ScopedSetting[B]) ): Apply2[A,B] = new Apply2(t2) - implicit def t3ToApp3[A,B,C](t3: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C]) ): Apply3[A,B,C] = new Apply3(t3) - implicit def t4ToApp4[A,B,C,D](t4: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D]) ): Apply4[A,B,C,D] = new Apply4(t4) - implicit def t5ToApp5[A,B,C,D,E](t5: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E]) ): Apply5[A,B,C,D,E] = new Apply5(t5) - implicit def t6ToApp6[A,B,C,D,E,F](t6: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F]) ): Apply6[A,B,C,D,E,F] = new Apply6(t6) - implicit def t7ToApp7[A,B,C,D,E,F,G](t7: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F], ScopedSetting[G]) ): Apply7[A,B,C,D,E,F,G] = new Apply7(t7) - implicit def t8ToApp8[A,B,C,D,E,F,G,H](t8: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F], ScopedSetting[G], ScopedSetting[H]) ): Apply8[A,B,C,D,E,F,G,H] = new Apply8(t8) - implicit def t9ToApp9[A,B,C,D,E,F,G,H,I](t9: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F], ScopedSetting[G], ScopedSetting[H], ScopedSetting[I]) ): Apply9[A,B,C,D,E,F,G,H,I] = new Apply9(t9) + implicit def t2ToApp2[A,B](t2: (Initialize[A], Initialize[B]) ): Apply2[A,B] = new Apply2(t2) + implicit def t3ToApp3[A,B,C](t3: (Initialize[A], Initialize[B], Initialize[C]) ): Apply3[A,B,C] = new Apply3(t3) + implicit def t4ToApp4[A,B,C,D](t4: (Initialize[A], Initialize[B], Initialize[C], Initialize[D]) ): Apply4[A,B,C,D] = new Apply4(t4) + implicit def t5ToApp5[A,B,C,D,E](t5: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E]) ): Apply5[A,B,C,D,E] = new Apply5(t5) + implicit def t6ToApp6[A,B,C,D,E,F](t6: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F]) ): Apply6[A,B,C,D,E,F] = new Apply6(t6) + implicit def t7ToApp7[A,B,C,D,E,F,G](t7: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F], Initialize[G]) ): Apply7[A,B,C,D,E,F,G] = new Apply7(t7) + implicit def t8ToApp8[A,B,C,D,E,F,G,H](t8: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F], Initialize[G], Initialize[H]) ): Apply8[A,B,C,D,E,F,G,H] = new Apply8(t8) + implicit def t9ToApp9[A,B,C,D,E,F,G,H,I](t9: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F], Initialize[G], Initialize[H], Initialize[I]) ): Apply9[A,B,C,D,E,F,G,H,I] = new Apply9(t9) object Apply { - def single[I,T](in: ScopedKey[I])(f: I => T): Initialize[T] = - Project.app(in :^: KNil)(hl => f(hl.head)) - def apply[HL <: HList, T](in: KList[ScopedSetting, HL])(f: HL => T): Initialize[T] = Project.app(in transform ssToSK)(f) - def uniformTasks[S](inputs: Seq[ScopedTask[S]]): Initialize[Task[Seq[S]]] = - Project.uniform( inputs map stToSK.fn )(_ join) - def uniform[S,T](inputs: Seq[ScopedSetting[S]])(f: Seq[S] => T): Initialize[T] = - Project.uniform( inputs map ssToSK.fn )(f) - def tasks[HL <: HList, T](in: KList[ScopedTask, HL])(f: KList[Task, HL] => T): Initialize[T] = - { - val kapp = new Project.KApp[HL, Task, T] - kapp(in transform stToSK)(f) - } private val ssToSK = new (ScopedSetting ~> ScopedKey) { def apply[T](sk: ScopedSetting[T]) = new ScopedKey(sk.scope, sk.key) } - private val stToSK = new (ScopedTask ~> ScopedTaskKey) { def apply[T](st: ScopedTask[T]) = new ScopedKey(st.scope, st.key) } - type ScopedTaskKey[T] = ScopedKey[Task[T]] } @@ -475,36 +426,36 @@ object Scoped def mkTuple8[A,B,C,D,E,F,G,H] = (a:A,b:B,c:C,d:D,e:E,f:F,g:G,h:H) => (a,b,c,d,e,f,g,h) def mkTuple9[A,B,C,D,E,F,G,H,I] = (a:A,b:B,c:C,d:D,e:E,f:F,g:G,h:H,i:I) => (a,b,c,d,e,f,g,h,i) - final class Apply2[A,B](t2: (ScopedSetting[A], ScopedSetting[B])) { - def apply[T](z: (A,B) => T) = Apply( k2(t2) )( hf2(z) ) + final class Apply2[A,B](t2: (Initialize[A], Initialize[B])) { + def apply[T](z: (A,B) => T) = Project.app( k2(t2) )( hf2(z) ) def identity = apply(mkTuple2) } - final class Apply3[A,B,C](t3: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C])) { - def apply[T](z: (A,B,C) => T) = Apply( k3(t3) )( hf3(z) ) + final class Apply3[A,B,C](t3: (Initialize[A], Initialize[B], Initialize[C])) { + def apply[T](z: (A,B,C) => T) = Project.app( k3(t3) )( hf3(z) ) def identity = apply(mkTuple3) } - final class Apply4[A,B,C,D](t4: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D])) { - def apply[T](z: (A,B,C,D) => T) = Apply( k4(t4) )( hf4(z) ) + final class Apply4[A,B,C,D](t4: (Initialize[A], Initialize[B], Initialize[C], Initialize[D])) { + def apply[T](z: (A,B,C,D) => T) = Project.app( k4(t4) )( hf4(z) ) def identity = apply(mkTuple4) } - final class Apply5[A,B,C,D,E](t5: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E])) { - def apply[T](z: (A,B,C,D,E) => T) = Apply( k5(t5) )( hf5(z) ) + final class Apply5[A,B,C,D,E](t5: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E])) { + def apply[T](z: (A,B,C,D,E) => T) = Project.app( k5(t5) )( hf5(z) ) def identity = apply(mkTuple5) } - final class Apply6[A,B,C,D,E,F](t6: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F])) { - def apply[T](z: (A,B,C,D,E,F) => T) = Apply( k6(t6) )( hf6(z) ) + final class Apply6[A,B,C,D,E,F](t6: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F])) { + def apply[T](z: (A,B,C,D,E,F) => T) = Project.app( k6(t6) )( hf6(z) ) def identity = apply(mkTuple6) } - final class Apply7[A,B,C,D,E,F,G](t7: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F], ScopedSetting[G])) { - def apply[T](z: (A,B,C,D,E,F,G) => T) = Apply( k7(t7) )( hf7(z) ) + final class Apply7[A,B,C,D,E,F,G](t7: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F], Initialize[G])) { + def apply[T](z: (A,B,C,D,E,F,G) => T) = Project.app( k7(t7) )( hf7(z) ) def identity = apply(mkTuple7) } - final class Apply8[A,B,C,D,E,F,G,H](t8: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F], ScopedSetting[G], ScopedSetting[H])) { - def apply[T](z: (A,B,C,D,E,F,G,H) => T) = Apply( k8(t8) )( hf8(z) ) + final class Apply8[A,B,C,D,E,F,G,H](t8: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F], Initialize[G], Initialize[H])) { + def apply[T](z: (A,B,C,D,E,F,G,H) => T) = Project.app( k8(t8) )( hf8(z) ) def identity = apply(mkTuple8) } - final class Apply9[A,B,C,D,E,F,G,H,I](t9: (ScopedSetting[A], ScopedSetting[B], ScopedSetting[C], ScopedSetting[D], ScopedSetting[E], ScopedSetting[F], ScopedSetting[G], ScopedSetting[H], ScopedSetting[I])) { - def apply[T](z: (A,B,C,D,E,F,G,H,I) => T) = Apply( k9(t9) )( hf9(z) ) + final class Apply9[A,B,C,D,E,F,G,H,I](t9: (Initialize[A], Initialize[B], Initialize[C], Initialize[D], Initialize[E], Initialize[F], Initialize[G], Initialize[H], Initialize[I])) { + def apply[T](z: (A,B,C,D,E,F,G,H,I) => T) = Project.app( k9(t9) )( hf9(z) ) def identity = apply(mkTuple9) } diff --git a/util/collection/Settings.scala b/util/collection/Settings.scala index f37302f7f..41fbd4bc3 100644 --- a/util/collection/Settings.scala +++ b/util/collection/Settings.scala @@ -44,28 +44,31 @@ trait Init[Scope] /** The Show instance used when a detailed String needs to be generated. It is typically used when no context is available.*/ def showFullKey: Show[ScopedKey[_]] - final case class ScopedKey[T](scope: Scope, key: AttributeKey[T]) + final case class ScopedKey[T](scope: Scope, key: AttributeKey[T]) extends KeyedInitialize[T] { + def scopedKey = this + } type SettingSeq[T] = Seq[Setting[T]] type ScopedMap = IMap[ScopedKey, SettingSeq] type CompiledMap = Map[ScopedKey[_], Compiled] type MapScoped = ScopedKey ~> ScopedKey type ValidatedRef[T] = Either[Undefined, ScopedKey[T]] + type ValidatedInit[T] = Either[Seq[Undefined], Initialize[T]] type ValidateRef = ScopedKey ~> ValidatedRef type ScopeLocal = ScopedKey[_] => Seq[Setting[_]] type MapConstant = ScopedKey ~> Option def setting[T](key: ScopedKey[T], init: Initialize[T]): Setting[T] = new Setting[T](key, init) def value[T](value: => T): Initialize[T] = new Value(value _) - def optional[T,U](key: ScopedKey[T])(f: Option[T] => U): Initialize[U] = new Optional(Some(key), f) + def optional[T,U](i: Initialize[T])(f: Option[T] => U): Initialize[U] = new Optional(Some(i), f) def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, app(key :^: KNil)(hl => f(hl.head))) - def app[HL <: HList, T](inputs: KList[ScopedKey, HL])(f: HL => T): Initialize[T] = new Apply(f, inputs) - def uniform[S,T](inputs: Seq[ScopedKey[S]])(f: Seq[S] => T): Initialize[T] = new Uniform(f, inputs) - def kapp[HL <: HList, M[_], T](inputs: KList[({type l[t] = ScopedKey[M[t]]})#l, HL])(f: KList[M, HL] => T): Initialize[T] = new KApply[HL, M, T](f, inputs) + def app[HL <: HList, T](inputs: KList[Initialize, HL])(f: HL => T): Initialize[T] = new Apply(f, inputs) + def uniform[S,T](inputs: Seq[Initialize[S]])(f: Seq[S] => T): Initialize[T] = new Uniform(f, inputs) + def kapp[HL <: HList, M[_], T](inputs: KList[({type l[t] = Initialize[M[t]]})#l, HL])(f: KList[M, HL] => T): Initialize[T] = new KApply[HL, M, T](f, inputs) // the following is a temporary workaround for the "... cannot be instantiated from ..." bug, which renders 'kapp' above unusable outside this source file class KApp[HL <: HList, M[_], T] { - type Composed[S] = ScopedKey[M[S]] + type Composed[S] = Initialize[M[S]] def apply(inputs: KList[Composed, HL])(f: KList[M, HL] => T): Initialize[T] = new KApply[HL, M, T](f, inputs) } @@ -152,7 +155,7 @@ trait Init[Scope] private[this] def applySetting[T](map: Settings[Scope], setting: Setting[T]): Settings[Scope] = { - val value = setting.init.get(map) + val value = setting.init.evaluate(map) val key = setting.key map.set(key.scope, key.key, value) } @@ -194,28 +197,26 @@ trait Init[Scope] sealed trait Initialize[T] { def dependsOn: Seq[ScopedKey[_]] - def map[S](g: T => S): Initialize[S] + def apply[S](g: T => S): Initialize[S] def mapReferenced(g: MapScoped): Initialize[T] - def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Initialize[T]] + def validateReferenced(g: ValidateRef): ValidatedInit[T] def zip[S](o: Initialize[S]): Initialize[(T,S)] = zipWith(o)((x,y) => (x,y)) - def zipWith[S,U](o: Initialize[S])(f: (T,S) => U): Initialize[U] = new Joined[T,S,U](this, o, f) + def zipWith[S,U](o: Initialize[S])(f: (T,S) => U): Initialize[U] = + new Apply[T :+: S :+: HNil, U]( { case t :+: s :+: HNil => f(t,s)}, this :^: o :^: KNil) def mapConstant(g: MapConstant): Initialize[T] - def get(map: Settings[Scope]): T + def evaluate(map: Settings[Scope]): T } object Initialize { implicit def joinInitialize[T](s: Seq[Initialize[T]]): JoinInitSeq[T] = new JoinInitSeq(s) final class JoinInitSeq[T](s: Seq[Initialize[T]]) { - def join[S](f: Seq[T] => S): Initialize[S] = this.join map f - def join: Initialize[Seq[T]] = Initialize.join(s) + def joinWith[S](f: Seq[T] => S): Initialize[S] = uniform(s)(f) + def join: Initialize[Seq[T]] = uniform(s)(idFun) } - def join[T](inits: Seq[Initialize[T]]): Initialize[Seq[T]] = - inits match - { - case Seq() => value( Nil ) - case Seq(x, xs @ _*) => (join(xs) zipWith x)( (t,h) => h +: t) - } + def join[T](inits: Seq[Initialize[T]]): Initialize[Seq[T]] = uniform(inits)(idFun) + def joinAny[M[_]](inits: Seq[Initialize[M[T]] forSome { type T }]): Initialize[Seq[M[_]]] = + join(inits.asInstanceOf[Seq[Initialize[M[Any]]]]).asInstanceOf[Initialize[Seq[M[T] forSome { type T }]]] } object SettingsDefinition { implicit def unwrapSettingsDefinition(d: SettingsDefinition): Seq[Setting[_]] = d.settings @@ -233,103 +234,120 @@ trait Init[Scope] def mapReferenced(g: MapScoped): Setting[T] = new Setting(key, init mapReferenced g) def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Setting[T]] = (init validateReferenced g).right.map(newI => new Setting(key, newI)) def mapKey(g: MapScoped): Setting[T] = new Setting(g(key), init) - def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init.map(t => f(key,t))) + def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = new Setting(key, init(t => f(key,t))) def mapConstant(g: MapConstant): Setting[T] = new Setting(key, init mapConstant g) override def toString = "setting(" + key + ")" } - private[this] final class Optional[S,T](a: Option[ScopedKey[S]], f: Option[S] => T) extends Initialize[T] + // mainly for reducing generated class count + private[this] def validateReferencedT(g: ValidateRef) = + new (Initialize ~> ValidatedInit) { def apply[T](i: Initialize[T]) = i validateReferenced g } + + private[this] def mapReferencedT(g: MapScoped) = + new (Initialize ~> Initialize) { def apply[T](i: Initialize[T]) = i mapReferenced g } + + private[this] def mapConstantT(g: MapConstant) = + new (Initialize ~> Initialize) { def apply[T](i: Initialize[T]) = i mapConstant g } + + private[this] def evaluateT(g: Settings[Scope]) = + new (Initialize ~> Id) { def apply[T](i: Initialize[T]) = i evaluate g } + + private[this] def dependencies(ls: Seq[Initialize[_]]): Seq[ScopedKey[_]] = ls.flatMap(_.dependsOn) + + sealed trait Keyed[S, T] extends Initialize[T] { - def dependsOn = a.toList - def map[Z](g: T => Z): Initialize[Z] = new Optional[S,Z](a, g compose f) - def get(map: Settings[Scope]): T = f(a map asFunction(map)) - def mapReferenced(g: MapScoped) = new Optional(a map g.fn, f) - def validateReferenced(g: ValidateRef) = Right( new Optional(a flatMap { sk => g(sk).right.toOption }, f) ) - def mapConstant(g: MapConstant): Initialize[T] = - (a flatMap g.fn) match { - case None => this - case s => new Value(() => f(s)) - } + def scopedKey: ScopedKey[S] + protected def transform: S => T + final def dependsOn = scopedKey :: Nil + final def apply[Z](g: T => Z): Initialize[Z] = new GetValue(scopedKey, g compose transform) + final def evaluate(ss: Settings[Scope]): T = transform(getValue(ss, scopedKey)) + final def mapReferenced(g: MapScoped): Initialize[T] = new GetValue( g(scopedKey), transform) + final def validateReferenced(g: ValidateRef): ValidatedInit[T] = g(scopedKey) match { + case Left(un) => Left(un :: Nil) + case Right(nk) => Right(new GetValue(nk, transform)) + } + final def mapConstant(g: MapConstant): Initialize[T] = g(scopedKey) match { + case None => this + case Some(const) => new Value(() => transform(const)) + } + @deprecated("Use scopedKey.") + def scoped = scopedKey } - private[this] final class Joined[S,T,U](a: Initialize[S], b: Initialize[T], f: (S,T) => U) extends Initialize[U] + private[this] final class GetValue[S,T](val scopedKey: ScopedKey[S], val transform: S => T) extends Keyed[S, T] + trait KeyedInitialize[T] extends Keyed[T, T] { + protected final val transform = idFun[T] + } + + private[this] final class Optional[S,T](a: Option[Initialize[S]], f: Option[S] => T) extends Initialize[T] { - def dependsOn = a.dependsOn ++ b.dependsOn - def mapReferenced(g: MapScoped) = new Joined(a mapReferenced g, b mapReferenced g, f) - def validateReferenced(g: ValidateRef) = - (a validateReferenced g, b validateReferenced g) match { - case (Right(ak), Right(bk)) => Right( new Joined(ak, bk, f) ) - case (au, bu) => Left( (au.left.toSeq ++ bu.left.toSeq).flatten ) - } - def map[Z](g: U => Z) = new Joined[S,T,Z](a, b, (s,t) => g(f(s,t))) - def mapConstant(g: MapConstant) = new Joined[S,T,U](a mapConstant g, b mapConstant g, f) - def get(map: Settings[Scope]): U = f(a get map, b get map) + def dependsOn = dependencies(a.toList) + def apply[Z](g: T => Z): Initialize[Z] = new Optional[S,Z](a, g compose f) + def evaluate(ss: Settings[Scope]): T = f(a map evaluateT(ss).fn) + def mapReferenced(g: MapScoped) = new Optional(a map mapReferencedT(g).fn, f) + def validateReferenced(g: ValidateRef) = Right( new Optional(a flatMap { _.validateReferenced(g).right.toOption }, f) ) + def mapConstant(g: MapConstant): Initialize[T] = new Optional(a map mapConstantT(g).fn, f) } private[this] final class Value[T](value: () => T) extends Initialize[T] { def dependsOn = Nil def mapReferenced(g: MapScoped) = this def validateReferenced(g: ValidateRef) = Right(this) - def map[S](g: T => S) = new Value[S](() => g(value())) + def apply[S](g: T => S) = new Value[S](() => g(value())) def mapConstant(g: MapConstant) = this - def get(map: Settings[Scope]): T = value() + def evaluate(map: Settings[Scope]): T = value() } - private[this] final class Apply[HL <: HList, T](val f: HL => T, val inputs: KList[ScopedKey, HL]) extends Initialize[T] + private[this] final class Apply[HL <: HList, T](val f: HL => T, val inputs: KList[Initialize, HL]) extends Initialize[T] { - def dependsOn = inputs.toList - def mapReferenced(g: MapScoped) = new Apply(f, inputs transform g) - def map[S](g: T => S) = new Apply(g compose f, inputs) - def mapConstant(g: MapConstant) = Reduced.reduceH(inputs, g).combine( (keys, expand) => new Apply(f compose expand, keys) ) - def get(map: Settings[Scope]) = f(inputs down asTransform(map) ) + def dependsOn = dependencies(inputs.toList) + def mapReferenced(g: MapScoped) = mapInputs( mapReferencedT(g) ) + def apply[S](g: T => S) = new Apply(g compose f, inputs) + def mapConstant(g: MapConstant) = mapInputs( mapConstantT(g) ) + def mapInputs(g: Initialize ~> Initialize): Initialize[T] = new Apply(f, inputs transform g) + def evaluate(ss: Settings[Scope]) = f(inputs down evaluateT(ss)) def validateReferenced(g: ValidateRef) = { - val tx = inputs.transform(g) - val undefs = tx.toList.flatMap(_.left.toSeq) - val get = new (ValidatedRef ~> ScopedKey) { def apply[T](vr: ValidatedRef[T]) = vr.right.get } + val tx = inputs transform validateReferencedT(g) + val undefs = tx.toList.flatMap(_.left.toSeq.flatten) + val get = new (ValidatedInit ~> Initialize) { def apply[T](vr: ValidatedInit[T]) = vr.right.get } if(undefs.isEmpty) Right(new Apply(f, tx transform get)) else Left(undefs) } } - private[this] final class KApply[HL <: HList, M[_], T](val f: KList[M, HL] => T, val inputs: KList[({type l[t] = ScopedKey[M[t]]})#l, HL]) extends Initialize[T] + private[this] final class KApply[HL <: HList, M[_], T](val f: KList[M, HL] => T, val inputs: KList[({type l[t] = Initialize[M[t]]})#l, HL]) extends Initialize[T] { - type ScopedKeyM[T] = ScopedKey[M[T]] - type VRefM[T] = ValidatedRef[M[T]] - def dependsOn = unnest(inputs.toList) - def mapReferenced(g: MapScoped) = new KApply[HL, M, T](f, inputs.transform[({type l[t] = ScopedKey[M[t]]})#l]( nestCon(g) ) ) - def map[S](g: T => S) = new KApply[HL, M, S](g compose f, inputs) - def get(map: Settings[Scope]) = f(inputs.transform[M]( nestCon[ScopedKey, Id, M](asTransform(map)) )) - def mapConstant(g: MapConstant) = - { - def mk[HLk <: HList](keys: KList[ScopedKeyM, HLk], expand: KList[M, HLk] => KList[M, HL]) = new KApply[HLk, M, T](f compose expand, keys) - Reduced.reduceK[HL, ScopedKey, M](inputs, nestCon(g)) combine mk - } + type InitializeM[T] = Initialize[M[T]] + type VInitM[T] = ValidatedInit[M[T]] + def dependsOn = dependencies(unnest(inputs.toList)) + def mapReferenced(g: MapScoped) = mapInputs( mapReferencedT(g) ) + def apply[S](g: T => S) = new KApply[HL, M, S](g compose f, inputs) + def evaluate(ss: Settings[Scope]) = f(inputs.transform[M]( nestCon(evaluateT(ss)) )) + def mapConstant(g: MapConstant) = mapInputs(mapConstantT(g)) + def mapInputs(g: Initialize ~> Initialize): Initialize[T] = + new KApply[HL, M, T](f, inputs.transform[({type l[t] = Initialize[M[t]]})#l]( nestCon(g) )) def validateReferenced(g: ValidateRef) = { - val tx = inputs.transform[VRefM](nestCon(g)) - val undefs = tx.toList.flatMap(_.left.toSeq) - val get = new (VRefM ~> ScopedKeyM) { def apply[T](vr: ValidatedRef[M[T]]) = vr.right.get } + val tx = inputs.transform[VInitM](nestCon(validateReferencedT(g))) + val undefs = tx.toList.flatMap(_.left.toSeq.flatten) + val get = new (VInitM ~> InitializeM) { def apply[T](vr: VInitM[T]) = vr.right.get } if(undefs.isEmpty) - Right(new KApply[HL, M, T](f, tx.transform( get ) )) + Right(new KApply[HL, M, T](f, tx transform get)) else Left(undefs) } - private[this] def unnest(l: List[ScopedKey[M[T]] forSome { type T }]): List[ScopedKey[_]] = l.asInstanceOf[List[ScopedKey[_]]] + private[this] def unnest(l: List[Initialize[M[T]] forSome { type T }]): List[Initialize[_]] = l.asInstanceOf[List[Initialize[_]]] } - private[this] final class Uniform[S, T](val f: Seq[S] => T, val inputs: Seq[ScopedKey[S]]) extends Initialize[T] + private[this] final class Uniform[S, T](val f: Seq[S] => T, val inputs: Seq[Initialize[S]]) extends Initialize[T] { - def dependsOn = inputs - def mapReferenced(g: MapScoped) = new Uniform(f, inputs map g.fn[S]) + def dependsOn = dependencies(inputs) + def mapReferenced(g: MapScoped) = new Uniform(f, inputs map mapReferencedT(g).fn) def validateReferenced(g: ValidateRef) = { - val (undefs, ok) = List.separate(inputs map g.fn[S]) - if(undefs.isEmpty) Right( new Uniform(f, ok) ) else Left(undefs) + val (undefs, ok) = List.separate(inputs map validateReferencedT(g).fn ) + if(undefs.isEmpty) Right( new Uniform(f, ok) ) else Left(undefs.flatten) } - def map[S](g: T => S) = new Uniform(g compose f, inputs) - def mapConstant(g: MapConstant) = - { - val red = Reduced.reduceSeq(inputs, g) - new Uniform(f compose red.expand, red.keys) - } - def get(map: Settings[Scope]) = f(inputs map asFunction(map)) + def apply[S](g: T => S) = new Uniform(g compose f, inputs) + def mapConstant(g: MapConstant) = new Uniform(f, inputs map mapConstantT(g).fn) + def evaluate(ss: Settings[Scope]) = f(inputs map evaluateT(ss).fn ) } private def remove[T](s: Seq[T], v: T) = s filterNot (_ == v) } diff --git a/util/collection/src/test/scala/SettingsExample.scala b/util/collection/src/test/scala/SettingsExample.scala index 38c09d634..8d7136f0f 100644 --- a/util/collection/src/test/scala/SettingsExample.scala +++ b/util/collection/src/test/scala/SettingsExample.scala @@ -12,9 +12,10 @@ final case class Scope(index: Int) // That would be a general pain.) object SettingsExample extends Init[Scope] { - // This is the only abstract method, providing a way of showing a Scope+AttributeKey[_] - override def display(key: ScopedKey[_]): String = - key.scope.index + "/" + key.key.label + // Provides a way of showing a Scope+AttributeKey[_] + val showFullKey: Show[ScopedKey[_]] = new Show[ScopedKey[_]] { + def apply(key: ScopedKey[_]) = key.scope.index + "/" + key.key.label + } // A sample delegation function that delegates to a Scope with a lower index. val delegates: Scope => Seq[Scope] = { case s @ Scope(index) => @@ -55,7 +56,7 @@ object SettingsUsage // "compiles" and applies the settings. // This can be split into multiple steps to access intermediate results if desired. // The 'inspect' command operates on the output of 'compile', for example. - val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal) + val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal, showFullKey) // Show results. for(i <- 0 to 5; k <- Seq(a, b)) {