[Ironruby-core] Module#class_eval

John Messerly jomes at microsoft.com
Fri Jan 18 18:37:50 EST 2008


Peter Bacon Darwin:

> I have been playing around with implementing Module#class_eval, partly
> because I wanted to use it in a test case and partly because I thought
> it would help my understanding of the guts of IronRuby.  I managed to
> get the following code to work but it is not pretty.
>
>         [RubyMethod("class_eval")]
>         public static object Evaluate(CodeContext/*!*/ context,
> RubyModule/*!*/ module, MutableString code) {
>
>             // Create a new context for running the code string - not
> sure if this is necessary.
>             CodeContext context2 = new CodeContext(context);
>
>             // We need a localscope for GetRfc.
>             RubyScope localScope = RubyUtils.GetScope(context);
>
>             // Create a local scope for this module definition.
>             // (This has a side-effect that context2 has the new module
> scope attached in its LocalScope property.)
>             RubyScope moduleScope = RubyOps.CreateModuleScope(context2,
> localScope.RuntimeFlowControl, module);
>
>             // Compile up the code in the new context
>             SourceUnit sourceUnit =
> context2.LanguageContext.CreateSnippet(code);
>             ScriptCode scriptCode =
> sourceUnit.Compile(context2.LanguageContext.GetModuleCompilerOptions(co
> n
> text2.Scope), null);
>
>             // Run the code in the new context.
>             // (This overload is currently private but we need to be
> able to pass in the new context).
>             return scriptCode.Run(context2, false);
>
>         }
>
> I added superfluous comments for the benefit of posting it her.  The
> main issue, as noted at the bottom of the code, is that the overload of
> ScriptCode.Run that is called is currently private.  All the public
> overloads create a new CodeContext and you lose the LocalScope which is
> needed to ensure that the code is run in the context of the module
> being defined.
>
> Any comments on this?  I assume that as the Hosting spec evolves this
> could get a lot cleaner.  Is there a better way right now to achieve
> the same result?

Nice that you got that working!

I think the main issue you're running into is that hosting APIs are in flux. That's been a delaying factor on getting all the string-based "evals" working. Also, there might be some more work in the compiler too; e.g. are we burning in references where we should be looking them up dynamically, etc. There might be other things that Tomas has in mind that need to be changed. Anyway, I think it makes sense for us to do all the eval-related stuff in one push.

> Also, one thing that really messed my head up for quite a while is the
> use of the word scope.  It took me a while to come to terms with the
> fact that there are numerous completely separate scopes: Scope,
> ScopeExtension (which contains a Scope property), ScriptScope (which
> implements IScriptScope) and RubyScope (which derives from LocalScope).
>
> Am I right in saying:
>
> Scope is the global scope in which the current Ruby program is running
> (with ScopeExtension just wrapping that and ScriptScope being a
> container for code being run within that scope)?
>
> RubyScope is the local scope within a Ruby program that tells you
> things like what the current self object is and what variables are
> accessible?

I think that's correct. Scope is the DLR global scope thing, while ScriptScope is the hosting API version. RubyScope will probably end up roughly equivalent to a binding (but it doesn't have all the stuff yet--e.g. locals)

- John



More information about the Ironruby-core mailing list