Starting input task

This commit is contained in:
Eugene Yokota 2022-06-20 01:58:45 -04:00
parent b715917d95
commit f3dd2dff36
12 changed files with 216 additions and 167 deletions

View File

@ -24,12 +24,26 @@ trait Cont:
*/ */
def contMapN[A: Type, F[_], Effect[_]: Type]( def contMapN[A: Type, F[_], Effect[_]: Type](
tree: Expr[A], tree: Expr[A],
instanceExpr: Expr[Applicative[F]]
)(using
iftpe: Type[F],
eatpe: Type[Effect[A]],
): Expr[F[Effect[A]]] =
contMapN[A, F, Effect](tree, instanceExpr, conv.idTransform)
/**
* Implementation of a macro that provides a direct syntax for applicative functors. It is
* intended to be used in conjunction with another macro that conditions the inputs.
*/
def contMapN[A: Type, F[_], Effect[_]: Type](
tree: Expr[A],
instanceExpr: Expr[Applicative[F]],
inner: conv.TermTransform[Effect] inner: conv.TermTransform[Effect]
)(using )(using
iftpe: Type[F], iftpe: Type[F],
eatpe: Type[Effect[A]], eatpe: Type[Effect[A]],
): Expr[F[Effect[A]]] = ): Expr[F[Effect[A]]] =
contImpl[A, F, Effect](Left(tree), inner) contImpl[A, F, Effect](Left(tree), instanceExpr, inner)
/** /**
* Implementation of a macro that provides a direct syntax for applicative functors. It is * Implementation of a macro that provides a direct syntax for applicative functors. It is
@ -37,16 +51,38 @@ trait Cont:
*/ */
def contFlatMap[A: Type, F[_], Effect[_]: Type]( def contFlatMap[A: Type, F[_], Effect[_]: Type](
tree: Expr[F[A]], tree: Expr[F[A]],
instanceExpr: Expr[Applicative[F]],
)(using
iftpe: Type[F],
eatpe: Type[Effect[A]],
): Expr[F[Effect[A]]] =
contFlatMap[A, F, Effect](tree, instanceExpr, conv.idTransform)
/**
* Implementation of a macro that provides a direct syntax for applicative functors. It is
* intended to be used in conjunction with another macro that conditions the inputs.
*/
def contFlatMap[A: Type, F[_], Effect[_]: Type](
tree: Expr[F[A]],
instanceExpr: Expr[Applicative[F]],
inner: conv.TermTransform[Effect] inner: conv.TermTransform[Effect]
)(using )(using
iftpe: Type[F], iftpe: Type[F],
eatpe: Type[Effect[A]], eatpe: Type[Effect[A]],
): Expr[F[Effect[A]]] = ): Expr[F[Effect[A]]] =
contImpl[A, F, Effect](Right(tree), inner) contImpl[A, F, Effect](Right(tree), instanceExpr, inner)
def summonAppExpr[F[_]: Type]: Expr[Applicative[F]] =
import conv.qctx
import qctx.reflect.*
given qctx.type = qctx
Expr
.summon[Applicative[F]]
.getOrElse(sys.error(s"Applicative[F] not found for ${TypeRepr.of[F].typeSymbol}"))
/** /**
* Implementation of a macro that provides a direct syntax for applicative functors and monads. * Implementation of a macro that provides a direct syntax for applicative functors and monads.
* It is intended to be used in conjunction with another macro that conditions the inputs. * It is intended to bcke used in conjunction with another macro that conditions the inputs.
* *
* This method processes the Term `t` to find inputs of the form `wrap[A]( input )` This form is * This method processes the Term `t` to find inputs of the form `wrap[A]( input )` This form is
* typically constructed by another macro that pretends to be able to get a value of type `A` * typically constructed by another macro that pretends to be able to get a value of type `A`
@ -83,6 +119,7 @@ trait Cont:
*/ */
def contImpl[A: Type, F[_], Effect[_]: Type]( def contImpl[A: Type, F[_], Effect[_]: Type](
eitherTree: Either[Expr[A], Expr[F[A]]], eitherTree: Either[Expr[A], Expr[F[A]]],
instanceExpr: Expr[Applicative[F]],
inner: conv.TermTransform[Effect] inner: conv.TermTransform[Effect]
)(using )(using
iftpe: Type[F], iftpe: Type[F],
@ -98,11 +135,6 @@ trait Cont:
case Left(l) => (l, TypeRepr.of[Effect[A]]) case Left(l) => (l, TypeRepr.of[Effect[A]])
case Right(r) => (r, faTpe) case Right(r) => (r, faTpe)
// we can extract i out of i.type
val instanceExpr =
Expr
.summon[Applicative[F]]
.getOrElse(sys.error(s"Applicative[F] not found for ${fTypeCon.typeSymbol}"))
val inputBuf = ListBuffer[Input]() val inputBuf = ListBuffer[Input]()
def makeApp(body: Term, inputs: List[Input]): Expr[F[Effect[A]]] = inputs match def makeApp(body: Term, inputs: List[Input]): Expr[F[Effect[A]]] = inputs match

View File

@ -62,5 +62,5 @@ trait ContextUtil[C <: Quotes & scala.Singleton](val qctx: C):
def apply(in: Term): Term def apply(in: Term): Term
end TermTransform end TermTransform
def idTransform: TermTransform[Id] = in => in def idTransform[F[_]]: TermTransform[F] = in => in
end ContextUtil end ContextUtil

View File

@ -39,12 +39,19 @@ trait Convert[C <: Quotes & Singleton](override val qctx: C) extends ContextUtil
subWrapper: (String, TypeRepr, Term, Term) => Converted, subWrapper: (String, TypeRepr, Term, Term) => Converted,
owner: Symbol, owner: Symbol,
): Term = ): Term =
object ApplySelectOrIdent:
def unapply(tree: Term): Option[(String, TypeTree, Term)] = tree match
case Apply(TypeApply(Select(_, nme), targ :: Nil), qual :: Nil) => Some((nme, targ, qual))
case Apply(TypeApply(Ident(nme), targ :: Nil), qual :: Nil) => Some((nme, targ, qual))
case _ => None
end ApplySelectOrIdent
// the main tree transformer that replaces calls to InputWrapper.wrap(x) with // the main tree transformer that replaces calls to InputWrapper.wrap(x) with
// plain Idents that reference the actual input value // plain Idents that reference the actual input value
object appTransformer extends TreeMap: object appTransformer extends TreeMap:
override def transformTerm(tree: Term)(owner: Symbol): Term = override def transformTerm(tree: Term)(owner: Symbol): Term =
tree match tree match
case Apply(TypeApply(Select(_, nme), targ :: Nil), qual :: Nil) => case ApplySelectOrIdent(nme, targ, qual) =>
subWrapper(nme, targ.tpe, qual, tree) match subWrapper(nme, targ.tpe, qual, tree) match
case Converted.Success(tree, finalTransform) => case Converted.Success(tree, finalTransform) =>
finalTransform(tree) finalTransform(tree)

