www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling arbitrary functions at runtime?

reply Kevin Balbas <kbalbas hotmail.com> writes:
I'm writing a system to register functions to be called at 
runtime.  With zero-argument functions, it works fine.  However, 
I run into a problem with functions that take arguments.

This is the relevant code I started with (zero-argument version):

mixin template CommandSystemRegister(string s = __MODULE__)
{
     void CommandSystemRegisterCommands()
     {
         foreach(name; __traits(allMembers, mixin(s)))
         {
             static if (hasUDA!(mixin(name), RegisterCmd))
             {
                 commandTable[name] = &mixin(name);
             }
         }
     }
}

void CommandSystemExecuteCommand(string cmd)
{
     auto result = cmd in commandTable;

     if (result !is null)
     {
         (*result)();
     }
     else
     {
         writefln("command %s not found.", cmd);
     }
}

The way to extend this seemed fairly straightforward.  I did the 
following things:

1.  Wrap function with a Variant, and put that Variant into a 
struct alongside an array of stringified parameter types (because 
Parameters!T can't be stored directly).

2.  On execution, parse the arguments to their correct types.

The problem is, I can't figure out how to actually *call* the 
function.  If it were python, I could construct a tuple with a 
comprehension and unpack that, but I can't figure out any way to 
dynamically construct tuples this way in D.

Basically, I need some way to turn an array of strings into an 
argument list at runtime.  Is this possible?
Dec 11 2016
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 11 December 2016 at 22:00:27 UTC, Kevin Balbas wrote:
 Basically, I need some way to turn an array of strings
 into an argument list at runtime.  Is this possible?
Write (or generate) a helper function that loops over the Parameters!Func tuple and populates it from the strings. Call the helper function. // declare your arguments tuple Parameters!Func args; // populate the arguments foreach(idx, ref arg; args) { arg = to!(typeof(arg))(string_args[idx]); } Func(args); // call the function with that tuple The free sample of my book: https://www.packtpub.com/application-development/d-cookbook has a more in-depth example near the end of it.
Dec 11 2016
parent Kevin Balbas <kbalbas hotmail.com> writes:
On Sunday, 11 December 2016 at 22:18:02 UTC, Adam D. Ruppe wrote:
 On Sunday, 11 December 2016 at 22:00:27 UTC, Kevin Balbas wrote:
 Basically, I need some way to turn an array of strings
 into an argument list at runtime.  Is this possible?
Write (or generate) a helper function that loops over the Parameters!Func tuple and populates it from the strings. Call the helper function. // declare your arguments tuple Parameters!Func args; // populate the arguments foreach(idx, ref arg; args) { arg = to!(typeof(arg))(string_args[idx]); } Func(args); // call the function with that tuple The free sample of my book: https://www.packtpub.com/application-development/d-cookbook has a more in-depth example near the end of it.
I see. I was planning on doing a wrapper-based approach to the function calls if this didn't work out, but I didn't expect it'd be that simple. Thanks for the tip.
Dec 11 2016
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
import std.traits;
import std.stdio;


alias FDg = void delegate (string args);

FDg[string] cmdlist;

void register(DG) (string name, DG dg) if (isCallable!DG) {
   cmdlist[name] = delegate (string args) {
     import std.array : split;
     import std.conv : to;
     alias Args = Parameters!DG;
     auto spx = args.split(' ');
     Args ara;
     foreach (immutable idx, ref a; ara) {
       a = spx[idx].to!(typeof(a));
     }
     dg(ara);
   };
}


void main () {
   register("test", (int a, bool b) { writeln("a=", a, "; b=", b); 
});
   cmdlist["test"]("42 true");
}
Dec 11 2016