digitalmars.D - "multi morphic" classes
- BCS (23/23) May 01 2008 I'm working on a compiler and have run into a bit of a design challenge....
- Russell Lewis (7/7) May 01 2008 I apologize if I'm missing some subtlety, but it seems to me that this
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
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
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
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
pragma wrote:That in turn opens the door for a kind of AOPIt'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
BCS wrote:pragma wrote: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. - PragmaThat in turn opens the door for a kind of AOPIt'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).
May 02 2008