| /++ | |
| This module provides definitions to support D's | |
| interpolated expression sequence literal, sometimes | |
| called string interpolation. | |
| --- | |
| string str; | |
| int num; | |
| // the compiler uses this module to implement the | |
| // i"..." literal used here. | |
| auto a = i"$(str) has $(num) items."; | |
| --- | |
| The variable `a` is a sequence of expressions: | |
| --- | |
| a[0] == InterpolationHeader() | |
| a[$-1] == InterpolationFooter() | |
| --- | |
| First and last, you see the header and footer, to | |
| clearly indicate where interpolation begins and ends. | |
| Note that there may be nested interpolated sequences too, | |
| each with their own header and footer. Think of them | |
| as a set of balanced parenthesis around the contents. | |
| Inside, you will find three general categories of | |
| content: `InterpolatedLiteral!"string"` for string | |
| expressions, `InterpolatedExpression!"code"` for code | |
| expressions, and then the values themselves as their | |
| own type. | |
| In the example: | |
| --- | |
| auto a = i"$(str) has $(num) items."; | |
| --- | |
| We will find: | |
| --- | |
| a[0] == InterpolationHeader() | |
| a[1] == InterpolatedExpression!"str" | |
| a[2] == str | |
| a[3] == InterpolatedLiteral!" has "; | |
| a[4] == InterpolatedExpression!"num"; | |
| a[5] == num | |
| a[6] == InterpolatedLiteral!" items."; | |
| a[7] == InterpolationFooter() | |
| a.length == 8; | |
| --- | |
| You can see the correspondence with the original | |
| input: when you write `$(expression)`, the string of the | |
| expression is passed as `InterpolatedExpression!ThatString`, | |
| (excluding any parenthesis around the expression), | |
| and everything else is passed as `InterpolatedLiteral!str`, | |
| in the same sequence as they appeared in the source. | |
| After an `InterpolatedExpression!...`, you will find the | |
| actual value(s) in the tuple. (If the expression expanded | |
| to multiple values - for example, if it was itself a tuple, | |
| there will be multiple values for a single expression.) | |
| Library functions should NOT attempt to mixin the code | |
| from an `InterpolatedExpression` themselves. Doing so | |
| will fail, since it is coming from a different scope anyway. | |
| The string is provided to you only for informational purposes | |
| and as a sentinel to separate things the user wrote. | |
| Your code should be able to handle an empty code string | |
| in `InterpolatedExpression` or even an entirely missing | |
| `InterpolatedExpression`, in case an implementation decides to | |
| not emit these. | |
| The `toString` members on these return `null`, except for | |
| the `InterpolatedLiteral`, which returns the literal string. | |
| This is to ease processing by generic functions like | |
| `std.stdio.write` or `std.conv.text`, making them effectively | |
| transparently skipped. | |
| To extract the string from an `InterpolatedLiteral`, you can | |
| use an `is` expression or the `.toString` method. | |
| To extract the string from a `InterpolatedExpression`, you can | |
| use an `is` expression or the `.expression` member. | |
| None of these structures have runtime state. | |
| History: | |
| Added in dmd 2.10x frontend, released in late 2023. | |
| +/ | |
| module core.interpolation; | |
| /++ | |
| Common implementation for returning an empty string, to avoid storing | |
| multiple versions of the same function based on templated types below. | |
| +/ | |
| public string __getEmptyString() @nogc pure nothrow @safe { | |
| return ""; | |
| } | |
| /++ | |
| Sentinel values to indicate the beginning and end of an | |
| interpolated expression sequence. | |
| Note that these can nest, so while processing a sequence, | |
| it may be helpful to keep a nesting count if that knowledge | |
| is important to your application. | |
| +/ | |
| struct InterpolationHeader { | |
| /++ | |
| Returns `null` for easy compatibility with existing functions | |
| like `std.stdio.writeln` and `std.conv.text`. | |
| +/ | |
| alias toString = __getEmptyString; | |
| } | |
| /// ditto | |
| struct InterpolationFooter { | |
| /++ | |
| Returns `null` for easy compatibility with existing functions | |
| like `std.stdio.writeln` and `std.conv.text`. | |
| +/ | |
| alias toString = __getEmptyString; | |
| } | |
| /++ | |
| Represents a fragment of a string literal in between expressions | |
| passed as part of an interpolated expression sequence. | |
| +/ | |
| struct InterpolatedLiteral(string text) { | |
| /++ | |
| Returns the text of the interpolated string literal for this | |
| segment of the tuple, for easy access and compatibility with | |
| existing functions like `std.stdio.writeln` and `std.conv.text`. | |
| +/ | |
| static string toString() @nogc pure nothrow @safe { | |
| return text; | |
| } | |
| } | |
| /++ | |
| Represents the source code of an expression passed as part of an | |
| interpolated expression sequence. | |
| +/ | |
| struct InterpolatedExpression(string text) { | |
| /++ | |
| Returns the text of an interpolated expression used in the | |
| original literal, if provided by the implementation. | |
| +/ | |
| enum expression = text; | |
| /++ | |
| Returns `null` for easy compatibility with existing functions | |
| like `std.stdio.writeln` and `std.conv.text`. | |
| +/ | |
| alias toString = __getEmptyString; | |
| } |