IronRuby on Your Phone

Windows Phone 7 application platform was finally revealed at MIX10. It generated a lot of excitement among .NET developers presumably due to the fact that it’s based on Silverlight. No need to learn a completely new programming model or libraries. Since the .NET Framework supports many languages you might wonder if you have the same choice on the Phone. In particular, could you script the Phone using languages built on Dynamic Language Runtime? I’m excited to announce that IronRuby 1.0 RC4 works on Windows Phone 7! Although there are some limitations the basic scripting just works as you’d expect. But keep in mind that the platform is still a technology preview (CTP) so not all features need to work seamlessly. Let’s dig into details.

Limitations

First of all, why are there any limitations at all if the Phone’s platform is Silverlight and IronRuby works on Silverlight since its inception? Although the UI and Media APIs are pretty much the same the Phone differs from the browser plug-in in the CLR execution engine and the Base Class Library. The Phone uses Compact Framework (CF) which provides only a subset of functionality available in the browser. The two platforms should converge in the future and the limitations will hopefully go away.

The main feature missing from the CF is Reflection.Emit. There are other differences but this is the most important one concerning dynamic languages. As you can imagine we do emit some code at runtime to implement dynamic features of our languages. However we also have an interpreter around. Each DLR based language can choose when to use the interpreter and when the compiler. Both IronRuby and IronPython interpret user code that is executed only a few times. It’s not efficient to compile such code since the cost for doing so is high and the execution throughput is not important. On the other hand code that’s running many times should be compiled and optimized. If the interpreter finds out that a function or a loop body is being executed more than N times it spawns its asynchronous background compilation. When the compilation is done the instructions that call the function or enter the loop are replaced by new ones that jump to the compiled code. The threshold N is configurable.

It should be clear now how to work around the lack of Reflection.Emit on the Phone. Let’s just interpret all the time! And indeed it mostly works. You won’t get a great throughput performance out of it but it works just fine for common scripts. Since the CLR interop is still available you can write performance critical code in C# and call it from the scripts. There are only a few CLR features that you need to avoid since the current interpreter doesn’t handle them without resorting to Reflection.Emit. The most significant are calls to methods with out or ref parameters. You also won’t be able to inherit a Ruby class from a CLR class or implement a CLR interface since that requires us to emit a proper CLR type. We are going to address both of these limitations in future versions.

So, IronRuby runs on the Phone. Why IronPython doesn’t yet? There is no technical reason why it couldn’t. Some parts of the IronPython runtime were just written before we implemented the interpreter and thus need some refactoring to enable full interpretation. You can motivate us to do the work faster by voting on CodePlex.

Sample App

Let’s write an app that hosts IronRuby on the Phone. It’s really simple! You just use the DLR Hosting APIs as you would do when embedding a DLR scripting language in a Silverlight app. I’ll show only the interesting parts of the app. You can download the full source code here. You’ll need Visual Studio 2010 for Windows Phone CTP and IronRuby 1.0 RC4 to try it out. Install them both and then open PhoneScripter.sln, build the solution and deploy to the emulator. Make sure that references to IronRuby and DLR assemblies in the project are correct.

The few lines that you need to run a Ruby script in the Phone emulator (and hopefully on the real device when available) are:

  • _engine = Ruby.CreateEngine((setup) => { setup.Options["CompilationThreshold"] = Int32.MaxValue; });

    Creates a Ruby engine that never compiles the interpreted code. I guess IronRuby could max out the compilation threshold by default when running on the Compact Framework. For now you need to do this manually.

  • _engine.Runtime.LoadAssembly(typeof(Color).Assembly);

    Loads System.Windows assembly into the dynamic runtime so that we can script the UI. System and mscorlib assemblies are loaded by default.

  • RubyContext context = (RubyContext)HostingHelpers.GetLanguageContext(_engine);
    context.ObjectClass.SetConstant("Phone", this);

    Makes the MainPage class instance (this) available to the script via a global constant Phone. We’ll use it to access UI elements on the page. This is a hack! You should use ScriptScope Hosting API to expose host objects to the script in your .NET apps. However, the scope dynamic object internally uses methods with out parameters and we can’t interpret calls to it from Ruby. We’ll enable this in future. For now, we work it around by directly accessing IronRuby’s RubyContext class. Be aware that this class is not a part of the Hosting APIs, we might change it in future versions and break your code. So do not use it in any production code.

  • MemoryStream stream = new MemoryStream();
    _engine.Runtime.IO.SetOutput(stream, Encoding.UTF8);
    
    try {
        try {
            _engine.Execute(Input.Text);
        } finally {
            byte[] bytes = stream.ToArray();
            Output.Text += Encoding.UTF8.GetString(bytes, 0, bytes.Length);
        }
    } catch (Exception ex) {
        Output.Text += ex.Message;
    }

    Executes a script entered in Input TextBox, captures its output and appends it to the content of Output TextBox.

We can now enter and run a Ruby script:

PhoneScripter

About these ads

5 Responses to “IronRuby on Your Phone”

  1. Markus Says:

    Very cool stuff. I am not very familiar with Ruby or Python, but knowing that other languages than C# could be integrated is a good thing. And havin a small scripting kernel inside an app would open up a whole lot of possibilities – web extensibility etc… Depends only on the speed the interpreted code is running.
    Maybe MS is loosing a bit of the restrictions and permit the Emit requests…

  2. phone translators Says:

    Good post. Thanks for sharing it in here.

  3. Joe Says:

    Good post. But if I want to add the ‘gets’ function, how do I implement that? thanks.

  4. Andrew Says:

    Hi,

    This article dates back from 2010, you mentioned about some limitations:
    ” The most significant are calls to methods with out or ref parameters. You also won’t be able to inherit a Ruby class from a CLR class or implement a CLR interface since that requires us to emit a proper CLR type. ”

    Are these still issues in the latest version of IronRuby for WP7?

    Thank you!
    Andrew

  5. tomasmatousek Says:

    Yes. The current build targets WP 7.0. Once we move to 7.5 (aka Mango) we’ll be able to lift some restrictions. The inheritace still won’t be available though.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: