[phobos] expand for std.metastrings

kenji hara k.hara.pg at gmail.com
Tue Nov 2 23:04:45 PDT 2010


Paste my old code which creates tagged-union.
Is this a example of strong argument?

----
class Exp
{
    mixin TagUnion!(
        "CONST",IntT,
        "NAME", Label,
        "ESEQ", Stm, Exp
    );
}
Exp e;
e = CONST(10);
e = LABEL(l)
e = ESEQ(s, e);

template TagUnion(T...)
{
  ...

  // tycon tags
    enum MakeTyconTags =
        "enum Tag:"~(LeastUnsignedType!TyconCnt).stringof~"{ "
            ~staticReduce!(q{A==""?B~"=0":A~", "~B}, "", TyconTags)~" "
        "}";

  // tycon types
    template MakeTyconTypeField(size_t N)
    {
        template MakeTyconTypeField(size_t I)
        {
            enum MakeTyconTypeField = ToLongString!(TyconSig!N[I])~"
_"~to!string(I);
        }
    }
    template MakeTyconType(size_t N)
    {
        enum MakeTyconType =
            "static struct "~TyconTag!N~"_T{ "
                "Tag tag; "
                ~staticReduce!(q{A==""?B:A~"; "~B}, "",
generateTuple!(0, TyconSig!N.length, MakeTyconTypeField!N))~"; "
            "}";
    }
    enum MakeTyconTypes =
        staticReduce!(q{A==""?B:A~"\n"~B}, "", generateTuple!(0,
TyconCnt, MakeTyconType));

  // tycon datas
    template MakeTyconData(size_t N)
    {
        enum MakeTyconData = TyconTag!N~"_T data"~to!string(N)~";";
    }
    enum MakeTyconDatas =
        "union{ "~
            "Tag tag; "
            ~staticReduce!(q{A==""?B:A~" "~B}, "", generateTuple!(0,
TyconCnt, MakeTyconData))~
        " }";

  // ctors
    template MakeCtor(size_t N){
        enum MakeCtor =
            "this(ref "~TyconTag!N~"_T data){ data"~to!string(N)~" = data; }";
    }
    enum MakeCtors =
        staticReduce!(q{A==""?B:A~"\n"~B}, "", generateTuple!(0,
TyconCnt, MakeCtor));

  // tycons
    template MakeTycon(size_t N){
        enum MakeTycon =
            `static auto `~TyconTag!N~`(U...)(U args){`
                                         "\n"
            `   static if (is(U == TypeTuple!(`
                        ~staticReduce!(q{A==""?B:A~", "~B}, "",
staticMap!(ToLongString, TyconSig!N))~  `)))`   "\n"
            `   {`
                                         "\n"
            `       return new
typeof(this)(`~TyconTag!N~`_T(Tag.`~TyconTag!N~`, args));`
          "\n"
            `   }`
                                         "\n"
            `   else static if (Tie!U.isMatchingTuple!(`
                        ~staticReduce!(q{A==""?B:A~", "~B}, "",
staticMap!(ToLongString, TyconSig!N))~  `))`    "\n"
            `   {`
                                         "\n"
            `       return tie(Tag.`~TyconTag!N~`, args);`
                                         "\n"
            `   }`
                                         "\n"
            `   else`
                                         "\n"
            `   {`
                                         "\n"
            `       static assert(0);`
                                         "\n"
            `   }`
                                         "\n"
            `}`;
    }
    enum MakeTycons =
        staticReduce!(q{A==""?B:A~"\n"~B}, "", generateTuple!(0,
TyconCnt, MakeTycon));

  // opTieMatch
    template MakeTieMatchCase(size_t N){
        enum MakeTieMatchCase =
            `   case Tag.`~TyconTag!N~`:`
                         "\n"
            `       static if (Tie!U.isMatchingTuple!(Tag,
TyconSig!`~to!string(N)~`))`         "\n"
            `       {`
                         "\n"
            `           return tie =
tuple(data`~to!string(N)~`.tupleof);`                      "\n"
            `       }`
            `       else`
                         "\n"
            `       {`
                         "\n"
            `           return false;`
                         "\n"
            `       }`;
    }
    template MakeTieMatchInstanceIf(size_t N)
    {
        enum MakeTieMatchInstanceIf =
            `Tie!U.isMatchingTuple!(Tag, TyconSig!`~to!string(N)~`)`;
    }
    enum MakeTieMatch =
        `bool opTieMatch(U...)(ref Tie!U tie){`
                         "\n"
        `   static if (!(`
                ~staticReduce!(q{A==""?""~B:A~" || "~B}, "",
generateTuple!(0, TyconCnt, MakeTieMatchInstanceIf))~
            `))`
                         "\n"
        `   {`
                         "\n"
        `       static assert(0);`
                         "\n"
        `   }`
                         "\n"
        "   \n"
        `   final switch( tag ){`
                         "\n"
        ~staticReduce!(q{A==""?B:A~"\n"~B}, "", generateTuple!(0,
TyconCnt, MakeTieMatchCase))~ "\n"
        `   }`
                         "\n"
        `}`;

  // export tycons out of class/struct
    enum MakeTyconAlias =
        `import meta;`
                                         "\n"
        `template MakeAlias(size_t N)`
                                         "\n"
        `{`
                                         "\n"
        `   enum MakeAlias =`
                                         "\n"
        `       "alias "`
                                         "\n"
        `           ~ToLongString!(typeof(this))~"."~`
                                         "\n"
        `
TypeTuple!(`~staticReduce!(q{A==""?"\""~B:A~"\", \""~B}, "",
TyconTags)~`")[N]`         "\n"
        `               ~" "~`
                                         "\n"
        `
TypeTuple!(`~staticReduce!(q{A==""?"\""~B:A~"\", \""~B}, "",
TyconTags)~`")[N]`         "\n"
        `           ~";";`
                                         "\n"
        `}`
                                         "\n"
        `template Tycons()`
                                         "\n"
        `{`
                                         "\n"
        `   enum Tycons =`
                                         "\n"
        `       staticReduce!(q{A==""?B:A~"\n"~B}, "",
generateTuple!(0, `~to!string(TyconCnt)~`, MakeAlias));` "\n"
        `}`;

private:
    mixin(MakeTyconTags);
    mixin(MakeTyconTypes);
    mixin(MakeTyconDatas);
    mixin(MakeTieMatch);
public:
    mixin(MakeCtors);
    mixin(MakeTycons);
    mixin(MakeTyconAlias);
}
----


