digitalmars.D.learn - Resolve function pointers using UDA during CT
- Tim Volckmann (42/42) Feb 09 2014 Hi guys,
- Jakob Ovrum (5/6) Feb 09 2014 No, associative arrays cannot be transferred from compile-time to
- Tim Volckmann (27/33) Feb 09 2014 You mean using static this as follows?:
- Jakob Ovrum (15/17) Feb 09 2014 There is no global list of symbols with a given UDA, you have to
- Philippe Sigaud (66/67) Feb 09 2014 Here is a possibility:
- Jakob Ovrum (2/3) Feb 09 2014 callbacks[attribute.Name] = &mixin(symbol);
- Tim Volckmann (2/78) Feb 23 2014 Works as expected, thanks Jakob and Philippe!
- Philippe Sigaud (4/7) Feb 09 2014 Hmm, std.typetuple is not necessary. And std.traits is used only to
Hi guys, is there any way to create an function-array during CT using UDAs like the following: module myUdaFunctions; struct MyUDA { string Name; } MyUDA("Function1") string myFirstUdaFunction(string myString) { // ... do something } MyUDA("Function2") string mySecondUdaFunction(string myString) { // ... do something } ///////////////////// module myMain; private { string function(string)[string] callbacks; } void main(string[] args) { // during ct: { // do something like this: // // auto u = __traits(getFunctionsByAttribute, "MyUDA") // foreach (myFunction; u) // callbacks[myFunction.GetAttribute("MyUDA").Name] = myFunction } // during runtime: if (args[1] in callbacks) { callbacks[args[1]]("myString"); } } Any way to do something like this?
Feb 09 2014
On Sunday, 9 February 2014 at 12:48:36 UTC, Tim Volckmann wrote:Any way to do something like this?No, associative arrays cannot be transferred from compile-time to runtime yet, due to implementation issues. The next best thing you can do is to use a module constructor with a generated body that fills the AA.
Feb 09 2014
On Sunday, 9 February 2014 at 13:03:47 UTC, Jakob Ovrum wrote:On Sunday, 9 February 2014 at 12:48:36 UTC, Tim Volckmann wrote:You mean using static this as follows?: module myMain; private { string function(string)[string] callbacks; } static this() { { // do something like this: // // auto u = __traits(getFunctionsByAttribute, "MyUDA") // foreach (myFunction; u) // callbacks[myFunction.GetAttribute("MyUDA").Name] = myFunction } } void main(string[] args) { if (args[1] in callbacks) { callbacks[args[1]]("myString"); } } That's also possible... but how can I find all functions with MyUDA?Any way to do something like this?No, associative arrays cannot be transferred from compile-time to runtime yet, due to implementation issues. The next best thing you can do is to use a module constructor with a generated body that fills the AA.
Feb 09 2014
On Sunday, 9 February 2014 at 13:10:14 UTC, Tim Volckmann wrote:That's also possible... but how can I find all functions with MyUDA?There is no global list of symbols with a given UDA, you have to search using __traits(allMembers) and such. the allMembers trait can be used on modules. If the functions with the UDAs are in user-defined modules, you need to have the user specify those modules (so a module constructor is not an option): --- import mylib; import usermod1, usermod2; void main() { registerFunctions!(usermod1, usermod2)(); } ---
Feb 09 2014
On Sun, Feb 9, 2014 at 2:10 PM, Tim Volckmann <timvol ymail.com> wrote:That's also possible... but how can I find all functions with MyUDA?Here is a possibility: *********** module myUDAFunctions; import std.stdio; struct MyUDA { string Name; } MyUDA("Function1") string myFirstUdaFunction(string myString) { writeln("MyFirstUDAFunction called with ", myString); return "first"; } MyUDA("Function2") string mySecondUdaFunction(string myString) { writeln("MySecondUDAFunction called with ", myString); return "second"; } ************** module myMain; import std.stdio; import std.traits; import std.typetuple; import myUDAFunctions; private { string function(string)[string] callbacks; } static this() { // Getting all symbols from module myUDAFunctions // Beware: we get strings, not aliases. // Hence the mixin() afterwards to inject them in our code foreach(symbol; __traits(allMembers, myUDAFunctions)) static if (isCallable!(mixin(symbol))) // Found some callable { // Extracting attributes foreach(attribute; __traits(getAttributes, mixin(symbol))) { // Finding those which are MyUDA's static if (is(typeof(attribute) == MyUDA)) callbacks[attribute.Name] = mixin("&" ~ symbol); } } } void main(string[] args) { writeln("Callbacks: ", callbacks); writeln("Args: ", args); if (args[1] in callbacks) { writeln(args[1], " known in callbacks"); callbacks[args[1]]("myString"); } } ************ it's a be cumbersome, you should extract the pattern and put it in a template with MyUDA and the module name as parameters. Note the ` callbacks[attribute.Name] = mixin("&" ~ symbol);` line: since `symbol` is a string, we have to mix it in the code. And since `functionName` is seen as a call to `functionName` and not as the function itself, I had to put an `&` before it (the generated code is `callbakcs["Func1"] = &Fun1;`, for example)
Feb 09 2014
On Sunday, 9 February 2014 at 13:48:36 UTC, Philippe Sigaud wrote:callbacks[attribute.Name] = mixin("&" ~ symbol);callbacks[attribute.Name] = &mixin(symbol);
Feb 09 2014
On Sunday, 9 February 2014 at 13:48:36 UTC, Philippe Sigaud wrote:On Sun, Feb 9, 2014 at 2:10 PM, Tim Volckmann <timvol ymail.com> wrote:Works as expected, thanks Jakob and Philippe!That's also possible... but how can I find all functions with MyUDA?Here is a possibility: *********** module myUDAFunctions; import std.stdio; struct MyUDA { string Name; } MyUDA("Function1") string myFirstUdaFunction(string myString) { writeln("MyFirstUDAFunction called with ", myString); return "first"; } MyUDA("Function2") string mySecondUdaFunction(string myString) { writeln("MySecondUDAFunction called with ", myString); return "second"; } ************** module myMain; import std.stdio; import std.traits; import std.typetuple; import myUDAFunctions; private { string function(string)[string] callbacks; } static this() { // Getting all symbols from module myUDAFunctions // Beware: we get strings, not aliases. // Hence the mixin() afterwards to inject them in our code foreach(symbol; __traits(allMembers, myUDAFunctions)) static if (isCallable!(mixin(symbol))) // Found some callable { // Extracting attributes foreach(attribute; __traits(getAttributes, mixin(symbol))) { // Finding those which are MyUDA's static if (is(typeof(attribute) == MyUDA)) callbacks[attribute.Name] = mixin("&" ~ symbol); } } } void main(string[] args) { writeln("Callbacks: ", callbacks); writeln("Args: ", args); if (args[1] in callbacks) { writeln(args[1], " known in callbacks"); callbacks[args[1]]("myString"); } } ************ it's a be cumbersome, you should extract the pattern and put it in a template with MyUDA and the module name as parameters. Note the ` callbacks[attribute.Name] = mixin("&" ~ symbol);` line: since `symbol` is a string, we have to mix it in the code. And since `functionName` is seen as a call to `functionName` and not as the function itself, I had to put an `&` before it (the generated code is `callbakcs["Func1"] = &Fun1;`, for example)
Feb 23 2014
On Sun, Feb 9, 2014 at 2:48 PM, Philippe Sigaud <philippe.sigaud gmail.com> wrote:import std.stdio; import std.traits; import std.typetuple;Hmm, std.typetuple is not necessary. And std.traits is used only to import `isCallable`.
Feb 09 2014