@@ -356,11 +356,11 @@ again together with a program that calls `assert`.
356356``` scala
357357object Macros {
358358
359- inline def assert (expr : => Boolean ): Unit =
359+ inline def assert (inline expr : Boolean ): Unit =
360360 $ { assertImpl(' expr ) }
361361
362362 def assertImpl (expr : Expr [Boolean ]) =
363- ' { if ! ($expr) then throw new AssertionError (s " failed assertion: ${$ expr} " ) }
363+ ' { if ! ($expr) then throw new AssertionError (" failed assertion: " + $ { expr.show} ) }
364364}
365365
366366object App {
@@ -414,33 +414,26 @@ assume that both definitions are local.
414414
415415The ` inline ` modifier is used to declare a ` val ` that is
416416either a constant or is a parameter that will be a constant when instantiated. This
417- aspect is also important for macro expansion. To illustrate this,
418- consider an implementation of the ` power ` function that makes use of a
419- statically known exponent:
417+ aspect is also important for macro expansion.
418+
419+ To get values out of expressions containing constants ` Expr ` provides the methods
420+ ` value ` (or ` getValue ` ). This will convert the ` Expr[T] ` into a ` T ` (or ` Some[T] ` ) when the
421+ expression contains value. Otherwise it will emit an error (or retrun ` None ` ).
422+ To avoid having incidental val bindings generated by the inlining of the ` def `
423+ it is recomended to use an inline parameter. To illustrate this, consider an
424+ implementation of the ` power ` function that makes use of a statically known exponent:
420425``` scala
421- inline def power (inline n : Int , x : Double ) = $ { powerCode(n, ' x ) }
426+ inline def power (x : Double , inline n : Int ) = $ { powerCode(' x , ' n ) }
427+
428+ private def powerCode (x : Expr [Double ], n : Expr [Int ]): Expr [Double ] =
429+ powerCode(x, n.value) // Transform `n` into an Int or emit an error if it is not possible
422430
423- private def powerCode (n : Int , x : Expr [Double ]): Expr [Double ] =
431+ private def powerCode (x : Expr [Double ], n : Int ): Expr [Double ] =
424432 if (n == 0 ) ' { 1.0 }
425433 else if (n == 1 ) x
426- else if (n % 2 == 0 ) ' { val y = $x * $x; $ { powerCode(n / 2 , ' y ) } }
427- else ' { $x * $ { powerCode(n - 1 , x) } }
428- ```
429- The reference to ` n ` as an argument in ` ${ powerCode(n, 'x) } ` is not
430- phase-consistent, since ` n ` appears in a splice without an enclosing
431- quote. Normally that would be a problem because it means that we need
432- the _ value_ of ` n ` at compile time, which is not available for general
433- parameters. But since ` n ` is an inline parameter of a macro, we know
434- that at the macro’s expansion point ` n ` will be instantiated to a
435- constant, so the value of ` n ` will in fact be known at this
436- point. To reflect this, we loosen the phase consistency requirements
437- as follows:
438-
439- - If ` x ` is a inline value (or a inline parameter of an inline
440- function) of type Boolean, Byte, Short, Int, Long, Float, Double,
441- Char or String, it can be accessed in all contexts where the number
442- of splices minus the number of quotes between use and definition
443- is either 0 or 1.
434+ else if (n % 2 == 0 ) ' { val y = $x * $x; $ { powerCode(' y , n / 2 ) } }
435+ else ' { $x * $ { powerCode(x, n - 1 ) } }
436+ ```
444437
445438### Scope Extrusion
446439
@@ -472,7 +465,7 @@ that invokation of `run` in splices. Consider the following expression:
472465' { (x : Int ) => $ { run(' x ); 1 } }
473466```
474467This is again phase correct, but will lead us into trouble. Indeed, evaluating
475- the splice will reduce the expression ` ('x).run ` to ` x ` . But then the result
468+ the splice will reduce the expression ` run ('x)` to ` x ` . But then the result
476469
477470``` scala
478471' { (x : Int ) => $ { x; 1 } }
@@ -590,9 +583,9 @@ inline method that can calculate either a value of type `Int` or a value of type
590583` String ` .
591584
592585``` scala
593- inline def defaultOf (inline str : String ) <: Any = $ { defaultOfImpl(str) }
586+ inline def defaultOf (inline str : String ) <: Any = $ { defaultOfImpl(' str ) }
594587
595- def defaultOfImpl (str : String ): Expr [Any ] = str match {
588+ def defaultOfImpl (strExpr : Expr [ String ] ): Expr [Any ] = strExpr.value match {
596589 case " int" => ' {1 }
597590 case " string" => ' {" a" }
598591}
@@ -624,8 +617,10 @@ It is possible to deconstruct or extract values out of `Expr` using pattern matc
624617In ` scala.quoted.matching ` contains object that can help extract values from ` Expr ` .
625618
626619* ` scala.quoted.matching.Const ` : matches an expression a literal value and returns the value.
620+ * ` scala.quoted.matching.Value ` : matches an expression a value and returns the value.
627621* ` scala.quoted.matching.ExprSeq ` : matches an explicit sequence of expresions and returns them. These sequences are useful to get individual ` Expr[T] ` out of a varargs expression of type ` Expr[Seq[T]] ` .
628622* ` scala.quoted.matching.ConstSeq ` : matches an explicit sequence of literal values and returns them.
623+ * ` scala.quoted.matching.ValueSeq ` : matches an explicit sequence of values and returns them.
629624
630625These could be used in the following way to optimize any call to ` sum ` that has statically known values.
631626``` scala
@@ -661,7 +656,7 @@ optimize {
661656```
662657
663658``` scala
664- def sum (args : => Int * ): Int = args.sum
659+ def sum (args : Int * ): Int = args.sum
665660inline def optimize (arg : Int ): Int = $ { optimizeExpr(' arg ) }
666661private def optimizeExpr (body : Expr [Int ])(given QuoteContext ): Expr [Int ] = body match {
667662 // Match a call to sum without any arguments
0 commit comments