www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - static code generation

reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
How can I create mixes of stringified code and code itself?

http://dlang.org/mixin.html

explains how to create structs using strings. But what if I do 
not want to have to encode the whole struct as a string but only 
parts of it?


mixin template GenStruct(stringname)
{
      struct stringname ~ "alpha"
      {
          ....
      }
}


mixin GenStruct!("Helpme");

would be equivalent to do the following

struct Helpmealpha
{
     ....
}
Dec 09 2012
next sibling parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 10:42:40 UTC, js.mdnq wrote:
 How can I create mixes of stringified code and code itself?

 http://dlang.org/mixin.html

 explains how to create structs using strings. But what if I do 
 not want to have to encode the whole struct as a string but 
 only parts of it?


 mixin template GenStruct(stringname)
 {
      struct stringname ~ "alpha"
      {
          ....
      }
 }


 mixin GenStruct!("Helpme");

 would be equivalent to do the following

 struct Helpmealpha
 {
     ....
 }
I do realize I can probably do this by importing a file into a string but I do not want a ton of little files floating around to try and manage something relatively simple.
Dec 09 2012
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
You can use a templated string-returning function and mix it in:


string codeGenerator(compileTimeArguments, Other...)(Other others)
{
     string result = ...
    (...) // build your code here
     return result;
}

(...)

class C
{
     mixin(codeGenerator!(args)(1, 2, 3));
}
Dec 09 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 11:25:25 UTC, Philippe Sigaud wrote:
 You can use a templated string-returning function and mix it in:


 string codeGenerator(compileTimeArguments, Other...)(Other 
 others)
 {
      string result = ...
     (...) // build your code here
      return result;
 }

 (...)

 class C
 {
      mixin(codeGenerator!(args)(1, 2, 3));
 }
If I'm not mistaken isn't the "code" I'm trying to generate still in a string? (you've unfortunately left out the most important part at `//build your code here`)
Dec 09 2012
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 If I'm not mistaken isn't the "code" I'm trying to generate still in a
 string?
