Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Last active October 18, 2023 05:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rikkimax/90a4b21feabcf34dbecb8efcb587f8e1 to your computer and use it in GitHub Desktop.
Save rikkimax/90a4b21feabcf34dbecb8efcb587f8e1 to your computer and use it in GitHub Desktop.
Formattable string DIP idea

Fundamental syntax requirements

  • Has four parts in a syntax
    • Prefix string literal
    • Mapping to another argument via offset
    • Expression
    • Format string literal
  • Must work for code generation
  • Must work for business logic (i.e. date/time heavy code)
struct FormattableStringArg {
    string prefix, format;
    ptrdiff_t expressionOffset;
}

alias FormattableString = const(FormattableStringArg)[];

Proposal

Introduce a binary-less expression, this will handle the expression that are to be interpolated.

+ QualifiedBinaryLessExpression:
+    BinaryLessExpression
+    BinaryLessExpression '.' QualifiedBinaryLessExpression

+ BinaryLessExpression:
+    TemplateSingleArgument
+    '(' AssignExpression ')'

StringLiteral:
+ 'f' '"' InterpolatedDoubleQuotedCharacters|opt '"'
+ 'f' '"' InterpolatedDoubleQuotedCharacters|opt '"' 'c'
+ 'f' '"' InterpolatedDoubleQuotedCharacters|opt '"' 'w'
+ 'f' '"' InterpolatedDoubleQuotedCharacters|opt '"' 'd'

+ InterpolatedDoubleQuotedCharacters:
+   '$' '{' QualifiedBinaryLessExpression '}'
+   '$' '{' QualifiedBinaryLessExpression|opt ':' DoubleQuotedCharacters|opt '}'
+   '$' BinaryLessExpression
+   "\$"
+   DoubleQuotedCharacters

In addition a new attribute is to be introduced in core.attributes. This attribute ConvertFormatAsString will automatically flatten a formattable string into a single string literal allowing for passing to functions like printf. It does not support out of order positional arguments.

The positional field of the FormattableStringArg must take into account the position of the formattable string literal.

If given as an argument to a function, it must take into account what the next parameter is. If it is variable argument by template or C, it must use that sequence as the basis for 0, not from the same of the function parameter list.

If given as a template argument, the positional parameters will refer to the function arguments which is how the expressions will be passed by.

When the expression parameter is given as an integer literal and followed by either : or }, it is interpreted to be the position into the expression list.

int a, b;

mixin(f"$a = $b;");

log(f"Output of a = $a, and user has name ${(user.name):s} and is ${(accurateDateTime() - user.dob) : %D}");

void log(Args...)(Args args) if (is(Args[0] == FormattableString)) {
}

void log(FormattableString format, Args...)(Args args) {
}

This will expand as:

int a, b;

mixin(cast(FormattableString)[FormattableStringArg("", "", 1), FormattableStringArg(" = ", "", -1), FormattableStringArg("", "", 2), FormattableStringArg(";", "", -1)], a, b);

log(cast(FormattableString)[FormattableStringArg("Output of a = ", "", 1), FormattableStringArg(", and user has name ", "s", 2), FormattableStringArg(" and is ", " %D", 3),], a, (user.name), (accurateDateTime() - user.dob));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment