OdeToCode IC Logo

Execute<T> With IronRuby

Tuesday, October 4, 2011

Imagine (or dream) that you have some IronRuby code to execute.

require 'net/telnet'

host = Net::Telnet.new(:Host => 'localhost')

#...
#...
#...

return data

One way to execute the code and capture the result is to use Execute<T> on the ScriptEngine object.

public T Execute<T>(string fileName)
{
    var script = File.ReadAllText(fileName);
    var engine = IronRuby.Ruby.CreateEngine();
    engine.SetSearchPaths(
        SearchPaths // will contain paths like: 
        // @"C:\Program Files (x86)\IronRuby 1.1\Lib\ironruby" and
        // @"C:\Program Files (x86)\IronRuby 1.1\Lib\ruby\1.9.1"        
    );
    var result = engine.Execute<T>(script);
    return result;
}

However, if you want syntax checks and error messages with line numbers, you'll need to take a couple additional steps. First, define a class that derives from the abstract ErrorListener class in Microsoft.Scripting.Hosting. The ErrorReported method can provide details about errors.

public class ReportingErrorListener  : ErrorListener
{
    private readonly TextWriter _writer;

    public ReportingErrorListener(TextWriter writer)
    {
        _writer = writer;
    }

    public override void ErrorReported(
        ScriptSource source, string message, 
        SourceSpan span, int errorCode, 
        Severity severity)
    {
        _writer.WriteLine("Error starting at line {0} column {1}",
                           span.Start.Line, span.Start.Column);
        _writer.WriteLine(message);
    }
}

Now you can create a ScriptSource from the Ruby file, and use the ScriptSource object to Compile and Execute the result.

public T Execute<T>(string fileName)
{
    var engine = IronRuby.Ruby.CreateEngine();
    engine.SetSearchPaths(SearchPaths);
    var source = engine.CreateScriptSourceFromFile(fileName);
    source.Compile(new ReportingErrorListener(Console.Out));
    var result = source.Execute<T>();
    return result;
}