Well, yes, but not when you mix it in. It's a string mixin in this case, not a template mixin.
 (you've unfortunately left out the most important part at `//build your
 code here`)
Because it's just simple string operations using the entire language/Phobos/whatever to get the code you want. And then, you mix it in. Anonymous gave you http://dpaste.dzfl.pl/5d4cb742 With a string mixin, this gives: http://dpaste.dzfl.pl/8fc32179 string genStruct(string stringname) { return "struct " ~ stringname ~ " { //.... }"; } mixin(genStruct("s1")); mixin(genStruct("s2")); static assert(is(s1)); static assert(is(s2)); void main() {}
Dec 10 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Monday, 10 December 2012 at 20:17:41 UTC, Philippe Sigaud 
wrote:
 If I'm not mistaken isn't the "code" I'm trying to generate 
 still in a
 string?
Well, yes, but not when you mix it in. It's a string mixin in this case, not a template mixin.
My whole point is not to use strings to insert code but to use code to insert code. (essentially I want to avoid having to wrap the code with " " as it disables highlighting and possibly other features(intellisense, etc...)) We went off on a tangent before as it doesn't really solve my problem. I want to generate a partial struct and global functions and have the user supply the rest of the struct.
Dec 10 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/10/2012 01:52 PM, js.mdnq wrote:

 I want to avoid having to wrap the code with "
 " as it disables highlighting and possibly other features(intellisense,
 etc...))
The q{} syntax is supposed to help with that issue. Emacs manages syntax highlighting correctly for the q{} strings: import std.stdio; void main() { enum s = q{ writeln("hello world"); }; mixin (s); // <-- s is a string } Ali
Dec 10 2012
next sibling parent "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Monday, 10 December 2012 at 22:01:37 UTC, Ali Çehreli wrote:
 On 12/10/2012 01:52 PM, js.mdnq wrote:

 I want to avoid having to wrap the code with "
 " as it disables highlighting and possibly other
features(intellisense,
 etc...))
The q{} syntax is supposed to help with that issue. Emacs manages syntax highlighting correctly for the q{} strings: import std.stdio; void main() { enum s = q{ writeln("hello world"); }; mixin (s); // <-- s is a string } Ali
Thanks, this is definitely a step up. In Visual D, highlighting and intellisense does not work correctly but it does seem to make it easier than using a string directly. (I imagine it is the fault of Visual D for treating the argument of q as different than code) It should, though, let me do what I want easier than the other methods. Thanks again!
Dec 10 2012
prev sibling parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Monday, 10 December 2012 at 22:01:37 UTC, Ali Çehreli wrote:
 On 12/10/2012 01:52 PM, js.mdnq wrote:

 I want to avoid having to wrap the code with "
 " as it disables highlighting and possibly other
features(intellisense,
 etc...))
The q{} syntax is supposed to help with that issue. Emacs manages syntax highlighting correctly for the q{} strings: import std.stdio; void main() { enum s = q{ writeln("hello world"); }; mixin (s); // <-- s is a string } Ali
I think the issue I have with all this is that when you put code inside a string you lose a lot of compile time features AFAICT. I can do q{ struct _name_ { .... normal struct code ... } } (but everything inside q is a string) when I want to do struct _name_ { .... normal struct code ... } in code. The first is in a string and the second isn't. The difference is that with q, I can parse the code and replace _name, for example, while in the second case I can't. It makes it difficult to build up code by mixing stringified code and code. It's like, either you have to completely used stringified code or not use any at all. For example, what if I mispell writeln? Sure I get an error but it's not at all the correct line number. But if I could use "actual code" that then the error should be normal.
     enum s = q{
         writelin("hello world");
     };
in a large program, it could get confusing very quickly because essentially all errors will be pointing to oblivion. This is why I want to all the user to supply actual code(and not stringified code) so that errors will show up properly.
Dec 12 2012
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 13.12.2012 04:32, schrieb js.mdnq:
 I think the issue I have with all this is that when you put code
 inside a string you lose a lot of compile time features AFAICT.
your right - but...try to come up with an similar ("easy" to implement) powerfull solution that is not based on strings and you will see how hard it is to get it right - thats the reason for string based mixins
Dec 12 2012
parent "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Thursday, 13 December 2012 at 06:26:15 UTC, dennis luehring 
wrote:
 Am 13.12.2012 04:32, schrieb js.mdnq:
 I think the issue I have with all this is that when you put 
 code
 inside a string you lose a lot of compile time features AFAICT.
your right - but...try to come up with an similar ("easy" to implement) powerfull solution that is not based on strings and you will see how hard it is to get it right - thats the reason for string based mixins
It's not that I do not want to use strings. I simply want to allow the user to insert their own code into places I want them too. q{} helps make this easier but it still mangles the code. My prototypical example for doing this is simply creating a struct with a "custom" name. struct _name_ { .... } where _name_ is replaced with some user defined value(it can be generated at compile time based on various static settings. In this case, though, we can't just generate the struct _name string and insert it because the mixin will be invalid. The user can't supply the block({ }) because there is no way to do so, well, unless they do it with a string or q{}, which breaks debugging, highlighting, and intellisense to some degree or another. partial structs would work as well as partial mixins. pmixin(GenStructTag("mystruct")) // (inserts struct "mystruct" at this line) { .... } which, in this simple example would result in the exact same as if the user just did struct mystruct { .... } (BUT realize in both cases the code block {} are identical) We could do this: mixin(GenStructTag("mystruct", q{ .... }); and this is a workable solution I suppose... it just doesn't seem to work that well in visual D(debugging stepping is broke, highlighting is different, etc...). It is better than using a string directly though. There are many simple ways to solve the problem. Pre-processing is the easiest to implement but probably doesn't keep in line with D's approach. I think partial structs and classes will work in my case as I could generate the struct using mixin's then let the user add on to them with a partial struct. Another approach would be possibly to let one pass a code block at compile time as a sort of lambda function. A compile time type "Code" could be created, which is real code passed to a template or mixin but stringified in the process. So: mixin(GenStructTag("mystruct", struct _name_ { .... }); Where the 2nd argument is real code(possibly with "markup" or meta-tokens) that is stringified in the template mixin which can then be processed. This creates little "pre-processor" like mixin that work on code blocks and lets one generate code at compile time. It might not seem like one is gaining much from leaving out a q{} but I think it will make it much easier to debug such things as one can actually see the code and step through it, at least what is shown. The mixin might mangle the code. q{} has no idea about code. It's not meant for code. The debugger does not know it it's real code or not. But having something like c{}, or a Code type, it knows that it's a real code block and not a set of arbitrary tokens... in any case q{} is close, but IMO, not close enough.
Dec 13 2012
prev sibling next sibling parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 9 December 2012 at 10:42:40 UTC, js.mdnq wrote:
 How can I create mixes of stringified code and code itself?
[...]
 mixin template GenStruct(stringname)
 {
      struct stringname ~ "alpha"
      {
          ....
      }
 }


 mixin GenStruct!("Helpme");

 would be equivalent to do the following

 struct Helpmealpha
 {
     ....
 }
In this particular case you can do this: mixin template GenStruct(string stringname) { struct S { .... } mixin("alias S " ~ stringname ~ "alpha;"); }
Dec 09 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 19:09:49 UTC, anonymous wrote:
 On Sunday, 9 December 2012 at 10:42:40 UTC, js.mdnq wrote:
 How can I create mixes of stringified code and code itself?
[...]
 mixin template GenStruct(stringname)
 {
     struct stringname ~ "alpha"
     {
         ....
     }
 }


 mixin GenStruct!("Helpme");

 would be equivalent to do the following

 struct Helpmealpha
 {
    ....
 }
In this particular case you can do this: mixin template GenStruct(string stringname) { struct S { .... } mixin("alias S " ~ stringname ~ "alpha;"); }
But what if I use more than one mixin? I'll have multiple structs with the same name.
Dec 09 2012
parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 9 December 2012 at 19:24:24 UTC, js.mdnq wrote:
 In this particular case you can do this:
 mixin template GenStruct(string stringname)
 {
     struct S
     {
         ....
     }
     mixin("alias S " ~ stringname ~ "alpha;");
 }
But what if I use more than one mixin? I'll have multiple structs with the same name.
That's not an issue. "If two different mixins are put in the same scope, and each define a declaration with the same name, there is an ambiguity error when the declaration is referenced" (note: when it's referenced, not when it's declared) and "If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one" - http://dlang.org/template-mixin.html
Dec 09 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 9 December 2012 at 19:34:05 UTC, anonymous wrote:
 On Sunday, 9 December 2012 at 19:24:24 UTC, js.mdnq wrote:
 In this particular case you can do this:
 mixin template GenStruct(string stringname)
 {
    struct S
    {
        ....
    }
    mixin("alias S " ~ stringname ~ "alpha;");
 }
But what if I use more than one mixin? I'll have multiple structs with the same name.
That's not an issue. "If two different mixins are put in the same scope, and each define a declaration with the same name, there is an ambiguity error when the declaration is referenced" (note: when it's referenced, not when it's declared) and "If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one" - http://dlang.org/template-mixin.html
Huh? No, I mean, if I use the mixin more than once? GenStruct("s1"); GenStruct("s2"); then I'll have struct s { } alias s s1; struct s { } alias s s2; which will fail or not be what I want, since I want to generate the structs s1 and s1.
Dec 09 2012
next sibling parent Benjamin Thaut <code benjamin-thaut.de> writes:
If you need a small example for code generation, the following code will 
generate code for translating any enum value into a string:

string EnumToStringGenerate(T,string templateVar = "T", string pre = 
"")(string var){
	string res = "final switch(" ~ var ~ "){";
	foreach(m;__traits(allMembers,T)){
		res ~= "case " ~ templateVar ~ "." ~ m ~ ": return \"" ~ pre ~ m ~ "\";";
	}
	res ~= "}";
	return res;
}

string EnumToString(T)(T value){
	mixin(EnumToStringGenerate!(T)("value"));
}

Example usage:

enum Test
{
   Value1,
   Value2
}

writefln(EnumToString(Test.Value1)); //Will print "Value1"

Kind Regards
Benjamin Thaut
Dec 09 2012
prev sibling next sibling parent reply "anonymous" <anonymous example.com> writes:
On Sunday, 9 December 2012 at 19:54:17 UTC, js.mdnq wrote:
 On Sunday, 9 December 2012 at 19:34:05 UTC, anonymous wrote:
 On Sunday, 9 December 2012 at 19:24:24 UTC, js.mdnq wrote:
 In this particular case you can do this:
 mixin template GenStruct(string stringname)
 {
   struct S
   {
       ....
   }
   mixin("alias S " ~ stringname ~ "alpha;");
 }
But what if I use more than one mixin? I'll have multiple structs with the same name.
That's not an issue. "If two different mixins are put in the same scope, and each define a declaration with the same name, there is an ambiguity error when the declaration is referenced" (note: when it's referenced, not when it's declared) and "If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one" - http://dlang.org/template-mixin.html
Huh? No, I mean, if I use the mixin more than once? GenStruct("s1"); GenStruct("s2"); then I'll have struct s { } alias s s1; struct s { } alias s s2; which will fail or not be what I want, since I want to generate the structs s1 and s1.
It won't fail and you'll get s1alpha and s2alpha. Maybe it helps if you see it in action: http://dpaste.dzfl.pl/5d4cb742 (Note: "Result: Success", i.e. the asserts hold)
Dec 09 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/10/2012 01:43 AM, anonymous wrote:
 Maybe it helps if you see it in action: http://dpaste.dzfl.pl/5d4cb742
Here's a slightly modified version: http://dpaste.dzfl.pl/f2bd1428 regards, r_m_r
Dec 15 2012
parent reply "anonymous" <anonymous example.com> writes:
On Saturday, 15 December 2012 at 15:15:21 UTC, r_m_r wrote:
 On 12/10/2012 01:43 AM, anonymous wrote:
 Maybe it helps if you see it in action: 
 http://dpaste.dzfl.pl/5d4cb742
Note that here s1alpha and s2alpha are distinct types.
 Here's a slightly modified version: 
 http://dpaste.dzfl.pl/f2bd1428
Whereas here they are the same.
Dec 15 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/15/2012 08:57 PM, anonymous wrote:
 Note that here s1alpha and s2alpha are distinct types.
what about this: http://dpaste.dzfl.pl/95f7a74d regards, r_m_r
Dec 15 2012
parent reply "anonymous" <anonymous example.com> writes:
On Saturday, 15 December 2012 at 16:32:27 UTC, r_m_r wrote:
 On 12/15/2012 08:57 PM, anonymous wrote:
 Note that here s1alpha and s2alpha are distinct types.
what about this: http://dpaste.dzfl.pl/95f7a74d
Consider struct Foo {mixin (genStruct!("s1"));} struct Bar {mixin (genStruct!("s1"));} Foo.s1alpha and Bar.s1alpha are the same type. In my version they are not.
Dec 15 2012
next sibling parent r_m_r <r_m_r mailinator.com> writes:
On 12/16/2012 12:08 PM, anonymous wrote:
 Foo.s1alpha and Bar.s1alpha are the same type. In my version they are not.
OK. Fair Enough :-)
Dec 15 2012
prev sibling parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 16 December 2012 at 06:38:13 UTC, anonymous wrote:
 On Saturday, 15 December 2012 at 16:32:27 UTC, r_m_r wrote:
 On 12/15/2012 08:57 PM, anonymous wrote:
 Note that here s1alpha and s2alpha are distinct types.
what about this: http://dpaste.dzfl.pl/95f7a74d
Consider struct Foo {mixin (genStruct!("s1"));} struct Bar {mixin (genStruct!("s1"));} Foo.s1alpha and Bar.s1alpha are the same type. In my version they are not.
Yes, they should be the same type. If you are inserting an actual struct with the same name("s1") then you would expect them to be identical. (else you could just do something like mixin(genStruct!("_1", "s1")); to get a different copy of the struct. But we are not talking about inserting a field but "combining" structs. I think the updated answer is more pertinent: http://dpaste.dzfl.pl/d9f001db Here we are "inserting" a struct(well, now it is simply a template) into another(not a struct field, different things). struct B { int x; } struct A { Insert(B); } should be indentical to struct A { int x; } r_rm_r has parameterized it so that it's really A!(B) which is better so we can combine them in many ways. What all this is analogous to is multiple inheritance at compile time. A inherits B, so to speak. It is helpful in breaking down larges structs into smaller ones and being able to mix and match. One could also think of it as an algebra of structs. It would be nice to be able to do stuff like A + B, A - B(possibly useless), A*B(possibly useless), etc... A + B would just combine the members, A - B could remove the members that overlap, A*B could qualify overlapping members. struct A { int x; int y; } struct B { int x; int z; } A + B <==> struct ApB { int x; // Possible error because of overlap int y; int z; } A - B <==> struct AmB { int y; int z; } A*B <==> struct AtB { int x.A; int x.B; int y; int z; } or whatever. The usefulness is mainly that you can decompose a struct into pieces then recombine them into something possibly different. I'm not interested in the algebra aspect, just the ability to break down into two pieces, one I supply, one the user of the struct supplies. A simple A + B type of operation. The point, is, a lot of possible with such a feature. Possibly no one will use it but it could be quite powerful if it was designed appropriately.
Dec 16 2012
next sibling parent "anonymous" <anonymous example.com> writes:
On Sunday, 16 December 2012 at 08:49:10 UTC, js.mdnq wrote:
 On Sunday, 16 December 2012 at 06:38:13 UTC, anonymous wrote:
 On Saturday, 15 December 2012 at 16:32:27 UTC, r_m_r wrote:
 On 12/15/2012 08:57 PM, anonymous wrote:
 Note that here s1alpha and s2alpha are distinct types.
what about this: http://dpaste.dzfl.pl/95f7a74d
Consider struct Foo {mixin (genStruct!("s1"));} struct Bar {mixin (genStruct!("s1"));} Foo.s1alpha and Bar.s1alpha are the same type. In my version they are not.
Yes, they should be the same type. If you are inserting an actual struct with the same name("s1") then you would expect them to be identical.
I would not, actually. I'd expect it to behave like this: struct Foo {struct s1 {}} struct Bar {struct s1 {}} and not like this: struct s1 {} struct Foo {alias .s1 s1;} struct Bar {alias .s1 s1;} However, if the alias version makes more sense in your case, by all means, use that one.
Dec 16 2012
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 One could also think of it as an algebra of structs.

 It would be nice to be able to do stuff like

 A + B, A - B(possibly useless), A*B(possibly useless), etc...

 A + B would just combine the members, A - B could remove the members that
 overlap, A*B could qualify overlapping members.
Usually, given types A and B, A+B means `A or B` (in D, std.typecons.Algebraic!(A,B) ) and A*B means the tuple containing A and B (in D, std.typecons.Tuple!(A,B) ). What you're trying to do is doable in D, but you'd have to define it a bit more: if we have struct A { int a; int b} struct B { int b; int a} // just a and b swapped. What is `A+B`? `A-B`?
Dec 16 2012
parent "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 16 December 2012 at 15:34:34 UTC, Philippe Sigaud 
wrote:
 One could also think of it as an algebra of structs.

 It would be nice to be able to do stuff like

 A + B, A - B(possibly useless), A*B(possibly useless), etc...

 A + B would just combine the members, A - B could remove the 
 members that
 overlap, A*B could qualify overlapping members.
Usually, given types A and B, A+B means `A or B` (in D, std.typecons.Algebraic!(A,B) ) and A*B means the tuple containing A and B (in D, std.typecons.Tuple!(A,B) ). What you're trying to do is doable in D, but you'd have to define it a bit more: if we have struct A { int a; int b} struct B { int b; int a} // just a and b swapped. What is `A+B`? `A-B`?
(Thanks for the typeof(this) works great!) Yes, A+B = A or B. Or is inclusive though.. and "overlap" and order is immaterial. So `A+B` is equivalent to struct ApB { int a; int b; } Since order ultimately matters(the layout of the struct in memory) we could define `B+A` = struct BpA { int b; int a; } `A-B` = `B-A` = (only in this case) struct AmB { } = struct BmA { } So A*B = std.typecons.Algebraic!(A,B) which is what I initially said * should be. That should take care of that operation. How do you do the other ops?
Dec 16 2012
prev sibling parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/10/2012 01:24 AM, js.mdnq wrote:
 which will fail or not be what I want, since I want to generate the
 structs s1 and s1.
how about this: http://dpaste.dzfl.pl/c0325def regards, r_m_r
Dec 15 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Saturday, 15 December 2012 at 19:09:25 UTC, r_m_r wrote:
 On 12/10/2012 01:24 AM, js.mdnq wrote:
 which will fail or not be what I want, since I want to 
 generate the
 structs s1 and s1.
how about this: http://dpaste.dzfl.pl/c0325def regards, r_m_r
Cool, That looks like a step in the right direction. Now, the next step is to be able to "insert" code into the struct! ;) If we can get the template as a string then it can be parsed and code can be inserted, and we can also then do away with the alias and just change the name directly. Also, maybe declaring the template as static would be better?
Dec 15 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/16/2012 04:00 AM, js.mdnq wrote:
 Now, the next step is to be able to "insert" code into the struct! ;)
how about this: http://dpaste.dzfl.pl/8161d00a regards, r_m_r
Dec 15 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Saturday, 15 December 2012 at 23:04:37 UTC, r_m_r wrote:
 On 12/16/2012 04:00 AM, js.mdnq wrote:
 Now, the next step is to be able to "insert" code into the 
 struct! ;)
how about this: http://dpaste.dzfl.pl/8161d00a regards, r_m_r
No, it's backwards! ;) Or, sort of what one wants to do is: template MasterStruct_A(alias f, string c = "") { enum F = f; struct S { int X; int Y; this(int x, int y) { X = x; Y= y; } mixin (c); } } template UserStruct(alias f) { enum F = f; struct S { int A; int B; } } and mixin the UserStruct.S with the MasterStruct_A something like mixin (genStruct!(MasterStruct_A, UserStruct, "s3"); which is equivalent of to the following struct S { int X; int Y; this(int x, int y) { X = x; Y= y; } int A; int B; } S s3; This, then basically adds the ability to do partial structs(or classes) relatively easily(although not as easy if the compiler did it automatically).
Dec 15 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/16/2012 05:30 AM, js.mdnq wrote:
 and mixin the UserStruct.S with the MasterStruct_A
this is the closest I can get: http://dpaste.dzfl.pl/9d11d060 regards, r_m_r
Dec 15 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/16/2012 06:36 AM, r_m_r wrote:
 this is the closest I can get: http://dpaste.dzfl.pl/9d11d060
Cleaned up a bit: http://dpaste.dzfl.pl/d9f001db regards, r_m_r
Dec 15 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 16 December 2012 at 01:32:44 UTC, r_m_r wrote:
 On 12/16/2012 06:36 AM, r_m_r wrote:
 this is the closest I can get: http://dpaste.dzfl.pl/9d11d060
Cleaned up a bit: http://dpaste.dzfl.pl/d9f001db regards, r_m_r
That looks like it might be pretty close. I was also thinking that one could just use mixin templates of trying to do it with structs directly. I think it is the right approach but the code as is will not work with additional type parameters from MasterStruct and UserStruct. I ran into the same issues in my nested struct code: http://dpaste.dzfl.pl/64025e0a Where I had to pass the types as strings and then append the hidden parameter. Possibly you could try to figure out how to solve this problem? Maybe there is a better way then doing it with strings. (it would be real nice if I there was a compile time construct for this. like "me" or something that would return type info inside the current scope. class A(T) { this() { writeln(me.typeinfo.name); } would print "A(T)". (of course me is probably a bad name but just an example :) I'll be using your code soon once it works with multiple template parameters. (I'll make the changes if you don't) Thanks.
Dec 16 2012
next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
 it would be real nice if I there was a compile time construct for this.
 like "me" or something that would return type info inside the current
scope.
 class A(T) { this() { writeln(me.typeinfo.name); }

 would print "A(T)".

 (of course me is probably a bad name but just an example :)
You could use `typeof(this)`. It returns the static type of `this`.
Dec 16 2012
prev sibling parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/16/2012 02:03 PM, js.mdnq wrote:
 That looks like it might be pretty close. I was also thinking that one
 could just use mixin templates of trying to do it with structs directly.
i dunno if this is what u want, but have a look: http://dpaste.dzfl.pl/f5616d77 cheers, r_m_r
Dec 16 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Sunday, 16 December 2012 at 20:29:19 UTC, r_m_r wrote:
 On 12/16/2012 02:03 PM, js.mdnq wrote:
 That looks like it might be pretty close. I was also thinking 
 that one
 could just use mixin templates of trying to do it with structs 
 directly.
i dunno if this is what u want, but have a look: http://dpaste.dzfl.pl/f5616d77 cheers, r_m_r
Well, it a slightly another way and close. Let me see if I can come up with something that expresses better what I'm after. It will be a week or two though till I get around to it probably.
Dec 16 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/17/2012 04:33 AM, js.mdnq wrote:
 Well, it a slightly another way and close. Let me see if I can come up
 with something that expresses better what I'm after. It will be a week
 or two though till I get around to it probably.
OK. I'll just leave this here for future reference: http://dpaste.dzfl.pl/d8faa96a http://dpaste.dzfl.pl/fc88273b regards, r_m_r
Dec 17 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Monday, 17 December 2012 at 22:24:58 UTC, r_m_r wrote:
 On 12/17/2012 04:33 AM, js.mdnq wrote:
 Well, it a slightly another way and close. Let me see if I can 
 come up
 with something that expresses better what I'm after. It will 
 be a week
 or two though till I get around to it probably.
OK. I'll just leave this here for future reference: http://dpaste.dzfl.pl/d8faa96a http://dpaste.dzfl.pl/fc88273b regards, r_m_r
Cool. You have some useful stuff there. I'll have to go through it and see if it does what I want or could be used to do it. It looks like it does the combining so that is a definite plus. I think, though, one problem is, is you would want to wrap the user struct in a template because you might want to access the master's members from the user struct. It looks like the approach 2 does what I'm looking for pretty nicely except that, If I'm not mistaken the user struct will error out when trying to access members from the master. e.g., struct S_AB(AT, BT) { AT A; BT B; } struct S_CD(CT, DT) { void check() { writeln(A); } // error, No A CT C; DT D; } mixin ( gen!("S_ABCD", S_AB!(int, float), S_CD!(double, string)) ); I'm not actually sure about the best approach here. Using a template mixin will work but I like the look & feel of just using normal structs(as we don't have to access A in S_CD if we don't need too). In any case, it seems your method does not work with methods? if I add the `check()` to your approach-2 it fails with several strange errors. Any ideas?
Dec 17 2012
next sibling parent r_m_r <r_m_r mailinator.com> writes:
On 12/18/2012 04:42 AM, js.mdnq wrote:
 In any case, it seems your method does not work with methods? if I add
 the `check()` to your approach-2 it fails with several strange errors.
 Any ideas?
approach-2 can only combine struct fields (i.e., no method support - for that you have to use approach1). regards, r_m_r
Dec 17 2012
prev sibling parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/18/2012 04:42 AM, js.mdnq wrote:
 It looks like the approach 2 does what I'm looking for pretty nicely
 except that, If I'm not mistaken the user struct will error out when
 trying to access members from the master.
Another approach that works: http://dpaste.dzfl.pl/966d9f3a (could have been very simple if ``multiple alias this'' was available). regards, r_m_r
Dec 19 2012
parent reply "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Thursday, 20 December 2012 at 04:17:48 UTC, r_m_r wrote:
 On 12/18/2012 04:42 AM, js.mdnq wrote:
 It looks like the approach 2 does what I'm looking for pretty 
 nicely
 except that, If I'm not mistaken the user struct will error 
 out when
 trying to access members from the master.
Another approach that works: http://dpaste.dzfl.pl/966d9f3a (could have been very simple if ``multiple alias this'' was available). regards, r_m_r
I see what you are doing and it is a possible good approach. There are 2 issues I have with it: 1. Wrapping the members could be a performance hit if D does not inline. This isn't so much of an issue with the method but of D as it seems not to inline well. It's really not a big deal though at this point. 2. More serious is the inability to access elements from one struct in another. E.g., You should have some way to access S_A's members from S_B. This is difficult to do properly though since S_B generally shouldn't know about S_A. You can insert a reference to A inside B to do this, and this leads to the same issues I came across with nested structs. You end up not needing that ptr in the composite class(your S_ABC) since everything is offset from each other. So you could go down the route I went(or try and some up with another solution) to make this work. For example, possibly a simpler way to do this is: struct S_AB(bool _NestLevel) { ... public: struct S_A(int _Offset) { S_B B_f() { 'return B;' } } struct S_B(int _Offset) { S_A A_f() { 'return A;' } } mixin S_A sA; mixin S_B sB; GenUnion(...) } Where GenUnion is your mixin technique that wraps all members of S_A and S_B. Basically combining our techniques. That way no extra pointers are wasted AND we have access to "siblings". One problem with your method is it is more of a product rather than a union. A true union will allow duplicates and not store them. Technically we do not wrap the members but store everything in the composite class. Any "overlap" between the sub structures will produce only one "copy". e.g., struct S_A { int x; } struct S_B { int x; } then GenUnion(S_A, S_B) will produce a struct like S_AB { int x; } in your method, you have two x's. Now it might be impossible to efficiently generate at true union in D at the moment and your method may be the only possibility(which, is more of a product). If we could get a the struct's code rather than just the member declarations then it would be rather easy. struct S_A { int x; int y; void func(); void funcA(); } struct S_B { int x; int z; void func(); void funcB(); } then GenUnion(S_A, S_B) will produce a struct like S_AB { int x; int y; void func(); void funcA(); void funcB(); } Note that S_AB does not waste space. size(S_AB) < size(S_A) + size(S_B). Issues may arise if, say, S_A.func != S_B.func. Ways around this is to generate an error, warn, OR, we could use your method and has "perspectives" e.g., S_AB() { string Perspective = "A"; S_A sA; S_B sB; ... void func() { if (Perspective == "A") sA.func(); else sB.func(); } ... } In which case we have sort of run-time polymorphism(or you could make it compile time by using a static if instead). S_AB can change it's behavior just by setting the "perspective". This could be lead to problems conceptually since we generally do not think of structs behaving like this. It would, though, make more GenStruct more union like since the wrappers are not qualified(which produces a more product like structure). I think, but not totally sure, that the above method of perspectives is essentially a sort of of set "inheritance"(not parent child but through siblings though), For example, if A is human and B is mammal the S_AB can be made to be a human or a mammal by setting it's "perspective" but it's it's really a union one can have unrelated things, so it is not quite the same thing as inheritance. It may be useful to create variant types since or possibly other things. In any case, I think your on the right track to be able to get something useful out of it. I think, though, your limited to what you can achieve because of D's limitations of getting the code of things. For me, the two things I would need from your method to use is: 1. True union like behavior(it's ok to wrap but do not over qualify the member names). 2. The ability to access siblings without storing additional ptr's(I'm not sure if this is possible without access to the method code, my method of offsets might not work with a true union because it could change the struct's memory layout). Thanks for your work.
Dec 20 2012
parent reply r_m_r <r_m_r mailinator.com> writes:
On 12/21/2012 07:18 AM, js.mdnq wrote:
 struct S_A { int x; int y; void func(); void funcA(); }
 struct S_B { int x; int z; void func(); void funcB(); }

 then GenUnion(S_A, S_B) will produce a struct like
 S_AB
 {
     int x;
     int y;
int z; //did u miss this? ;)
     void func();
     void funcA();
     void funcB();
 }
check this: http://pastebin.com/BQW7DtSD struct S_A { int x; int y; void func() { x = 2*x; }; void funcA() { }; } struct S_B { int x; int z; void func() { x = 3*x; }; void funcB() { }; } void main() { import std.stdio: writeln; mixin (Gen!("S_AB", S_A, S_B)); pragma(msg, __traits(allMembers, S_AB)); //prints: tuple("_s0","_s1","x","y","func","funcA","z","funcB") S_AB s_ab; s_ab.x = 10; s_ab.func(); assert(s_ab.x == 20); } BTW what you are trying to achieve with your GenUnion(S_A, S_B) may require functionality currently missing in D (as you've already mentioned). For example, I can generate a struct with the fields from the two structs S_A and S_B like so: struct S_AB { int x; int y; int z; void func() { } ; //note the empty function body void funcA() { } ; void funcB() { }; } but it will be useless since AFAIK I cannot get a stringof S_A.func()'s body at compile time. One alternative as I've shown is to generate a struct with hidden fields and properties (until 'multiple alias this' functionality gets implemented) which will atleast behave like your GenUnion(S_A, S_B) struct (from a user perspective). BTW if you find any interesting alternative, please consider adding it to the dwiki - http://wiki.dlang.org/ (for e.g.: http://wiki.dlang.org/Combining_Structs) regards, r_m_r
Dec 20 2012
parent r_m_r <r_m_r mailinator.com> writes:
On 12/21/2012 10:30 AM, r_m_r wrote:
 http://wiki.dlang.org/Combining_Structs)
the link should be: http://wiki.dlang.org/Combining_structs regards, r_m_r
Dec 21 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-12-09 11:42, js.mdnq wrote:
 How can I create mixes of stringified code and code itself?

 http://dlang.org/mixin.html

 explains how to create structs using strings. But what if I do not want
 to have to encode the whole struct as a string but only parts of it?


 mixin template GenStruct(stringname)
 {
       struct stringname ~ "alpha"
       {
           ....
       }
 }


 mixin GenStruct!("Helpme");

 would be equivalent to do the following

 struct Helpmealpha
 {
      ....
 }
Sounds like someone wants AST-macros. Yes I know, we don't have a proposal. -- /Jacob Carlborg
Dec 13 2012