Settings overhaul, intended to be source compatible where it matters.

Moves many methods previously provided by implicit conversions directly onto the classes
  for better discoverability, especially with scaladoc.

1. Initialize now allowed in more places.  Minor renamings in Initialize to avoid conflicts
  a. map -> apply
  b. get -> evaluate
2. Identity on Scoped* is deprecated- it is now redundant
3. Can now use += and <+= for String, Int, Long, Double settings.
  There may be some problematic corner cases in inference, especially with +=, ++, <+=, <++=
4. Some classes with a scoped: ScopedKey[T] method now have scopedKey: ScopedKey[T] instead.
5. The implicit conversion to ScopedKey[T] is now deprecated.  Use the scopedKey method.
6. :== and ::= are now private[sbt] to better reflect that they were internal use only.
This commit is contained in:
Mark Harrah 2011-08-14 10:53:37 -04:00
parent 112f58db28
commit 90f25b234e
9 changed files with 285 additions and 273 deletions

41
main/Append.scala Normal file
View File

@ -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)
}
}

View File

@ -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."

View File

@ -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))
}

View File

@ -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 =

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)) {