www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "multi morphic" classes

reply BCS <BCS pathlink.com> writes:
I'm working on a compiler and have run into a bit of a design challenge. 
The issue is that I want to be able to manipulate a number of aspects of 
the compiler at run time so that command line switches can turn on and 
off a number of different features. For example, modified lookup rules 
or auto typing of function returns.

This is somewhat complicated by the fact that I want to have the bulk of 
the code be unaware of the features that can be turned on. This is 
because I want the default behavior to be to function as a standard 
compiler and the the feature to implement extensions. However I want the 
standard portions of the code base to, as much as practical, be 
independent of the extensions.

One way I have thought of to do this would be to implement the AST node 
types using the default behavior but at runtime construct the AST with 
nodes of types that are modified copies of the base types. This would be 
done by having each extensions be implemented as a derived types and 
then, at runtime, construct new v-tbls that have selected methods 
replaced with the derived type methods. Then this would be used in the 
construction of nodes.

This would give a sort of "dynamically created" type. I think I could 
hack together a (highly non portable) implementation but would rather be 
able to do it within the bounds of the language. I have no idea what the 
syntax for this would be though.

thoughts ideas?
May 01 2008
parent reply Russell Lewis <webmaster villagersonline.com> writes:
I apologize if I'm missing some subtlety, but it seems to me that this 
would be pretty straightforward...

How about just building a class by hand using a struct?  You declare  a 
struct type which contains a bunch of function pointers, and each 
instance struct has a pointer to that common vtbl.  Then you write 
wrappers as member functions of the struct, which call the vtbl 
functions, pass "this" as the first argument.
May 01 2008
next sibling parent BCS <BCS pathlink.com> writes:
Russell Lewis wrote:
 I apologize if I'm missing some subtlety, but it seems to me that this 
 would be pretty straightforward...
 
 How about just building a class by hand using a struct?  You declare  a 
 struct type which contains a bunch of function pointers, and each 
 instance struct has a pointer to that common vtbl.  Then you write 
 wrappers as member functions of the struct, which call the vtbl 
 functions, pass "this" as the first argument.
yes you /could/ do this. But you can do regular OO program that way as well (and people used to IIRC). But for the same reason that all the mechanics is handled by the compiler with normal classes I'm wondering if the same could be done with these "dynamic classes". (also I kinda rather not have the extra function call to do the shelling)
May 01 2008
prev sibling parent reply pragma <eric.t.anderton gmail.com> writes:
Russell Lewis wrote:
 I apologize if I'm missing some subtlety, but it seems to me that this 
 would be pretty straightforward...
 
 How about just building a class by hand using a struct?  You declare  a 
 struct type which contains a bunch of function pointers, and each 
 instance struct has a pointer to that common vtbl.  Then you write 
 wrappers as member functions of the struct, which call the vtbl 
 functions, pass "this" as the first argument.
BCS pretty much said it all. However, I would like to mention that there is one thing that can be accomplished via this technique: interceptors/decorators. That in turn opens the door for a kind of AOP (without point-cuts obviously). Anyway, by implementing the a vtbl in plain code, you have the ability to manipulate it on the fly. Were each instance allowed to have it's own personal copy of that table, all kinds of modifications become possible. Informal decorators are just one kind of thing that's do-able in such a scheme. A practical example of a language that supports this is ECMAScript (javascript). You can modify a "class" prototype's methods, or muck about with any given instance's methods in this way. It's handy if you want to eavesdrop on just one instance of an object (insert debug code on the fly), or want to change the behavior of a whole class of objects while the system is running. - Pragma
May 01 2008
parent reply BCS <BCS pathlink.com> writes:
pragma wrote:
 That in turn opens the door for a kind of AOP 
It's neat that it could get that. I had some nebulous thoughts in that direction but don't known enough about it to really comment. I think programming for that would result in some interesting code (LOTS of SMALL methods).
 
 Anyway, by implementing the a vtbl in plain code, you have the ability 
 to manipulate it on the fly.  Were each instance allowed to have it's 
 own personal copy of that table, all kinds of modifications become 
 possible.
I wasn't really thinking of vtbl per instance but that would provide some interesting effects. I guess with the right construct you could take any object and, on the fly, replace it's vtbl with a copy and then muck around to your harts content. After thinking a bit more I think the privative that woulds be needed would work something like this // get a "type structure" that is a copy auto tmp = this.dynamic_typeof.dup; // set members tmp.methoud!(bar) = (int i) { writef("bar called with %d\n", i) // get the old memebers return tmp.methoud!(bar)(i); }; // set the instances type this.dynamic_typeof = tmp;
May 02 2008
parent pragma <eric.t.anderton gmail.com> writes:
BCS wrote:
 pragma wrote:
 That in turn opens the door for a kind of AOP 
It's neat that it could get that. I had some nebulous thoughts in that direction but don't known enough about it to really comment. I think programming for that would result in some interesting code (LOTS of SMALL methods).
Its funny you say that. If you have some time to kill take a look at Python's decorators if you're not already familiar with them: def hello(fn): print "hello" fn() hello def world(): print "world" When you call world(), you get "hello" "world" as you'd expect. Of course python's decorators are just sugar for the following: world = hello(world) ... and so forth. Decorators are also allowed to stack ad infinitum. Unfortunately, this arrangement isn't reflective *at all*, since decorators can be applied in any order the developer wishes, and they always compose into a call chain. I once naively expected the ' ' to work like Java's annotations. Boy was I in for a surprise. So with Python you get just like you said: LOTS of SMALL methods. Anyway, we can do some of this kind of stuff in D already, provided you feel like putting up with ugly russian-doll-like template compositions on your methods: void fnImpl(){ /*...*/ } alias DecoratorA!(DecoratorB!(DecoratorC!(fnImpl))) fn; //yuck! Runtime stuff, as you illustrated, would involve some delegate wizardry, but it's anything but impossible. - Pragma
May 02 2008