Skip to content

Commit fa9f19e

Browse files
committed
Cleanup dispatch to interpolations
1 parent ffeaa5f commit fa9f19e

File tree

1 file changed

+43
-41
lines changed

1 file changed

+43
-41
lines changed

compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -117,55 +117,57 @@ class StringInterpolatorOpt extends MiniPhase {
117117
}
118118

119119
override def transformApply(tree: Apply)(using Context): Tree = {
120+
def mkConcat(strs: List[Literal], elems: List[Tree]): Tree =
121+
val stri = strs.iterator
122+
val elemi = elems.iterator
123+
var result: Tree = stri.next
124+
def concat(tree: Tree): Unit =
125+
result = result.select(defn.String_+).appliedTo(tree).withSpan(tree.span)
126+
while elemi.hasNext
127+
do
128+
concat(elemi.next)
129+
val str = stri.next
130+
if !str.const.stringValue.isEmpty then concat(str)
131+
result
132+
end mkConcat
120133
val sym = tree.symbol
121-
val isInterpolatedMethod = // Test names first to avoid loading scala.StringContext if not used
122-
(sym.name == nme.raw_ && sym.eq(defn.StringContext_raw)) ||
123-
(sym.name == nme.f && sym.eq(defn.StringContext_f)) ||
124-
(sym.name == nme.s && sym.eq(defn.StringContext_s))
134+
// Test names first to avoid loading scala.StringContext if not used, and common names first
135+
val isInterpolatedMethod =
136+
sym.name match
137+
case nme.s => sym eq defn.StringContext_s
138+
case nme.raw_ => sym eq defn.StringContext_raw
139+
case nme.f => sym eq defn.StringContext_f
140+
case _ => false
125141
def transformF(fun: Tree, args: Tree): Tree =
126142
val (parts1, args1) = FormatInterpolatorTransform.checked(fun, args)
127143
resolveConstructor(defn.StringOps.typeRef, List(parts1))
128144
.select(nme.format)
129145
.appliedTo(args1)
130-
if (isInterpolatedMethod)
131-
(tree: @unchecked) match {
146+
// Starting with Scala 2.13, s and raw are macros in the standard
147+
// library, so we need to expand them manually.
148+
// sc.s(args) --> standardInterpolator(processEscapes, args, sc.parts)
149+
// sc.raw(args) --> standardInterpolator(x => x, args, sc.parts)
150+
def transformS(fun: Tree, args: Tree, isRaw: Boolean): Tree =
151+
val pre = fun match
152+
case Select(pre, _) => pre
153+
case intp: Ident => tpd.desugarIdentPrefix(intp)
154+
val stringToString = defn.StringContextModule_processEscapes.info.asInstanceOf[MethodType]
155+
val process = tpd.Lambda(stringToString, args =>
156+
if isRaw then args.head else ref(defn.StringContextModule_processEscapes).appliedToTermArgs(args)
157+
)
158+
evalOnce(pre) { sc =>
159+
val parts = sc.select(defn.StringContext_parts)
160+
ref(defn.StringContextModule_standardInterpolator)
161+
.appliedToTermArgs(List(process, args, parts))
162+
}
163+
end transformS
164+
if isInterpolatedMethod then
165+
(tree: @unchecked) match
132166
case StringContextIntrinsic(strs: List[Literal], elems: List[Tree]) =>
133-
val stri = strs.iterator
134-
val elemi = elems.iterator
135-
var result: Tree = stri.next
136-
def concat(tree: Tree): Unit = {
137-
result = result.select(defn.String_+).appliedTo(tree).withSpan(tree.span)
138-
}
139-
while (elemi.hasNext) {
140-
concat(elemi.next)
141-
val str = stri.next
142-
if (!str.const.stringValue.isEmpty) concat(str)
143-
}
144-
result
145-
case Apply(intp, args :: Nil) if sym.eq(defn.StringContext_f) =>
146-
transformF(intp, args)
147-
// Starting with Scala 2.13, s and raw are macros in the standard
148-
// library, so we need to expand them manually.
149-
// sc.s(args) --> standardInterpolator(processEscapes, args, sc.parts)
150-
// sc.raw(args) --> standardInterpolator(x => x, args, sc.parts)
167+
mkConcat(strs, elems)
151168
case Apply(intp, args :: Nil) =>
152-
val pre = intp match {
153-
case Select(pre, _) => pre
154-
case intp: Ident => tpd.desugarIdentPrefix(intp)
155-
}
156-
val isRaw = sym eq defn.StringContext_raw
157-
val stringToString = defn.StringContextModule_processEscapes.info.asInstanceOf[MethodType]
158-
159-
val process = tpd.Lambda(stringToString, args =>
160-
if (isRaw) args.head else ref(defn.StringContextModule_processEscapes).appliedToTermArgs(args))
161-
162-
evalOnce(pre) { sc =>
163-
val parts = sc.select(defn.StringContext_parts)
164-
165-
ref(defn.StringContextModule_standardInterpolator)
166-
.appliedToTermArgs(List(process, args, parts))
167-
}
168-
}
169+
if sym eq defn.StringContext_f then transformF(intp, args)
170+
else transformS(intp, args, isRaw = sym eq defn.StringContext_raw)
169171
else
170172
tree.tpe match
171173
case _: ConstantType => tree

0 commit comments

Comments
 (0)