Ruby integration into hosting API is not finished yet. Last week I’ve checked 
in some basic support for scopes.

“I was expecting when I set a variable in globals that it becomes a global 
variable or do I have to access that differently?”

Globals dictionary on ScriptRuntime are actually not the same globals as Ruby 
globals. Think of ScriptRuntime.Globals as a top level namespace. If you load 
.NET assembly, say mscorlib, into ScriptRuntime, top namespaces (e.g. “System”) 
are added to Globals. In IronRuby, you’ll see content of ScriptRuntime.Globals 
thru Object class. When searching for a constant on Object class the 
ScriptRuntime.Globals is looked up. Therefore you can do System::Collections in 
your IronRuby code. See RubyModule.TryGetConstant.

So the right way of doing what you’re trying to do is (as you have it below):

var runtime = IronRuby.CreateRuntime();
var ec = IronRuby.GetExecutionContext(runtime);
ec.DefineGlobalVariable(“version”, “foo”);
runtime.ExecuteFile(“commands.rb”);

I’m using the latest bits where I’ve recently added DefineGlobalVariable 
method. If you don’t see it yet, use GlobalVariables collection on ec.

As for the ScriptScope. In general, ScriptScope is a host provided dictionary 
against which you can execute code. ScriptScope has an extension for each 
language that is executed against it. For IronRuby it is GlobalScopeExtension 
class. This extension associates the scope with a singleton self object on 
top-level scope and with the top-level binding. The singleton object “type” is 
defined in MainSingletonOps class. If file is executed as a regular Ruby source 
code the singleton is exactly like in MRI. If executed using hosting API it 
redefines method_missing. The method_missing implementation goes to the 
ScriptScope’s dictionary. This way the following works:

var scope = engine.CreateScope();
scope.SetVariable(“x”, 1);
scope.SetVariable(“y”, 2);
scope.Execute(“puts x + y”);

In this code, ‘puts’, ‘x’ and ‘y’ are method calls (since there is no 
assignment to these identifiers in the code). ‘puts’ get resolved to 
Kernel#puts as usual. ‘x’ and ‘y’ don’t exist so ‘method_missing’ is called as 
usual in MRI. Since the current ‘self’ object is main singleton that in 
IronRuby defines ‘method_missing’, ‘x’ and ‘y’ values are loaded from the scope.

Note, that this doesn’t work yet:
var scope = engine.CreateScope();
scope.SetVariable(“x”, 1);
scope.SetVariable(“y”, 2);
scope.Execute(“z = x + y”);
var z = scope.GetVariable<int>(“z”);

It’s because ‘z’ is a local variable (it is assigned to in the code) and 
therefore it lives on the top-level binding. The plan is to associate the 
top-level binding with the scope but we are not there yet.

Instead you can do this:
var scope = engine.CreateScope();
scope.SetVariable(“x”, 1);
scope.SetVariable(“y”, 2);
scope.Execute(“def self.z; x + y; end”);
var z = scope.GetVariable<Function<int>>(“z”)();

This works since methods defined on the singleton are accessible to the host 
via the scope.

BTW: John is now working on syncing our TFS with SVN (there is some issue that 
needs to be fixed). So some of the changes I’ve done recently to enable the 
above scenarios haven’t probably been pushed out yet.

Any feedback on hosting API is welcomed. There are few missing pieces that are 
described in the spec but not yet in the code and also IronRuby is not yet 
plugged completely into the hosting infrastructure.

Tomas


From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Ivan Porto 
Carrero
Sent: Monday, March 17, 2008 6:05 PM
To: [email protected]
Subject: [Ironruby-core] hosting ironruby: globals confusion

Hi,

I updated the hosting wiki page to work with the current revision. But this 
raises a couple of questions.

I'm just working my way through the dlr-hosting-spec.
And if I read it correctly then there are 3 levels of hosting/integration 
possible.

Now AFAICT level 1 hosting is only supposed to work with external files, 
because for compiling to a source unit you need a different class than either 
ScriptRuntime or ScriptScope
I was expecting when I set a variable in globals that it becomes a global 
variable or do I have to access that differently?

So I tried the following bit of code:

ScriptRuntime runtime = IronRuby.CreateRuntime();
runtime.Globals.SetVariable("version", "simplest test possible with a variable 
succeeded");
runtime.ExecuteFile("commands.rb");

and the file commands.rb contains one line of ruby code: puts $version
put the output of that code is nil instead of the expected string.

This returns nil. I have trouble reconciling that with what I read in the 
hosting spec. Because this should be totally doable with Level 1 hosting or am 
I wrong in this assumption?

When I create a ScriptRuntime shouldn't it then have a DefaultScope (Globals) 
that is language-specific to ruby because I create it with the static method on 
IronRuby?

Also for as far as i understand it a ScriptScope is like a container for your 
scripts so globals in that container are only alive in that script scope?

Anyway when I go and use level 2 hosting because I need the execution context 
and script engine and these are only introduced in level 2 hosting. I can set 
global variables and then things do work

ScriptRuntime runtime = IronRuby.CreateRuntime();
ScriptEngine rubyengine = IronRuby.GetEngine(runtime);
RubyExecutionContext ctx = IronRuby.GetExecutionContext(runtime);

ctx.GlobalVariables[SymbolTable.StringToId("variable")] = "simplest test 
possible with a variable succeeded";
runtime.ExecuteSourceUnit(rubyengine.CreateScriptSourceFromString("puts 
\"#{$variable}\""));

And in the level 2 hosting sample the RubyExecutionContext seems to do what I 
was expecting ScriptScope to do.

Am I reading the spec wrong ?

Cheers
Ivan

_______________________________________________
Ironruby-core mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ironruby-core

Reply via email to