Skip to content

Commit fdff56e

Browse files
committed
Fix decompilation of while loops
1 parent f1140e9 commit fdff56e

File tree

3 files changed

+74
-42
lines changed

3 files changed

+74
-42
lines changed

library/src/scala/tasty/util/ShowSourceCode.scala

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,26 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
145145
this
146146
}
147147

148+
case While(cond, stats) =>
149+
this += "while ("
150+
printTree(cond)
151+
this += ") {"
152+
indented {
153+
this += lineBreak()
154+
printTrees(stats, lineBreak())
155+
}
156+
this += lineBreak() += "}"
157+
158+
case DoWhile(stats, cond) =>
159+
this += "do {"
160+
indented {
161+
this += lineBreak()
162+
printTrees(stats, lineBreak())
163+
}
164+
this += lineBreak() += "} while ("
165+
printTree(cond)
166+
this += ")"
167+
148168
case ddef@DefDef(name, targs, argss, tpt, rhs) =>
149169
val flags = ddef.flags
150170
if (flags.isOverride) sb.append("override ")
@@ -225,7 +245,14 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
225245
this += " = "
226246
printTree(rhs)
227247

228-
case Term.Block(stats, expr) =>
248+
case Term.Block(stats0, expr) =>
249+
def isLoopEntryPoint(tree: Tree): Boolean = tree match {
250+
case Term.Apply(Term.Ident("while$" | "doWhile$"), _) => true
251+
case _ => false
252+
}
253+
254+
val stats = stats0.filterNot(isLoopEntryPoint)
255+
229256
expr match {
230257
case Term.Lambda(_, _) =>
231258
// Decompile lambda from { def annon$(...) = ...; closure(annon$, ...)}
@@ -236,30 +263,17 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
236263
printTree(rhs)
237264
this += ")"
238265

239-
case Term.Apply(Term.Ident("while$"), _) =>
240-
val DefDef("while$", _, _, _, Some(Term.If(cond, Term.Block(body :: Nil, _), _))) = stats.head
241-
this += "while ("
242-
printTree(cond)
243-
this += ") "
244-
printTree(body)
245-
246-
case Term.Apply(Term.Ident("doWhile$"), _) =>
247-
val DefDef("doWhile$", _, _, _, Some(Term.Block(List(body), Term.If(cond, _, _)))) = stats.head
248-
this += "do "
249-
printTree(body)
250-
this += " while ("
251-
printTree(cond)
252-
this += ")"
253-
254266
case _ =>
255267
this += "{"
256268
indented {
257269
if (!stats.isEmpty) {
258270
this += lineBreak()
259271
printTrees(stats, lineBreak())
260272
}
261-
this += lineBreak()
262-
printTree(expr)
273+
if (!isLoopEntryPoint(expr)) {
274+
this += lineBreak()
275+
printTree(expr)
276+
}
263277
}
264278
this += lineBreak() += "}"
265279
}
@@ -719,6 +733,20 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
719733
}
720734
}
721735

736+
private object While {
737+
def unapply(arg: Tree)(implicit ctx: Context): Option[(Term, List[Statement])] = arg match {
738+
case DefDef("while$", _, _, _, Some(Term.If(cond, Term.Block(bodyStats, _), _))) => Some((cond, bodyStats))
739+
case _ => None
740+
}
741+
}
742+
743+
private object DoWhile {
744+
def unapply(arg: Tree)(implicit ctx: Context): Option[(List[Statement], Term)] = arg match {
745+
case DefDef("doWhile$", _, _, _, Some(Term.Block(body, Term.If(cond, _, _)))) => Some((body, cond))
746+
case _ => None
747+
}
748+
}
749+
722750
// TODO Provide some of these in scala.tasty.Tasty.scala and implement them using checks on symbols for performance
723751
private object Types {
724752

tests/run/quote-inline-function.check

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
Normal function
22
{
3-
var i: Int = 0
4-
val j: Int = 5
5-
<label> def while$(): Unit =
6-
if i.<(j) then
7-
{
8-
val x$1: Int = i
9-
f.apply(x$1)
10-
i = i.+(1)
11-
while$()
12-
}
13-
else ()
14-
while$()
3+
var i: scala.Int = 0
4+
val j: scala.Int = 5
5+
while (i.<(j)) {
6+
val x$1: scala.Int = i
7+
f.apply(x$1)
8+
i = i.+(1)
9+
}
10+
do {
11+
val x$2: scala.Int = i
12+
f.apply(x$2)
13+
i = i.+(1)
14+
} while (i.<(j))
1515
}
1616

1717
By name function
1818
{
19-
var i: Int = 0
20-
val j: Int = 5
21-
<label> def while$(): Unit =
22-
if i.<(j) then
23-
{
24-
val x$1: Int = i
25-
scala.Predef.println(x$1)
26-
i = i.+(1)
27-
while$()
28-
}
29-
else ()
30-
while$()
19+
var i: scala.Int = 0
20+
val j: scala.Int = 5
21+
while (i.<(j)) {
22+
val x$1: scala.Int = i
23+
scala.Predef.println(x$1)
24+
i = i.+(1)
25+
}
26+
do {
27+
val x$2: scala.Int = i
28+
scala.Predef.println(x$2)
29+
i = i.+(1)
30+
} while (i.<(j))
3131
}

tests/run/quote-inline-function/quoted_1.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ object Macros {
1515
~f.apply('(i))
1616
i += 1
1717
}
18+
do {
19+
~f.apply('(i))
20+
i += 1
21+
} while (i < j)
1822
}
1923
res.show.toExpr
2024
}

0 commit comments

Comments
 (0)