Skip to content

Use Values to create and match value Exprs #10673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ object FieldsImpl:
val projectsTree = Term.of(from)
val symbols = TypeTree.of[V].symbol.memberMethods.filter(isProjectField)
val selects = symbols.map(Select(projectsTree, _).asExprOf[T])
'{ println(${Expr(retType.show)}); ${Varargs(selects)} }
'{ println(${Value(retType.show)}); ${Varargs(selects)} }
2 changes: 1 addition & 1 deletion docs/docs/reference/changed-features/numeric-literals.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ implementation method `fromDigitsImpl`. Here is its definition:
case Some(ds) =>
try {
val BigFloat(m, e) = apply(ds)
'{BigFloat(${Expr(m)}, ${Expr(e)})}
'{BigFloat(${Value(m)}, ${Value(e)})}
}
catch {
case ex: FromDigits.FromDigitsException =>
Expand Down
12 changes: 6 additions & 6 deletions docs/docs/reference/contextual/derivation-macro.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ given derived[T: Type](using Quotes): Expr[Eq[T]] = {
case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} =>
val elemInstances = summonAll[elementTypes]
val eqProductBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => {
elemInstances.zipWithIndex.foldLeft(Expr(true: Boolean)) {
elemInstances.zipWithIndex.foldLeft(Value(true: Boolean)) {
case (acc, (elem, index)) =>
val e1 = '{$x.asInstanceOf[Product].productElement(${Expr(index)})}
val e2 = '{$y.asInstanceOf[Product].productElement(${Expr(index)})}
val e1 = '{$x.asInstanceOf[Product].productElement(${Value(index)})}
val e2 = '{$y.asInstanceOf[Product].productElement(${Value(index)})}

'{ $acc && $elem.asInstanceOf[Eq[Any]].eqv($e1, $e2) }
}
Expand Down Expand Up @@ -185,10 +185,10 @@ object Eq {
case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} =>
val elemInstances = summonAll[elementTypes]
val eqProductBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => {
elemInstances.zipWithIndex.foldLeft(Expr(true: Boolean)) {
elemInstances.zipWithIndex.foldLeft(Value(true: Boolean)) {
case (acc, (elem, index)) =>
val e1 = '{$x.asInstanceOf[Product].productElement(${Expr(index)})}
val e2 = '{$y.asInstanceOf[Product].productElement(${Expr(index)})}
val e1 = '{$x.asInstanceOf[Product].productElement(${Value(index)})}
val e2 = '{$y.asInstanceOf[Product].productElement(${Value(index)})}

'{ $acc && $elem.asInstanceOf[Eq[Any]].eqv($e1, $e2) }
}
Expand Down
24 changes: 12 additions & 12 deletions docs/docs/reference/metaprogramming/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ import scala.quoted._

def compile(e: Exp, env: Map[String, Expr[Int]])(using Quotes): Expr[Int] = e match {
case Num(n) =>
Expr(n)
Value(n)
case Plus(e1, e2) =>
'{ ${ compile(e1, env) } + ${ compile(e2, env) } }
case Var(x) =>
Expand All @@ -259,8 +259,8 @@ Running `compile(letExp, Map())` would yield the following Scala code:
```scala
'{ val y = 3; (2 + y) + 4 }
```
The body of the first clause, `case Num(n) => Expr(n)`, looks suspicious. `n`
is declared as an `Int`, yet it is converted to an `Expr[Int]` with `Expr()`.
The body of the first clause, `case Num(n) => Value(n)`, looks suspicious. `n`
is declared as an `Int`, yet it is converted to an `Expr[Int]` with `Value()`.
Shouldn’t `n` be quoted? In fact this would not
work since replacing `n` by `'n` in the clause would not be phase
correct.
Expand Down Expand Up @@ -312,7 +312,7 @@ a `List` is liftable if its element type is:
```scala
given [T: ToExpr : Type]: ToExpr[List[T]] with
def toExpr(xs: List[T]) = xs match {
case head :: tail => '{ ${ Expr(head) } :: ${ toExpr(tail) } }
case head :: tail => '{ ${ Value(head) } :: ${ toExpr(tail) } }
case Nil => '{ Nil: List[T] }
}
```
Expand All @@ -326,7 +326,7 @@ Using lifting, we can now give the missing definition of `showExpr` in the intro
```scala
def showExpr[T](expr: Expr[T])(using Quotes): Expr[String] = {
val code: String = expr.show
Expr(code)
Value(code)
}
```
That is, the `showExpr` method converts its `Expr` argument to a string (`code`), and lifts
Expand Down Expand Up @@ -375,7 +375,7 @@ object Macros {
${ assertImpl('expr) }

def assertImpl(expr: Expr[Boolean])(using Quotes) =
val failMsg: Expr[String] = Expr("failed assertion: " + expr.show)
val failMsg: Expr[String] = Value("failed assertion: " + expr.show)
'{ if !($expr) then throw new AssertionError($failMsg) }
}

Expand Down Expand Up @@ -641,14 +641,14 @@ These could be used in the following way to optimize any call to `sum` that has
```scala
inline def sum(inline args: Int*): Int = ${ sumExpr('args) }
private def sumExpr(argsExpr: Expr[Seq[Int]])(using Quotes): Expr[Int] = argsExpr match {
case Varargs(args @ Exprs(argValues)) =>
case Varargs(args @ Values(argValues)) =>
// args is of type Seq[Expr[Int]]
// argValues is of type Seq[Int]
Expr(argValues.sum) // precompute result of sum
Value(argValues.sum) // precompute result of sum
case Varargs(argExprs) => // argExprs is of type Seq[Expr[Int]]
val staticSum: Int = argExprs.map(_.value.getOrElse(0))
val dynamicSum: Seq[Expr[Int]] = argExprs.filter(_.value.isEmpty)
dynamicSum.foldLeft(Expr(staticSum))((acc, arg) => '{ $acc + $arg })
dynamicSum.foldLeft(Value(staticSum))((acc, arg) => '{ $acc + $arg })
case _ =>
'{ $argsExpr.sum }
}
Expand All @@ -671,7 +671,7 @@ def sum(args: Int*): Int = args.sum
inline def optimize(inline arg: Int): Int = ${ optimizeExpr('arg) }
private def optimizeExpr(body: Expr[Int])(using Quotes): Expr[Int] = body match {
// Match a call to sum without any arguments
case '{ sum() } => Expr(0)
case '{ sum() } => Value(0)
// Match a call to sum with an argument $n of type Int. n will be the Expr[Int] representing the argument.
case '{ sum($n) } => n
// Match a call to sum and extracts all its args in an `Expr[Seq[Int]]`
Expand All @@ -686,7 +686,7 @@ private def sumExpr(args1: Seq[Expr[Int]])(using Quotes): Expr[Int] = {
val args2 = args1.flatMap(flatSumArgs)
val staticSum: Int = args2.map(_.value.getOrElse(0)).sum
val dynamicSum: Seq[Expr[Int]] = args2.filter(_.value.isEmpty)
dynamicSum.foldLeft(Expr(staticSum))((acc, arg) => '{ $acc + $arg })
dynamicSum.foldLeft(Value(staticSum))((acc, arg) => '{ $acc + $arg })
}
```

Expand Down Expand Up @@ -762,7 +762,7 @@ private def evalExpr(e: Expr[Int])(using Quotes): Expr[Int] = {
evalExpr(Expr.betaReduce(body)(evalExpr(x)))
case '{ ($x: Int) * ($y: Int) } =>
(x.value, y.value) match
case (Some(a), Some(b)) => Expr(a * b)
case (Some(a), Some(b)) => Value(a * b)
case _ => e
case _ => e
}
Expand Down
26 changes: 14 additions & 12 deletions library/src-bootstrapped/scala/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,23 @@ object Expr {
}

/** Creates an expression that will construct the value `x` */
@deprecated("Use `scala.quoted.Value.apply` instead. This will be removed in 3.0.0-RC1", "3.0.0-M3")
def apply[T](x: T)(using ToExpr[T])(using Quotes): Expr[T] =
scala.Predef.summon[ToExpr[T]].apply(x)

/** Get `Some` of a copy of the value if the expression contains a literal constant or constructor of `T`.
* Otherwise returns `None`.
*
* Usage:
* ```
* case '{ ... ${expr @ Expr(value)}: T ...} =>
* // expr: Expr[T]
* // value: T
* ```
*
* To directly get the value of an expression `expr: Expr[T]` consider using `expr.value`/`expr.valueOrError` insead.
*/
* Otherwise returns `None`.
*
* Usage:
* ```
* case '{ ... ${expr @ Expr(value)}: T ...} =>
* // expr: Expr[T]
* // value: T
* ```
*
* To directly get the value of an expression `expr: Expr[T]` consider using `expr.value`/`expr.valueOrError` insead.
*/
@deprecated("Use `scala.quoted.Value.unapply` instead. This will be removed in 3.0.0-RC1", "3.0.0-M3")
def unapply[T](x: Expr[T])(using FromExpr[T])(using Quotes): Option[T] =
scala.Predef.summon[FromExpr[T]].unapply(x)

Expand All @@ -70,7 +72,7 @@ object Expr {
* `'{ List($e1, $e2, ...) }` typed as an `Expr[List[T]]`
*/
def ofList[T](xs: Seq[Expr[T]])(using Type[T])(using Quotes): Expr[List[T]] =
if (xs.isEmpty) Expr(Nil) else '{ List(${Varargs(xs)}: _*) }
if (xs.isEmpty) Value(Nil) else '{ List(${Varargs(xs)}: _*) }

/** Creates an expression that will construct a copy of this tuple
*
Expand Down
Loading