2010/11/3 Robert Jacques <sandford at jhu.edu>:
> On Tue, 02 Nov 2010 14:27:28 -0400, kenji hara <k.hara.pg at gmail.com> wrote:
>
>>> enum code = text(q{ enum msg = "I call you "}, count, q{" times"} );
>>> enum code = text(` enum msg = "I call you `, count, ` times;` );
>>> enum code = ` enum msg = "I call you ` ~ count ~ ` times;`
>>> enum code = q{ enum msg = "I call you "} ~ count ~ q{" times"; }
>>
>> 1st and 4th does not generate intended code string, but generates invalid
>> one.
>> expand! generates 3rd code automatically cooperation with mixin.
>> (2nd is ... the code currently others want to generate for run-time
>> performance?)
>
> Opps. Sorry, I tested 2 & 3, but forgot to test 1 & 2. I also seemed to have
> forgotten a " after times in 2 & 3.
>
> Also, what do you mean by: (2nd is ... the code currently others want to
> generate for run-time performance?)
>
>>> I admit ${n} is slightly better than },n,q{, but it's by no means ugly.
>>> (And
>>> using `` instead of q{} makes it better: `,n,`)
>>
>> The advantage of expand! is that escapes string quotations and
>> concatenates correctly while keeping readability of our meta-code
>> well.
>> (In above 3rd, you escape q{} to `` and interpolate "count" *manually*.)
>
> Yes, manually escaping and concatenating, in all but the trivial cases, is
> really annoying. But my main point was that text is both CTFE-able and lets
> you cleanly do everything expand does naturally. Expand is more complex to
> use, isn't self-documenting (i.e. you have to remember to use a mixin), is
> mostly redundant and increases the radius of comprehension of phobos.
> However, it does allow you to escape a token strings inside a nested string
> in a nice in-lined way. So far, the examples don't seem to provide a strong
> argument for yet another text formater beyond text and Format. Also, if I
> recall correctly the plan is to get a large portion of both phobos and D
> CTFE compatible, which would eventually eliminate the need for the current
> metastrings.
>
>
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos
>


More information about the phobos mailing list