New syntax for string mixins

Graham St Jack Graham.StJack at internode.on.net
Tue Dec 14 15:19:46 PST 2010


> I don't know, do you have an example ?
>
>> For example taking a classname and a bunch of field types and names, and
>> turning it into a class definition complete with constructor from field
>> values, constructor from an input stream, a method to write to an output
>> stream, and const getters. Or maybe std.typecons.AutoImplement.
>
> Could you post an example of how that mixin would be used and the code 
> it would generate then I can see if I can translate it to my syntax. 
> AutoImplement seems to just contain template mixins which is something 
> else.
>

I have attached my concurrency framework, which relies heavily on 
mixins, plus its unit test to show how it is used. I haven't included 
the various dependencies because I assume you just want the example 
code. Let me know if you want something buildable, or perhaps something 
more cut-down.

What the code-generating template does is to create from something like 
this (you can have any number of Messages in a Protocol):


alias Protocol!("Requests",    Message!("job",    string, "name")).code 
jobCode;
mixin(jobCode);


this code:


class Requests {
     struct jobMsg {
         string name;
         this(string name) {
              this.name = name;
         }
         void read(InStream stream) {
              name = stream.get!string;
         }
         void write(OutStream stream) {
             stream(name);
         }
     }
     struct Message {
         uint kind;
         union {
         jobMsg job;
         }
         this(ref jobMsg msg) {
             kind = 0;
             job = msg;
         }
         this(InStream stream) {
             kind = stream.get!uint;
             switch(kind) {
             case 0: job.read(stream); break;
                 default: assert(0, "Cannot read unsupported message kind");
             }
         }
         void write(OutStream stream) {
             stream(kind);
             switch(kind) {
             case 0: job.write(stream); break;
                 default: assert(0, "Cannot write unsupported message 
kind");
             }
         }
     }
     private alias Channel!(Message) _Chan;
     private alias shared _Chan Chan;

     private Chan channel;
     this() { channel = new Chan(); }
     ChannelSelectable newSelectable() { return channel.newSelectable(); }
     void finalize() { channel.finalize; }

     interface IHandler {
         void job(string name);
     }
     void job(string name) {
         channel.add(Message(jobMsg(name)));
     }
     void receive(IHandler handler) {
         auto message = channel.remove;
         switch (message.kind) {
             case 0: handler.job(message.job.name); break;
             default: assert(0, "Cannot dispatch unsupported message kind");
         }
     }
}



I use this for inter-thread communications, and I use the discriminated 
union to pass messages between processes. The manual mixin after the 
alias is a debugging aid - the compiler errors when doing mixins aren't 
helpful at all. I case you are wondering why I did all this, it was 
partly a learning experience, but mostly an attempt to do something 
properly thread-safe (!hasAliasing), using shared, const and immutable 
properly.

-- 
Graham St Jack

-------------- next part --------------
A non-text attachment was scrubbed...
Name: concurrency.d
Type: text/x-dsrc
Size: 18980 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20101215/ed14b56f/attachment-0002.d>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: concurrency_test.d
Type: text/x-dsrc
Size: 3095 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20101215/ed14b56f/attachment-0003.d>


More information about the Digitalmars-d mailing list