Skip to content

Commit 6ea9f72

Browse files
committed
A string interpolation implementation of SIP-11.
This is the complete implementation of SIP-11, in its version of 15-Jan-2012. For now, the interpolations are enabled only under the -Xexperimental flag.
1 parent b0de5f1 commit 6ea9f72

File tree

10 files changed

+427
-137
lines changed

10 files changed

+427
-137
lines changed

src/compiler/scala/reflect/internal/StdNames.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
271271
// Compiler utilized names
272272
// val productElementName: NameType = "productElementName"
273273
val Ident: NameType = "Ident"
274+
val StringContext: NameType = "StringContext"
274275
val TYPE_ : NameType = "TYPE"
275276
val TypeTree: NameType = "TypeTree"
276277
val UNIT : NameType = "UNIT"
@@ -320,7 +321,6 @@ trait StdNames extends NameManglers { self: SymbolTable =>
320321
val find_ : NameType = "find"
321322
val flatMap: NameType = "flatMap"
322323
val foreach: NameType = "foreach"
323-
val formatted: NameType = "formatted"
324324
val freeValue : NameType = "freeValue"
325325
val genericArrayOps: NameType = "genericArrayOps"
326326
val get: NameType = "get"

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ self =>
617617

618618
def isLiteralToken(token: Int) = token match {
619619
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
620-
STRINGLIT | STRINGPART | SYMBOLLIT | TRUE | FALSE | NULL => true
620+
STRINGLIT | INTERPOLATIONID | SYMBOLLIT | TRUE | FALSE | NULL => true
621621
case _ => false
622622
}
623623
def isLiteral = isLiteralToken(in.token)
@@ -1103,27 +1103,27 @@ self =>
11031103
* }}}
11041104
* @note The returned tree does not yet have a position
11051105
*/
1106-
def literal(isNegated: Boolean): Tree = {
1106+
def literal(isNegated: Boolean = false): Tree = {
11071107
def finish(value: Any): Tree = {
11081108
val t = Literal(Constant(value))
11091109
in.nextToken()
11101110
t
11111111
}
11121112
if (in.token == SYMBOLLIT)
11131113
Apply(scalaDot(nme.Symbol), List(finish(in.strVal)))
1114-
else if (in.token == STRINGPART)
1114+
else if (in.token == INTERPOLATIONID)
11151115
interpolatedString()
11161116
else finish(in.token match {
1117-
case CHARLIT => in.charVal
1118-
case INTLIT => in.intVal(isNegated).toInt
1119-
case LONGLIT => in.intVal(isNegated)
1120-
case FLOATLIT => in.floatVal(isNegated).toFloat
1121-
case DOUBLELIT => in.floatVal(isNegated)
1122-
case STRINGLIT => in.strVal.intern()
1123-
case TRUE => true
1124-
case FALSE => false
1125-
case NULL => null
1126-
case _ =>
1117+
case CHARLIT => in.charVal
1118+
case INTLIT => in.intVal(isNegated).toInt
1119+
case LONGLIT => in.intVal(isNegated)
1120+
case FLOATLIT => in.floatVal(isNegated).toFloat
1121+
case DOUBLELIT => in.floatVal(isNegated)
1122+
case STRINGLIT | STRINGPART => in.strVal.intern()
1123+
case TRUE => true
1124+
case FALSE => false
1125+
case NULL => null
1126+
case _ =>
11271127
syntaxErrorOrIncomplete("illegal literal", true)
11281128
null
11291129
})
@@ -1138,16 +1138,27 @@ self =>
11381138
}
11391139
}
11401140

1141-
private def interpolatedString(): Tree = {
1142-
var t = atPos(o2p(in.offset))(New(TypeTree(definitions.StringBuilderClass.tpe), List(List())))
1141+
private def interpolatedString(): Tree = atPos(in.offset) {
1142+
val start = in.offset
1143+
val interpolator = in.name
1144+
1145+
val partsBuf = new ListBuffer[Tree]
1146+
val exprBuf = new ListBuffer[Tree]
1147+
in.nextToken()
11431148
while (in.token == STRINGPART) {
1144-
t = stringOp(t, nme.append)
1145-
var e = expr()
1146-
if (in.token == STRINGFMT) e = stringOp(e, nme.formatted)
1147-
t = atPos(t.pos.startOrPoint)(Apply(Select(t, nme.append), List(e)))
1149+
partsBuf += literal()
1150+
exprBuf += {
1151+
if (in.token == IDENTIFIER) atPos(in.offset)(Ident(ident()))
1152+
else expr()
1153+
}
11481154
}
1149-
if (in.token == STRINGLIT) t = stringOp(t, nme.append)
1150-
atPos(t.pos)(Select(t, nme.toString_))
1155+
if (in.token == STRINGLIT) partsBuf += literal()
1156+
1157+
val t1 = atPos(o2p(start)) { Ident(nme.StringContext) }
1158+
val t2 = atPos(start) { Apply(t1, partsBuf.toList) }
1159+
t2 setPos t2.pos.makeTransparent
1160+
val t3 = Select(t2, interpolator) setPos t2.pos
1161+
atPos(start) { Apply(t3, exprBuf.toList) }
11511162
}
11521163

11531164
/* ------------- NEW LINES ------------------------------------------------- */
@@ -1469,7 +1480,7 @@ self =>
14691480
atPos(in.offset) {
14701481
val name = nme.toUnaryName(rawIdent())
14711482
// val name = nme.toUnaryName(ident()) // val name: Name = "unary_" + ident()
1472-
if (name == nme.UNARY_- && isNumericLit) simpleExprRest(atPos(in.offset)(literal(true)), true)
1483+
if (name == nme.UNARY_- && isNumericLit) simpleExprRest(atPos(in.offset)(literal(isNegated = true)), true)
14731484
else Select(stripParens(simpleExpr()), name)
14741485
}
14751486
}
@@ -1493,7 +1504,7 @@ self =>
14931504
def simpleExpr(): Tree = {
14941505
var canApply = true
14951506
val t =
1496-
if (isLiteral) atPos(in.offset)(literal(false))
1507+
if (isLiteral) atPos(in.offset)(literal())
14971508
else in.token match {
14981509
case XMLSTART =>
14991510
xmlLiteral()
@@ -1827,7 +1838,7 @@ self =>
18271838
case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>
18281839
t match {
18291840
case Ident(nme.MINUS) =>
1830-
return atPos(start) { literal(true) }
1841+
return atPos(start) { literal(isNegated = true) }
18311842
case _ =>
18321843
}
18331844
case _ =>
@@ -1844,8 +1855,8 @@ self =>
18441855
in.nextToken()
18451856
atPos(start, start) { Ident(nme.WILDCARD) }
18461857
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
1847-
STRINGLIT | STRINGPART | SYMBOLLIT | TRUE | FALSE | NULL =>
1848-
atPos(start) { literal(false) }
1858+
STRINGLIT | INTERPOLATIONID | SYMBOLLIT | TRUE | FALSE | NULL =>
1859+
atPos(start) { literal() }
18491860
case LPAREN =>
18501861
atPos(start)(makeParens(noSeq.patterns()))
18511862
case XMLSTART =>

0 commit comments

Comments
 (0)