diff options
author | Martin Odersky <odersky@gmail.com> | 2016-09-24 19:13:20 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-09-24 19:16:29 +0200 |
commit | 962377ebc23a4c6a2757bee99e6558dd6a93c067 (patch) | |
tree | 19134d4bfb0e804110b74c623e2460f51891af2a | |
parent | e2e1e8a43123de3c5594bad24af486b730e0b3c7 (diff) | |
download | dotty-962377ebc23a4c6a2757bee99e6558dd6a93c067.tar.gz dotty-962377ebc23a4c6a2757bee99e6558dd6a93c067.tar.bz2 dotty-962377ebc23a4c6a2757bee99e6558dd6a93c067.zip |
Make InterpolatedString conform to ordering requirement
Arrange its sub-elements so that they appear strictly left to right.
-rw-r--r-- | src/dotty/tools/dotc/ast/Desugar.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/Positioned.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/untpd.scala | 22 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 40 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 14 | ||||
-rw-r--r-- | test/test/parsePackage.scala | 4 |
6 files changed, 53 insertions, 42 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index d7ae1bf85..1bfbcdbeb 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -889,7 +889,15 @@ object desugar { Apply( ref(defn.SymbolClass.companionModule.termRef), Literal(Constant(str)) :: Nil) - case InterpolatedString(id, strs, elems) => + case InterpolatedString(id, segments) => + val strs = segments map { + case ts: Thicket => ts.trees.head + case t => t + } + val elems = segments flatMap { + case ts: Thicket => ts.trees.tail + case t => Nil + } Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems) case InfixOp(l, op, r) => if (ctx.mode is Mode.Type) @@ -1054,8 +1062,8 @@ object desugar { ctx.error("illegal variable in pattern alternative", vble.pos) case Annotated(arg, _) => collect(arg) - case InterpolatedString(_, _, elems) => - elems foreach collect + case InterpolatedString(_, segments) => + segments foreach collect case InfixOp(left, _, right) => collect(left) collect(right) diff --git a/src/dotty/tools/dotc/ast/Positioned.scala b/src/dotty/tools/dotc/ast/Positioned.scala index 1e992bd01..216446e93 100644 --- a/src/dotty/tools/dotc/ast/Positioned.scala +++ b/src/dotty/tools/dotc/ast/Positioned.scala @@ -171,7 +171,6 @@ abstract class Positioned extends DotClass with Product { } if (nonOverlapping) { this match { - case _: InterpolatedString => // ignore, strings and elements are interleaved in source, separated in tree case _: Function => // ignore, functions produced from wildcards (e.g. (_ op _) mix parameters and body case _ => assert(!lastPos.exists || !p.pos.exists || lastPos.end <= p.pos.start, diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index fdc4be823..7e1892253 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -35,7 +35,13 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree case class SymbolLit(str: String) extends TermTree - case class InterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) extends TermTree + + /** An interpolated string + * @param segments a list of two element tickets consisting of string literal and argument tree, + * possibly with a simple string literal as last element of the list + */ + case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree + case class Function(args: List[Tree], body: Tree) extends Tree { override def isTerm = body.isTerm override def isType = body.isType @@ -305,9 +311,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case tree: SymbolLit if str == tree.str => tree case _ => untpd.SymbolLit(str).withPos(tree.pos) } - def InterpolatedString(tree: Tree)(id: TermName, strings: List[Literal], elems: List[Tree]) = tree match { - case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree - case _ => untpd.InterpolatedString(id, strings, elems).withPos(tree.pos) + def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree]) = tree match { + case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree + case _ => untpd.InterpolatedString(id, segments).withPos(tree.pos) } def Function(tree: Tree)(args: List[Tree], body: Tree) = tree match { 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 { cpy.ParsedTry(tree)(transform(expr), transform(handler), transform(finalizer)) case SymbolLit(str) => cpy.SymbolLit(tree)(str) - case InterpolatedString(id, strings, elems) => - cpy.InterpolatedString(tree)(id, transformSub(strings), transform(elems)) + case InterpolatedString(id, segments) => + cpy.InterpolatedString(tree)(id, transform(segments)) case Function(args, body) => cpy.Function(tree)(transform(args), transform(body)) case InfixOp(left, op, right) => @@ -426,8 +432,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { this(this(this(x, expr), handler), finalizer) case SymbolLit(str) => x - case InterpolatedString(id, strings, elems) => - this(this(x, strings), elems) + case InterpolatedString(id, segments) => + this(x, segments) case Function(args, body) => this(this(x, args), body) case InfixOp(left, op, right) => diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index b8ec38268..6ba576a34 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -600,30 +600,30 @@ object Parsers { } private def interpolatedString(inPattern: Boolean = false): Tree = atPos(in.offset) { - val partsBuf = new ListBuffer[Literal] - val exprBuf = new ListBuffer[Tree] + val segmentBuf = new ListBuffer[Tree] val interpolator = in.name in.nextToken() while (in.token == STRINGPART) { - partsBuf += literal().asInstanceOf[Literal] - exprBuf += atPos(in.offset) { - if (in.token == IDENTIFIER) - termIdent() - else if (in.token == THIS) { - in.nextToken() - This(tpnme.EMPTY) - } - else if (in.token == LBRACE) - if (inPattern) Block(Nil, inBraces(pattern())) - else expr() - else { - syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected") - EmptyTree - } - } + segmentBuf += Thicket(List( + literal(), + atPos(in.offset) { + if (in.token == IDENTIFIER) + termIdent() + else if (in.token == THIS) { + in.nextToken() + This(tpnme.EMPTY) + } + else if (in.token == LBRACE) + if (inPattern) Block(Nil, inBraces(pattern())) + else expr() + else { + syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected") + EmptyTree + } + })) } - if (in.token == STRINGLIT) partsBuf += literal().asInstanceOf[Literal] - InterpolatedString(interpolator, partsBuf.toList, exprBuf.toList) + if (in.token == STRINGLIT) segmentBuf += literal() + InterpolatedString(interpolator, segmentBuf.toList) } /* ------------- NEW LINES ------------------------------------------------- */ diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 9744e7026..32d152c2e 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -446,15 +446,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } case SymbolLit(str) => "'" + str - case InterpolatedString(id, strings, elems) => - def interleave(strs: List[Text], elems: List[Text]): Text = ((strs, elems): @unchecked) match { - case (Nil, Nil) => "" - case (str :: Nil, Nil) => str - case (str :: strs1, elem :: elems1) => str ~ elem ~ interleave(strs1, elems1) + case InterpolatedString(id, segments) => + def strText(str: Literal) = Str(escapedString(str.const.stringValue)) + def segmentText(segment: Tree) = segment match { + case Thicket(List(str: Literal, expr)) => strText(str) ~ "{" ~ toTextGlobal(expr) ~ "}" + case str: Literal => strText(str) } - val strTexts = strings map (str => Str(escapedString(str.const.stringValue))) - val elemsTexts = elems map (elem => "{" ~ toTextGlobal(elem) ~ "}") - toText(id) ~ "\"" ~ interleave(strTexts, elemsTexts) ~ "\"" + toText(id) ~ "\"" ~ Text(segments map segmentText, "") ~ "\"" case Function(args, body) => var implicitSeen: Boolean = false def argToText(arg: Tree) = arg match { diff --git a/test/test/parsePackage.scala b/test/test/parsePackage.scala index bef7bbe06..6fa5c0f86 100644 --- a/test/test/parsePackage.scala +++ b/test/test/parsePackage.scala @@ -23,8 +23,8 @@ object parsePackage extends ParserTest { TypedSplice(t) case SymbolLit(str) => tree - case InterpolatedString(id, parts, elems) => - InterpolatedString(id, parts map (transformSub(_)), elems map transform) + case InterpolatedString(id, segments) => + InterpolatedString(id, segments map transform) case mdef @ ModuleDef(name, impl) => ModuleDef(name, transformSub(impl)).withMods(mdef.mods) case Function(params, body) => |