Skip to content

Commit 93d2f1e

Browse files
committed
WIP - support TypeApply
1 parent 055cb5c commit 93d2f1e

File tree

1 file changed

+38
-39
lines changed

1 file changed

+38
-39
lines changed

scalatest.dotty/src/main/scala/org/scalatest/DiagrammedExprMacro.scala

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,10 @@ import scala.quoted._
2121

2222

2323
object DiagrammedExprMacro {
24-
def let[S: Type, T: Type](expr: Expr[S])(body: Expr[S] => Expr[T]): Expr[T] =
25-
'{
26-
val x = $expr
27-
${ body('{x}) }
28-
}
29-
30-
def lets[S: Type, T: Type](xs: List[Expr[S]])(body: List[Expr[S]] => Expr[T]): Expr[T] = {
31-
def rec(xs: List[Expr[S]], acc: List[Expr[S]]): Expr[T] = xs match {
32-
case Nil => body(acc)
33-
case x :: xs => let(x) { (x: Expr[S]) => rec(xs, x :: acc) }
34-
}
35-
rec(xs, Nil)
36-
}
37-
3824
// Transform the input expression by parsing out the anchor and generate expression that can support diagram rendering
3925
def parse[T:Type](expr: Expr[T])(implicit refl: Reflection): Expr[DiagrammedExpr[T]] = {
4026
import refl._
27+
import util._
4128

4229
def isXmlSugar(apply: Apply): Boolean = apply.tpe <:< typeOf[scala.xml.Elem]
4330
def isJavaStatic(tree: Tree): Boolean = tree.symbol.flags.is(Flags.Static)
@@ -49,6 +36,14 @@ object DiagrammedExprMacro {
4936

5037
def default: Expr[DiagrammedExpr[T]] = '{ DiagrammedExpr.simpleExpr($expr, ${ getAnchor(expr) } ) }
5138

39+
def lets(xs: List[Term])(body: List[Term] => Term): Term = {
40+
def rec(xs: List[Term], acc: List[Term]): Term = xs match {
41+
case Nil => body(acc)
42+
case x :: xs => let(x) { (x: Term) => rec(xs, x :: acc) }
43+
}
44+
rec(xs, Nil)
45+
}
46+
5247
expr.unseal.underlyingArgument match {
5348
case Apply(Select(New(_), _), _) => default
5449

@@ -121,41 +116,45 @@ object DiagrammedExprMacro {
121116
case Apply(sel @ Select(lhs, op), args) =>
122117
type S
123118
implicit val tpS: quoted.Type[S] = lhs.tpe.seal.asInstanceOf[quoted.Type[S]]
124-
val left = parse[S](lhs.seal.asInstanceOf[Expr[S]])
119+
val left = parse[S](lhs.seal.asInstanceOf[Expr[S]]).unseal
125120
val anchor = getAnchorForSelect(refl)(sel.asInstanceOf[Select])
126121

127122
val rights = args.map { arg =>
128123
type V
129124
implicit val tpV: quoted.Type[V] = arg.tpe.seal.asInstanceOf[quoted.Type[V]]
130-
parse[V](arg.seal.asInstanceOf[Expr[V]])
125+
parse[V](arg.seal.asInstanceOf[Expr[V]]).unseal
131126
}
132127

133-
let(left) { (l: Expr[DiagrammedExpr[_]]) =>
134-
lets(rights) { (rs: List[Expr[DiagrammedExpr[_]]]) =>
135-
val res = apply('{($l).value}, op, Nil, rs)
136-
'{ DiagrammedExpr.applyExpr($l, ${rs.toExprOfList}, $res, $anchor) }
128+
let(left) { l =>
129+
lets(rights) { rs =>
130+
val left = l.seal.cast[DiagrammedExpr[_]]
131+
val rights = rs.map(_.seal.cast[DiagrammedExpr[_]])
132+
val res = Select.overloaded('{$left.value}.unseal, op, Nil, rs).seal.cast[T]
133+
'{ DiagrammedExpr.applyExpr($left, ${rights.toExprOfList}, $res, $anchor) }.unseal
137134
}
138-
}
135+
}.seal.cast[DiagrammedExpr[T]]
139136

140137
// TODO: Dotty produces a confusing error message about `let`
141-
// case Apply(TypeApply(sel @ Select(lhs, op), targs), args) =>
142-
// type S
143-
// implicit val tpS: quoted.Type[S] = lhs.tpe.seal.asInstanceOf[quoted.Type[S]]
144-
// val left = parse[S](lhs.seal.asInstanceOf[Expr[S]])
145-
// val anchor = getAnchorForSelect(refl)(sel.asInstanceOf[Select])
146-
147-
// val rights = args.map { arg =>
148-
// type V
149-
// implicit val tpV: quoted.Type[V] = arg.tpe.seal.asInstanceOf[quoted.Type[V]]
150-
// parse[V](arg.seal.asInstanceOf[Expr[V]])
151-
// }
152-
153-
// let(left) { (l: Expr[DiagrammedExpr[_]]) =>
154-
// lets(rights) { (rs: List[Expr[DiagrammedExpr[_]]]) =>
155-
// val res = apply('{($l).value}, op, targs, rs)
156-
// '{ DiagrammedExpr.applyExpr($l, ${rs.toExprOfList}, $res, $anchor) }
157-
// }
158-
// }
138+
case Apply(TypeApply(sel @ Select(lhs, op), targs), args) =>
139+
type S
140+
implicit val tpS: quoted.Type[S] = lhs.tpe.seal.asInstanceOf[quoted.Type[S]]
141+
val left = parse[S](lhs.seal.asInstanceOf[Expr[S]]).unseal
142+
val anchor = getAnchorForSelect(refl)(sel.asInstanceOf[Select])
143+
144+
val rights = args.map { arg =>
145+
type V
146+
implicit val tpV: quoted.Type[V] = arg.tpe.seal.asInstanceOf[quoted.Type[V]]
147+
parse[V](arg.seal.asInstanceOf[Expr[V]]).unseal
148+
}
149+
150+
let(left) { l =>
151+
lets(rights) { rs =>
152+
val left = l.seal.cast[DiagrammedExpr[_]]
153+
val rights = rs.map(_.seal.cast[DiagrammedExpr[_]])
154+
val res = Select.overloaded('{$left.value}.unseal, op, targs.map(_.tpe), rs).seal.cast[T]
155+
'{ DiagrammedExpr.applyExpr($left, ${rights.toExprOfList}, $res, $anchor) }.unseal
156+
}
157+
}.seal.cast[DiagrammedExpr[T]]
159158

160159
case _ =>
161160
default

0 commit comments

Comments
 (0)