Ivan Porto Carrero
2008-Mar-18 01:05 UTC
[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 -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/ironruby-core/attachments/20080318/502dac1e/attachment.html
Ivan Porto carrero
2008-Mar-18 02:25 UTC
[Ironruby-core] hosting ironruby: globals confusion
I figured out that ScriptRuntime and ScriptScope are still language agnostic. So if you want to host IronRuby in your application you''re always looking at Level 2 hosting as soon as you want some communication between Host and IronRuby, because you need the RubyEngine. I''m still a bit unsure of how the ScriptScope ties in to everything. I understand that the ScriptRuntime is like the complete host for dyn languages and you can create a bunch of them they will always run in isolation. But how does ScriptScope work because so far I''ve been unsuccessful in talking to a ScriptScope ? Is this hosting API still too much of a moving target to really get into it? Ivan Porto Carrero wrote:> 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-- Posted via http://www.ruby-forum.com/.
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: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Ivan Porto Carrero Sent: Monday, March 17, 2008 6:05 PM To: ironruby-core at rubyforge.org 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/ironruby-core/attachments/20080319/940cd7cd/attachment-0001.html