View File

@ -16,6 +16,6 @@ object ContTestMacro:
object ContSyntax extends Cont object ContSyntax extends Cont
import ContSyntax.* import ContSyntax.*
val convert1: Convert[qctx.type] = new InputInitConvert(qctx) val convert1: Convert[qctx.type] = new InputInitConvert(qctx)
convert1.contMapN[A, List, Id](expr, convert1.idTransform) convert1.contMapN[A, List, Id](expr, convert1.summonAppExpr[List], convert1.idTransform)
end ContTestMacro end ContTestMacro

View File

@ -210,38 +210,33 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits:
/** Lifts the result of a setting initialization into a Task. */ /** Lifts the result of a setting initialization into a Task. */
def toITask[A1](i: Initialize[A1]): Initialize[Task[A1]] = map(i)(std.TaskExtra.inlineTask) def toITask[A1](i: Initialize[A1]): Initialize[Task[A1]] = map(i)(std.TaskExtra.inlineTask)
def toSParser[T](p: Parser[T]): State => Parser[T] = const(p) inline def toSParser[A1](p: Parser[A1]): State => Parser[A1] = const(p)
def toISParser[T](p: Initialize[Parser[T]]): Initialize[State => Parser[T]] = p(toSParser) def toISParser[A1](p: Initialize[Parser[A1]]): Initialize[State => Parser[A1]] =
def toIParser[T](p: Initialize[InputTask[T]]): Initialize[State => Parser[Task[T]]] = p(_.parser) p.apply[State => Parser[A1]](toSParser(_))
def toIParser[A1](p: Initialize[InputTask[A1]]): Initialize[State => Parser[Task[A1]]] =
p(_.parser)
import std.SettingMacro.{ import std.SettingMacro.{
// settingDynMacroImpl, // settingDynMacroImpl,
settingMacroImpl settingMacroImpl
} }
import std.TaskMacro.{ import std.*
// inputTaskDynMacroImpl,
// inputTaskMacroImpl,
taskDynMacroImpl,
// taskIfMacroImpl,
taskMacroImpl,
}
import std._
import language.experimental.macros import language.experimental.macros
inline def task[A1](inline a1: A1): Def.Initialize[Task[A1]] = inline def task[A1](inline a1: A1): Def.Initialize[Task[A1]] =
${ taskMacroImpl[A1]('a1) } ${ TaskMacro.taskMacroImpl[A1]('a1) }
inline def taskDyn[A1](a1: Def.Initialize[Task[A1]]): Def.Initialize[Task[A1]] = inline def taskDyn[A1](a1: Def.Initialize[Task[A1]]): Def.Initialize[Task[A1]] =
${ taskDynMacroImpl[A1]('a1) } ${ TaskMacro.taskDynMacroImpl[A1]('a1) }
inline def setting[A1](inline a: A1): Def.Initialize[A1] = ${ settingMacroImpl[A1]('a) } inline def setting[A1](inline a: A1): Def.Initialize[A1] = ${ settingMacroImpl[A1]('a) }
// def settingDyn[T](t: Def.Initialize[T]): Def.Initialize[T] = macro settingDynMacroImpl[T] // def settingDyn[T](t: Def.Initialize[T]): Def.Initialize[T] = macro settingDynMacroImpl[T]
// def inputTask[T](t: T): Def.Initialize[InputTask[T]] = macro inputTaskMacroImpl[T]
// def inputTaskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[InputTask[T]] = { inline def inputTask[A1](inline a: A1): Def.Initialize[InputTask[A1]] =
// macro inputTaskDynMacroImpl[T] ${ TaskMacro.inputTaskMacroImpl[A1]('a) }
// }
// def taskIf[T](a: T): Def.Initialize[Task[T]] = macro taskIfMacroImpl[T] // def taskIf[T](a: T): Def.Initialize[Task[T]] = macro taskIfMacroImpl[T]
private[sbt] def selectITask[A1, A2]( private[sbt] def selectITask[A1, A2](
@ -310,14 +305,14 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits:
// The following conversions enable the types Parser[T], Initialize[Parser[T]], and // The following conversions enable the types Parser[T], Initialize[Parser[T]], and
// Initialize[State => Parser[T]] to be used in the inputTask macro as an input with an ultimate // Initialize[State => Parser[T]] to be used in the inputTask macro as an input with an ultimate
// result of type T // result of type A1, previously implemented using ParserInput.parsedMacroImpl[A1].
// implicit def parserInitToInput[T](
// @deprecated("unused", "") p: Initialize[Parser[T]]
// ): ParserInput[T] = ???
// implicit def parserInitStateToInput[T]( extension [A1](in: Initialize[Parser[A1]])
// @deprecated("unused", "") p: Initialize[State => Parser[T]] inline def parsed: A1 = ParserInput.wrapInit[A1](Def.toISParser(in))
// ): ParserInput[T] = ???
extension [A1](in: Initialize[State => Parser[A1]])
@targetName("parsedISPA1")
inline def parsed: A1 = ParserInput.wrapInit[A1](in)
inline def settingKey[A1](inline description: String): SettingKey[A1] = inline def settingKey[A1](inline description: String): SettingKey[A1] =
${ std.KeyMacro.settingKeyImpl[A1]('description) } ${ std.KeyMacro.settingKeyImpl[A1]('description) }
@ -382,18 +377,19 @@ end Def
// these need to be mixed into the sbt package object // these need to be mixed into the sbt package object
// because the target doesn't involve Initialize or anything in Def // because the target doesn't involve Initialize or anything in Def
trait TaskMacroExtra { trait TaskMacroExtra:
import sbt.std.ParserInput
// implicit def macroValueT[T](@deprecated("unused", "") in: Task[T]): std.MacroValue[T] = ??? // implicit def macroValueT[T](@deprecated("unused", "") in: Task[T]): std.MacroValue[T] = ???
// implicit def macroValueIn[T](@deprecated("unused", "") in: InputTask[T]): std.InputEvaluated[T] = // implicit def macroValueIn[T](@deprecated("unused", "") in: InputTask[T]): std.InputEvaluated[T] =
// ??? // ???
// implicit def parserToInput[T](@deprecated("unused", "") in: Parser[T]): std.ParserInput[T] = ??? extension [A1](in: Parser[A1])
inline def parsed: A1 = ParserInput.`parser_\u2603\u2603`[A1](Def.toSParser(in))
// implicit def stateParserToInput[T]( extension [A1](in: State => Parser[A1])
// @deprecated("unused", "") in: State => Parser[T] inline def parsed: A1 = ParserInput.`parser_\u2603\u2603`[A1](in)
// ): std.ParserInput[T] = ??? end TaskMacroExtra
}
sealed trait InitializeImplicits0 { self: Def.type => sealed trait InitializeImplicits0 { self: Def.type =>
implicit def initOps[T](x: Def.Initialize[T]): Def.InitOps[T] = new Def.InitOps(x) implicit def initOps[T](x: Def.Initialize[T]): Def.InitOps[T] = new Def.InitOps(x)

View File

@ -33,8 +33,8 @@ final class InputTask[A1] private (val parser: State => Parser[Task[A1]]):
) )
end InputTask end InputTask
/* object InputTask:
object InputTask { /*
implicit class InitializeInput[T](i: Initialize[InputTask[T]]) { implicit class InitializeInput[T](i: Initialize[InputTask[T]]) {
def partialInput(in: String): Initialize[InputTask[T]] = i(_ partialInput in) def partialInput(in: String): Initialize[InputTask[T]] = i(_ partialInput in)
def fullInput(in: String): Initialize[InputTask[T]] = i(_ fullInput in) def fullInput(in: String): Initialize[InputTask[T]] = i(_ fullInput in)
@ -61,9 +61,11 @@ object InputTask {
implicit def inputTaskInitParsed[T]( implicit def inputTaskInitParsed[T](
@deprecated("unused", "") in: Initialize[InputTask[T]] @deprecated("unused", "") in: Initialize[InputTask[T]]
): std.ParserInputTask[T] = ??? ): std.ParserInputTask[T] = ???
*/
def make[T](p: State => Parser[Task[T]]): InputTask[T] = new InputTask[T](p) def make[A1](p: State => Parser[Task[A1]]): InputTask[A1] = new InputTask[A1](p)
/*
def static[T](p: Parser[Task[T]]): InputTask[T] = free(_ => p) def static[T](p: Parser[Task[T]]): InputTask[T] = free(_ => p)
def static[I, T](p: Parser[I])(c: I => Task[T]): InputTask[T] = static(p map c) def static[I, T](p: Parser[I])(c: I => Task[T]): InputTask[T] = static(p map c)
@ -89,10 +91,10 @@ object InputTask {
} }
/** /**
* Constructs an InputTask from: * Constructs an InputTask from:
* a) a Parser constructed using other Settings, but not Tasks * a) a Parser constructed using other Settings, but not Tasks
* b) a dynamically constructed Task that uses Settings, Tasks, and the result of parsing. * b) a dynamically constructed Task that uses Settings, Tasks, and the result of parsing.
*/ */
def createDyn[I, T]( def createDyn[I, T](
p: Initialize[State => Parser[I]] p: Initialize[State => Parser[I]]
)(action: Initialize[Task[I => Initialize[Task[T]]]]): Initialize[InputTask[T]] = )(action: Initialize[Task[I => Initialize[Task[T]]]]): Initialize[InputTask[T]] =
@ -124,10 +126,10 @@ object InputTask {
} }
/** /**
* The proper solution is to have a Manifest context bound and accept slight source incompatibility, * The proper solution is to have a Manifest context bound and accept slight source incompatibility,
* The affected InputTask construction methods are all deprecated and so it is better to keep complete * The affected InputTask construction methods are all deprecated and so it is better to keep complete
* compatibility. Because the AttributeKey is local, it uses object equality and the manifest is not used. * compatibility. Because the AttributeKey is local, it uses object equality and the manifest is not used.
*/ */
private[this] def localKey[T]: AttributeKey[T] = private[this] def localKey[T]: AttributeKey[T] =
AttributeKey.local[Unit].asInstanceOf[AttributeKey[T]] AttributeKey.local[Unit].asInstanceOf[AttributeKey[T]]
@ -173,5 +175,5 @@ object InputTask {
} }
f(task) f(task)
} }
} */
*/ end InputTask

