[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