@@ -422,41 +422,121 @@ import scala.quoted._
422
422
423
423
424
424
object DiagrammedExprMacro {
425
+ def let [S : Type , T ](expr : Expr [S ])(body : Expr [S ] => Expr [T ]): Expr [T ] =
426
+ ' {
427
+ val x = ~ expr
428
+ ~ body('(x))
429
+ }
430
+
431
+ def lets [S : Type , T ](xs : List [Expr [S ]])(body : List [Expr [S ]] => Expr [T ]): Expr [T ] = {
432
+ def rec (xs : List [Expr [S ]], acc : List [Expr [S ]]): Expr [T ] = xs match {
433
+ case Nil => body(acc)
434
+ case x :: xs => let(x) { (x : Expr [S ]) => rec(xs, x :: acc) }
435
+ }
436
+ rec(xs, Nil )
437
+ }
425
438
426
439
// Transform the input expression by parsing out the anchor and generate expression that can support diagram rendering
427
- def parse ( condition : Expr [Boolean ])(implicit refl : Reflection ): Expr [DiagrammedExpr [Boolean ]] = {
440
+ def parse [ T : Type ]( expr : Expr [T ])(implicit refl : Reflection ): Expr [DiagrammedExpr [T ]] = {
428
441
import refl ._
429
442
import quoted .Toolbox .Default ._
430
443
import Term ._
431
444
432
445
def isXmlSugar (apply : Apply ): Boolean = apply.tpe <:< typeOf[scala.xml.Elem ]
433
446
def isJavaStatic (tree : Tree ): Boolean = tree.symbol.flags.is(Flags .Static )
434
447
435
- condition .unseal match {
436
- case Apply (Select (New (_), _), _) => simpleExpr(condition ) // delegate to simpleExpr if it is a New expression
437
- case IsApply (apply) if isXmlSugar(apply) => simpleExpr(condition )
438
- case IsApply (apply) if isJavaStatic(apply) => simpleExpr(condition )
439
- case IsApply (apply) => applyExpr(condition ) // delegate to applyExpr if it is Apply
440
- case IsTypeApply (apply) => applyExpr(condition ) // delegate to applyExpr if it is Apply
441
- case Select (This (_), _) => simpleExpr(condition ) // delegate to simpleExpr if it is a Select for this, e.g. referring a to instance member.
442
- case IsSelect (x) if x.symbol.flags.is(Flags .Object ) => simpleExpr(condition ) // don't traverse packages
443
- case IsSelect (x) if isJavaStatic(x) => simpleExpr(condition )
444
- case IsSelect (select) => selectExpr(condition ) // delegate to selectExpr if it is a Select
448
+ expr .unseal match {
449
+ case Apply (Select (New (_), _), _) => simpleExpr(expr ) // delegate to simpleExpr if it is a New expression
450
+ case IsApply (apply) if isXmlSugar(apply) => simpleExpr(expr )
451
+ case IsApply (apply) if isJavaStatic(apply) => simpleExpr(expr )
452
+ case IsApply (apply) => applyExpr(expr ) // delegate to applyExpr if it is Apply
453
+ case IsTypeApply (apply) => applyExpr(expr ) // delegate to applyExpr if it is Apply
454
+ case Select (This (_), _) => simpleExpr(expr ) // delegate to simpleExpr if it is a Select for this, e.g. referring a to instance member.
455
+ case IsSelect (x) if x.symbol.flags.is(Flags .Object ) => simpleExpr(expr ) // don't traverse packages
456
+ case IsSelect (x) if isJavaStatic(x) => simpleExpr(expr )
457
+ case IsSelect (select) => selectExpr(expr ) // delegate to selectExpr if it is a Select
445
458
case Block (stats, expr) =>
446
- Block (stats, parse(expr.seal[Boolean ]).unseal).seal[DiagrammedExpr [Boolean ]] // call parse recursively using the expr argument if it is a block
447
- case _ => simpleExpr(condition ) // for others, just delegate to simpleExpr
459
+ Block (stats, parse(expr.seal[T ]).unseal).seal[DiagrammedExpr [T ]] // call parse recursively using the expr argument if it is a block
460
+ case _ => simpleExpr(expr ) // for others, just delegate to simpleExpr
448
461
}
449
462
}
450
463
451
- def applyExpr (condition : Expr [Boolean ])(implicit refl : Reflection ): Expr [DiagrammedExpr [Boolean ]] = ???
452
- def selectExpr (condition : Expr [Boolean ])(implicit refl : Reflection ): Expr [DiagrammedExpr [Boolean ]] = ???
464
+ def applyExpr [T : Type ](expr : Expr [T ])(implicit refl : Reflection ): Expr [DiagrammedExpr [T ]] = {
465
+ import refl ._
466
+ import quoted .Toolbox .Default ._
467
+ import Term ._
468
+
469
+ def apply (l : Expr [_], name : String , r : List [Expr [_]]): Expr [T ] = ???
470
+
471
+ expr.unseal.underlyingArgument match {
472
+ case Term .Apply (Term .Select (lhs, op), rhs :: Nil ) =>
473
+ op match {
474
+ case " ||" | " |" =>
475
+ val left = parse(lhs.seal[T & Boolean ])
476
+ val right = parse(rhs.seal[T & Boolean ])
477
+ ' {
478
+ val l = ~ left
479
+ val r = ~ right
480
+ if (l.value) l
481
+ else DiagrammedExpr .applyExpr(l, r :: Nil , r.value, ~ getAnchor(expr))
482
+ }
483
+ case " &&" | " &" =>
484
+ val left = parse(lhs.seal[T & Boolean ])
485
+ val right = parse(rhs.seal[T & Boolean ])
486
+ ' {
487
+ val l = ~ left
488
+ val r = ~ right
489
+ if (l.value) DiagrammedExpr .applyExpr(l, r :: Nil , r.value, ~ getAnchor(expr))
490
+ else l
491
+ }
492
+ case _ =>
493
+ val left = parse(lhs.seal[Any ])
494
+ val right = parse(rhs.seal[Any ])
495
+ ' {
496
+ val l = ~ left
497
+ val r = ~ right
498
+ val res = ~ apply('(l.value), op, ' (r.value) :: Nil )
499
+ DiagrammedExpr .applyExpr(l, r :: Nil , res, ~ getAnchor(expr))
500
+ }
501
+ }
502
+ case Term .Apply (Term .Select (lhs, op), args) =>
503
+ val left = parse(lhs.seal[Any ])
504
+ val rights = args.map(arg => parse(arg.seal[Any ]))
505
+
506
+ let(left) { (l : Expr [DiagrammedExpr [_]]) =>
507
+ lets(rights) { (rs : List [Expr [DiagrammedExpr [_]]]) =>
508
+ val res = apply('((~l).value), op, rs)
509
+ ' { DiagrammedExpr .applyExpr(~ l, ~ rs.toExprOfList, ~ res, ~ getAnchor(expr)) }
510
+ }
511
+ }
512
+ case _ =>
513
+ simpleExpr(expr)
514
+ }
515
+ }
516
+
517
+ def selectExpr [T : Type ](expr : Expr [T ])(implicit refl : Reflection ): Expr [DiagrammedExpr [T ]] = {
518
+ import refl ._
519
+ import quoted .Toolbox .Default ._
520
+ import Term ._
521
+
522
+ def selectField (o : Expr [_], name : String ): Expr [T ] = ???
523
+
524
+ expr.unseal match {
525
+ case Select (qual, name) =>
526
+ val obj = parse(qual.seal[Any ])
527
+
528
+ ' {
529
+ val o = ~ obj
530
+ DiagrammedExpr .selectExpr(o, ~ selectField('(o.value), name), ~getAnchor(expr))
531
+ }
532
+ }
533
+ }
453
534
454
535
def transform (
455
- helper: Expr [(DiagrammedExpr [Boolean ], Any , String , source.Position ) => Assertion ],
536
+ helper : Expr [(DiagrammedExpr [Boolean ], Any , String , source.Position ) => Assertion ],
456
537
condition : Expr [Boolean ], prettifier : Expr [Prettifier ],
457
538
pos : Expr [source.Position ], clue : Expr [Any ], sourceText : String
458
- )
459
- (implicit refl : Reflection ): Expr [Assertion ] = ???
539
+ )(implicit refl : Reflection ): Expr [Assertion ] = ???
460
540
461
541
462
542
/**
0 commit comments