Conversation
|
One more challenge to make this a slam-dunk, not focused on specific syntax: auto a = 4;
auto b = 2;
auto c = 7;
debugLog(i"criticalVarsHere: $a, $b, $(c + 2)");prints edit: see #2 (comment) |
|
How can a function distinguish between an argument to be formatted and any other string component that can be taken as-is? E.g. how can a format function provide escaping of string arguments? Very doable with edit: see #2 (comment) |
|
I think the missing things I mention here can be solved with a totally optional, without modifying anything from the existing DIP intermediate object (names are deliberately long-winded for exposition, we could definitely think of much shorter ones) e.g. struct StringComponent(string sIn) {
enum string s = sIn;
}
struct Formatee(string rawIn, FormateeType) {
enum string raw = rawIn;
FormateeType v;
}
struct FormatObject(string rawIn, Components ...) {
enum string raw = rawIn;
Components components;
alias expand = // inverse of `.formatObject`
// not actually sure `expand is really needed
}int a, b;
auto fo = i"$a asdf $(b + 1) fdsa".formatObject;is lowered to auto fo = FormatObject!("$a asdf $(b + 1) fdsa", Formatee!("a", int), StringComponent!" asdf ", Formatee!("a", int), StringComponent!" fdsa")(
Formatee!("a", int)(a), StringComponent!" asdf "(),
Formatee!("b + 1", int)(b + 1), StringComponent!" fdsa"()
);Why bother with all of this? Well you can do this: void debugLog(FO)(FO formatObj)
if (isInstanceOf!(FormatObject, FO)) {
foreach (component; formatObj.components)
static if (isInstanceOf!(StringComponent, typeof(component)))
stderr.write(component.s);
else // it's an instance of Formatee
stderr.write(i"$(component.raw) = $(component.v)"); // format-ception
}
debugLog(i"criticalVarsHere: $a, $b, $(c + 2)".formatObject);
// prints:
// criticalVarsHere: a = 4, b = 2, c + 2 = 9and this: string bashEscape(string); // assuming we already have this
string bashEscape(FO)(FO formatObj)
if (isInstanceOf!(FormatObject, FO)) {
string res;
foreach (component; formatObj.components)
static if (isInstanceOf!(StringComponent, typeof(component)))
res ~= component.s;
else // it's an instance of Formatee
res ~= .bashEscape(text(component.v));
return res;
}
// unix allows fun filenames
string cmd = "/\"\"specialBinDir\"\"/mv";
string fn1 = "asdf";
string fn2 = "\\ ?? &| 32"
bashEscape(i"$cmd $fn1 $fn2 &".formatObject);
// escapes correctly i.e. carefully wraps up `cmd` & `fn2` but leaves final `&` alone( and this: string format(FO)(FO formatObj) {
// format now has compile-time access to the format string
// and pre-sliced components
}Maybe this is a separate DIP? |
Co-authored-by: John Colvin <john.loughran.colvin@gmail.com>
Co-authored-by: John Colvin <john.loughran.colvin@gmail.com>
Co-authored-by: John Colvin <john.loughran.colvin@gmail.com>
Co-authored-by: John Colvin <john.loughran.colvin@gmail.com>
|
Simplified version of that same feature, using m"" strings as syntax: struct Formatee(string rawIn) {
enum string raw = rawIn;
enum size_t index;
}
struct FormatObject(ComponentsIn ...) {
alias components = ComponentsIn; // these are all Formatee or string
}void debugLog(FO, Args...)(FO formatObj, auto ref Args args)
if (isInstanceOf!(FormatObject, FO)) {
foreach (i, component; formatObj.components)
static if (is(typeof(component) == string))
stderr.write(component);
else // it's an instance of Formatee
stderr.write(i"$(component.raw) = $(args[component.index])"); // format-ception
}
debugLog(m"criticalVarsHere: $a, $(c + 2)");
// prints:
// criticalVarsHere: a = 4, c + 2 = 9
//lowering
debugLog(FormatObject!("criticalVarsHere: ", Formatee!("a", 0), " ", Formatee!("c + 2", 1)), a, c + 2); |
Tweak wording. Fix lowering. Replace a remaining f-string.
Q is a value sequence, not a type. Also rename Q -> p, because it holds values, not types.
Corrected error
Improve AliasSeq example
Simple fixes
No description provided.