Skip to content

Commit 962377e

Browse files
committed
Make InterpolatedString conform to ordering requirement
Arrange its sub-elements so that they appear strictly left to right.
1 parent e2e1e8a commit 962377e

File tree

6 files changed

+53
-42
lines changed

6 files changed

+53
-42
lines changed

src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,15 @@ object desugar {
889889
Apply(
890890
ref(defn.SymbolClass.companionModule.termRef),
891891
Literal(Constant(str)) :: Nil)
892-
case InterpolatedString(id, strs, elems) =>
892+
case InterpolatedString(id, segments) =>
893+
val strs = segments map {
894+
case ts: Thicket => ts.trees.head
895+
case t => t
896+
}
897+
val elems = segments flatMap {
898+
case ts: Thicket => ts.trees.tail
899+
case t => Nil
900+
}
893901
Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
894902
case InfixOp(l, op, r) =>
895903
if (ctx.mode is Mode.Type)
@@ -1054,8 +1062,8 @@ object desugar {
10541062
ctx.error("illegal variable in pattern alternative", vble.pos)
10551063
case Annotated(arg, _) =>
10561064
collect(arg)
1057-
case InterpolatedString(_, _, elems) =>
1058-
elems foreach collect
1065+
case InterpolatedString(_, segments) =>
1066+
segments foreach collect
10591067
case InfixOp(left, _, right) =>
10601068
collect(left)
10611069
collect(right)

src/dotty/tools/dotc/ast/Positioned.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ abstract class Positioned extends DotClass with Product {
171171
}
172172
if (nonOverlapping) {
173173
this match {
174-
case _: InterpolatedString => // ignore, strings and elements are interleaved in source, separated in tree
175174
case _: Function => // ignore, functions produced from wildcards (e.g. (_ op _) mix parameters and body
176175
case _ =>
177176
assert(!lastPos.exists || !p.pos.exists || lastPos.end <= p.pos.start,

src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
3535
case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree
3636

3737
case class SymbolLit(str: String) extends TermTree
38-
case class InterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) extends TermTree
38+
39+
/** An interpolated string
40+
* @param segments a list of two element tickets consisting of string literal and argument tree,
41+
* possibly with a simple string literal as last element of the list
42+
*/
43+
case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree
44+
3945
case class Function(args: List[Tree], body: Tree) extends Tree {
4046
override def isTerm = body.isTerm
4147
override def isType = body.isType
@@ -305,9 +311,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
305311
case tree: SymbolLit if str == tree.str => tree
306312
case _ => untpd.SymbolLit(str).withPos(tree.pos)
307313
}
308-
def InterpolatedString(tree: Tree)(id: TermName, strings: List[Literal], elems: List[Tree]) = tree match {
309-
case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree
310-
case _ => untpd.InterpolatedString(id, strings, elems).withPos(tree.pos)
314+
def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree]) = tree match {
315+
case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree
316+
case _ => untpd.InterpolatedString(id, segments).withPos(tree.pos)
311317
}
312318
def Function(tree: Tree)(args: List[Tree], body: Tree) = tree match {
313319
case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
@@ -379,8 +385,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
379385
cpy.ParsedTry(tree)(transform(expr), transform(handler), transform(finalizer))
380386
case SymbolLit(str) =>
381387
cpy.SymbolLit(tree)(str)
382-
case InterpolatedString(id, strings, elems) =>
383-
cpy.InterpolatedString(tree)(id, transformSub(strings), transform(elems))
388+
case InterpolatedString(id, segments) =>
389+
cpy.InterpolatedString(tree)(id, transform(segments))
384390
case Function(args, body) =>
385391
cpy.Function(tree)(transform(args), transform(body))
386392
case InfixOp(left, op, right) =>
@@ -426,8 +432,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
426432
this(this(this(x, expr), handler), finalizer)
427433
case SymbolLit(str) =>
428434
x
429-
case InterpolatedString(id, strings, elems) =>
430-
this(this(x, strings), elems)
435+
case InterpolatedString(id, segments) =>
436+
this(x, segments)
431437
case Function(args, body) =>
432438
this(this(x, args), body)
433439
case InfixOp(left, op, right) =>

src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -600,30 +600,30 @@ object Parsers {
600600
}
601601

602602
private def interpolatedString(inPattern: Boolean = false): Tree = atPos(in.offset) {
603-
val partsBuf = new ListBuffer[Literal]
604-
val exprBuf = new ListBuffer[Tree]
603+
val segmentBuf = new ListBuffer[Tree]
605604
val interpolator = in.name
606605
in.nextToken()
607606
while (in.token == STRINGPART) {
608-
partsBuf += literal().asInstanceOf[Literal]
609-
exprBuf += atPos(in.offset) {
610-
if (in.token == IDENTIFIER)
611-
termIdent()
612-
else if (in.token == THIS) {
613-
in.nextToken()
614-
This(tpnme.EMPTY)
615-
}
616-
else if (in.token == LBRACE)
617-
if (inPattern) Block(Nil, inBraces(pattern()))
618-
else expr()
619-
else {
620-
syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected")
621-
EmptyTree
622-
}
623-
}
607+
segmentBuf += Thicket(List(
608+
literal(),
609+
atPos(in.offset) {
610+
if (in.token == IDENTIFIER)
611+
termIdent()
612+
else if (in.token == THIS) {
613+
in.nextToken()
614+
This(tpnme.EMPTY)
615+
}
616+
else if (in.token == LBRACE)
617+
if (inPattern) Block(Nil, inBraces(pattern()))
618+
else expr()
619+
else {
620+
syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected")
621+
EmptyTree
622+
}
623+
}))
624624
}
625-
if (in.token == STRINGLIT) partsBuf += literal().asInstanceOf[Literal]
626-
InterpolatedString(interpolator, partsBuf.toList, exprBuf.toList)
625+
if (in.token == STRINGLIT) segmentBuf += literal()
626+
InterpolatedString(interpolator, segmentBuf.toList)
627627
}
628628

629629
/* ------------- NEW LINES ------------------------------------------------- */

src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -446,15 +446,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
446446
}
447447
case SymbolLit(str) =>
448448
"'" + str
449-
case InterpolatedString(id, strings, elems) =>
450-
def interleave(strs: List[Text], elems: List[Text]): Text = ((strs, elems): @unchecked) match {
451-
case (Nil, Nil) => ""
452-
case (str :: Nil, Nil) => str
453-
case (str :: strs1, elem :: elems1) => str ~ elem ~ interleave(strs1, elems1)
449+
case InterpolatedString(id, segments) =>
450+
def strText(str: Literal) = Str(escapedString(str.const.stringValue))
451+
def segmentText(segment: Tree) = segment match {
452+
case Thicket(List(str: Literal, expr)) => strText(str) ~ "{" ~ toTextGlobal(expr) ~ "}"
453+
case str: Literal => strText(str)
454454
}
455-
val strTexts = strings map (str => Str(escapedString(str.const.stringValue)))
456-
val elemsTexts = elems map (elem => "{" ~ toTextGlobal(elem) ~ "}")
457-
toText(id) ~ "\"" ~ interleave(strTexts, elemsTexts) ~ "\""
455+
toText(id) ~ "\"" ~ Text(segments map segmentText, "") ~ "\""
458456
case Function(args, body) =>
459457
var implicitSeen: Boolean = false
460458
def argToText(arg: Tree) = arg match {

test/test/parsePackage.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ object parsePackage extends ParserTest {
2323
TypedSplice(t)
2424
case SymbolLit(str) =>
2525
tree
26-
case InterpolatedString(id, parts, elems) =>
27-
InterpolatedString(id, parts map (transformSub(_)), elems map transform)
26+
case InterpolatedString(id, segments) =>
27+
InterpolatedString(id, segments map transform)
2828
case mdef @ ModuleDef(name, impl) =>
2929
ModuleDef(name, transformSub(impl)).withMods(mdef.mods)
3030
case Function(params, body) =>

0 commit comments

Comments
 (0)