mirror of https://github.com/sbt/sbt.git
Rewrite to polymorphic function syntax
This commit is contained in:
parent
f662fdda8e
commit
9f1d60be60
|
|
@ -148,6 +148,10 @@ val collectionProj = (project in file("internal") / "util-collection")
|
|||
// Dropped in favour of kind-projector's inline type lambda syntax
|
||||
exclude[MissingClassProblem]("sbt.internal.util.TypeFunctions$P1of2"),
|
||||
|
||||
// Dropped in favour of kind-projector's polymorphic lambda literals
|
||||
exclude[MissingClassProblem]("sbt.internal.util.Param"),
|
||||
exclude[MissingClassProblem]("sbt.internal.util.Param$"),
|
||||
|
||||
// Dropped in favour of plain scala.Function, and its compose method
|
||||
exclude[MissingClassProblem]("sbt.internal.util.Fn1"),
|
||||
exclude[DirectMissingMethodProblem]("sbt.internal.util.TypeFunctions.toFn1"),
|
||||
|
|
@ -432,6 +436,10 @@ lazy val sbtProj = (project in file("sbt"))
|
|||
exclude[ReversedMissingMethodProblem]("sbt.Import.sbt$Import$_setter_$WatchSource_="),
|
||||
exclude[ReversedMissingMethodProblem]("sbt.Import.WatchSource"),
|
||||
|
||||
// Dropped in favour of kind-projector's polymorphic lambda literals
|
||||
exclude[DirectMissingMethodProblem]("sbt.Import.Param"),
|
||||
exclude[DirectMissingMethodProblem]("sbt.package.Param"),
|
||||
|
||||
// Dropped in favour of plain scala.Function, and its compose method
|
||||
exclude[DirectMissingMethodProblem]("sbt.package.toFn1"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -196,11 +196,9 @@ object AttributeMap {
|
|||
def apply(entries: AttributeEntry[_]*): AttributeMap = empty ++ entries
|
||||
|
||||
/** Presents an `AttributeMap` as a natural transformation. */
|
||||
implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = new (AttributeKey ~> Id) {
|
||||
def apply[T](key: AttributeKey[T]): T = map(key)
|
||||
}
|
||||
|
||||
implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = λ[AttributeKey ~> Id](map(_))
|
||||
}
|
||||
|
||||
private class BasicAttributeMap(private val backing: Map[AttributeKey[_], Any])
|
||||
extends AttributeMap {
|
||||
|
||||
|
|
|
|||
|
|
@ -32,27 +32,25 @@ abstract class EvaluateSettings[Scope] {
|
|||
private[this] def getStatic[T](key: ScopedKey[T]): INode[T] =
|
||||
static get key getOrElse sys.error("Illegal reference to key " + key)
|
||||
|
||||
private[this] val transform: Initialize ~> INode = new (Initialize ~> INode) {
|
||||
def apply[T](i: Initialize[T]): INode[T] = i match {
|
||||
case k: Keyed[s, T] @unchecked => single(getStatic(k.scopedKey), k.transform)
|
||||
case a: Apply[k, T] @unchecked =>
|
||||
new MixedNode[k, T](
|
||||
a.alist.transform[Initialize, INode](a.inputs, transform),
|
||||
a.f,
|
||||
a.alist
|
||||
)
|
||||
case b: Bind[s, T] @unchecked => new BindNode[s, T](transform(b.in), x => transform(b.f(x)))
|
||||
case v: Value[T] @unchecked => constant(v.value)
|
||||
case v: ValidationCapture[T] @unchecked => strictConstant(v.key)
|
||||
case t: TransformCapture => strictConstant(t.f)
|
||||
case o: Optional[s, T] @unchecked =>
|
||||
o.a match {
|
||||
case None => constant(() => o.f(None))
|
||||
case Some(i) => single[s, T](transform(i), x => o.f(Some(x)))
|
||||
}
|
||||
case x if x == StaticScopes =>
|
||||
strictConstant(allScopes.asInstanceOf[T]) // can't convince scalac that StaticScopes => T == Set[Scope]
|
||||
}
|
||||
private[this] val transform: Initialize ~> INode = λ[Initialize ~> INode] {
|
||||
case k: Keyed[s, A1$] @unchecked => single(getStatic(k.scopedKey), k.transform)
|
||||
case a: Apply[k, A1$] @unchecked =>
|
||||
new MixedNode[k, A1$](
|
||||
a.alist.transform[Initialize, INode](a.inputs, transform),
|
||||
a.f,
|
||||
a.alist
|
||||
)
|
||||
case b: Bind[s, A1$] @unchecked => new BindNode[s, A1$](transform(b.in), x => transform(b.f(x)))
|
||||
case v: Value[A1$] @unchecked => constant(v.value)
|
||||
case v: ValidationCapture[A1$] @unchecked => strictConstant(v.key)
|
||||
case t: TransformCapture => strictConstant(t.f)
|
||||
case o: Optional[s, A1$] @unchecked =>
|
||||
o.a match {
|
||||
case None => constant(() => o.f(None))
|
||||
case Some(i) => single[s, A1$](transform(i), x => o.f(Some(x)))
|
||||
}
|
||||
case x if x == StaticScopes =>
|
||||
strictConstant(allScopes.asInstanceOf[A1$]) // can't convince scalac that StaticScopes => T == Set[Scope]
|
||||
}
|
||||
|
||||
private[this] lazy val roots: Seq[INode[_]] = compiledSettings flatMap { cs =>
|
||||
|
|
@ -84,7 +82,7 @@ abstract class EvaluateSettings[Scope] {
|
|||
if (key.key.isLocal) ss else ss.set(key.scope, key.key, node.get)
|
||||
}
|
||||
|
||||
private[this] val getValue = new (INode ~> Id) { def apply[T](node: INode[T]) = node.get }
|
||||
private[this] val getValue = λ[INode ~> Id](_.get)
|
||||
|
||||
private[this] def submitEvaluate(node: INode[_]) = submit(node.evaluate())
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2017, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under BSD-3-Clause license (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt.internal.util
|
||||
|
||||
// Used to emulate ~> literals
|
||||
trait Param[A[_], B[_]] {
|
||||
type T
|
||||
def in: A[T]
|
||||
def ret(out: B[T]): Unit
|
||||
def ret: B[T]
|
||||
}
|
||||
|
||||
object Param {
|
||||
implicit def pToT[A[_], B[_]](p: Param[A, B] => Unit): A ~> B = new (A ~> B) {
|
||||
def apply[s](a: A[s]): B[s] = {
|
||||
val v: Param[A, B] { type T = s } = new Param[A, B] {
|
||||
type T = s
|
||||
def in = a
|
||||
private var r: B[T] = _
|
||||
def ret(b: B[T]): Unit = { r = b }
|
||||
def ret: B[T] = r
|
||||
}
|
||||
p(v)
|
||||
v.ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,9 +156,7 @@ trait Init[Scope] {
|
|||
def empty(implicit delegates: Scope => Seq[Scope]): Settings[Scope] =
|
||||
new Settings0(Map.empty, delegates)
|
||||
|
||||
def asTransform(s: Settings[Scope]): ScopedKey ~> Id = new (ScopedKey ~> Id) {
|
||||
def apply[T](k: ScopedKey[T]): T = getValue(s, k)
|
||||
}
|
||||
def asTransform(s: Settings[Scope]): ScopedKey ~> Id = λ[ScopedKey ~> Id](k => getValue(s, k))
|
||||
|
||||
def getValue[T](s: Settings[Scope], k: ScopedKey[T]) =
|
||||
s.get(k.scope, k.key) getOrElse (throw new InvalidReference(k))
|
||||
|
|
@ -246,13 +244,11 @@ trait Init[Scope] {
|
|||
|
||||
type ValidatedSettings[T] = Either[Seq[Undefined], SettingSeq[T]]
|
||||
|
||||
val f = new (SettingSeq ~> ValidatedSettings) {
|
||||
def apply[T](ks: Seq[Setting[T]]) = {
|
||||
val (undefs, valid) = Util.separate(ks.zipWithIndex) {
|
||||
case (s, i) => s validateKeyReferenced refMap(s, i == 0)
|
||||
}
|
||||
if (undefs.isEmpty) Right(valid) else Left(undefs.flatten)
|
||||
val f = λ[SettingSeq ~> ValidatedSettings] { (ks: Seq[Setting[_]]) =>
|
||||
val (undefs, valid) = Util.separate(ks.zipWithIndex) {
|
||||
case (s, i) => s validateKeyReferenced refMap(s, i == 0)
|
||||
}
|
||||
if (undefs.isEmpty) Right(valid) else Left(undefs.flatten)
|
||||
}
|
||||
|
||||
type Undefs[_] = Seq[Undefined]
|
||||
|
|
@ -685,23 +681,15 @@ trait Init[Scope] {
|
|||
case Right(x) => x
|
||||
}
|
||||
|
||||
private[this] lazy val getValidated =
|
||||
new (ValidatedInit ~> Initialize) { def apply[T](v: ValidatedInit[T]) = handleUndefined[T](v) }
|
||||
private[this] lazy val getValidated = λ[ValidatedInit ~> Initialize](handleUndefined(_))
|
||||
|
||||
// mainly for reducing generated class count
|
||||
private[this] def validateKeyReferencedT(g: ValidateKeyRef) =
|
||||
new (Initialize ~> ValidatedInit) {
|
||||
def apply[T](i: Initialize[T]) = i validateKeyReferenced g
|
||||
}
|
||||
λ[Initialize ~> ValidatedInit](_ validateKeyReferenced 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 mapReferencedT(g: MapScoped) = λ[Initialize ~> Initialize](_ mapReferenced g)
|
||||
private[this] def mapConstantT(g: MapConstant) = λ[Initialize ~> Initialize](_ mapConstant g)
|
||||
private[this] def evaluateT(g: Settings[Scope]) = λ[Initialize ~> Id](_ evaluate g)
|
||||
|
||||
private[this] def deps(ls: Seq[Initialize[_]]): Seq[ScopedKey[_]] = ls.flatMap(_.dependencies)
|
||||
|
||||
|
|
@ -853,9 +841,7 @@ trait Init[Scope] {
|
|||
def validateKeyReferenced(g: ValidateKeyRef) = {
|
||||
val tx = alist.transform(inputs, validateKeyReferencedT(g))
|
||||
val undefs = alist.toList(tx).flatMap(_.left.toSeq.flatten)
|
||||
val get = new (ValidatedInit ~> Initialize) {
|
||||
def apply[B](vr: ValidatedInit[B]) = vr.right.get
|
||||
}
|
||||
val get = λ[ValidatedInit ~> Initialize](_.right.get)
|
||||
if (undefs.isEmpty) Right(new Apply(f, alist.transform(tx, get), alist)) else Left(undefs)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,19 +14,17 @@ trait TypeFunctions {
|
|||
sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
|
||||
sealed trait ∙[A[_], B[_]] { type l[T] = A[B[T]] }
|
||||
|
||||
final val left = new (Id ~> Left[?, Nothing]) { def apply[T](t: T) = Left(t) }
|
||||
final val right = new (Id ~> Right[Nothing, ?]) { def apply[T](t: T) = Right(t) }
|
||||
final val some = new (Id ~> Some) { def apply[T](t: T) = Some(t) }
|
||||
final val left = λ[Id ~> Left[?, Nothing]](Left(_))
|
||||
final val right = λ[Id ~> Right[Nothing, ?]](Right(_))
|
||||
final val some = λ[Id ~> Some](Some(_))
|
||||
final def idFun[T] = (t: T) => t
|
||||
final def const[A, B](b: B): A => B = _ => b
|
||||
final def idK[M[_]]: M ~> M = new (M ~> M) { def apply[T](m: M[T]): M[T] = m }
|
||||
final def idK[M[_]]: M ~> M = λ[M ~> M](m => m)
|
||||
|
||||
def nestCon[M[_], N[_], G[_]](f: M ~> N): (M ∙ G)#l ~> (N ∙ G)#l =
|
||||
f.asInstanceOf[(M ∙ G)#l ~> (N ∙ G)#l] // implemented with a cast to avoid extra object+method call. castless version:
|
||||
|
||||
/* new ( (M ∙ G)#l ~> (N ∙ G)#l ) {
|
||||
def apply[T](mg: M[G[T]]): N[G[T]] = f(mg)
|
||||
} */
|
||||
f.asInstanceOf[(M ∙ G)#l ~> (N ∙ G)#l] // implemented with a cast to avoid extra object+method call.
|
||||
// castless version:
|
||||
// λ[(M ∙ G)#l ~> (N ∙ G)#l](f(_))
|
||||
|
||||
type Endo[T] = T => T
|
||||
type ~>|[A[_], B[_]] = A ~> Compose[Option, B]#Apply
|
||||
|
|
@ -37,13 +35,13 @@ object TypeFunctions extends TypeFunctions
|
|||
trait ~>[-A[_], +B[_]] { outer =>
|
||||
def apply[T](a: A[T]): B[T]
|
||||
// directly on ~> because of type inference limitations
|
||||
final def ∙[C[_]](g: C ~> A): C ~> B = new (C ~> B) { def apply[T](c: C[T]) = outer.apply(g(c)) }
|
||||
final def ∙[C[_]](g: C ~> A): C ~> B = λ[C ~> B](c => outer.apply(g(c)))
|
||||
final def ∙[C, D](g: C => D)(implicit ev: D <:< A[D]): C => B[D] = i => apply(ev(g(i)))
|
||||
final def fn[T] = (t: A[T]) => apply[T](t)
|
||||
}
|
||||
|
||||
object ~> {
|
||||
import TypeFunctions._
|
||||
val Id: Id ~> Id = new (Id ~> Id) { def apply[T](a: T): T = a }
|
||||
val Id: Id ~> Id = idK[Id]
|
||||
implicit def tcIdEquals: (Id ~> Id) = Id
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2017, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under BSD-3-Clause license (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt.internal.util
|
||||
|
||||
// compilation test
|
||||
object LiteralTest {
|
||||
def x[A[_], B[_]](f: A ~> B) = f
|
||||
|
||||
import Param._
|
||||
val f = x { (p: Param[Option, List]) =>
|
||||
p.ret(p.in.toList)
|
||||
}
|
||||
|
||||
val a: List[Int] = f(Some(3))
|
||||
val b: List[String] = f(Some("aa"))
|
||||
}
|
||||
|
|
@ -21,9 +21,7 @@ import scala.util.control.NonFatal
|
|||
*/
|
||||
private[sbt] final class Previous(streams: Streams, referenced: IMap[ScopedTaskKey, Referenced]) {
|
||||
private[this] val map = referenced.mapValues(toValue)
|
||||
private[this] def toValue = new (Referenced ~> ReferencedValue) {
|
||||
def apply[T](x: Referenced[T]) = new ReferencedValue(x)
|
||||
}
|
||||
private[this] def toValue = λ[Referenced ~> ReferencedValue](new ReferencedValue(_))
|
||||
|
||||
private[this] final class ReferencedValue[T](referenced: Referenced[T]) {
|
||||
import referenced.{ stamped, task }
|
||||
|
|
|
|||
|
|
@ -434,11 +434,7 @@ object Scoped {
|
|||
|
||||
protected def convert[M[_], Ret](f: Fun[M, Ret]): K[M] => Ret
|
||||
|
||||
private[this] val inputs: K[App] =
|
||||
a.transform(
|
||||
keys,
|
||||
new (ScopedTaskable ~> App) { def apply[T](in: ScopedTaskable[T]): App[T] = in.toTask }
|
||||
)
|
||||
private[this] val inputs: K[App] = a.transform(keys, λ[ScopedTaskable ~> App](_.toTask))
|
||||
|
||||
private[this] def onTasks[T](f: K[Task] => Task[T]): App[T] =
|
||||
Def.app[λ[L[x] => K[(L ∙ Task)#l]], Task[T]](inputs)(f)(AList.asplit[K, Task](a))
|
||||
|
|
|
|||
|
|
@ -515,10 +515,7 @@ object Project extends ProjectExtra {
|
|||
def fillTaskAxis(scoped: ScopedKey[_]): ScopedKey[_] =
|
||||
ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key)
|
||||
|
||||
def mapScope(f: Scope => Scope) = new (ScopedKey ~> ScopedKey) {
|
||||
def apply[T](key: ScopedKey[T]) =
|
||||
ScopedKey(f(key.scope), key.key)
|
||||
}
|
||||
def mapScope(f: Scope => Scope) = λ[ScopedKey ~> ScopedKey](k => ScopedKey(f(k.scope), k.key))
|
||||
|
||||
def transform(g: Scope => Scope, ss: Seq[Def.Setting[_]]): Seq[Def.Setting[_]] = {
|
||||
val f = mapScope(g)
|
||||
|
|
|
|||
|
|
@ -291,12 +291,12 @@ private[sbt] object Load {
|
|||
// 3. resolvedScoped is replaced with the defining key as a value
|
||||
// Note: this must be idempotent.
|
||||
def finalTransforms(ss: Seq[Setting[_]]): Seq[Setting[_]] = {
|
||||
def mapSpecial(to: ScopedKey[_]) = new (ScopedKey ~> ScopedKey) {
|
||||
def apply[T](key: ScopedKey[T]) =
|
||||
def mapSpecial(to: ScopedKey[_]) = λ[ScopedKey ~> ScopedKey](
|
||||
(key: ScopedKey[_]) =>
|
||||
if (key.key == streams.key)
|
||||
ScopedKey(Scope.fillTaskAxis(Scope.replaceThis(to.scope)(key.scope), to.key), key.key)
|
||||
else key
|
||||
}
|
||||
)
|
||||
def setDefining[T] =
|
||||
(key: ScopedKey[T], value: T) =>
|
||||
value match {
|
||||
|
|
@ -304,13 +304,13 @@ private[sbt] object Load {
|
|||
case ik: InputTask[t] => ik.mapTask(tk => setDefinitionKey(tk, key)).asInstanceOf[T]
|
||||
case _ => value
|
||||
}
|
||||
def setResolved(defining: ScopedKey[_]) = new (ScopedKey ~> Option) {
|
||||
def apply[T](key: ScopedKey[T]): Option[T] =
|
||||
def setResolved(defining: ScopedKey[_]) = λ[ScopedKey ~> Option](
|
||||
(key: ScopedKey[_]) =>
|
||||
key.key match {
|
||||
case resolvedScoped.key => Some(defining.asInstanceOf[T])
|
||||
case resolvedScoped.key => Some(defining.asInstanceOf[A1$])
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
ss.map(s =>
|
||||
s mapConstant setResolved(s.key) mapReferenced mapSpecial(s.key) mapInit setDefining)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,8 +166,6 @@ trait Import {
|
|||
val NoPosition = sbt.internal.util.NoPosition
|
||||
val PMap = sbt.internal.util.PMap
|
||||
type PMap[K[_], V[_]] = sbt.internal.util.PMap[K, V]
|
||||
val Param = sbt.internal.util.Param
|
||||
type Param[A[_], B[_]] = sbt.internal.util.Param[A, B]
|
||||
type RMap[K[_], V[_]] = sbt.internal.util.RMap[K, V]
|
||||
val RangePosition = sbt.internal.util.RangePosition
|
||||
type RangePosition = sbt.internal.util.RangePosition
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ object Transform {
|
|||
|
||||
/** Applies `map`, returning the result if defined or returning the input unchanged otherwise.*/
|
||||
implicit def getOrId(map: Task ~>| Task): Task ~> Task =
|
||||
new (Task ~> Task) {
|
||||
def apply[T](in: Task[T]): Task[T] = map(in).getOrElse(in)
|
||||
}
|
||||
λ[Task ~> Task](in => map(in).getOrElse(in))
|
||||
|
||||
def apply(dummies: DummyTaskMap) = taskToNode(getOrId(dummyMap(dummies)))
|
||||
|
||||
|
|
|
|||
|
|
@ -57,12 +57,13 @@ private[sbt] final class Execute[A[_] <: AnyRef](
|
|||
private[this] val viewCache = pMap[A, Node[A, ?]]
|
||||
private[this] val results = pMap[A, Result]
|
||||
|
||||
private[this] val getResult: A ~> Result = new (A ~> Result) {
|
||||
def apply[T](a: A[T]): Result[T] = view.inline(a) match {
|
||||
case Some(v) => Value(v())
|
||||
case None => results(a)
|
||||
private[this] val getResult: A ~> Result = λ[A ~> Result](
|
||||
a =>
|
||||
view.inline(a) match {
|
||||
case Some(v) => Value(v())
|
||||
case None => results(a)
|
||||
}
|
||||
}
|
||||
)
|
||||
private[this] var progressState: progress.S = progress.initial
|
||||
|
||||
private[this] type State = State.Value
|
||||
|
|
|
|||
|
|
@ -28,12 +28,9 @@ final case class Value[+T](value: T) extends Result[T] {
|
|||
|
||||
object Result {
|
||||
type Id[X] = X
|
||||
val tryValue = new (Result ~> Id) {
|
||||
def apply[T](r: Result[T]): T =
|
||||
r match {
|
||||
case Value(v) => v
|
||||
case Inc(i) => throw i
|
||||
}
|
||||
val tryValue = λ[Result ~> Id] {
|
||||
case Value(v) => v
|
||||
case Inc(i) => throw i
|
||||
}
|
||||
def tryValues[S](r: Seq[Result[Unit]], v: Result[S]): S = {
|
||||
r foreach tryValue[Unit]
|
||||
|
|
|
|||
Loading…
Reference in New Issue