@@ -32,7 +32,7 @@ prints it again in an error message if it evaluates to `false`.
32
32
~ assertImpl(’(expr))
33
33
34
34
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 }") }
36
36
37
37
38
38
If ` e ` is an expression, then ` ’(e) ` or ` ’{e} ` represent the typed
@@ -490,14 +490,14 @@ is defined in the companion object of class `Expr` as follows:
490
490
The conversion says that values of types implementing the ` Liftable `
491
491
type class can be converted ("lifted") automatically to ` Expr `
492
492
values. Dotty comes with instance definitions of ` Liftable ` for
493
- several types including all underlying types of literals. For example,
494
- ` Int ` values can be converted to ` Expr[Int] ` values by wrapping the
495
- value in a ` Literal ` tree node. This makes use of the underlying tree
496
- representation in the compiler for efficiency. But the ` Liftable `
497
- instances are nevertheless not "magic" in the sense that they could
498
- all be defined in a user program without knowing anything about the
499
- representation of ` Expr ` trees. For instance, here is a possible
500
- instance of ` Liftable[Boolean] ` :
493
+ several types including ` Boolean ` , ` String ` , and all primitive number
494
+ types. For example, ` Int ` values can be converted to ` Expr[Int] `
495
+ values by wrapping the value in a ` Literal ` tree node. This makes use
496
+ of the underlying tree representation in the compiler for
497
+ efficiency. But the ` Liftable ` instances are nevertheless not "magic"
498
+ in the sense that they could all be defined in a user program without
499
+ knowing anything about the representation of ` Expr ` trees. For
500
+ instance, here is a possible instance of ` Liftable[Boolean] ` :
501
501
502
502
implicit def BooleanIsLiftable: Liftable[Boolean] = new {
503
503
implicit def toExpr(b: Boolean) = if (b) ’(true) else ’(false)
@@ -531,6 +531,16 @@ In the end, `Liftable` resembles very much a serialization
531
531
framework. Like the latter it can be derived systematically for all
532
532
collections, case classes and enums.
533
533
534
+ In fact, the initial example of assertions also uses a lifting conversion under the hood.
535
+ Recall the failure clause:
536
+
537
+ throw new AssertionError(s"failed assertion: ${~expr.toString}") }
538
+
539
+ Here, ` expr.toString ` yields ` expr ` 's representation in String form. That string
540
+ is lifted to an ` Expr[String] ` since the required type of a splice argument is an ` Expr ` .
541
+ The lifted result is then spliced in into the ` AssertionError ` argument, giving
542
+ back again the original string representation of ` expr ` .
543
+
534
544
## Implementation
535
545
536
546
### Syntax changes
@@ -602,9 +612,9 @@ The syntax of terms, values, and types is given as follows:
602
612
~t splice
603
613
604
614
Values v ::= (x: T) => t lambda
605
- ’q pure quote
615
+ ’u quote
606
616
607
- Quoted q ::= x | (x: T) => q | q q | ’t
617
+ Simple terms u ::= x | (x: T) => u | u u | ’t
608
618
609
619
Types T ::= A base type
610
620
T -> T function type
@@ -634,7 +644,7 @@ We define a small step reduction relation `-->` with the following rules:
634
644
635
645
((x: T) => t) v --> [x := v]t
636
646
637
- ~(’t ) --> t
647
+ ~(’u ) --> u
638
648
639
649
t1 --> t2
640
650
-----------------
@@ -647,7 +657,7 @@ position of an evaluation context. Evaluation contexts `e` and
647
657
splice evaluation context ` e_s ` are defined syntactically as follows:
648
658
649
659
Eval context e ::= [ ] | e t | v e | ’e_s[~e]
650
- Splice context e_s ::= [ ] | (x: T) => e_s | e_s t | q e_s
660
+ Splice context e_s ::= [ ] | (x: T) => e_s | e_s t | u e_s
651
661
652
662
### Typing rules
653
663
0 commit comments