From f3dd2dff36e3082cdc6b61857aac11caf49e41f8 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 20 Jun 2022 01:58:45 -0400 Subject: [PATCH] Starting input task --- .../sbt/internal/util/appmacro/Cont.scala | 48 ++++- .../internal/util/appmacro/ContextUtil.scala | 2 +- .../sbt/internal/util/appmacro/Convert.scala | 9 +- .../scala/sbt/internal/ContTestMacro.scala | 2 +- main-settings/src/main/scala/sbt/Def.scala | 56 +++--- .../src/main/scala/sbt/InputTask.scala | 28 +-- .../src/main/scala/sbt/std/InputConvert.scala | 13 ++ .../src/main/scala/sbt/std/InputWrapper.scala | 22 +-- .../src/main/scala/sbt/std/Instances.scala | 8 +- .../src/main/scala/sbt/std/SettingMacro.scala | 8 +- .../src/main/scala/sbt/std/TaskMacro.scala | 177 +++++++++--------- .../src/test/scala/sbt/std/UsageTest.scala | 10 +- 12 files changed, 216 insertions(+), 167 deletions(-) diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala index 959845638..e253345ae 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala @@ -24,12 +24,26 @@ trait Cont: */ def contMapN[A: Type, F[_], Effect[_]: Type]( 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] )(using iftpe: Type[F], eatpe: Type[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 @@ -37,16 +51,38 @@ trait Cont: */ def contFlatMap[A: Type, F[_], Effect[_]: Type]( 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] )(using iftpe: Type[F], eatpe: Type[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. - * 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 * 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]( eitherTree: Either[Expr[A], Expr[F[A]]], + instanceExpr: Expr[Applicative[F]], inner: conv.TermTransform[Effect] )(using iftpe: Type[F], @@ -98,11 +135,6 @@ trait Cont: case Left(l) => (l, TypeRepr.of[Effect[A]]) 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]() def makeApp(body: Term, inputs: List[Input]): Expr[F[Effect[A]]] = inputs match diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala index a0ba7328c..8faacb2ee 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala @@ -62,5 +62,5 @@ trait ContextUtil[C <: Quotes & scala.Singleton](val qctx: C): def apply(in: Term): Term end TermTransform - def idTransform: TermTransform[Id] = in => in + def idTransform[F[_]]: TermTransform[F] = in => in end ContextUtil diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/Convert.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/Convert.scala index 86af8d2cc..14b42d7e4 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/Convert.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/Convert.scala @@ -39,12 +39,19 @@ trait Convert[C <: Quotes & Singleton](override val qctx: C) extends ContextUtil subWrapper: (String, TypeRepr, Term, Term) => Converted, owner: Symbol, ): 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 // plain Idents that reference the actual input value object appTransformer extends TreeMap: override def transformTerm(tree: Term)(owner: Symbol): Term = tree match - case Apply(TypeApply(Select(_, nme), targ :: Nil), qual :: Nil) => + case ApplySelectOrIdent(nme, targ, qual) => subWrapper(nme, targ.tpe, qual, tree) match case Converted.Success(tree, finalTransform) => finalTransform(tree) diff --git a/core-macros/src/test/scala/sbt/internal/ContTestMacro.scala b/core-macros/src/test/scala/sbt/internal/ContTestMacro.scala index 1bd76c168..0fb9e1c0b 100644 --- a/core-macros/src/test/scala/sbt/internal/ContTestMacro.scala +++ b/core-macros/src/test/scala/sbt/internal/ContTestMacro.scala @@ -16,6 +16,6 @@ object ContTestMacro: object ContSyntax extends Cont import ContSyntax.* 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 diff --git a/main-settings/src/main/scala/sbt/Def.scala b/main-settings/src/main/scala/sbt/Def.scala index 1ad526786..88e82fb17 100644 --- a/main-settings/src/main/scala/sbt/Def.scala +++ b/main-settings/src/main/scala/sbt/Def.scala @@ -210,38 +210,33 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits: /** 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 toSParser[T](p: Parser[T]): State => Parser[T] = const(p) - def toISParser[T](p: Initialize[Parser[T]]): Initialize[State => Parser[T]] = p(toSParser) - def toIParser[T](p: Initialize[InputTask[T]]): Initialize[State => Parser[Task[T]]] = p(_.parser) + inline def toSParser[A1](p: Parser[A1]): State => Parser[A1] = const(p) + def toISParser[A1](p: Initialize[Parser[A1]]): Initialize[State => Parser[A1]] = + p.apply[State => Parser[A1]](toSParser(_)) + def toIParser[A1](p: Initialize[InputTask[A1]]): Initialize[State => Parser[Task[A1]]] = + p(_.parser) import std.SettingMacro.{ // settingDynMacroImpl, settingMacroImpl } - import std.TaskMacro.{ - // inputTaskDynMacroImpl, - // inputTaskMacroImpl, - taskDynMacroImpl, - // taskIfMacroImpl, - taskMacroImpl, - } - import std._ + import std.* import language.experimental.macros 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]] = - ${ taskDynMacroImpl[A1]('a1) } + ${ TaskMacro.taskDynMacroImpl[A1]('a1) } 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 inputTask[T](t: T): Def.Initialize[InputTask[T]] = macro inputTaskMacroImpl[T] - // def inputTaskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[InputTask[T]] = { - // macro inputTaskDynMacroImpl[T] - // } + + inline def inputTask[A1](inline a: A1): Def.Initialize[InputTask[A1]] = + ${ TaskMacro.inputTaskMacroImpl[A1]('a) } + // def taskIf[T](a: T): Def.Initialize[Task[T]] = macro taskIfMacroImpl[T] 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 // Initialize[State => Parser[T]] to be used in the inputTask macro as an input with an ultimate - // result of type T - // implicit def parserInitToInput[T]( - // @deprecated("unused", "") p: Initialize[Parser[T]] - // ): ParserInput[T] = ??? + // result of type A1, previously implemented using ParserInput.parsedMacroImpl[A1]. - // implicit def parserInitStateToInput[T]( - // @deprecated("unused", "") p: Initialize[State => Parser[T]] - // ): ParserInput[T] = ??? + extension [A1](in: Initialize[Parser[A1]]) + inline def parsed: A1 = ParserInput.wrapInit[A1](Def.toISParser(in)) + + 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] = ${ std.KeyMacro.settingKeyImpl[A1]('description) } @@ -382,18 +377,19 @@ end Def // these need to be mixed into the sbt package object // 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 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]( - // @deprecated("unused", "") in: State => Parser[T] - // ): std.ParserInput[T] = ??? -} + extension [A1](in: State => Parser[A1]) + inline def parsed: A1 = ParserInput.`parser_\u2603\u2603`[A1](in) +end TaskMacroExtra sealed trait InitializeImplicits0 { self: Def.type => implicit def initOps[T](x: Def.Initialize[T]): Def.InitOps[T] = new Def.InitOps(x) diff --git a/main-settings/src/main/scala/sbt/InputTask.scala b/main-settings/src/main/scala/sbt/InputTask.scala index 3f0ea338a..92d6e8eed 100644 --- a/main-settings/src/main/scala/sbt/InputTask.scala +++ b/main-settings/src/main/scala/sbt/InputTask.scala @@ -33,8 +33,8 @@ final class InputTask[A1] private (val parser: State => Parser[Task[A1]]): ) end InputTask -/* -object InputTask { +object InputTask: + /* implicit class InitializeInput[T](i: Initialize[InputTask[T]]) { def partialInput(in: String): Initialize[InputTask[T]] = i(_ partialInput in) def fullInput(in: String): Initialize[InputTask[T]] = i(_ fullInput in) @@ -61,9 +61,11 @@ object InputTask { implicit def inputTaskInitParsed[T]( @deprecated("unused", "") in: Initialize[InputTask[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[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: - * a) a Parser constructed using other Settings, but not Tasks - * b) a dynamically constructed Task that uses Settings, Tasks, and the result of parsing. - */ + * Constructs an InputTask from: + * a) a Parser constructed using other Settings, but not Tasks + * b) a dynamically constructed Task that uses Settings, Tasks, and the result of parsing. + */ def createDyn[I, T]( p: Initialize[State => Parser[I]] )(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 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. - */ + * 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 + * compatibility. Because the AttributeKey is local, it uses object equality and the manifest is not used. + */ private[this] def localKey[T]: AttributeKey[T] = AttributeKey.local[Unit].asInstanceOf[AttributeKey[T]] @@ -173,5 +175,5 @@ object InputTask { } f(task) } -} - */ + */ +end InputTask diff --git a/main-settings/src/main/scala/sbt/std/InputConvert.scala b/main-settings/src/main/scala/sbt/std/InputConvert.scala index 7b35dc276..2cdcf4886 100644 --- a/main-settings/src/main/scala/sbt/std/InputConvert.scala +++ b/main-settings/src/main/scala/sbt/std/InputConvert.scala @@ -11,6 +11,8 @@ package std import sbt.internal.util.appmacro.{ Convert, ContextUtil } import sbt.internal.util.complete.Parser import Def.Initialize +import sbt.util.Applicative +import sbt.internal.util.Types.Compose import scala.quoted.* 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() private def initTaskErrorMessage = "Internal sbt error: initialize+task wrapper not split" + + def appExpr: Expr[Applicative[Initialize]] = + '{ InitializeInstance.initializeMonad } end InputInitConvert /** 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() private def initParserErrorMessage = "Internal sbt error: initialize+parser wrapper not split" + + def appExpr: Expr[Applicative[ParserInstance.F1]] = + '{ ParserInstance.parserFunApplicative } end ParserConvert /** 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 = if nme == InputWrapper.WrapTaskName then Converted.success(in) else Converted.NotApplicable() + + def appExpr[Expr[Monad[Task]]] = + '{ Task.taskMonad } end TaskConvert /** @@ -83,6 +94,8 @@ class FullConvert[C <: Quotes & scala.Singleton](override val qctx: C) } Converted.success(t.asTerm) + def appExpr: Expr[Applicative[Compose[Initialize, Task]]] = + '{ FullInstance.initializeTaskMonad } end FullConvert /** diff --git a/main-settings/src/main/scala/sbt/std/InputWrapper.scala b/main-settings/src/main/scala/sbt/std/InputWrapper.scala index d36b63184..eae014af0 100644 --- a/main-settings/src/main/scala/sbt/std/InputWrapper.scala +++ b/main-settings/src/main/scala/sbt/std/InputWrapper.scala @@ -64,6 +64,9 @@ object InputWrapper: private[this] def implDetailError = 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)( ts: c.Expr[Any], @@ -189,12 +192,6 @@ sealed abstract class MacroValue[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] { @compileTimeOnly( "`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 = 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]( using qctx: Quotes )(t: c.Expr[InputTask[T]]): c.Expr[State => Parser[Task[T]]] = diff --git a/main-settings/src/main/scala/sbt/std/Instances.scala b/main-settings/src/main/scala/sbt/std/Instances.scala index f97dc70c0..692527ffc 100644 --- a/main-settings/src/main/scala/sbt/std/Instances.scala +++ b/main-settings/src/main/scala/sbt/std/Instances.scala @@ -29,10 +29,12 @@ end InitializeInstance private[std] object ComposeInstance: import InitializeInstance.initializeMonad 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 object ParserInstance: + type F1[x] = State => Parser[x] // import sbt.internal.util.Classes.Applicative // 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) } @@ -40,7 +42,7 @@ object ParserInstance: // 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] 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] = @@ -60,7 +62,7 @@ object FullInstance: given Monad[Initialize] = InitializeInstance.initializeMonad 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]] override def pure[A1](x: () => A1): Initialize[Task[A1]] = F1F2.pure(x) override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])( diff --git a/main-settings/src/main/scala/sbt/std/SettingMacro.scala b/main-settings/src/main/scala/sbt/std/SettingMacro.scala index 9b9171209..32c29bb35 100644 --- a/main-settings/src/main/scala/sbt/std/SettingMacro.scala +++ b/main-settings/src/main/scala/sbt/std/SettingMacro.scala @@ -16,6 +16,7 @@ import sbt.internal.util.appmacro.{ Convert, // LinterDSL, } +import sbt.util.Applicative import scala.quoted.* 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 => Converted.Failure(in.pos, "A setting cannot depend on a task's previous value.") case _ => Converted.NotApplicable() + + def appExpr: Expr[Applicative[Initialize]] = + '{ InitializeInstance.initializeMonad } end InitializeConvert object SettingMacro: @@ -41,8 +45,8 @@ object SettingMacro: import ContSyntax.* def settingMacroImpl[A1: Type](in: Expr[A1])(using qctx: Quotes): Expr[Initialize[A1]] = - val convert1: Convert[qctx.type] = InitializeConvert(qctx) - convert1.contMapN[A1, F, Id](in, convert1.idTransform) + val convert1 = InitializeConvert(qctx) + convert1.contMapN[A1, F, Id](in, convert1.appExpr) /* def settingDynMacroImpl[T: c.WeakTypeTag]( diff --git a/main-settings/src/main/scala/sbt/std/TaskMacro.scala b/main-settings/src/main/scala/sbt/std/TaskMacro.scala index 2d0901e60..b3f8107a9 100644 --- a/main-settings/src/main/scala/sbt/std/TaskMacro.scala +++ b/main-settings/src/main/scala/sbt/std/TaskMacro.scala @@ -22,6 +22,7 @@ import sbt.internal.util.appmacro.{ } // import Instance.Transform import sbt.internal.util.{ AList, LinePosition, NoPosition, SourcePosition, ~> } +import sbt.internal.util.complete.Parser import language.experimental.macros import scala.annotation.tailrec @@ -56,8 +57,8 @@ object TaskMacro: t match case '{ if ($cond) then $thenp else $elsep } => mkIfS[A1](t) case _ => - val convert1: Convert[qctx.type] = new FullConvert(qctx) - convert1.contMapN[A1, F, Id](t, convert1.idTransform) + val convert1 = new FullConvert(qctx) + convert1.contMapN[A1, F, Id](t, convert1.appExpr) def mkIfS[A1: Type](t: Expr[A1])(using qctx: Quotes): Expr[Initialize[Task[A1]]] = t match @@ -69,8 +70,8 @@ object TaskMacro: def taskDynMacroImpl[A1: Type]( t: Expr[Initialize[Task[A1]]] )(using qctx: Quotes): Expr[Initialize[Task[A1]]] = - val convert1: Convert[qctx.type] = new FullConvert(qctx) - convert1.contFlatMap[A1, F, Id](t, convert1.idTransform) + val convert1 = new FullConvert(qctx) + convert1.contFlatMap[A1, F, Id](t, convert1.appExpr) /* def taskIfMacroImpl[A: Type]( @@ -157,16 +158,14 @@ object TaskMacro: $rec.set0($app, $sourcePosition) } - /* /** Implementation of := macro for tasks. */ - def inputTaskAssignMacroImpl[A1: Type](using + def inputTaskAssignMacroImpl[A1: Type](v: Expr[A1])(using qctx: Quotes - )(v: c.Expr[A1]): c.Expr[Setting[InputTask[A1]]] = { - val init = inputTaskMacroImpl[A1](c)(v) - val assign = transformMacroImpl(c)(init.tree)(AssignInitName) - c.Expr[Setting[InputTask[A1]]](assign) - } - */ + ): Expr[Setting[InputTask[A1]]] = + val init = inputTaskMacroImpl[A1](v) + // val assign = transformMacroImpl(init.tree)(AssignInitName) + // Expr[Setting[InputTask[A1]]](assign) + ??? /** Implementation of += macro for settings. */ def settingAppend1Impl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], v: Expr[A2])(using @@ -238,94 +237,97 @@ object TaskMacro: import c.universe._ c.Expr[A1](Literal(Constant(t))) } + */ - def inputTaskMacroImpl[A1: Type]( - c: blackbox.Context - )(t: c.Expr[A1]): c.Expr[Initialize[InputTask[A1]]] = - inputTaskMacro0[A1](c)(t) + def inputTaskMacroImpl[A1: Type](tree: Expr[A1])(using + qctx: Quotes + ): Expr[Initialize[InputTask[A1]]] = + inputTaskMacro0[A1](tree) - def inputTaskDynMacroImpl[A1: Type]( - c: blackbox.Context - )(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[InputTask[A1]]] = - inputTaskDynMacro0[A1](c)(t) + // def inputTaskDynMacroImpl[A1: Type](t: c.Expr[Initialize[Task[A1]]])(using qctx: Quotes): c.Expr[Initialize[InputTask[A1]]] = + // inputTaskDynMacro0[A1](c)(t) - private[this] def inputTaskMacro0[A1: Type]( - c: blackbox.Context - )(t: c.Expr[A1]): c.Expr[Initialize[InputTask[A1]]] = - iInitializeMacro(c)(t) { et => - val pt = iParserMacro(c)(et) { pt => - iTaskMacro(c)(pt) + private[this] def inputTaskMacro0[A1: Type](tree: Expr[A1])(using + qctx: Quotes + ): Expr[Initialize[InputTask[A1]]] = + iInitializeMacro(tree) { et => + val pt = iParserMacro(et) { 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])( - f: c.Expr[A1] => c.Expr[M[A1]] - )(implicit tt: Type[A1], mt: Type[M[A1]]): c.Expr[Initialize[M[A1]]] = { - val inner: Transform[c.type, M] = (in: c.Tree) => f(c.Expr[A1](in)).tree - val cond = c.Expr[A1](conditionInputTaskTree(c)(t.tree)) - Instance - .contImpl[A1, M](c, InitializeInstance, InputInitConvert, MixedBuilder, EmptyLinter)( - Left(cond), - inner - ) - } + private[this] def iInitializeMacro[F1[_]: Type, A1: Type](tree: Expr[A1])( + f: Expr[A1] => Expr[F1[A1]] + )(using qctx: Quotes): Expr[Initialize[F1[A1]]] = + import qctx.reflect.* + import InputWrapper.* + val convert1 = new InputInitConvert(qctx) + import convert1.Converted - private[this] def conditionInputTaskTree(c: blackbox.Context)(t: c.Tree): c.Tree = { - import c.universe._ - import InputWrapper._ - def wrapInitTask[A1: Type](tree: Tree) = { - val e = c.Expr[Initialize[Task[A1]]](tree) - 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 wrapInitTask[A2: Type](tree: Term): Term = + val expr = tree.asExprOf[Initialize[Task[A2]]] + '{ + InputWrapper.wrapTask[A2](InputWrapper.wrapInit[A2]($expr)) + }.asTerm - def expand(nme: String, tpe: Type, tree: Tree): Converted[c.type] = nme match { - case WrapInitTaskName => Converted.Success(wrapInitTask(tree)(Type(tpe))) - case WrapPreviousName => Converted.Success(wrapInitTask(tree)(Type(tpe))) - case ParserInput.WrapInitName => Converted.Success(wrapInitParser(tree)(Type(tpe))) - case WrapInitInputName => Converted.Success(wrapInitInput(tree)(Type(tpe))) - 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)) - } + def wrapInitParser[A2: Type](tree: Term): Term = + val expr = tree.asExprOf[Initialize[State => Parser[A2]]] + '{ + ParserInput.wrap[A2](InputWrapper.wrapInit[State => Parser[A2]]($expr)) + }.asTerm - private[this] def iParserMacro[M[_], T](c: blackbox.Context)(t: c.Expr[A1])( - f: c.Expr[A1] => c.Expr[M[A1]] - )(implicit tt: Type[A1], mt: Type[M[A1]]): c.Expr[State => Parser[M[A1]]] = { - val inner: Transform[c.type, M] = (in: c.Tree) => f(c.Expr[A1](in)).tree - Instance.contImpl[A1, M](c, ParserInstance, ParserConvert, MixedBuilder, LinterDSL.Empty)( - Left(t), - inner - ) - } + def wrapInitInput[A2: Type](tree: Term): Term = + val expr = tree.asExprOf[Initialize[InputTask[A2]]] + wrapInput[A2]('{ + InputWrapper.wrapInit[InputTask[A2]]($expr) + }.asTerm) - private[this] def iTaskMacro[A1: Type]( - c: blackbox.Context - )(t: c.Expr[A1]): c.Expr[Task[A1]] = - Instance - .contImpl[A1, Id](c, TaskInstance, TaskConvert, MixedBuilder, EmptyLinter)( - Left(t), - Instance.idTransform + def wrapInput[A2: Type](tree: Term): Term = + val expr = tree.asExprOf[InputTask[A1]] + '{ + InputWrapper.wrapTask[A2](ParserInput.wrap[Task[A2]]($expr.parser)) + }.asTerm + + 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]( - c: blackbox.Context - )(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[InputTask[A1]]] = { + t: Expr[Initialize[Task[A1]]] + )(using qctx: Quotes): Expr[Initialize[InputTask[A1]]] = { import c.universe.{ Apply => ApplyTree, _ } import internal.decorators._ @@ -406,7 +408,6 @@ object TaskMacro: } } */ - end TaskMacro object DefinableTaskMacro: diff --git a/main-settings/src/test/scala/sbt/std/UsageTest.scala b/main-settings/src/test/scala/sbt/std/UsageTest.scala index 25f943814..2ca0da508 100644 --- a/main-settings/src/test/scala/sbt/std/UsageTest.scala +++ b/main-settings/src/test/scala/sbt/std/UsageTest.scala @@ -10,10 +10,9 @@ package sbt.std import sbt.internal.util.complete import sbt.internal.util.complete.DefaultParsers import sbt.{ Def, InputTask, Task } +import sbt.Def.parsed object UseTask: - import sbt.std.FullInstance.given - val set = Def.setting { 23 } val x = Def.task { set.value } val y = Def.task { true } @@ -88,9 +87,10 @@ object Assign { // ik := { if (tsk.parsed.value == "blue") tk.value else mk.value } ) - // val it1 = Def.inputTask { - // tsk.parsed // "as" //dummy.value.parsed - // } + val it1 = Def.inputTask { + // + tsk.parsed // "as" //dummy.value.parsed + } // val it2 = Def.inputTask { // "lit" // }