Description
Inlining cannot deal with varargs well, which means we are stopped in the starting block when trying to turn string interpolators into whitebox macros. For instance, consider the f
interpolator. An interpolated string is expanded to:
new StringContext(s_0, ..., s_n).f(e_1, ..., e_n)
Currently f
is a whitebox macro which produces a specialized interpolator with some specific function type, such as
(Int, Double, String) => String
How can we get analogous functionality with just inlining? Here's a sequence of action items that could help get us there:
- Turn
f
into an extension method. I.e.
inline def f(this sc: StringContext)(args: Any*): String =
Makes it easier to get at the string context. Requires #5114.
-
Make varargs immutable arrays instead of Seqs (this just makes the next step easier). Requires Opaque types - selftype encoding #5300.
-
Add rewrite rules that deal with array length and indexing. I.e.
new Array(x_0, ..., x_n)(i) --> x_i
new Array(x_0, ..., x_n).length = n + 1
This lets us get to the arguments passed in the parts
array.
- Implement string parsing using string constant folding (#5406)
- Define a type and implicit instances from strings to the types they represent. Something like
trait Format[S <: String & Singleton, T]
- Summon an implicit instance of
Format
for each suffix string. - Somehow assemble a result type from this, which has the form
((T_1, ..., _T_n)) => String
and cast the runtime implementation off
to this type. - Apply an
untuple
operation (i.e. the inverse oftupled
) to the result, yielding an n-ary method. This last step also needs to be supported with a native rewrite rule.
Or some other mix. In any case, to get off the ground we need to be able to recursively access a sequence of vararg arguments and synthesize a method of arbitrary arity. These require specialized support.