mirror of
https://github.com/autc04/Retro68.git
synced 2026-03-15 16:16:51 +00:00
159 lines
5.0 KiB
D
159 lines
5.0 KiB
D
/++
|
||
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;
|
||
}
|