www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Any idea for a solution to handle overloads when dynamically

reply "Gary Willoughby" <dev nomad.so> writes:
Just wondered if i could pick you brains for a nice solution to 
dynamically add methods to a class, paying particular attention 
to overloads. I'm currently writing a mocking framework and 
everything's coming along nicely and i'm wondering how to handle 
replacing overloads of the mocked class.

To create a new mocked class this is the code:

	auto mock = new Mock!Person();

Simple enough, mock now contains an extended class with all the 
methods set to assert(false) because there are no implementations 
yet. What i need to do is to add the implementations dynamically. 
This is the code i propose.

	mock.addMethod("getAge", int delegate(){
		return 40;
	});

	assert(mock.getAge() == 40);

Which i guess would be easy to implement but it doesn't handle 
overloads because the method string doesn't contain enough 
information to define which overload it's implementing.

Any nice ideas what would be a nice way of supporting this? I 
thought i'd ask while i have a think and get some tea. :)
Sep 09 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Sep 09, 2013 at 10:16:42PM +0200, Gary Willoughby wrote:
 Just wondered if i could pick you brains for a nice solution to
 dynamically add methods to a class, paying particular attention to
 overloads. I'm currently writing a mocking framework and
 everything's coming along nicely and i'm wondering how to handle
 replacing overloads of the mocked class.
 
 To create a new mocked class this is the code:
 
 	auto mock = new Mock!Person();
 
 Simple enough, mock now contains an extended class with all the
 methods set to assert(false) because there are no implementations
 yet. What i need to do is to add the implementations dynamically.
 This is the code i propose.
 
 	mock.addMethod("getAge", int delegate(){
 		return 40;
 	});
 
 	assert(mock.getAge() == 40);
 
 Which i guess would be easy to implement but it doesn't handle
 overloads because the method string doesn't contain enough
 information to define which overload it's implementing.
 
 Any nice ideas what would be a nice way of supporting this? I
 thought i'd ask while i have a think and get some tea. :)
One idea I have is to use the built-in "typetuples" as a way of disambiguating between different overloads. For example, something like this: // This captures the function argument type list in a form that // we can call .mangleof on. template ArgTypesWrapper(ArgTypes...) { } // This builds a unique string to identify a specific overload // based on the function name and the .mangleof of its argument // types. The key to this trick is that the .mangleof of a // template encodes its argument types, so it is unique per // combination of argument types. template FuncSignature(string funcName, ArgTypes...) { enum FuncSignature = funcName ~ ArgTypesWrapper.mangleof; } class Mock(... /* whatever you currently have here */) { // This unfortunately has to be a template function in // order to be able to capture the argument types of the // delegate in the typetuple A. This may complicate the // implementation of how you'd actually dispatch to the // overload implementation at runtime. void addMethod(R, A...)(string funcName, R delegate(A...) dg) { string overloadName = FuncSignature!(funcName, A); // Now overloadName should be a unique string // representing that particular combination of // function name and argument types, i.e., it's // a function signature. So you can use it to // identify which overload is which. } } T -- Meat: euphemism for dead animal. -- Flora
Sep 11 2013
parent "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 11 September 2013 at 18:24:31 UTC, H. S. Teoh wrote:
 On Mon, Sep 09, 2013 at 10:16:42PM +0200, Gary Willoughby wrote:
 Just wondered if i could pick you brains for a nice solution to
 dynamically add methods to a class, paying particular 
 attention to
 overloads. I'm currently writing a mocking framework and
 everything's coming along nicely and i'm wondering how to 
 handle
 replacing overloads of the mocked class.
 
 To create a new mocked class this is the code:
 
 	auto mock = new Mock!Person();
 
 Simple enough, mock now contains an extended class with all the
 methods set to assert(false) because there are no 
 implementations
 yet. What i need to do is to add the implementations 
 dynamically.
 This is the code i propose.
 
 	mock.addMethod("getAge", int delegate(){
 		return 40;
 	});
 
 	assert(mock.getAge() == 40);
 
 Which i guess would be easy to implement but it doesn't handle
 overloads because the method string doesn't contain enough
 information to define which overload it's implementing.
 
 Any nice ideas what would be a nice way of supporting this? I
 thought i'd ask while i have a think and get some tea. :)
One idea I have is to use the built-in "typetuples" as a way of disambiguating between different overloads. For example, something like this: // This captures the function argument type list in a form that // we can call .mangleof on. template ArgTypesWrapper(ArgTypes...) { } // This builds a unique string to identify a specific overload // based on the function name and the .mangleof of its argument // types. The key to this trick is that the .mangleof of a // template encodes its argument types, so it is unique per // combination of argument types. template FuncSignature(string funcName, ArgTypes...) { enum FuncSignature = funcName ~ ArgTypesWrapper.mangleof; } class Mock(... /* whatever you currently have here */) { // This unfortunately has to be a template function in // order to be able to capture the argument types of the // delegate in the typetuple A. This may complicate the // implementation of how you'd actually dispatch to the // overload implementation at runtime. void addMethod(R, A...)(string funcName, R delegate(A...) dg) { string overloadName = FuncSignature!(funcName, A); // Now overloadName should be a unique string // representing that particular combination of // function name and argument types, i.e., it's // a function signature. So you can use it to // identify which overload is which. } } T
Thanks for the idea, i have implemented something based on this and it seems to be working well.
Sep 12 2013