Meta-programming - examples

Bill Baxter dnewsgroup at billbaxter.com
Sat Feb 10 22:00:21 PST 2007


kris wrote:
> janderson wrote:
>> A couple of people have been asking questions about pseudo-real-life 
>> examples for the new compile time code aspects of D.  I ask this 
>> question for my interest as well.
>>
>> Assuming that we have a good mechanism to process the input how could 
>> compile time code improve your every-day proficiency?  (This is 
>> specifically about the Mixin Expressions aspect).
>>
>> I'll start with a few of my own.  Note my background is
>> game-programming.  In my experience, we care constantly creating tools 
>> to generate code because its impracticable to write and maintain it by 
>> hand.
>>
>> Statemachine (and AI logic) written by design and coders are common in 
>> game programming.  Normally we have to fallback on a script language 
>> which is never as powerful.
>>
>> mixin(statemachine(
>> "
>>     state FireAtEnemy
>>     {
>>         transition EnemyRange < 10
>>         {
>>             goto ChaseEnemy
>>         }
>>         transition FacingEnemy < .2
>>         {
>>             goto ChaseEnemy
>>         }
>>     }
>>
>>     state ChaseEnemy
>>     {
>>         ...
>>     }
>>
>> ");
>>
>> You might imagine doing the above with if statement and arrays of 
>> delegates however designers have a much harder time with that.
>>
>> 3D Object rendering
>>
>> //Render a 3D model.  For instance this may generate the vertexbuffers 
>> and textures directly into code, or may extract some of the data from 
>> the 3Dmodel.obj and load the rest at run-time.
>> mixin(renderModel(import("3Dmodel.obj")));
>>
>> Transforming Textures
>> DXDtexture* texture = mixin(textureToD3D(import("3Dmodel.bmp")));
>>
>> Simplify saving/loading of arbitrary structures.
>>
>> //Only write this once.  Things are re-ordered for best fit in memory, 
>> localization ect...
>> mixin(Serailzable("Ship",
>> "
>>     struct Part
>>     {
>>         float firePower;
>>         char[] Model;
>>     }
>>
>>     struct Ship
>>     {
>>         bool Friendly;
>>         Part Parts[];
>>     }
>> ");
>>
>> ... Later
>>
>> Load("Ship", "Ship.asset");
>>
>> GUI -> not sure about this one as I can't come up with a format thats 
>> much neater then straight code. I'll post it anyways.
>>
>> mixin(MyGUI(
>> "
>>     Button "OK", 10, 30
>>     {
>>         Exit;
>>     }
>> ");
>>
>> Multi-threading
>>
>> The suggestion with multi-threading I came up with a little while ago:
>>
>> int[] array ...
>> int result = 0;
>> mixin(threadIt(
>> "
>>     foreach(A a; array)
>>     {
>>         result += a;
>>     }
>>     combiner //If necessary?
>>     {
>>         result = result[0] + result[1];
>>     }
>> ");
>>
>> Compile time checking of code for coding standards or what have u:
>>
>> mixin(CheckCode("
>>
>> ect...
>>
>>
>> ");
>> //Note that there should be a way to disable CheckCode in the general 
>> case to save compile time

Hmm.  Me hopes more and more that something can be done about string 
literals.  I don't really want to end up having big chunks of my code 
stashed away in quotes.  Editors don't know how to highlight it or 
format it, even if it's plain D on the inside.

>> There's heaps of other stuff, but that would make this post way to long.
>>
>> Personally I see this new mixin format as giving us the power to 
>> extend D in whatever way meets our goals.  As Walter adds more 
>> features some of them will be rarely used (law of demising returns) 
>> because they are special case.  Mixin Expressions circumvent this 
>> because now the programmer has the power to create the language 
>> features they need.
>>
>> The only downside I see is compile-time, which I hope can be solved 
>> with a smart caching system.
> 
> 
> Thanks, very much. It's refreshing to see some concrete examples.
> 

I had forgotten about this, but there's also the example of Qt's dynamic 
signals and slots that was discussed a while back.  Qt's moc compiler 
/sort of/ knows how to process most /garden-variety/ C++ in order to 
extract method signatures, so that it can generate string-based run-time 
stubs.  The stubs let you write code like:
     connect(object1,"notifyFoo(int)", object2,"fooChanged(int)");
To connect up object1's notifyFoo signal with object2's fooChanged 
method.  In Qt's implementation, the moc compiler generates a 
string->method_pointer lookup table in each QObject and some other 
boilerplate so that the lookup can be done dynamically at runtime.  That 
allows you to load a UI script at runtime and connect up the signals and 
slots dynamically based on just the names of methods.

Actually, that seems like it should be mostly doable already via tuples 
and mixins.  But instead of syntax like
     slot void myMethod(int x) { . . . }
you'd need
     void myMethod(int x) { . . . }
     mixin DynamicSlot!("myMethod");

But you'd probably need to declare all the dynamic slots in one place, like
     mixin DynamicSlots!("myMethod",
			"myOtherMethod",
			"aThirdMethod");
It would be nice if you could do them a method at a time, though, to 
keep them close to the place where they're declared.  Even better if it 
could be done without repeating the name.   Maybe something like

     mixin(DynamicSlot!("void myMethod(int x)")) { . . . }

Meh.  Still ugly.  It would be a lot nicer if it could just be
     DynamicSlot! void myMethod(int x) { . . . }

Still not sure how that would manage to collect all the slot info into 
one big function that does the run-time lookup, though.

--bb



More information about the Digitalmars-d mailing list