View File

@ -11,6 +11,8 @@ package std
import sbt.internal.util.appmacro.{ Convert, ContextUtil } import sbt.internal.util.appmacro.{ Convert, ContextUtil }
import sbt.internal.util.complete.Parser import sbt.internal.util.complete.Parser
import Def.Initialize import Def.Initialize
import sbt.util.Applicative
import sbt.internal.util.Types.Compose
import scala.quoted.* import scala.quoted.*
class InputInitConvert[C <: Quotes & scala.Singleton](override val qctx: C) class InputInitConvert[C <: Quotes & scala.Singleton](override val qctx: C)
@ -25,6 +27,9 @@ class InputInitConvert[C <: Quotes & scala.Singleton](override val qctx: C)
case _ => Converted.NotApplicable() case _ => Converted.NotApplicable()
private def initTaskErrorMessage = "Internal sbt error: initialize+task wrapper not split" private def initTaskErrorMessage = "Internal sbt error: initialize+task wrapper not split"
def appExpr: Expr[Applicative[Initialize]] =
'{ InitializeInstance.initializeMonad }
end InputInitConvert end InputInitConvert
/** Converts an input `Term` of type `Parser[A]` or `State => Parser[A]` into a `Term` of type `State => Parser[A]`. */ /** Converts an input `Term` of type `Parser[A]` or `State => Parser[A]` into a `Term` of type `State => Parser[A]`. */
@ -40,6 +45,9 @@ class ParserConvert[C <: Quotes & scala.Singleton](override val qctx: C)
case _ => Converted.NotApplicable() case _ => Converted.NotApplicable()
private def initParserErrorMessage = "Internal sbt error: initialize+parser wrapper not split" private def initParserErrorMessage = "Internal sbt error: initialize+parser wrapper not split"
def appExpr: Expr[Applicative[ParserInstance.F1]] =
'{ ParserInstance.parserFunApplicative }
end ParserConvert end ParserConvert
/** Convert instance for plain `Task`s not within the settings system. */ /** Convert instance for plain `Task`s not within the settings system. */
@ -50,6 +58,9 @@ class TaskConvert[C <: Quotes & scala.Singleton](override val qctx: C)
override def convert[A: Type](nme: String, in: Term): Converted = override def convert[A: Type](nme: String, in: Term): Converted =
if nme == InputWrapper.WrapTaskName then Converted.success(in) if nme == InputWrapper.WrapTaskName then Converted.success(in)
else Converted.NotApplicable() else Converted.NotApplicable()
def appExpr[Expr[Monad[Task]]] =
'{ Task.taskMonad }
end TaskConvert end TaskConvert
/** /**
@ -83,6 +94,8 @@ class FullConvert[C <: Quotes & scala.Singleton](override val qctx: C)
} }
Converted.success(t.asTerm) Converted.success(t.asTerm)
def appExpr: Expr[Applicative[Compose[Initialize, Task]]] =
'{ FullInstance.initializeTaskMonad }
end FullConvert end FullConvert
/** /**

View File

@ -64,6 +64,9 @@ object InputWrapper:
private[this] def implDetailError = private[this] def implDetailError =
sys.error("This method is an implementation detail and should not be referenced.") sys.error("This method is an implementation detail and should not be referenced.")
inline def wrapTask[A](in: Any): A = `wrapTask_\u2603\u2603`[A](in)
inline def wrapInit[A](in: Any): A = `wrapInit_\u2603\u2603`[A](in)
/* /*
private[std] def wrapInitInputTask[T: c.WeakTypeTag](using qctx: Quotes)( private[std] def wrapInitInputTask[T: c.WeakTypeTag](using qctx: Quotes)(
ts: c.Expr[Any], ts: c.Expr[Any],
@ -189,12 +192,6 @@ sealed abstract class MacroValue[A1] {
def value: A1 = macro InputWrapper.valueMacroImpl[A1] def value: A1 = macro InputWrapper.valueMacroImpl[A1]
} }
sealed abstract class ParserInput[T] {
@compileTimeOnly(
"`parsed` can only be used within an input task macro, such as := or Def.inputTask."
)
def parsed: T = macro ParserInput.parsedMacroImpl[T]
}
sealed abstract class InputEvaluated[T] { sealed abstract class InputEvaluated[T] {
@compileTimeOnly( @compileTimeOnly(
"`evaluated` can only be used within an input task macro, such as := or Def.inputTask." "`evaluated` can only be used within an input task macro, such as := or Def.inputTask."
@ -239,16 +236,11 @@ object ParserInput:
) )
def `initParser_\u2603\u2603`[T](@deprecated("unused", "") i: Any): T = def `initParser_\u2603\u2603`[T](@deprecated("unused", "") i: Any): T =
sys.error("This method is an implementation detail and should not be referenced.") sys.error("This method is an implementation detail and should not be referenced.")
/*
private[std] def wrap[T: c.WeakTypeTag](
using qctx: Quotes
)(ts: c.Expr[Any], pos: c.Position): c.Expr[T] =
InputWrapper.wrapImpl[T, ParserInput.type](c, ParserInput, WrapName)(ts, pos)
private[std] def wrapInit[T: c.WeakTypeTag](
using qctx: Quotes
)(ts: c.Expr[Any], pos: c.Position): c.Expr[T] =
InputWrapper.wrapImpl[T, ParserInput.type](c, ParserInput, WrapInitName)(ts, pos)
inline def wrap[A1](in: Any): A1 = `parser_\u2603\u2603`[A1](in)
inline def wrapInit[A1](in: Any): A1 = `initParser_\u2603\u2603`[A1](in)
/*
private[std] def inputParser[T: c.WeakTypeTag]( private[std] def inputParser[T: c.WeakTypeTag](
using qctx: Quotes using qctx: Quotes
)(t: c.Expr[InputTask[T]]): c.Expr[State => Parser[Task[T]]] = )(t: c.Expr[InputTask[T]]): c.Expr[State => Parser[Task[T]]] =

View File

@ -29,10 +29,12 @@ end InitializeInstance
private[std] object ComposeInstance: private[std] object ComposeInstance:
import InitializeInstance.initializeMonad import InitializeInstance.initializeMonad
val InitInstance = summon[Applicative[Initialize]] val InitInstance = summon[Applicative[Initialize]]
val F1F2: Applicative[Compose[Initialize, Task]] = summon[Applicative[Compose[Initialize, Task]]] val F1F2: Applicative[Compose[Initialize, Task]] =
summon[Applicative[Compose[Initialize, Task]]]
end ComposeInstance end ComposeInstance
object ParserInstance: object ParserInstance:
type F1[x] = State => Parser[x]
// import sbt.internal.util.Classes.Applicative // import sbt.internal.util.Classes.Applicative
// private[this] implicit val parserApplicative: Applicative[M] = new Applicative[M] { // private[this] implicit val parserApplicative: Applicative[M] = new Applicative[M] {
// def apply[S, T](f: M[S => T], v: M[S]): M[A1] = s => (f(s) ~ v(s)) map { case (a, b) => a(b) } // def apply[S, T](f: M[S => T], v: M[S]): M[A1] = s => (f(s) ~ v(s)) map { case (a, b) => a(b) }
@ -40,7 +42,7 @@ object ParserInstance:
// def map[S, T](f: S => T, v: M[S]) = s => v(s).map(f) // def map[S, T](f: S => T, v: M[S]) = s => v(s).map(f)
// } // }
given Applicative[[a] =>> State => Parser[a]] with given parserFunApplicative: Applicative[F1] with
type F[x] = State => Parser[x] type F[x] = State => Parser[x]
override def pure[A1](a: () => A1): State => Parser[A1] = const(DefaultParsers.success(a())) override def pure[A1](a: () => A1): State => Parser[A1] = const(DefaultParsers.success(a()))
override def ap[A1, A2](ff: F[A1 => A2])(fa: F[A1]): F[A2] = override def ap[A1, A2](ff: F[A1 => A2])(fa: F[A1]): F[A2] =
@ -60,7 +62,7 @@ object FullInstance:
given Monad[Initialize] = InitializeInstance.initializeMonad given Monad[Initialize] = InitializeInstance.initializeMonad
val F1F2: Applicative[Compose[Initialize, Task]] = ComposeInstance.F1F2 val F1F2: Applicative[Compose[Initialize, Task]] = ComposeInstance.F1F2
given Monad[Compose[Initialize, Task]] with given initializeTaskMonad: Monad[Compose[Initialize, Task]] with
type F[x] = Initialize[Task[x]] type F[x] = Initialize[Task[x]]
override def pure[A1](x: () => A1): Initialize[Task[A1]] = F1F2.pure(x) override def pure[A1](x: () => A1): Initialize[Task[A1]] = F1F2.pure(x)
override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])( override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])(

View File

@ -16,6 +16,7 @@ import sbt.internal.util.appmacro.{
Convert, Convert,
// LinterDSL, // LinterDSL,
} }
import sbt.util.Applicative
import scala.quoted.* import scala.quoted.*
class InitializeConvert[C <: Quotes & scala.Singleton](override val qctx: C) class InitializeConvert[C <: Quotes & scala.Singleton](override val qctx: C)
@ -31,6 +32,9 @@ class InitializeConvert[C <: Quotes & scala.Singleton](override val qctx: C)
case InputWrapper.WrapPreviousName => case InputWrapper.WrapPreviousName =>
Converted.Failure(in.pos, "A setting cannot depend on a task's previous value.") Converted.Failure(in.pos, "A setting cannot depend on a task's previous value.")
case _ => Converted.NotApplicable() case _ => Converted.NotApplicable()
def appExpr: Expr[Applicative[Initialize]] =
'{ InitializeInstance.initializeMonad }
end InitializeConvert end InitializeConvert
object SettingMacro: object SettingMacro:
@ -41,8 +45,8 @@ object SettingMacro:
import ContSyntax.* import ContSyntax.*
def settingMacroImpl[A1: Type](in: Expr[A1])(using qctx: Quotes): Expr[Initialize[A1]] = def settingMacroImpl[A1: Type](in: Expr[A1])(using qctx: Quotes): Expr[Initialize[A1]] =
val convert1: Convert[qctx.type] = InitializeConvert(qctx) val convert1 = InitializeConvert(qctx)
convert1.contMapN[A1, F, Id](in, convert1.idTransform) convert1.contMapN[A1, F, Id](in, convert1.appExpr)
/* /*
def settingDynMacroImpl[T: c.WeakTypeTag]( def settingDynMacroImpl[T: c.WeakTypeTag](

View File

@ -22,6 +22,7 @@ import sbt.internal.util.appmacro.{
} }
// import Instance.Transform // import Instance.Transform
import sbt.internal.util.{ AList, LinePosition, NoPosition, SourcePosition, ~> } import sbt.internal.util.{ AList, LinePosition, NoPosition, SourcePosition, ~> }
import sbt.internal.util.complete.Parser
import language.experimental.macros import language.experimental.macros
import scala.annotation.tailrec import scala.annotation.tailrec
@ -56,8 +57,8 @@ object TaskMacro:
t match t match
case '{ if ($cond) then $thenp else $elsep } => mkIfS[A1](t) case '{ if ($cond) then $thenp else $elsep } => mkIfS[A1](t)
case _ => case _ =>
val convert1: Convert[qctx.type] = new FullConvert(qctx) val convert1 = new FullConvert(qctx)
convert1.contMapN[A1, F, Id](t, convert1.idTransform) convert1.contMapN[A1, F, Id](t, convert1.appExpr)
def mkIfS[A1: Type](t: Expr[A1])(using qctx: Quotes): Expr[Initialize[Task[A1]]] = def mkIfS[A1: Type](t: Expr[A1])(using qctx: Quotes): Expr[Initialize[Task[A1]]] =
t match t match
@ -69,8 +70,8 @@ object TaskMacro:
def taskDynMacroImpl[A1: Type]( def taskDynMacroImpl[A1: Type](
t: Expr[Initialize[Task[A1]]] t: Expr[Initialize[Task[A1]]]
)(using qctx: Quotes): Expr[Initialize[Task[A1]]] = )(using qctx: Quotes): Expr[Initialize[Task[A1]]] =
val convert1: Convert[qctx.type] = new FullConvert(qctx) val convert1 = new FullConvert(qctx)
convert1.contFlatMap[A1, F, Id](t, convert1.idTransform) convert1.contFlatMap[A1, F, Id](t, convert1.appExpr)
/* /*
def taskIfMacroImpl[A: Type]( def taskIfMacroImpl[A: Type](
@ -157,16 +158,14 @@ object TaskMacro:
$rec.set0($app, $sourcePosition) $rec.set0($app, $sourcePosition)
} }
/*
/** Implementation of := macro for tasks. */ /** Implementation of := macro for tasks. */
def inputTaskAssignMacroImpl[A1: Type](using def inputTaskAssignMacroImpl[A1: Type](v: Expr[A1])(using
qctx: Quotes qctx: Quotes
)(v: c.Expr[A1]): c.Expr[Setting[InputTask[A1]]] = { ): Expr[Setting[InputTask[A1]]] =
val init = inputTaskMacroImpl[A1](c)(v) val init = inputTaskMacroImpl[A1](v)
val assign = transformMacroImpl(c)(init.tree)(AssignInitName) // val assign = transformMacroImpl(init.tree)(AssignInitName)
c.Expr[Setting[InputTask[A1]]](assign) // Expr[Setting[InputTask[A1]]](assign)
} ???
*/
/** Implementation of += macro for settings. */ /** Implementation of += macro for settings. */
def settingAppend1Impl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], v: Expr[A2])(using def settingAppend1Impl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], v: Expr[A2])(using
@ -238,94 +237,97 @@ object TaskMacro:
import c.universe._ import c.universe._
c.Expr[A1](Literal(Constant(t))) c.Expr[A1](Literal(Constant(t)))
} }
*/
def inputTaskMacroImpl[A1: Type]( def inputTaskMacroImpl[A1: Type](tree: Expr[A1])(using
c: blackbox.Context qctx: Quotes
)(t: c.Expr[A1]): c.Expr[Initialize[InputTask[A1]]] = ): Expr[Initialize[InputTask[A1]]] =
inputTaskMacro0[A1](c)(t) inputTaskMacro0[A1](tree)
def inputTaskDynMacroImpl[A1: Type]( // def inputTaskDynMacroImpl[A1: Type](t: c.Expr[Initialize[Task[A1]]])(using qctx: Quotes): c.Expr[Initialize[InputTask[A1]]] =
c: blackbox.Context // inputTaskDynMacro0[A1](c)(t)
)(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[InputTask[A1]]] =
inputTaskDynMacro0[A1](c)(t)
private[this] def inputTaskMacro0[A1: Type]( private[this] def inputTaskMacro0[A1: Type](tree: Expr[A1])(using
c: blackbox.Context qctx: Quotes
)(t: c.Expr[A1]): c.Expr[Initialize[InputTask[A1]]] = ): Expr[Initialize[InputTask[A1]]] =
iInitializeMacro(c)(t) { et => iInitializeMacro(tree) { et =>
val pt = iParserMacro(c)(et) { pt => val pt = iParserMacro(et) { pt =>
iTaskMacro(c)(pt) iTaskMacro(pt)
} }
c.universe.reify { InputTask.make(pt.splice) } '{ InputTask.make($pt) }
} }
private[this] def iInitializeMacro[M[_], T](c: blackbox.Context)(t: c.Expr[A1])( private[this] def iInitializeMacro[F1[_]: Type, A1: Type](tree: Expr[A1])(
f: c.Expr[A1] => c.Expr[M[A1]] f: Expr[A1] => Expr[F1[A1]]
)(implicit tt: Type[A1], mt: Type[M[A1]]): c.Expr[Initialize[M[A1]]] = { )(using qctx: Quotes): Expr[Initialize[F1[A1]]] =
val inner: Transform[c.type, M] = (in: c.Tree) => f(c.Expr[A1](in)).tree import qctx.reflect.*
val cond = c.Expr[A1](conditionInputTaskTree(c)(t.tree)) import InputWrapper.*
Instance val convert1 = new InputInitConvert(qctx)
.contImpl[A1, M](c, InitializeInstance, InputInitConvert, MixedBuilder, EmptyLinter)( import convert1.Converted
Left(cond),
inner
)
}
private[this] def conditionInputTaskTree(c: blackbox.Context)(t: c.Tree): c.Tree = { def wrapInitTask[A2: Type](tree: Term): Term =
import c.universe._ val expr = tree.asExprOf[Initialize[Task[A2]]]
import InputWrapper._ '{
def wrapInitTask[A1: Type](tree: Tree) = { InputWrapper.wrapTask[A2](InputWrapper.wrapInit[A2]($expr))
val e = c.Expr[Initialize[Task[A1]]](tree) }.asTerm
wrapTask[A1](c)(wrapInit[Task[A1]](c)(e, tree.pos), tree.pos).tree
}
def wrapInitParser[A1: Type](tree: Tree) = {
val e = c.Expr[Initialize[State => Parser[A1]]](tree)
ParserInput.wrap[A1](c)(wrapInit[State => Parser[A1]](c)(e, tree.pos), tree.pos).tree
}
def wrapInitInput[A1: Type](tree: Tree) = {
val e = c.Expr[Initialize[InputTask[A1]]](tree)
wrapInput[A1](wrapInit[InputTask[A1]](c)(e, tree.pos).tree)
}
def wrapInput[A1: Type](tree: Tree) = {
val e = c.Expr[InputTask[A1]](tree)
val p = ParserInput.wrap[Task[A1]](c)(ParserInput.inputParser(c)(e), tree.pos)
wrapTask[A1](c)(p, tree.pos).tree
}
def expand(nme: String, tpe: Type, tree: Tree): Converted[c.type] = nme match { def wrapInitParser[A2: Type](tree: Term): Term =
case WrapInitTaskName => Converted.Success(wrapInitTask(tree)(Type(tpe))) val expr = tree.asExprOf[Initialize[State => Parser[A2]]]
case WrapPreviousName => Converted.Success(wrapInitTask(tree)(Type(tpe))) '{
case ParserInput.WrapInitName => Converted.Success(wrapInitParser(tree)(Type(tpe))) ParserInput.wrap[A2](InputWrapper.wrapInit[State => Parser[A2]]($expr))
case WrapInitInputName => Converted.Success(wrapInitInput(tree)(Type(tpe))) }.asTerm
case WrapInputName => Converted.Success(wrapInput(tree)(Type(tpe)))
case _ => Converted.NotApplicable
}
val util = ContextUtil[c.type](c)
util.transformWrappers(t, (nme, tpe, tree, original) => expand(nme, tpe, tree))
}
private[this] def iParserMacro[M[_], T](c: blackbox.Context)(t: c.Expr[A1])( def wrapInitInput[A2: Type](tree: Term): Term =
f: c.Expr[A1] => c.Expr[M[A1]] val expr = tree.asExprOf[Initialize[InputTask[A2]]]
)(implicit tt: Type[A1], mt: Type[M[A1]]): c.Expr[State => Parser[M[A1]]] = { wrapInput[A2]('{
val inner: Transform[c.type, M] = (in: c.Tree) => f(c.Expr[A1](in)).tree InputWrapper.wrapInit[InputTask[A2]]($expr)
Instance.contImpl[A1, M](c, ParserInstance, ParserConvert, MixedBuilder, LinterDSL.Empty)( }.asTerm)
Left(t),
inner
)
}
private[this] def iTaskMacro[A1: Type]( def wrapInput[A2: Type](tree: Term): Term =
c: blackbox.Context val expr = tree.asExprOf[InputTask[A1]]
)(t: c.Expr[A1]): c.Expr[Task[A1]] = '{
Instance InputWrapper.wrapTask[A2](ParserInput.wrap[Task[A2]]($expr.parser))
.contImpl[A1, Id](c, TaskInstance, TaskConvert, MixedBuilder, EmptyLinter)( }.asTerm
Left(t),
Instance.idTransform def expand(nme: String, tpeRepr: TypeRepr, tree: Term): Converted =
tpeRepr.asType match
case '[tpe] =>
nme match
case WrapInitTaskName => Converted.success(wrapInitTask[tpe](tree))
case WrapPreviousName => Converted.success(wrapInitTask[tpe](tree))
case ParserInput.WrapInitName => Converted.success(wrapInitParser[tpe](tree))
case WrapInitInputName => Converted.success(wrapInitInput[tpe](tree))
case WrapInputName => Converted.success(wrapInput[tpe](tree))
case _ => Converted.NotApplicable()
def conditionInputTaskTree(t: Term): Term =
convert1.transformWrappers(
tree = t,
subWrapper = (nme, tpe, tree, original) => expand(nme, tpe, tree),
owner = Symbol.spliceOwner,
) )
val inner: convert1.TermTransform[F1] = (in: Term) => f(in.asExprOf[A1]).asTerm
val cond = conditionInputTaskTree(tree.asTerm).asExprOf[A1]
convert1.contMapN[A1, Def.Initialize, F1](cond, convert1.appExpr, inner)
private[this] def iParserMacro[F1[_]: Type, A1: Type](tree: Expr[A1])(
f: Expr[A1] => Expr[F1[A1]]
)(using qctx: Quotes): Expr[State => Parser[F1[A1]]] =
import qctx.reflect.*
val convert1 = new ParserConvert(qctx)
val inner: convert1.TermTransform[F1] = (in: Term) => f(in.asExprOf[A1]).asTerm
convert1.contMapN[A1, ParserInstance.F1, F1](tree, convert1.appExpr, inner)
private[this] def iTaskMacro[A1: Type](tree: Expr[A1])(using qctx: Quotes): Expr[Task[A1]] =
import qctx.reflect.*
val convert1 = new TaskConvert(qctx)
convert1.contMapN[A1, Task, Id](tree, convert1.appExpr)
/*
private[this] def inputTaskDynMacro0[A1: Type]( private[this] def inputTaskDynMacro0[A1: Type](
c: blackbox.Context t: Expr[Initialize[Task[A1]]]
)(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[InputTask[A1]]] = { )(using qctx: Quotes): Expr[Initialize[InputTask[A1]]] = {
import c.universe.{ Apply => ApplyTree, _ } import c.universe.{ Apply => ApplyTree, _ }
import internal.decorators._ import internal.decorators._
@ -406,7 +408,6 @@ object TaskMacro:
} }
} }
*/ */
end TaskMacro end TaskMacro
object DefinableTaskMacro: object DefinableTaskMacro:

View File

@ -10,10 +10,9 @@ package sbt.std
import sbt.internal.util.complete import sbt.internal.util.complete
import sbt.internal.util.complete.DefaultParsers import sbt.internal.util.complete.DefaultParsers
import sbt.{ Def, InputTask, Task } import sbt.{ Def, InputTask, Task }
import sbt.Def.parsed
object UseTask: object UseTask:
import sbt.std.FullInstance.given
val set = Def.setting { 23 } val set = Def.setting { 23 }
val x = Def.task { set.value } val x = Def.task { set.value }
val y = Def.task { true } val y = Def.task { true }
@ -88,9 +87,10 @@ object Assign {
// ik := { if (tsk.parsed.value == "blue") tk.value else mk.value } // ik := { if (tsk.parsed.value == "blue") tk.value else mk.value }
) )
// val it1 = Def.inputTask { val it1 = Def.inputTask {
// tsk.parsed // "as" //dummy.value.parsed //
// } tsk.parsed // "as" //dummy.value.parsed
}
// val it2 = Def.inputTask { // val it2 = Def.inputTask {
// "lit" // "lit"
// } // }