Make callable methods from scripts

May 12, 2010 at 10:41 AM

Hello all,

I know the subject is a bit cryptic. I hope I'll be able to explain correctly what I have in mind. And forgive the terrible terminology.

Let's pretend I have a simple file with the following content:

handler.js:

component.HP -= msg.Damage;

I'd like to know how I can "load" the file into a "delegate" I can call with parameters I'm passing via code.

componentInstance.Handler(comp, m); // should run the script loaded from the file

I know I have to tell the DLR that "component" and "msg" are objects defined in the current execution scope.

Still, is there a "ScriptedMethodBodyToDelegateWithParams" thingie around? :)

Any help is much appreciated!

 

May 12, 2010 at 4:45 PM
Edited May 12, 2010 at 4:47 PM

Using Python you could, for example, write:

var f = engine.Execute<Func<object, string>>(@"
def foo(component, msg): 
  component.HP -= msg.Damage
foo
"); 

f(comp, m); 

The language should support a conversion to a delegate type. Hosting APIs invoke such conversion in ScriptEngine.Execute<T>, ScriptScope.(Try)GetVariable<T> and ObjectOperations.(Try)(Explicit)ConvertTo<T>. Do you use IronJS to execute JScript code?

Coordinator
May 12, 2010 at 4:56 PM

Who is compiling the delegate in the first place?  Is it your language or is it some other language?

One answer might be if you’re using a language which is hostable via the DLR hosting APIs then when you compile code you get back a CompiledCode object which has an Execute method on it.  You could wrap this in a delegate such as:

(sender, args) => { compiledCode.Execute(); }

You could also set up some variables in a scope (e.g. Sender and args) and pass that into Execute.  If the language isn’t hostable via DLR hosting APIs you can use whatever APIs it does expose and do something similar.

If you are compiling this code yourself then you could produce the LambdaExpression for the JS code and have that lambda have a signature such as (object sender, EventArgs args) so that the produced delegate can be used w/ an event handler.

From: rcollina [mailto:notifications@codeplex.com]
Sent: Wednesday, May 12, 2010 3:41 AM
To: Dino Viehland
Subject: Make callable methods from scripts [dlr:212398]

From: rcollina

Hello all,

I know the subject is a bit cryptic. I hope I'll be able to explain correctly what I have in mind. And forgive the terrible terminology.

Let's pretend I have a simple file with the following content:

handler.js:

component.HP -= msg.Damage;

I'd like to know how I can "load" the file into a "delegate" I can call with parameters I'm passing via code.

componentInstance.Handler(comp, m); // should run the script loaded from the file
 
 

I know I have to tell the DLR that "component" and "msg" are objects defined in the current execution scope.

Still, is there a "ScriptedMethodBodyToDelegateWithParams" thingie around? :)

Any help is much appreciated!

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

May 12, 2010 at 10:23 PM

Thank you for your replies.

@TomasMatousek: no, I'm not using IronJS at the moment, though I will as soon as I'm out of the "design phase" (not much else to use when it comes to dlr and ecmascript, it seems).

@dinov: thanks for your input, I'll keep the "scope + .Execute()" suggestion in mind.

I'm writing a library. Some of the infrastructure provided by this library should be (scripting) language-independent. I chose Ecmascript as an example because that's the language I'd like to use when I'll be doing tests. Library users should be able to load a "schema", from either a xml file or a db for instance. This schema features scripted event handlers (something happens, script runs).

I'd like library users / end users to just type method bodies in the schema, in order to a) enforce a specific method signature b) specific param names c) minimize method signature mistakes or name collisions when dealing with many scripts d) have less to type for very simple event handlers (one line).

I also think that method bodies alone can help me swap out languages and scripts more easily, because of the following (purely imaginary) code:

IScriptingEngine engine = /* pick engine from config file or hardcoded here */;
IScript script = engine.LoadFromChunk("component.HP -= msg.Value;"); // valid only if it's the engine language, of course
var componentInst = /* */var msgInst = /* */; 
script.Run(new ScriptScope(new ScriptParam("component", componentInst), new ScriptParam("msg", msgInst)));

The only thing changing is the script passed to the LoadFromChunk method; parameters passed are something that I, as the library author, have full control on.

I hope that made sense...

Thank you again for your time.

 

May 12, 2010 at 11:35 PM

You can use scopes for this:

var scope = engine.CreateScope();
scope.SetVariable("component", componentInst);
scope.SetVariable("msg", msgInst);
engine.Execute("component.HP -= msg.Value", scope);

This doesn't create a funcion in a given language though, it executes the code as a global expression.

Composing functions in a language agnostic way is not supported today and would be more complicated.

May 13, 2010 at 3:21 PM

I'm not sure I understand what you mean by "composing function in a language agnostic way".

I think it's not uncommon to delegate behaviour to scripts wrapped in a pre-existing infrastructure (ERPs do this a lot).

Btw, I found some quality info in your blog, Tomas.

Thanks!