Skip to content

Commit

Permalink
SI-8703 add support for blocks with just a single expression to quasi…
Browse files Browse the repository at this point in the history
…quotes

Previously it was impossible to match a block that was constructed as

    Block(Nil, term)

Due to the fact that quasiquotes always flatten those into just term. This is
a correct behaviour for construction (for sake of consistency with parser) but
doing it in deconstruction mode make it impossible to match such blocks which
could have been constructed manually somewhere.

To fix this we just disable block flattening in deconstruction mode.
Interestingly enough this doesn't break existing code due to the fact that
quasiquote's block matcher also matches expressions as single-element blocks.

This allows to match single-element blocks with patterns like q"{ $foo }".
  • Loading branch information
densh committed Jul 2, 2014
1 parent e67146c commit 14d1fe0
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
11 changes: 8 additions & 3 deletions src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,14 @@ trait Parsers { self: Quasiquotes =>
override def makeTupleType(trees: List[Tree]): Tree = TupleTypePlaceholder(trees)

// q"{ $x }"
override def makeBlock(stats: List[Tree]): Tree = stats match {
case (head @ Ident(name)) :: Nil if isHole(name) => Block(Nil, head)
case _ => super.makeBlock(stats)
override def makeBlock(stats: List[Tree]): Tree = method match {
case nme.apply =>
stats match {
case (head @ Ident(name)) :: Nil if isHole(name) => Block(Nil, head)
case _ => super.makeBlock(stats)
}
case nme.unapply => gen.mkBlock(stats, doFlatten = false)
case other => global.abort("unreachable")
}

// tq"$a => $b"
Expand Down
4 changes: 2 additions & 2 deletions src/reflect/scala/reflect/internal/TreeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -451,10 +451,10 @@ abstract class TreeGen {
def mkSyntheticUnit() = Literal(Constant(())).updateAttachment(SyntheticUnitAttachment)

/** Create block of statements `stats` */
def mkBlock(stats: List[Tree]): Tree =
def mkBlock(stats: List[Tree], doFlatten: Boolean = true): Tree =
if (stats.isEmpty) mkSyntheticUnit()
else if (!stats.last.isTerm) Block(stats, mkSyntheticUnit())
else if (stats.length == 1) stats.head
else if (stats.length == 1 && doFlatten) stats.head
else Block(stats.init, stats.last)

/** Create a block that wraps multiple statements but don't
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,11 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction
assert(f ≈ `new`)
assert(argss.isEmpty)
}

property("SI-8703 extract block with single expression") = test {
val q"{ $a }" = Block(Nil, q"1")
val Literal(Constant(1)) = a
val q"{ $b }" = q"2"
val Literal(Constant(2)) = b
}
}

0 comments on commit 14d1fe0

Please sign in to comment.