@@ -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
@@ -491,14 +491,14 @@ is defined in the companion object of class `Expr` as follows:
491
491
The conversion says that values of types implementing the ` Liftable `
492
492
type class can be converted ("lifted") automatically to ` Expr `
493
493
values. 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] ` :
502
502
503
503
implicit def BooleanIsLiftable: Liftable[Boolean] = new {
504
504
implicit def toExpr(b: Boolean) = if (b) ’(true) else ’(false)
@@ -532,6 +532,16 @@ In the end, `Liftable` resembles very much a serialization
532
532
framework. Like the latter it can be derived systematically for all
533
533
collections, case classes and enums.
534
534
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
+
535
545
## Implementation
536
546
537
547
### Syntax changes
@@ -603,9 +613,9 @@ The syntax of terms, values, and types is given as follows:
603
613
~t splice
604
614
605
615
Values v ::= (x: T) => t lambda
606
- ’q pure quote
616
+ ’u quote
607
617
608
- Quoted q ::= x | (x: T) => q | q q | ’t
618
+ Simple terms u ::= x | (x: T) => u | u u | ’t
609
619
610
620
Types T ::= A base type
611
621
T -> T function type
@@ -635,7 +645,7 @@ We define a small step reduction relation `-->` with the following rules:
635
645
636
646
((x: T) => t) v --> [x := v]t
637
647
638
- ~(’t ) --> t
648
+ ~(’u ) --> u
639
649
640
650
t1 --> t2
641
651
-----------------
@@ -648,7 +658,7 @@ position of an evaluation context. Evaluation contexts `e` and
648
658
splice evaluation context ` e_s ` are defined syntactically as follows:
649
659
650
660
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
652
662
653
663
### Typing rules
654
664
0 commit comments