Skip to content

Conversation

@John-Colvin
Copy link
Owner

No description provided.

@John-Colvin
Copy link
Owner Author

John-Colvin commented Mar 24, 2021

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

criticalVarsHere: a = 4, b = 2, c + 2 = 9

edit: see #2 (comment)

@John-Colvin
Copy link
Owner Author

John-Colvin commented Mar 24, 2021

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 f-strings, not sure how with i-strings unless the caller wraps the arguments in another type (i"fdsa$(ToBeFormatted(a))"), or the callee uses some positional logic (1st argument as-is, 2nd needs escaping, 3rd as-is etc. based on how i-strings expand). But will positional logic work for i"$someString asdf"? No, because the rules say i-strings don't leave leading empty strings.

edit: see #2 (comment)

@John-Colvin
Copy link
Owner Author

John-Colvin commented Mar 24, 2021

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 = 9

and 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

(cmdEscape would probably be a better torture test)

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?

@John-Colvin John-Colvin changed the title Draft: Review Review Mar 24, 2021
andralex and others added 5 commits March 24, 2021 10:58
Co-authored-by: John Colvin <[email protected]>
Co-authored-by: John Colvin <[email protected]>
Co-authored-by: John Colvin <[email protected]>
Co-authored-by: John Colvin <[email protected]>
Co-authored-by: John Colvin <[email protected]>
@John-Colvin
Copy link
Owner Author

John-Colvin commented Mar 24, 2021

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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants