@@ -32,7 +32,7 @@ prints it again in an error message if it evaluates to `false`.
3232 ~ assertImpl(’(expr))
3333
3434 def assertImpl(expr: Expr[Boolean]) =
35- ’{ if !(~expr) then throw new AssertionError(s"failed assertion: ${~expr}") }
35+ ’{ if !(~expr) then throw new AssertionError(s"failed assertion: ${~expr.toString }") }
3636
3737
3838If ` e ` is an expression, then ` ’(e) ` or ` ’{e} ` represent the typed
@@ -491,14 +491,14 @@ is defined in the companion object of class `Expr` as follows:
491491The conversion says that values of types implementing the ` Liftable `
492492type class can be converted ("lifted") automatically to ` Expr `
493493values. Dotty comes with instance definitions of ` Liftable ` for
494- several types including all underlying types of literals. For example,
495- ` Int ` values can be converted to ` Expr[Int] ` values by wrapping the
496- value in a ` Literal ` tree node. This makes use of the underlying tree
497- representation in the compiler for efficiency. But the ` Liftable `
498- instances are nevertheless not "magic" in the sense that they could
499- all be defined in a user program without knowing anything about the
500- representation of ` Expr ` trees. For instance, here is a possible
501- instance of ` Liftable[Boolean] ` :
494+ several types including ` Boolean ` , ` String ` , and all primitive number
495+ types. For example, ` Int ` values can be converted to ` Expr[Int] `
496+ values by wrapping the value in a ` Literal ` tree node. This makes use
497+ of the underlying tree representation in the compiler for
498+ efficiency. But the ` Liftable ` instances are nevertheless not "magic"
499+ in the sense that they could all be defined in a user program without
500+ knowing anything about the representation of ` Expr ` trees. For
501+ instance, here is a possible instance of ` Liftable[Boolean] ` :
502502
503503 implicit def BooleanIsLiftable: Liftable[Boolean] = new {
504504 implicit def toExpr(b: Boolean) = if (b) ’(true) else ’(false)
@@ -532,6 +532,16 @@ In the end, `Liftable` resembles very much a serialization
532532framework. Like the latter it can be derived systematically for all
533533collections, case classes and enums.
534534
535+ In fact, the initial example of assertions also uses a lifting conversion under the hood.
536+ Recall the failure clause:
537+
538+ throw new AssertionError(s"failed assertion: ${~expr.toString}") }
539+
540+ Here, ` expr.toString ` yields ` expr ` 's representation in String form. That string
541+ is lifted to an ` Expr[String] ` since the required type of a splice argument is an ` Expr ` .
542+ The lifted result is then spliced in into the ` AssertionError ` argument, giving
543+ back again the original string representation of ` expr ` .
544+
535545## Implementation
536546
537547### Syntax changes
@@ -603,9 +613,9 @@ The syntax of terms, values, and types is given as follows:
603613 ~t splice
604614
605615 Values v ::= (x: T) => t lambda
606- ’q pure quote
616+ ’u quote
607617
608- Quoted q ::= x | (x: T) => q | q q | ’t
618+ Simple terms u ::= x | (x: T) => u | u u | ’t
609619
610620 Types T ::= A base type
611621 T -> T function type
@@ -635,7 +645,7 @@ We define a small step reduction relation `-->` with the following rules:
635645
636646 ((x: T) => t) v --> [x := v]t
637647
638- ~(’t ) --> t
648+ ~(’u ) --> u
639649
640650 t1 --> t2
641651 -----------------
@@ -648,7 +658,7 @@ position of an evaluation context. Evaluation contexts `e` and
648658splice evaluation context ` e_s ` are defined syntactically as follows:
649659
650660 Eval context e ::= [ ] | e t | v e | ’e_s[~e]
651- Splice context e_s ::= [ ] | (x: T) => e_s | e_s t | q e_s
661+ Splice context e_s ::= [ ] | (x: T) => e_s | e_s t | u e_s
652662
653663### Typing rules
654664
0 commit comments