Skip to content

Commit a4acea0

Browse files
committed
WIP - use refl.Term
1 parent 93d2f1e commit a4acea0

File tree

2 files changed

+81
-83
lines changed

2 files changed

+81
-83
lines changed

project/scalatest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,8 +2133,8 @@ object ScalatestBuild {
21332133

21342134
import dotty.tools.sbtplugin.DottyPlugin.autoImport._
21352135
// List of available night build at https://repo1.maven.org/maven2/ch/epfl/lamp/dotty-compiler_0.14/
2136-
lazy val dottyVersion = dottyLatestNightlyBuild.get
2137-
// lazy val dottyVersion = "0.14.0-bin-20190403-d00a7ba-NIGHTLY"
2136+
// lazy val dottyVersion = dottyLatestNightlyBuild.get
2137+
lazy val dottyVersion = "0.15.0-bin-20190522-ffb250d-NIGHTLY"
21382138
lazy val dottySettings = List(
21392139
scalaVersion := dottyVersion,
21402140
libraryDependencies := libraryDependencies.value.map(_.withDottyCompat(scalaVersion.value)),

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

Lines changed: 79 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,23 @@ import scala.quoted._
2222

2323
object DiagrammedExprMacro {
2424
// Transform the input expression by parsing out the anchor and generate expression that can support diagram rendering
25-
def parse[T:Type](expr: Expr[T])(implicit refl: Reflection): Expr[DiagrammedExpr[T]] = {
25+
def parse(refl: Reflection)(expr: refl.Term): refl.Term = {
2626
import refl._
2727
import util._
2828

29+
type R
30+
implicit val resTp: quoted.Type[R] = expr.tpe.seal.asInstanceOf[quoted.Type[R]]
31+
2932
def isXmlSugar(apply: Apply): Boolean = apply.tpe <:< typeOf[scala.xml.Elem]
3033
def isJavaStatic(tree: Tree): Boolean = tree.symbol.flags.is(Flags.Static)
3134

32-
def apply(l: Expr[_], name: String, targs: List[TypeTree], r: List[Expr[_]]): Expr[T] =
33-
Select.overloaded(l.unseal, name, targs.map(_.tpe), r.map(_.unseal)).seal.cast[T]
35+
def apply(l: Term, name: String, targs: List[TypeTree], args: List[Term]): Term =
36+
Select.overloaded(l, name, targs.map(_.tpe), args)
3437

35-
def selectField(o: Expr[_], name: String): Expr[T] = Select.unique(o.unseal, name).seal.cast[T]
38+
def selectField(o: Term, name: String): Term = Select.unique(o, name)
3639

37-
def default: Expr[DiagrammedExpr[T]] = '{ DiagrammedExpr.simpleExpr($expr, ${ getAnchor(expr) } ) }
40+
def default: Term =
41+
'{ DiagrammedExpr.simpleExpr[R](${expr.seal.cast[R]}, ${ getAnchor(expr) } ) }.unseal
3842

3943
def lets(xs: List[Term])(body: List[Term] => Term): Term = {
4044
def rec(xs: List[Term], acc: List[Term]): Term = xs match {
@@ -44,7 +48,22 @@ object DiagrammedExprMacro {
4448
rec(xs, Nil)
4549
}
4650

47-
expr.unseal.underlyingArgument match {
51+
def getAnchorForSelect(sel: Select): Expr[Int] = {
52+
if (sel.name == "unary_!")
53+
(sel.pos.startColumn - rootPosition.startColumn).toExpr
54+
else {
55+
val selOffset = sel.pos.endColumn - sel.qualifier.pos.endColumn - sel.name.length
56+
(sel.qualifier.pos.endColumn + selOffset - rootPosition.startColumn).toExpr
57+
}
58+
}
59+
60+
def getAnchor(expr: Term): Expr[Int] = {
61+
// -1 to match scala2 position
62+
// ((expr.unseal.pos.endColumn + expr.unseal.pos.startColumn - 1) / 2 - rootPosition.startColumn).toExpr
63+
(expr.pos.startColumn - rootPosition.startColumn).toExpr
64+
}
65+
66+
expr match {
4867
case Apply(Select(New(_), _), _) => default
4968

5069
case IsApply(apply) if isXmlSugar(apply) => default
@@ -58,103 +77,98 @@ object DiagrammedExprMacro {
5877
case IsSelect(x) if isJavaStatic(x) => default
5978

6079
case sel @ Select(qual, name) =>
61-
type S
62-
implicit val tpS: quoted.Type[S] = qual.tpe.seal.asInstanceOf[quoted.Type[S]]
63-
val obj = parse[S](qual.seal.asInstanceOf[Expr[S]])
64-
val anchor = getAnchorForSelect(refl)(sel.asInstanceOf[Select])
80+
type T
81+
implicit val objTp: quoted.Type[T] = qual.tpe.seal.asInstanceOf[quoted.Type[T]]
82+
val obj = parse(refl)(qual).seal.cast[DiagrammedExpr[T]]
83+
val anchor = getAnchorForSelect(sel.asInstanceOf[Select])
6584

6685
'{
6786
val o = $obj
68-
DiagrammedExpr.selectExpr(o, ${ selectField('{o.value}, name) }, $anchor)
69-
}
87+
DiagrammedExpr.selectExpr[R](o, ${ selectField('{o.value}.unseal, name).seal.cast[R] }, $anchor)
88+
}.unseal
7089

7190
case Block(stats, expr) =>
72-
Block(stats, parse(expr.seal.cast[T]).unseal).seal.cast[DiagrammedExpr[T]] // call parse recursively using the expr argument if it is a block
91+
// call parse recursively using the expr argument if it is a block
92+
Block(stats, parse(refl)(expr))
7393

7494
case Apply(sel @ Select(lhs, op), rhs :: Nil) =>
75-
val anchor = getAnchorForSelect(refl)(sel.asInstanceOf[Select])
95+
val anchor = getAnchorForSelect(sel.asInstanceOf[Select])
7696
op match {
7797
case "||" | "|" =>
78-
val left = parse(lhs.seal.cast[Boolean & T])
79-
val right = parse(rhs.seal.cast[Boolean & T])
98+
val left = parse(refl)(lhs).seal.cast[DiagrammedExpr[Boolean]]
99+
val right = parse(refl)(rhs).seal.cast[DiagrammedExpr[Boolean]]
80100

81101
'{
82102
val l = $left
83103
if (l.value) l
84104
else {
85105
val r = $right
86-
DiagrammedExpr.applyExpr(l, r :: Nil, r.value, $anchor)
106+
DiagrammedExpr.applyExpr[Boolean](l, r :: Nil, r.value, $anchor)
87107
}
88-
}
108+
}.unseal
89109
case "&&" | "&" =>
90-
val left = parse(lhs.seal.cast[Boolean & T])
91-
val right = parse(rhs.seal.cast[Boolean & T])
110+
val left = parse(refl)(lhs).seal.cast[DiagrammedExpr[Boolean]]
111+
val right = parse(refl)(rhs).seal.cast[DiagrammedExpr[Boolean]]
92112
'{
93113
val l = $left
94114
if (!l.value) l
95115
else {
96116
val r = $right
97-
DiagrammedExpr.applyExpr(l, r :: Nil, r.value, $anchor)
117+
DiagrammedExpr.applyExpr[Boolean](l, r :: Nil, r.value, $anchor)
98118
}
99-
}
119+
}.unseal
100120
case _ =>
101-
type S
102-
implicit val tpS: quoted.Type[S] = lhs.tpe.seal.asInstanceOf[quoted.Type[S]]
103-
val left = parse[S](lhs.seal.asInstanceOf[Expr[S]])
104-
105-
type V
106-
implicit val tpV: quoted.Type[V] = rhs.tpe.seal.asInstanceOf[quoted.Type[V]]
107-
val right = parse[V](rhs.seal.asInstanceOf[Expr[V]])
108-
'{
109-
val l = $left
110-
val r = $right
111-
val res = ${ apply('{l.value}, op, Nil, '{r.value} :: Nil) }
112-
DiagrammedExpr.applyExpr(l, r :: Nil, res, $anchor)
121+
type T
122+
implicit val tpT: quoted.Type[T] = lhs.tpe.seal.asInstanceOf[quoted.Type[T]]
123+
val left = parse(refl)(lhs)
124+
125+
val right = parse(refl)(rhs)
126+
127+
let(left) { l =>
128+
let(right) { r =>
129+
val left = l.seal.cast[DiagrammedExpr[T]]
130+
val right = r.seal.cast[DiagrammedExpr[_]]
131+
val res = apply('{$left.value}.unseal, op, Nil, '{$right.value}.unseal :: Nil).seal.cast[R]
132+
'{ DiagrammedExpr.applyExpr[R]($left, $right :: Nil, $res, $anchor) }.unseal
133+
}
113134
}
114135
}
115136

116137
case Apply(sel @ Select(lhs, op), args) =>
117-
type S
118-
implicit val tpS: quoted.Type[S] = lhs.tpe.seal.asInstanceOf[quoted.Type[S]]
119-
val left = parse[S](lhs.seal.asInstanceOf[Expr[S]]).unseal
120-
val anchor = getAnchorForSelect(refl)(sel.asInstanceOf[Select])
121-
122-
val rights = args.map { arg =>
123-
type V
124-
implicit val tpV: quoted.Type[V] = arg.tpe.seal.asInstanceOf[quoted.Type[V]]
125-
parse[V](arg.seal.asInstanceOf[Expr[V]]).unseal
126-
}
138+
type T
139+
implicit val tpT: quoted.Type[T] = lhs.tpe.seal.asInstanceOf[quoted.Type[T]]
140+
141+
val left = parse(refl)(lhs)
142+
val anchor = getAnchorForSelect(sel.asInstanceOf[Select])
143+
144+
val rights = args.map { arg => parse(refl)(arg) }
127145

128146
let(left) { l =>
129147
lets(rights) { rs =>
130-
val left = l.seal.cast[DiagrammedExpr[_]]
148+
val left = l.seal.cast[DiagrammedExpr[T]]
131149
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
150+
val res = Select.overloaded('{$left.value}.unseal, op, Nil, rs).seal.cast[R]
151+
'{ DiagrammedExpr.applyExpr[R]($left, ${rights.toExprOfList}, $res, $anchor) }.unseal
134152
}
135-
}.seal.cast[DiagrammedExpr[T]]
153+
}
136154

137-
// TODO: Dotty produces a confusing error message about `let`
138155
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-
}
156+
type T
157+
implicit val tpT: quoted.Type[T] = lhs.tpe.seal.asInstanceOf[quoted.Type[T]]
158+
159+
val left = parse(refl)(lhs)
160+
val anchor = getAnchorForSelect(sel.asInstanceOf[Select])
161+
162+
val rights = args.map { arg => parse(refl)(arg) }
149163

150164
let(left) { l =>
151165
lets(rights) { rs =>
152-
val left = l.seal.cast[DiagrammedExpr[_]]
166+
val left = l.seal.cast[DiagrammedExpr[T]]
153167
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
168+
val res = Select.overloaded('{$left.value}.unseal, op, targs.map(_.tpe), rs).seal.cast[R]
169+
'{ DiagrammedExpr.applyExpr[R]($left, ${rights.toExprOfList}, $res, $anchor) }.unseal
156170
}
157-
}.seal.cast[DiagrammedExpr[T]]
171+
}
158172

159173
case _ =>
160174
default
@@ -165,24 +179,8 @@ object DiagrammedExprMacro {
165179
helper: Expr[(DiagrammedExpr[Boolean], Any, String, source.Position) => Assertion],
166180
condition: Expr[Boolean], pos: Expr[source.Position], clue: Expr[Any], sourceText: String
167181
)(implicit refl: Reflection): Expr[Assertion] = {
168-
val diagExpr = parse(condition)
169-
'{ $helper($diagExpr, $clue, ${sourceText.toExpr}, $pos) }
170-
}
171-
172-
def getAnchorForSelect(refl: Reflection)(sel: refl.Select): Expr[Int] = {
173182
import refl._
174-
if (sel.name == "unary_!")
175-
(sel.pos.startColumn - rootPosition.startColumn).toExpr
176-
else {
177-
val selOffset = sel.pos.endColumn - sel.qualifier.pos.endColumn - sel.name.length
178-
(sel.qualifier.pos.endColumn + selOffset - rootPosition.startColumn).toExpr
179-
}
180-
}
181-
182-
def getAnchor(expr: Expr[_])(implicit refl: Reflection): Expr[Int] = {
183-
import refl._
184-
// -1 to match scala2 position
185-
// ((expr.unseal.pos.endColumn + expr.unseal.pos.startColumn - 1) / 2 - rootPosition.startColumn).toExpr
186-
(expr.unseal.pos.startColumn - rootPosition.startColumn).toExpr
183+
val diagExpr = parse(refl)(condition.unseal.underlyingArgument).seal.cast[DiagrammedExpr[Boolean]]
184+
'{ $helper($diagExpr, $clue, ${sourceText.toExpr}, $pos) }
187185
}
188186
}

0 commit comments

Comments
 (0)