Rewrite to polymorphic function syntax

This commit is contained in:
Dale Wijnand 2017-10-19 17:19:16 -05:00
parent f662fdda8e
commit 9f1d60be60
No known key found for this signature in database
GPG Key ID: 4F256E3D151DF5EF
15 changed files with 71 additions and 151 deletions

View File

@ -148,6 +148,10 @@ val collectionProj = (project in file("internal") / "util-collection")
// Dropped in favour of kind-projector's inline type lambda syntax // Dropped in favour of kind-projector's inline type lambda syntax
exclude[MissingClassProblem]("sbt.internal.util.TypeFunctions$P1of2"), 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 // Dropped in favour of plain scala.Function, and its compose method
exclude[MissingClassProblem]("sbt.internal.util.Fn1"), exclude[MissingClassProblem]("sbt.internal.util.Fn1"),
exclude[DirectMissingMethodProblem]("sbt.internal.util.TypeFunctions.toFn1"), 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.sbt$Import$_setter_$WatchSource_="),
exclude[ReversedMissingMethodProblem]("sbt.Import.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 // Dropped in favour of plain scala.Function, and its compose method
exclude[DirectMissingMethodProblem]("sbt.package.toFn1"), exclude[DirectMissingMethodProblem]("sbt.package.toFn1"),
) )

View File

