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(context
2.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?
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?
Regards,
Pete