Setting macro

This commit is contained in:
Eugene Yokota 2022-05-16 08:47:58 -04:00
parent 2f50a88a3d
commit 37f6ee6184
5 changed files with 281 additions and 274 deletions

View File

@ -214,7 +214,10 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits:
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)
// import std.SettingMacro.{ settingDynMacroImpl, settingMacroImpl }
import std.SettingMacro.{
// settingDynMacroImpl,
settingMacroImpl
}
import std.TaskMacro.{
// inputTaskDynMacroImpl,
// inputTaskMacroImpl,
@ -230,7 +233,9 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits:
${ taskMacroImpl[A1]('a1) }
// def taskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[Task[T]] = macro taskDynMacroImpl[T]
// def setting[T](t: T): Def.Initialize[T] = macro settingMacroImpl[T]
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]] = {
@ -290,14 +295,16 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits:
@targetName("valueIA1")
inline def value: A1 = InputWrapper.`wrapInitTask_\u2603\u2603`[A1](in)
/**
* This treats the `Initailize[Task[A]]` as a setting that returns the Task value,
* instead of evaluating the task.
*/
inline def taskValue: Task[A1] = InputWrapper.`wrapInit_\u2603\u2603`[Task[A1]](in)
// implicit def macroValueIInT[T](
// @deprecated("unused", "") in: Initialize[InputTask[T]]
// ): InputEvaluated[T] = ???
// implicit def taskMacroValueIT[T](
// @deprecated("unused", "") in: Initialize[Task[T]]
// ): MacroTaskValue[T] = ???
// implicit def macroPrevious[T](@deprecated("unused", "") in: TaskKey[T]): MacroPrevious[T] = ???
// The following conversions enable the types Parser[T], Initialize[Parser[T]], and

View File

@ -14,6 +14,7 @@ import sbt.internal.util.{ ~>, AList, AttributeKey, Settings, SourcePosition }
import sbt.util.OptJsonWriter
import sbt.ConcurrentRestrictions.Tag
import sbt.Def.{ Initialize, ScopedKey, Setting, setting }
import std.TaskMacro
import std.TaskExtra.{ task => mktask, _ }
/** An abstraction on top of Settings for build configuration and task definition. */
@ -72,30 +73,32 @@ sealed abstract class SettingKey[A1]
final def in(scope: Scope): SettingKey[A1] =
Scoped.scopedSetting(Scope.replaceThis(this.scope)(scope), this.key)
// final def :=(v: T): Setting[T] = macro std.TaskMacro.settingAssignMacroImpl[T]
final inline def :=(inline v: A1): Setting[A1] =
${ TaskMacro.settingAssignMacroImpl('this, 'v) }
// final def +=[U](v: U)(implicit a: Append.Value[T, U]): Setting[T] =
// macro std.TaskMacro.settingAppend1Impl[T, U]
final inline def +=[A2](inline v: A2)(using a: Append.Value[A1, A2]): Setting[A1] =
${ TaskMacro.settingAppend1Impl[A1, A2]('this, 'v) }
// final def ++=[U](vs: U)(implicit a: Append.Values[T, U]): Setting[T] =
// macro std.TaskMacro.settingAppendNImpl[T, U]
final inline def ++=[A2](inline vs: A2)(using a: Append.Values[A1, A2]): Setting[A1] =
${ TaskMacro.settingAppendNImpl[A1, A2]('this, 'vs) }
// final def <+=[V](v: Initialize[V])(implicit a: Append.Value[T, V]): Setting[T] =
// macro std.TaskMacro.fakeSettingAppend1Position[T, V]
final inline def <+=[A2](inline v: Initialize[A2]): Setting[A1] =
${ TaskMacro.fakeSettingAppend1Position[A1, A2]('v) }
// final def <++=[V](vs: Initialize[V])(implicit a: Append.Values[T, V]): Setting[T] =
// macro std.TaskMacro.fakeSettingAppendNPosition[T, V]
final inline def <++=[A2](inline vs: Initialize[A2]): Setting[A1] =
${ TaskMacro.fakeSettingAppendNPosition[A1, A2]('vs) }
// final def -=[U](v: U)(implicit r: Remove.Value[T, U]): Setting[T] =
// macro std.TaskMacro.settingRemove1Impl[T, U]
final inline def -=[A2](inline v: A2)(using Remove.Value[A1, A2]): Setting[A1] =
${ TaskMacro.settingRemove1Impl[A1, A2]('this, 'v) }
// final def --=[U](vs: U)(implicit r: Remove.Values[T, U]): Setting[T] =
// macro std.TaskMacro.settingRemoveNImpl[T, U]
final inline def --=[A2](inline vs: A2)(using Remove.Values[A1, A2]): Setting[A1] =
${ TaskMacro.settingRemoveNImpl[A1, A2]('this, 'vs) }
// final def ~=(f: T => T): Setting[T] = macro std.TaskMacro.settingTransformPosition[T]
final inline def ~=(inline f: A1 => A1): Setting[A1] =
${ TaskMacro.settingTransformPosition('this, 'f) }
final def append1[V](v: Initialize[V], source: SourcePosition)(implicit
a: Append.Value[A1, V]
final def append1[A2](v: Initialize[A2], source: SourcePosition)(using
a: Append.Value[A1, A2]
): Setting[A1] = make(v, source)(a.appendValue)
final def appendN[V](vs: Initialize[V], source: SourcePosition)(implicit
@ -212,7 +215,7 @@ sealed trait InputKey[A1]
def in(scope: Scope): InputKey[A1] =
Scoped.scopedInput(Scope.replaceThis(this.scope)(scope), this.key)
// final def :=(v: A1): Setting[InputTask[A1]] = macro std.TaskMacro.inputTaskAssignMacroImpl[A1]
// inline def :=(inline v: A1): Setting[InputTask[A1]] = macro std.TaskMacro.inputTaskAssignMacroImpl[A1]
// final def ~=(f: A1 => A1): Setting[InputTask[A1]] = macro std.TaskMacro.itaskTransformPosition[A1]
final def transform(f: A1 => A1, source: SourcePosition): Setting[InputTask[A1]] =
@ -297,8 +300,9 @@ object Scoped:
// private[sbt] final def :==(app: S): Setting[S] = macro std.TaskMacro.settingAssignPure[S]
// final def <<=(app: Initialize[S]): Setting[S] =
// macro std.TaskMacro.fakeSettingAssignPosition[S]
inline def <<=(inline app: Initialize[S]): Setting[S] = ${
TaskMacro.fakeSettingAssignImpl('app)
}
/** Internally used function for setting a value along with the `.sbt` file location where it is defined. */
final def set(app: Initialize[S], source: SourcePosition): Setting[S] =
@ -361,7 +365,11 @@ object Scoped:
// private[sbt] def ::=(app: Task[S]): Setting[Task[S]] =
// macro std.TaskMacro.taskAssignPositionT[S]
// def :=(v: S): Setting[Task[S]] = macro std.TaskMacro.taskAssignMacroImpl[S]
inline def :=(inline v: A1): Setting[Task[A1]] = ${
TaskMacro.taskAssignMacroImpl[A1]('self, 'v)
}
// macro std.TaskMacro.taskAssignMacroImpl[S]
// def ~=(f: S => S): Setting[Task[S]] = macro std.TaskMacro.taskTransformPosition[S]
// def <<=(app: Initialize[Task[S]]): Setting[Task[S]] =

View File

@ -9,53 +9,42 @@ package sbt
package std
import Def.Initialize
// import sbt.internal.util.Types.{ Id, idFun }
// import sbt.internal.util.AList
// import sbt.internal.util.appmacro.{
// Convert,
// Converted,
// Instance,
// LinterDSL,
// MixedBuilder,
// MonadInstance
// }
import sbt.internal.util.Types.Id
import sbt.internal.util.appmacro.{
Cont,
ContextUtil,
Convert,
// LinterDSL,
}
import scala.quoted.*
class InitializeConvert[C <: Quotes & scala.Singleton](override val qctx: C)
extends Convert[C](qctx)
with ContextUtil[C](qctx):
import qctx.reflect.*
override def convert[A: Type](nme: String, in: Term): Converted =
nme match
case InputWrapper.WrapInitName => Converted.success(in)
case InputWrapper.WrapTaskName | InputWrapper.WrapInitTaskName =>
Converted.Failure(in.pos, "A setting cannot depend on a task")
case InputWrapper.WrapPreviousName =>
Converted.Failure(in.pos, "A setting cannot depend on a task's previous value.")
case _ => Converted.NotApplicable()
end InitializeConvert
object SettingMacro:
// import LinterDSL.{ Empty => EmptyLinter }
type F[x] = Initialize[x]
object ContSyntax extends Cont
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)
/*
import reflect.macros._
object InitializeConvert extends Convert {
def apply[T: c.WeakTypeTag](c: blackbox.Context)(nme: String, in: c.Tree): Converted[c.type] =
nme match {
case InputWrapper.WrapInitName => convert[T](c)(in)
case InputWrapper.WrapTaskName | InputWrapper.WrapInitTaskName => failTask[c.type](c)(in.pos)
case InputWrapper.WrapPreviousName => failPrevious[c.type](c)(in.pos)
case _ => Converted.NotApplicable
}
private def convert[T: c.WeakTypeTag](c: blackbox.Context)(in: c.Tree): Converted[c.type] = {
val i = c.Expr[Initialize[T]](in)
val t = c.universe.reify(i.splice).tree
Converted.Success(t)
}
private def failTask[C <: blackbox.Context with Singleton](
c: C
)(pos: c.Position): Converted[c.type] =
Converted.Failure(pos, "A setting cannot depend on a task")
private def failPrevious[C <: blackbox.Context with Singleton](
c: C
)(pos: c.Position): Converted[c.type] =
Converted.Failure(pos, "A setting cannot depend on a task's previous value.")
}
object SettingMacro {
import LinterDSL.{ Empty => EmptyLinter }
def settingMacroImpl[T: c.WeakTypeTag](c: blackbox.Context)(t: c.Expr[T]): c.Expr[Initialize[T]] =
Instance.contImpl[T, Id](c, InitializeInstance, InitializeConvert, MixedBuilder, EmptyLinter)(
Left(t),
Instance.idTransform[c.type]
)
def settingDynMacroImpl[T: c.WeakTypeTag](
c: blackbox.Context
)(t: c.Expr[Initialize[T]]): c.Expr[Initialize[T]] =
@ -63,5 +52,6 @@ object SettingMacro {
Right(t),
Instance.idTransform[c.type]
)
}
*/
end SettingMacro

View File

@ -79,16 +79,14 @@ object TaskMacro:
val convert1: Convert[qctx.type] = new FullConvert(qctx)
convert1.contMapN[A1, F, Id](t, convert1.idTransform)
def mkIfS[A1: Type](using
qctx: Quotes
)(t: Expr[A1]): Expr[Initialize[Task[A1]]] =
def mkIfS[A1: Type](t: Expr[A1])(using qctx: Quotes): Expr[Initialize[Task[A1]]] =
t match
case '{ if ($cond) then $thenp else $elsep } =>
'{
Def.ifS[A1](Def.task($cond))(Def.task[A1]($thenp))(Def.task[A1]($elsep))
}
/*
/*
def taskDynMacroImpl[A1: Type](
c: blackbox.Context
)(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[Task[A1]]] =
@ -109,110 +107,126 @@ object TaskMacro:
case x => ContextUtil.unexpectedTree(x)
}
}
*/
/** Implementation of := macro for settings. */
def settingAssignMacroImpl[A1: Type](
c: blackbox.Context
)(v: c.Expr[A1]): c.Expr[Setting[A1]] = {
val init = SettingMacro.settingMacroImpl[A1](c)(v)
val assign = transformMacroImpl(c)(init.tree)(AssignInitName)
c.Expr[Setting[A1]](assign)
}
def settingAssignMacroImpl[A1: Type](rec: Expr[Scoped.DefinableSetting[A1]], v: Expr[A1])(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
val init = SettingMacro.settingMacroImpl[A1](v)
'{
$rec.set($init, $sourcePosition)
}
/** Implementation of := macro for tasks. */
def taskAssignMacroImpl[A1: Type](
c: blackbox.Context
)(v: c.Expr[A1]): c.Expr[Setting[Task[A1]]] = {
val init = taskMacroImpl[A1](c)(v)
val assign = transformMacroImpl(c)(init.tree)(AssignInitName)
c.Expr[Setting[Task[A1]]](assign)
}
def taskAssignMacroImpl[A1: Type](rec: Expr[Scoped.DefinableTask[A1]], v: Expr[A1])(using
qctx: Quotes
): Expr[Setting[Task[A1]]] =
import qctx.reflect.*
val init = taskMacroImpl[A1](v)
'{
$rec.set($init, $sourcePosition)
}
// Error macros (Restligeist)
// These macros are there just so we can fail old operators like `<<=` and provide useful migration information.
def fakeSettingAssignPosition[A1: Type](c: blackbox.Context)(
@deprecated("unused", "") app: c.Expr[Initialize[A1]]
): c.Expr[Setting[A1]] =
ContextUtil.selectMacroImpl[Setting[A1]](c)((_, pos) => c.abort(pos, assignMigration))
def fakeSettingAssignImpl[A1: Type](app: Expr[Initialize[A1]])(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
report.errorAndAbort(TaskMacro.assignMigration)
def fakeSettingAppend1Position[S: Type, V: Type](
c: blackbox.Context
)(@deprecated("unused", "") v: c.Expr[Initialize[V]])(
@deprecated("unused", "") a: c.Expr[Append.Value[S, V]]
): c.Expr[Setting[S]] =
ContextUtil.selectMacroImpl[Setting[S]](c)((_, pos) => c.abort(pos, append1Migration))
def fakeSettingAppend1Position[A1: Type, A2: Type](
@deprecated("unused", "") v: Expr[Initialize[A2]]
)(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
report.errorAndAbort(TaskMacro.append1Migration)
def fakeSettingAppendNPosition[S: Type, V: Type](
c: blackbox.Context
)(@deprecated("unused", "") vs: c.Expr[Initialize[V]])(
@deprecated("unused", "") a: c.Expr[Append.Values[S, V]]
): c.Expr[Setting[S]] =
ContextUtil.selectMacroImpl[Setting[S]](c)((_, pos) => c.abort(pos, appendNMigration))
def fakeSettingAppendNPosition[A1: Type, A2: Type](
@deprecated("unused", "") vs: Expr[Initialize[A2]]
)(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
report.errorAndAbort(TaskMacro.appendNMigration)
def fakeItaskAssignPosition[A1: Type](c: blackbox.Context)(
@deprecated("unused", "") app: c.Expr[Initialize[Task[A1]]]
): c.Expr[Setting[Task[A1]]] =
ContextUtil.selectMacroImpl[Setting[Task[A1]]](c)((_, pos) => c.abort(pos, assignMigration))
def fakeItaskAssignPosition[A1: Type](
@deprecated("unused", "") app: Expr[Initialize[Task[A1]]]
)(using qctx: Quotes): Expr[Setting[Task[A1]]] =
import qctx.reflect.*
report.errorAndAbort(TaskMacro.assignMigration)
def fakeTaskAppend1Position[S: Type, V: Type](
c: blackbox.Context
)(@deprecated("unused", "") v: c.Expr[Initialize[Task[V]]])(
@deprecated("unused", "") a: c.Expr[Append.Value[S, V]]
): c.Expr[Setting[Task[S]]] =
ContextUtil.selectMacroImpl[Setting[Task[S]]](c)((_, pos) => c.abort(pos, append1Migration))
def fakeTaskAppend1Position[A1: Type, A2: Type](
@deprecated("unused", "") v: Expr[Initialize[Task[A2]]]
)(using
qctx: Quotes
): Expr[Setting[Task[A2]]] =
import qctx.reflect.*
report.errorAndAbort(TaskMacro.append1Migration)
def fakeTaskAppendNPosition[S: Type, V: Type](
c: blackbox.Context
)(@deprecated("unused", "") vs: c.Expr[Initialize[Task[V]]])(
@deprecated("unused", "") a: c.Expr[Append.Values[S, V]]
): c.Expr[Setting[Task[S]]] =
ContextUtil.selectMacroImpl[Setting[Task[S]]](c)((_, pos) => c.abort(pos, appendNMigration))
def fakeTaskAppendNPosition[A1: Type, A2: Type](
@deprecated("unused", "") vs: Expr[Initialize[Task[A2]]]
)(using
qctx: Quotes
): Expr[Setting[Task[A1]]] =
import qctx.reflect.*
report.errorAndAbort(TaskMacro.appendNMigration)
/*
// Implementations of <<= macro variations for tasks and settings.
// These just get the source position of the call site.
def itaskAssignPosition[A1: Type](
c: blackbox.Context
def itaskAssignPosition[A1: Type](using
qctx: Quotes
)(app: c.Expr[Initialize[Task[A1]]]): c.Expr[Setting[Task[A1]]] =
settingAssignPosition(c)(app)
def taskAssignPositionT[A1: Type](
c: blackbox.Context
def taskAssignPositionT[A1: Type](using
qctx: Quotes
)(app: c.Expr[Task[A1]]): c.Expr[Setting[Task[A1]]] =
itaskAssignPosition(c)(c.universe.reify { Def.valueStrict(app.splice) })
def taskAssignPositionPure[A1: Type](
c: blackbox.Context
def taskAssignPositionPure[A1: Type](using
qctx: Quotes
)(app: c.Expr[A1]): c.Expr[Setting[Task[A1]]] =
taskAssignPositionT(c)(c.universe.reify { TaskExtra.constant(app.splice) })
def taskTransformPosition[S: Type](
c: blackbox.Context
def taskTransformPosition[S: Type](using
qctx: Quotes
)(f: c.Expr[S => S]): c.Expr[Setting[Task[S]]] =
c.Expr[Setting[Task[S]]](transformMacroImpl(c)(f.tree)(TransformInitName))
def settingTransformPosition[S: Type](
c: blackbox.Context
*/
def settingTransformPosition[A1: Type](rec: Expr[SettingKey[A1]], f: Expr[A1 => A1])(using
qctx: Quotes
): Expr[Setting[A1]] =
'{
$rec.transform($f, $sourcePosition)
}
/*
def itaskTransformPosition[S: Type](using
qctx: Quotes
)(f: c.Expr[S => S]): c.Expr[Setting[S]] =
c.Expr[Setting[S]](transformMacroImpl(c)(f.tree)(TransformInitName))
def itaskTransformPosition[S: Type](
c: blackbox.Context
)(f: c.Expr[S => S]): c.Expr[Setting[S]] =
c.Expr[Setting[S]](transformMacroImpl(c)(f.tree)(TransformInitName))
def settingAssignPure[A1: Type](c: blackbox.Context)(app: c.Expr[A1]): c.Expr[Setting[A1]] =
def settingAssignPure[A1: Type](using
qctx: Quotes)(app: c.Expr[A1]): c.Expr[Setting[A1]] =
settingAssignPosition(c)(c.universe.reify { Def.valueStrict(app.splice) })
def settingAssignPosition[A1: Type](
c: blackbox.Context
def settingAssignPosition[A1: Type](using
qctx: Quotes
)(app: c.Expr[Initialize[A1]]): c.Expr[Setting[A1]] =
c.Expr[Setting[A1]](transformMacroImpl(c)(app.tree)(AssignInitName))
/** Implementation of := macro for tasks. */
def inputTaskAssignMacroImpl[A1: Type](
c: blackbox.Context
def inputTaskAssignMacroImpl[A1: Type](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)
@ -220,42 +234,42 @@ object TaskMacro:
}
/** Implementation of += macro for tasks. */
def taskAppend1Impl[A1: Type, U: Type](
c: blackbox.Context
def taskAppend1Impl[A1: Type, U: Type](using
qctx: Quotes
)(v: c.Expr[U])(a: c.Expr[Append.Value[A1, U]]): c.Expr[Setting[Task[A1]]] = {
val init = taskMacroImpl[U](c)(v)
val append = appendMacroImpl(c)(init.tree, a.tree)(Append1InitName)
c.Expr[Setting[Task[A1]]](append)
}
*/
/** Implementation of += macro for settings. */
def settingAppend1Impl[A1: Type, U: Type](
c: blackbox.Context
)(v: c.Expr[U])(a: c.Expr[Append.Value[A1, U]]): c.Expr[Setting[A1]] = {
import c.universe._
val ttpe = c.weakTypeOf[A1]
val typeArgs = ttpe.typeArgs
v.tree.tpe match {
// To allow Initialize[Task[A]] in the position of += RHS, we're going to call "taskValue" automatically.
case tpe
if typeArgs.nonEmpty && (typeArgs.head weak_<:< c.weakTypeOf[Task[_]])
&& (tpe weak_<:< c.weakTypeOf[Initialize[_]]) =>
c.macroApplication match {
case Apply(Apply(TypeApply(Select(preT, _), _), _), _) =>
val tree = Apply(
TypeApply(Select(preT, TermName("+=").encodedName), TypeTree(typeArgs.head) :: Nil),
Select(v.tree, TermName("taskValue").encodedName) :: Nil
)
c.Expr[Setting[A1]](tree)
case x => ContextUtil.unexpectedTree(x)
}
case _ =>
val init = SettingMacro.settingMacroImpl[U](c)(v)
val append = appendMacroImpl(c)(init.tree, a.tree)(Append1InitName)
c.Expr[Setting[A1]](append)
}
}
def settingAppend1Impl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], v: Expr[A2])(using
qctx: Quotes,
): Expr[Setting[A1]] =
import qctx.reflect.*
// To allow Initialize[Task[A]] in the position of += RHS, we're going to call "taskValue" automatically.
if TypeRepr.of[A2] <:< TypeRepr.of[Def.Initialize[Task[_]]] then
Type.of[A2] match
case '[Def.Initialize[Task[a]]] =>
Expr.summon[Append.Value[A1, Task[a]]] match
case Some(ev) =>
val v2 = v.asExprOf[Def.Initialize[Task[a]]]
'{
$rec.+=($v2.taskValue)(using $ev)
}
case _ =>
report.errorAndAbort(s"Append.Value[${Type.of[A1]}, ${Type.of[Task[a]]}] missing")
else
Expr.summon[Append.Value[A1, A2]] match
case Some(ev) =>
val init = SettingMacro.settingMacroImpl[A2](v)
'{
$rec.append1[A2]($init, $sourcePosition)(using $ev)
}
case _ => report.errorAndAbort(s"Append.Value[${Type.of[A1]}, ${Type.of[A2]}] missing")
/*
/** Implementation of ++= macro for tasks. */
def taskAppendNImpl[A1: Type, U: Type](
c: blackbox.Context
@ -264,113 +278,97 @@ object TaskMacro:
val append = appendMacroImpl(c)(init.tree, a.tree)(AppendNInitName)
c.Expr[Setting[Task[A1]]](append)
}
*/
/** Implementation of ++= macro for settings. */
def settingAppendNImpl[A1: Type, U: Type](
c: blackbox.Context
)(vs: c.Expr[U])(a: c.Expr[Append.Values[A1, U]]): c.Expr[Setting[A1]] = {
val init = SettingMacro.settingMacroImpl[U](c)(vs)
val append = appendMacroImpl(c)(init.tree, a.tree)(AppendNInitName)
c.Expr[Setting[A1]](append)
}
def settingAppendNImpl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], vs: Expr[A2])(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
Expr.summon[Append.Values[A1, A2]] match
case Some(ev) =>
val init = SettingMacro.settingMacroImpl[A2](vs)
'{
$rec.appendN($init, $sourcePosition)(using $ev)
}
case _ => report.errorAndAbort(s"Append.Values[${Type.of[A1]}, ${Type.of[A2]}] missing")
/*
/** Implementation of -= macro for tasks. */
def taskRemove1Impl[A1: Type, U: Type](
c: blackbox.Context
def taskRemove1Impl[A1: Type, U: Type](using
qctx: Quotes
)(v: c.Expr[U])(r: c.Expr[Remove.Value[A1, U]]): c.Expr[Setting[Task[A1]]] = {
val init = taskMacroImpl[U](c)(v)
val remove = removeMacroImpl(c)(init.tree, r.tree)(Remove1InitName)
c.Expr[Setting[Task[A1]]](remove)
}
*/
/** Implementation of -= macro for settings. */
def settingRemove1Impl[A1: Type, U: Type](
c: blackbox.Context
)(v: c.Expr[U])(r: c.Expr[Remove.Value[A1, U]]): c.Expr[Setting[A1]] = {
val init = SettingMacro.settingMacroImpl[U](c)(v)
val remove = removeMacroImpl(c)(init.tree, r.tree)(Remove1InitName)
c.Expr[Setting[A1]](remove)
}
def settingRemove1Impl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], v: Expr[A2])(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
Expr.summon[Remove.Value[A1, A2]] match
case Some(ev) =>
val init = SettingMacro.settingMacroImpl[A2](v)
'{
$rec.remove1[A2]($init, $sourcePosition)(using $ev)
}
case _ => report.errorAndAbort(s"Remove.Value[${Type.of[A1]}, ${Type.of[A2]}] missing")
/*
/** Implementation of --= macro for tasks. */
def taskRemoveNImpl[A1: Type, U: Type](
c: blackbox.Context
def taskRemoveNImpl[A1: Type, U: Type](using
qctx: Quotes
)(vs: c.Expr[U])(r: c.Expr[Remove.Values[A1, U]]): c.Expr[Setting[Task[A1]]] = {
val init = taskMacroImpl[U](c)(vs)
val remove = removeMacroImpl(c)(init.tree, r.tree)(RemoveNInitName)
c.Expr[Setting[Task[A1]]](remove)
}
*/
/** Implementation of --= macro for settings. */
def settingRemoveNImpl[A1: Type, U: Type](
c: blackbox.Context
)(vs: c.Expr[U])(r: c.Expr[Remove.Values[A1, U]]): c.Expr[Setting[A1]] = {
val init = SettingMacro.settingMacroImpl[U](c)(vs)
val remove = removeMacroImpl(c)(init.tree, r.tree)(RemoveNInitName)
c.Expr[Setting[A1]](remove)
}
def settingRemoveNImpl[A1: Type, A2: Type](rec: Expr[SettingKey[A1]], vs: Expr[A2])(using
qctx: Quotes
): Expr[Setting[A1]] =
import qctx.reflect.*
Expr.summon[Remove.Values[A1, A2]] match
case Some(ev) =>
val init = SettingMacro.settingMacroImpl[A2](vs)
'{
$rec.removeN[A2]($init, $sourcePosition)(using $ev)
}
case _ => report.errorAndAbort(s"Remove.Values[${Type.of[A1]}, ${Type.of[A2]}] missing")
private[A1his] def appendMacroImpl(
c: blackbox.Context
)(init: c.Tree, append: c.Tree)(newName: String): c.Tree = {
import c.universe._
c.macroApplication match {
case Apply(Apply(TypeApply(Select(preT, _), targs), _), _) =>
Apply(
Apply(
TypeApply(Select(preT, TermName(newName).encodedName), targs),
init :: sourcePosition(c).tree :: Nil
),
append :: Nil
)
case x => ContextUtil.unexpectedTree(x)
}
}
private[A1his] def removeMacroImpl(
c: blackbox.Context
)(init: c.Tree, remove: c.Tree)(newName: String): c.Tree = {
import c.universe._
c.macroApplication match {
case Apply(Apply(TypeApply(Select(preT, _), targs), _), _) =>
Apply(
Apply(
TypeApply(Select(preT, TermName(newName).encodedName), targs),
init :: sourcePosition(c).tree :: Nil
),
remove :: Nil
)
case x => ContextUtil.unexpectedTree(x)
}
}
private[A1his] def transformMacroImpl(c: blackbox.Context)(init: c.Tree)(
/*
private[this] def transformMacroImpl[A](using qctx: Quotes)(init: Expr[A])(
newName: String
): c.Tree = {
import c.universe._
val target =
c.macroApplication match {
case Apply(Select(prefix, _), _) => prefix
case x => ContextUtil.unexpectedTree(x)
}
): qctx.reflect.Term = {
import qctx.reflect.*
// val target =
// c.macroApplication match {
// case Apply(Select(prefix, _), _) => prefix
// case x => ContextUtil.unexpectedTree(x)
// }
Apply.apply(
Select(target, TermName(newName).encodedName),
init :: sourcePosition(c).tree :: Nil
Select(This, TermName(newName).encodedName),
init.asTerm :: sourcePosition.asTerm :: Nil
)
}
*/
private[A1his] def sourcePosition(c: blackbox.Context): c.Expr[SourcePosition] = {
import c.universe.reify
val pos = c.enclosingPosition
if (!pos.isInstanceOf[UndefinedPosition] && pos.line >= 0 && pos.source != null) {
val f = pos.source.file
val name = constant[String](c, settingSource(c, f.path, f.name))
val line = constant[Int](c, pos.line)
reify { LinePosition(name.splice, line.splice) }
} else reify { NoPosition }
}
private[this] def sourcePosition(using qctx: Quotes): Expr[SourcePosition] =
import qctx.reflect.*
val pos = Position.ofMacroExpansion
if pos.startLine >= 0 && pos.sourceCode != None then
val name = Expr(pos.sourceCode.get)
val line = Expr(pos.startLine)
'{ LinePosition($name, $line) }
else '{ NoPosition }
private[A1his] def settingSource(c: blackbox.Context, path: String, name: String): String = {
/*
private[this] def settingSource(c: blackbox.Context, path: String, name: String): String = {
@tailrec def inEmptyPackage(s: c.Symbol): Boolean = s != c.universe.NoSymbol && (
s.owner == c.mirror.EmptyPackage || s.owner == c.mirror.EmptyPackageClass || inEmptyPackage(
s.owner
@ -383,7 +381,7 @@ object TaskMacro:
}
}
private[A1his] def constant[A1: c.TypeTag](c: blackbox.Context, t: T): c.Expr[A1] = {
private[this] def constant[A1: c.TypeTag](c: blackbox.Context, t: T): c.Expr[A1] = {
import c.universe._
c.Expr[A1](Literal(Constant(t)))
}
@ -398,7 +396,7 @@ object TaskMacro:
)(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[InputTask[A1]]] =
inputTaskDynMacro0[A1](c)(t)
private[A1his] def inputTaskMacro0[A1: Type](
private[this] def inputTaskMacro0[A1: Type](
c: blackbox.Context
)(t: c.Expr[A1]): c.Expr[Initialize[InputTask[A1]]] =
iInitializeMacro(c)(t) { et =>
@ -408,7 +406,7 @@ object TaskMacro:
c.universe.reify { InputTask.make(pt.splice) }
}
private[A1his] def iInitializeMacro[M[_], T](c: blackbox.Context)(t: c.Expr[A1])(
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
@ -420,7 +418,7 @@ object TaskMacro:
)
}
private[A1his] def conditionInputTaskTree(c: blackbox.Context)(t: c.Tree): c.Tree = {
private[this] def conditionInputTaskTree(c: blackbox.Context)(t: c.Tree): c.Tree = {
import c.universe._
import InputWrapper._
def wrapInitTask[A1: Type](tree: Tree) = {
@ -453,7 +451,7 @@ object TaskMacro:
util.transformWrappers(t, (nme, tpe, tree, original) => expand(nme, tpe, tree))
}
private[A1his] def iParserMacro[M[_], T](c: blackbox.Context)(t: c.Expr[A1])(
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
@ -463,7 +461,7 @@ object TaskMacro:
)
}
private[A1his] def iTaskMacro[A1: Type](
private[this] def iTaskMacro[A1: Type](
c: blackbox.Context
)(t: c.Expr[A1]): c.Expr[Task[A1]] =
Instance
@ -472,7 +470,7 @@ object TaskMacro:
Instance.idTransform
)
private[A1his] def inputTaskDynMacro0[A1: Type](
private[this] def inputTaskDynMacro0[A1: Type](
c: blackbox.Context
)(t: c.Expr[Initialize[Task[A1]]]): c.Expr[Initialize[InputTask[A1]]] = {
import c.universe.{ Apply => ApplyTree, _ }
@ -554,7 +552,7 @@ object TaskMacro:
inputTaskCreateFree(tag.tpe, init)
}
}
*/
*/
end TaskMacro

View File

@ -59,27 +59,29 @@ object Assign {
/* def azy = sk.value
def azy2 = appmacro.Debug.checkWild(Def.task{ sk.value.size })
*/
val settings = Seq(
ak += z.value + (if(y.value) set.value else plain.value),
ck := new File(ck.value, "asdf"),
ak := sk.value.size,
bk ++= Seq(z.value)
)*/
// ak += z.value + (if (y.value) set.value else plain.value),
ck := new File(ck.value, "asdf"),
ak := sk.value.size,
// bk ++= Seq(z.value)
)
val zz = Def.task {
mk.value + tk.value + mk.value + tk.value + mk.value + tk.value + mk.value + tk.value + mk.value + tk.value + mk.value + tk.value
}
// import DefaultParsers._
// val p = Def.setting { name.value ~> Space ~> ID }
// val is = Seq(
// mk := 3,
// name := "asdf",
// tk := (math.random() * 1000).toInt,
// isk := dummys.value.parsed // should not compile: cannot use a task to define the parser
// // ik := { if( tsk.parsed.value == "blue") tk.value else mk.value }
// )
import DefaultParsers._
val p = Def.setting { name.value ~> Space ~> ID }
val is = Seq(
mk := 3,
name := "asdf",
// name <<= name,
tk := (math.random() * 1000).toInt,
// isk := dummys.value.parsed, // should not compile: cannot use a task to define the parser
// ik := { if (tsk.parsed.value == "blue") tk.value else mk.value }
)
// val it1 = Def.inputTask {
// tsk.parsed // "as" //dummy.value.parsed
@ -126,6 +128,8 @@ object Assign {
// seqSetting += "test4"
// listSetting := List("test1")
// listSetting ++= List("test2")
// listSetting += "test4"
listSetting ++= List("test2")
listSetting += "test4"
listSetting ~= { (xs) => xs }
}