@ -196,11 +196,9 @@ object AttributeMap {
def apply(entries: AttributeEntry[_]*): AttributeMap = empty ++ entries def apply(entries: AttributeEntry[_]*): AttributeMap = empty ++ entries
/** Presents an `AttributeMap` as a natural transformation. */ /** Presents an `AttributeMap` as a natural transformation. */
implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = new (AttributeKey ~> Id) { implicit def toNatTrans(map: AttributeMap): AttributeKey ~> Id = λ[AttributeKey ~> Id](map(_))
def apply[T](key: AttributeKey[T]): T = map(key)
}
} }
private class BasicAttributeMap(private val backing: Map[AttributeKey[_], Any]) private class BasicAttributeMap(private val backing: Map[AttributeKey[_], Any])
extends AttributeMap { extends AttributeMap {

View File

@ -32,27 +32,25 @@ abstract class EvaluateSettings[Scope] {
private[this] def getStatic[T](key: ScopedKey[T]): INode[T] = private[this] def getStatic[T](key: ScopedKey[T]): INode[T] =
static get key getOrElse sys.error("Illegal reference to key " + key) static get key getOrElse sys.error("Illegal reference to key " + key)
private[this] val transform: Initialize ~> INode = new (Initialize ~> INode) { private[this] val transform: Initialize ~> INode = λ[Initialize ~> INode] {
def apply[T](i: Initialize[T]): INode[T] = i match { case k: Keyed[s, A1$] @unchecked => single(getStatic(k.scopedKey), k.transform)
case k: Keyed[s, T] @unchecked => single(getStatic(k.scopedKey), k.transform) case a: Apply[k, A1$] @unchecked =>
case a: Apply[k, T] @unchecked => new MixedNode[k, A1$](
new MixedNode[k, T]( a.alist.transform[Initialize, INode](a.inputs, transform),
a.alist.transform[Initialize, INode](a.inputs, transform), a.f,
a.f, a.alist
a.alist )
) case b: Bind[s, A1$] @unchecked => new BindNode[s, A1$](transform(b.in), x => transform(b.f(x)))
case b: Bind[s, T] @unchecked => new BindNode[s, T](transform(b.in), x => transform(b.f(x))) case v: Value[A1$] @unchecked => constant(v.value)
case v: Value[T] @unchecked => constant(v.value) case v: ValidationCapture[A1$] @unchecked => strictConstant(v.key)
case v: ValidationCapture[T] @unchecked => strictConstant(v.key) case t: TransformCapture => strictConstant(t.f)
case t: TransformCapture => strictConstant(t.f) case o: Optional[s, A1$] @unchecked =>
case o: Optional[s, T] @unchecked => o.a match {
o.a match { case None => constant(() => o.f(None))
case None => constant(() => o.f(None)) case Some(i) => single[s, A1$](transform(i), x => o.f(Some(x)))
case Some(i) => single[s, T](transform(i), x => o.f(Some(x))) }
} case x if x == StaticScopes =>
case x if x == StaticScopes => strictConstant(allScopes.asInstanceOf[A1$]) // can't convince scalac that StaticScopes => T == Set[Scope]
strictConstant(allScopes.asInstanceOf[T]) // can't convince scalac that StaticScopes => T == Set[Scope]
}
} }
private[this] lazy val roots: Seq[INode[_]] = compiledSettings flatMap { cs => 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) 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()) private[this] def submitEvaluate(node: INode[_]) = submit(node.evaluate())

View File

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

View File

@ -156,9 +156,7 @@ trait Init[Scope] {
def empty(implicit delegates: Scope => Seq[Scope]): Settings[Scope] = def empty(implicit delegates: Scope => Seq[Scope]): Settings[Scope] =
new Settings0(Map.empty, delegates) new Settings0(Map.empty, delegates)
def asTransform(s: Settings[Scope]): ScopedKey ~> Id = new (ScopedKey ~> Id) { def asTransform(s: Settings[Scope]): ScopedKey ~> Id = λ[ScopedKey ~> Id](k => getValue(s, k))
def apply[T](k: ScopedKey[T]): T = getValue(s, k)
}
def getValue[T](s: Settings[Scope], k: ScopedKey[T]) = def getValue[T](s: Settings[Scope], k: ScopedKey[T]) =
s.get(k.scope, k.key) getOrElse (throw new InvalidReference(k)) 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]] type ValidatedSettings[T] = Either[Seq[Undefined], SettingSeq[T]]
val f = new (SettingSeq ~> ValidatedSettings) { val f = λ[SettingSeq ~> ValidatedSettings] { (ks: Seq[Setting[_]]) =>
def apply[T](ks: Seq[Setting[T]]) = { val (undefs, valid) = Util.separate(ks.zipWithIndex) {
val (undefs, valid) = Util.separate(ks.zipWithIndex) { case (s, i) => s validateKeyReferenced refMap(s, i == 0)
case (s, i) => s validateKeyReferenced refMap(s, i == 0)
}
if (undefs.isEmpty) Right(valid) else Left(undefs.flatten)
} }
if (undefs.isEmpty) Right(valid) else Left(undefs.flatten)
} }
type Undefs[_] = Seq[Undefined] type Undefs[_] = Seq[Undefined]
@ -685,23 +681,15 @@ trait Init[Scope] {
case Right(x) => x case Right(x) => x
} }
private[this] lazy val getValidated = private[this] lazy val getValidated = λ[ValidatedInit ~> Initialize](handleUndefined(_))
new (ValidatedInit ~> Initialize) { def apply[T](v: ValidatedInit[T]) = handleUndefined[T](v) }
// mainly for reducing generated class count // mainly for reducing generated class count
private[this] def validateKeyReferencedT(g: ValidateKeyRef) = private[this] def validateKeyReferencedT(g: ValidateKeyRef) =
new (Initialize ~> ValidatedInit) { λ[Initialize ~> ValidatedInit](_ validateKeyReferenced g)
def apply[T](i: Initialize[T]) = i validateKeyReferenced g
}
private[this] def mapReferencedT(g: MapScoped) = private[this] def mapReferencedT(g: MapScoped) = λ[Initialize ~> Initialize](_ mapReferenced g)
new (Initialize ~> Initialize) { def apply[T](i: Initialize[T]) = i 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 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 deps(ls: Seq[Initialize[_]]): Seq[ScopedKey[_]] = ls.flatMap(_.dependencies) private[this] def deps(ls: Seq[Initialize[_]]): Seq[ScopedKey[_]] = ls.flatMap(_.dependencies)
@ -853,9 +841,7 @@ trait Init[Scope] {
def validateKeyReferenced(g: ValidateKeyRef) = { def validateKeyReferenced(g: ValidateKeyRef) = {
val tx = alist.transform(inputs, validateKeyReferencedT(g)) val tx = alist.transform(inputs, validateKeyReferencedT(g))
val undefs = alist.toList(tx).flatMap(_.left.toSeq.flatten) val undefs = alist.toList(tx).flatMap(_.left.toSeq.flatten)
val get = new (ValidatedInit ~> Initialize) { val get = λ[ValidatedInit ~> Initialize](_.right.get)
def apply[B](vr: ValidatedInit[B]) = vr.right.get
}
if (undefs.isEmpty) Right(new Apply(f, alist.transform(tx, get), alist)) else Left(undefs) if (undefs.isEmpty) Right(new Apply(f, alist.transform(tx, get), alist)) else Left(undefs)
} }

View File

@ -14,19 +14,17 @@ trait TypeFunctions {
sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] } sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
sealed trait [A[_], B[_]] { type l[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 left = λ[Id ~> Left[?, Nothing]](Left(_))
final val right = new (Id ~> Right[Nothing, ?]) { def apply[T](t: T) = Right(t) } final val right = λ[Id ~> Right[Nothing, ?]](Right(_))
final val some = new (Id ~> Some) { def apply[T](t: T) = Some(t) } final val some = λ[Id ~> Some](Some(_))
final def idFun[T] = (t: T) => t final def idFun[T] = (t: T) => t
final def const[A, B](b: B): A => B = _ => b 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 = 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: 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 ) { // λ[(M G)#l ~> (N G)#l](f(_))
def apply[T](mg: M[G[T]]): N[G[T]] = f(mg)
} */
type Endo[T] = T => T type Endo[T] = T => T
type ~>|[A[_], B[_]] = A ~> Compose[Option, B]#Apply type ~>|[A[_], B[_]] = A ~> Compose[Option, B]#Apply
@ -37,13 +35,13 @@ object TypeFunctions extends TypeFunctions
trait ~>[-A[_], +B[_]] { outer => trait ~>[-A[_], +B[_]] { outer =>
def apply[T](a: A[T]): B[T] def apply[T](a: A[T]): B[T]
// directly on ~> because of type inference limitations // 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 [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) final def fn[T] = (t: A[T]) => apply[T](t)
} }
object ~> { object ~> {
import TypeFunctions._ 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 implicit def tcIdEquals: (Id ~> Id) = Id
} }

View File

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

View File

@ -21,9 +21,7 @@ import scala.util.control.NonFatal
*/ */
private[sbt] final class Previous(streams: Streams, referenced: IMap[ScopedTaskKey, Referenced]) { private[sbt] final class Previous(streams: Streams, referenced: IMap[ScopedTaskKey, Referenced]) {
private[this] val map = referenced.mapValues(toValue) private[this] val map = referenced.mapValues(toValue)
private[this] def toValue = new (Referenced ~> ReferencedValue) { private[this] def toValue = λ[Referenced ~> ReferencedValue](new ReferencedValue(_))
def apply[T](x: Referenced[T]) = new ReferencedValue(x)
}
private[this] final class ReferencedValue[T](referenced: Referenced[T]) { private[this] final class ReferencedValue[T](referenced: Referenced[T]) {
import referenced.{ stamped, task } import referenced.{ stamped, task }

View File

@ -434,11 +434,7 @@ object Scoped {
protected def convert[M[_], Ret](f: Fun[M, Ret]): K[M] => Ret protected def convert[M[_], Ret](f: Fun[M, Ret]): K[M] => Ret
private[this] val inputs: K[App] = private[this] val inputs: K[App] = a.transform(keys, λ[ScopedTaskable ~> App](_.toTask))
a.transform(
keys,
new (ScopedTaskable ~> App) { def apply[T](in: ScopedTaskable[T]): App[T] = in.toTask }
)
private[this] def onTasks[T](f: K[Task] => Task[T]): App[T] = 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)) Def.app[λ[L[x] => K[(L Task)#l]], Task[T]](inputs)(f)(AList.asplit[K, Task](a))

View File

@ -515,10 +515,7 @@ object Project extends ProjectExtra {
def fillTaskAxis(scoped: ScopedKey[_]): ScopedKey[_] = def fillTaskAxis(scoped: ScopedKey[_]): ScopedKey[_] =
ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key) ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key)
def mapScope(f: Scope => Scope) = new (ScopedKey ~> ScopedKey) { def mapScope(f: Scope => Scope) = λ[ScopedKey ~> ScopedKey](k => ScopedKey(f(k.scope), k.key))
def apply[T](key: ScopedKey[T]) =
ScopedKey(f(key.scope), key.key)
}
def transform(g: Scope => Scope, ss: Seq[Def.Setting[_]]): Seq[Def.Setting[_]] = { def transform(g: Scope => Scope, ss: Seq[Def.Setting[_]]): Seq[Def.Setting[_]] = {
val f = mapScope(g) val f = mapScope(g)

View File

@ -291,12 +291,12 @@ private[sbt] object Load {
// 3. resolvedScoped is replaced with the defining key as a value // 3. resolvedScoped is replaced with the defining key as a value
// Note: this must be idempotent. // Note: this must be idempotent.
def finalTransforms(ss: Seq[Setting[_]]): Seq[Setting[_]] = { def finalTransforms(ss: Seq[Setting[_]]): Seq[Setting[_]] = {
def mapSpecial(to: ScopedKey[_]) = new (ScopedKey ~> ScopedKey) { def mapSpecial(to: ScopedKey[_]) = λ[ScopedKey ~> ScopedKey](
def apply[T](key: ScopedKey[T]) = (key: ScopedKey[_]) =>
if (key.key == streams.key) if (key.key == streams.key)
ScopedKey(Scope.fillTaskAxis(Scope.replaceThis(to.scope)(key.scope), to.key), key.key) ScopedKey(Scope.fillTaskAxis(Scope.replaceThis(to.scope)(key.scope), to.key), key.key)
else key else key
} )
def setDefining[T] = def setDefining[T] =
(key: ScopedKey[T], value: T) => (key: ScopedKey[T], value: T) =>
value match { value match {
@ -304,13 +304,13 @@ private[sbt] object Load {
case ik: InputTask[t] => ik.mapTask(tk => setDefinitionKey(tk, key)).asInstanceOf[T] case ik: InputTask[t] => ik.mapTask(tk => setDefinitionKey(tk, key)).asInstanceOf[T]
case _ => value case _ => value
} }
def setResolved(defining: ScopedKey[_]) = new (ScopedKey ~> Option) { def setResolved(defining: ScopedKey[_]) = λ[ScopedKey ~> Option](
def apply[T](key: ScopedKey[T]): Option[T] = (key: ScopedKey[_]) =>
key.key match { key.key match {
case resolvedScoped.key => Some(defining.asInstanceOf[T]) case resolvedScoped.key => Some(defining.asInstanceOf[A1$])
case _ => None case _ => None
} }
} )
ss.map(s => ss.map(s =>
s mapConstant setResolved(s.key) mapReferenced mapSpecial(s.key) mapInit setDefining) s mapConstant setResolved(s.key) mapReferenced mapSpecial(s.key) mapInit setDefining)
} }

View File

@ -166,8 +166,6 @@ trait Import {
val NoPosition = sbt.internal.util.NoPosition val NoPosition = sbt.internal.util.NoPosition
val PMap = sbt.internal.util.PMap val PMap = sbt.internal.util.PMap
type PMap[K[_], V[_]] = sbt.internal.util.PMap[K, V] 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] type RMap[K[_], V[_]] = sbt.internal.util.RMap[K, V]
val RangePosition = sbt.internal.util.RangePosition val RangePosition = sbt.internal.util.RangePosition
type RangePosition = sbt.internal.util.RangePosition type RangePosition = sbt.internal.util.RangePosition

View File

@ -37,9 +37,7 @@ object Transform {
/** Applies `map`, returning the result if defined or returning the input unchanged otherwise.*/ /** Applies `map`, returning the result if defined or returning the input unchanged otherwise.*/
implicit def getOrId(map: Task ~>| Task): Task ~> Task = implicit def getOrId(map: Task ~>| Task): Task ~> Task =
new (Task ~> Task) { λ[Task ~> Task](in => map(in).getOrElse(in))
def apply[T](in: Task[T]): Task[T] = map(in).getOrElse(in)
}
def apply(dummies: DummyTaskMap) = taskToNode(getOrId(dummyMap(dummies))) def apply(dummies: DummyTaskMap) = taskToNode(getOrId(dummyMap(dummies)))

View File

@ -57,12 +57,13 @@ private[sbt] final class Execute[A[_] <: AnyRef](
private[this] val viewCache = pMap[A, Node[A, ?]] private[this] val viewCache = pMap[A, Node[A, ?]]
private[this] val results = pMap[A, Result] private[this] val results = pMap[A, Result]
private[this] val getResult: A ~> Result = new (A ~> Result) { private[this] val getResult: A ~> Result = λ[A ~> Result](
def apply[T](a: A[T]): Result[T] = view.inline(a) match { a =>
case Some(v) => Value(v()) view.inline(a) match {
case None => results(a) case Some(v) => Value(v())
case None => results(a)
} }
} )
private[this] var progressState: progress.S = progress.initial private[this] var progressState: progress.S = progress.initial
private[this] type State = State.Value private[this] type State = State.Value

View File

@ -28,12 +28,9 @@ final case class Value[+T](value: T) extends Result[T] {
object Result { object Result {
type Id[X] = X type Id[X] = X
val tryValue = new (Result ~> Id) { val tryValue = λ[Result ~> Id] {
def apply[T](r: Result[T]): T = case Value(v) => v
r match { case Inc(i) => throw i
case Value(v) => v
case Inc(i) => throw i
}
} }
def tryValues[S](r: Seq[Result[Unit]], v: Result[S]): S = { def tryValues[S](r: Seq[Result[Unit]], v: Result[S]): S = {
r foreach tryValue[Unit] r foreach tryValue[Unit]