Angel \”Java\” Lopez on Blog

July 16, 2014

RubySharp, implementing Ruby in C# (3)

Filed under: .NET, C Sharp, Open Source Projects, Programming Languages, Ruby, RubySharp — ajlopez @ 4:43 pm

Previous Post

In RubySharp, we can define new functions (methods of the current object), and invoke them. There are some built-in functions in C#:

Every function should implement the interface:

public interface IFunction
{
    object Apply(DynamicObject self, Context context, IList<object> values);
}

On apply, each function receives the object (self), the context for variables (locals, arguments, closure….), and a list of already evaluated arguments.

An example, the implemention of puts:

public class PutsFunction : IFunction
{
    private TextWriter writer;

    public PutsFunction(TextWriter writer)
    {
        this.writer = writer;
    }

    public object Apply(DynamicObject self, Context context, IList<object> values)
    {
        foreach (var value in values)
            this.writer.WriteLine(value);

        return null;
    }
}

It receives the object to which it is a method, the context, and a list of arguments. Each of the arguments was evaluated. The implementation simply sends the arguments to a TextWriter, one argument per line. The TextWriter is provided when the function object is created (in the Machine object, that represents the current running environment). This injected facilites the test of the function, example:

[TestMethod]
public void PutsTwoIntegers()
{
    StringWriter writer = new StringWriter();
    PutsFunction function = new PutsFunction(writer);

    Assert.IsNull(function.Apply(null, null, new object[] { 123, 456 }));

    Assert.AreEqual("123\r\n456\r\n", writer.ToString());
}

The above code was born using the TDD workflow.

Let’s see another built-in function, require:

public class RequireFunction : IFunction
{
    private Machine machine;

    public RequireFunction(Machine machine)
    {
        this.machine = machine;
    }

    public object Apply(DynamicObject self, Context context, IList<object> values)
    {
        string filename = (string)values[0];
        return this.machine.RequireFile(filename);
    }
}

This time, the job of loading a file is delegated to the Machin object, injected in the constructor.

And finally, let’s review the code of a defined function (defined in RubySharp):

public class DefinedFunction : IFunction
{
    private IExpression body;
    private IList<string> parameters;
    private Context context;

    public DefinedFunction(IExpression body, IList<string> parameters, Context context)
    {
        this.body = body;
        this.context = context;
        this.parameters = parameters;
    }

    public object Apply(DynamicObject self, Context context, IList<object> values)
    {
        Context newcontext = new Context(self, this.context);

        int k = 0;
        int cv = values.Count;

        foreach (var parameter in this.parameters) 
        {
            newcontext.SetLocalValue(parameter, values[k]);
            k++;
        }

        return this.body.Evaluate(newcontext);
    }
}

In this case, a new contexts is built, containing the new arguments to the defined function, but with the original closure, injected in the constructor. The context provided in the Apply is not used.

Next topics: some command implementations, the Machine object, the REPL, etc…

Stay tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

1 Comment »

  1. […] Previous Post Next Post […]

    Pingback by RubySharp, Implementing Ruby In C# (2) | Angel "Java" Lopez on Blog — July 16, 2014 @ 4:44 pm


RSS feed for comments on this post. TrackBack URI

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

Create a free website or blog at WordPress.com.

%d bloggers like this: