Angel \”Java\” Lopez on Blog

April 13, 2011

Dynamic Language Runtime (Part 3) Binary Expressions

Filed under: .NET, C Sharp, Code Generation, Dynamic Language Runtime — ajlopez @ 2:27 pm

Next post
Previous post

I implement simple examples using DLR. I showed how to create and evaluate expressions. Every Expression has some exposed properties and methods:

Note that each Expression object has an NodeType, and separated Type. Let explore that values:

BinaryExpression expr = Expression.Add(Expression.Constant(10),
    Expression.Constant(20));
Console.WriteLine(expr.GetType().FullName);
Console.WriteLine(expr.Type);
Console.WriteLine(expr.Left.Type);
Console.WriteLine(expr.Right.Type);
Console.WriteLine(expr.NodeType);
Console.WriteLine(expr.Left.NodeType);
Console.WriteLine(expr.Right.NodeType);

This is the first time I wrote an Expression.Add. This is a binary expression. Every binary expression has to leafs:

The output of the above code:

Note that the .GetType() (the .NET type) of the created Expression, is SimpleBinaryExpression: it’s not only an Expression object. But there is no AddExpression in DLR. The expr.NodeType exposes that the created expression is an Add one. DLR creators decided not to write a dedicated class for Expression.Add.

The BinaryExpression has a Type: System.Int32, an integer. This is the type that indicates what is the type of the returned value. It is derived from the types of the left and right part of the binary expression.

As in C#, we can combine binary expressions:

// double result = (3d + 2d) / 7d;
// Console.WriteLine(result);
BinaryExpression expr2 = Expression.Divide(
    Expression.Add(Expression.Constant(3d),
        Expression.Constant(2d)),
    Expression.Constant(7d)
    );
Func<double> binaryDelegate = Expression.Lambda<Func<double>>(expr2).Compile();
Console.WriteLine(binaryDelegate.Invoke());

Main source for this example: “Pro DLR in .NET 4” by Chaur Wu. The code of this post series is at  http://code.google.com/p/ajcodekatas/ under trunk/Dlr.

Next steps: IfThenElse expressions, switch expression, what is a Visitor? and a Reduce?.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

April 7, 2011

Dynamic Language Runtime (Part 2) Hello Expressions!

Filed under: .NET, C Sharp, Code Generation, Dynamic Language Runtime — ajlopez @ 10:20 am

Next post
Previous post

In my previous post I wrote a simple “Hello, world” program. This time, I begin to explore the Expression features of DLR. The code of this post series is at 
http://code.google.com/p/ajcodekatas/ under trunk/Dlr.

First, an Expression in DLR is not a System.Linq.Expression (it was one of my first mistake, in this example, to use the Linq version). DLR has its own implementation, with more methods, at Microsoft.Scripting.Ast. AST is Abstract Syntax Tree: each expression, as in Linq, is a data structure in memory, that represents something like 4, 5+a, or method(arguments…).

Expression DLR class has static method to create expression objects. For example

var expr = Expression.Constant(“I’m a string”);

is the way to create a constant expression. But we need not only constants but variables too:

var expr = Expression.Variable(typeof(string), “foo”);

This statement creates a variable expression, a variable with name foo and type string.

How to invoke an expression? Remember, Expression objects are trees, data structures in memory, not code. The magic of DLR (and Linq, too) is to be able to COMPILE the expression to a delegate, and then, we can invoke it:

expr.Compile().Invoke(); // you can use Invoke with parameters, too

Then, in order to reproduce the “Hello, World” invocation, I wrote in this post sample code a fragment:

// Console.WriteLine("Hello, Method!");
MethodInfo method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
Expression callExpression = Expression.Call(method, Expression.Constant("Hello Method!"));
Expression.Lambda<Action>(callExpression).Compile().Invoke();

I precede the code with a comment containing the equivalent C# code.

Note: we need an Expression.Lambda (in this case, an Action lambda) to create a delegate around an expression. An Action is something to invoke, without returning value (a routine, instead of a function). An Action<string> would receive an string parameter. An Action alone don’t have parameters.

How to use a variable and assign a value to it? This example illustrates the case:

// string x = "Hello, Assign!";
// Console.WriteLine(x);
ParameterExpression x = Expression.Variable(typeof(string), "x");
Expression blockExpression = Expression.Block(
    new ParameterExpression[] { x }, 
    Expression.Assign(x, Expression.Constant("Hello, Assign!")),
    Expression.Call(method, x));
Expression.Lambda<Action>(blockExpression).Compile().Invoke();

Note that an Expression.Block receives a enumerable of ParameterExpressions, and a param array (variable number of arguments) with Expressions that are the body of the block to execute.

In the next example, I implemented an invalid C# code: a conditional that returns a value:

// x = "Hello";
// if (true)
//     x.ToLower();
MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", new Type[] {});
ParameterExpression y = Expression.Variable(typeof(string), "y");
ParameterExpression z = Expression.Variable(typeof(string), "z");
Expression blockExpression2 = Expression.Block(
    new ParameterExpression[] { x, y},
    Expression.Assign(x, Expression.Constant("Hello")),
    Expression.Condition(Expression.Constant(true),
        Expression.Call(x, toLowerMethod),
        Expression.Default(typeof(string)),
        typeof(string))
        );
string result = Expression.Lambda<Func<string>>(blockExpression2).Compile().Invoke();
Console.WriteLine(result);

The first expression in the block is the assignment of constant “Hello” to variable x. Note that any variable is injected as a parameter in the block. That is the way to declare a variable in DLR expression blocks. There is an Expression.Condition with first parameter a boolean expression, an Expression to evaluate if condition is true, an expression to evaluate if condition if false, and the type of the returning value. This kind of condition is like ?: operator in C#.

Main source for this example: “Pro DLR in .NET 4” by Chaur Wu.

Next steps: compile more complicated expressions, binary expressions, IfThenElse expressions, switch expression, and more.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

March 19, 2011

Dynamic Language Runtime (Part 1) Hello World!

Filed under: .NET, C Sharp, Code Generation, Dynamic Language Runtime — ajlopez @ 11:22 am

Next post

I want to compile my interpreters (AjSharp, AjLisp, upcoming AjScript), written in C#. I could use CodeDome, Reflection.Emit, Cecil. But there is a library dedicated to implement dynamic languages: Dynamic Language Runtime. I got 1.0 version from

http://dlr.codeplex.com

and I compiled its release version using VS2008. Notably, they removed a simple language implementation (I guess it is still at version 0.9, as ToyScript). So, I need help to understand the inner guts and features of this library. Documentation is technically good, but they introduce so many pieces with names like “Call Site” that for me (English is not my mother tongue) are ambiguous. What is a “Call Site”? Maybe a web site for phone calls 😉 ;-). So, I decided to write some code katas, short experiments, to investigate DLR. Hopefully, now I have the help of the book “Pro DLR in .NET 4” by Chaur Wu. I found this first example in that book.

First experiment: create a REPL (Read-Eval-Print Loop), for a simple “Hello, World!”.

(The code of this post series is at
http://code.google.com/p/ajcodekatas/
under trunk/Dlr)

I created a console project, using Visual Studio 2008 (my interpreters are simple, and they don’t need any .NET 4.x feature, yet), named DlrHelloWorld.

I added the reference to Microsoft.Scripting.dll, Microsoft.Scripting.Code.dll, Microsoft.Dynamic.dll (curiously, one of the class I need for this example, ConsoleHost, in this dll).

The first class:

    public class HelloScriptCode : ScriptCode
    {
        public HelloScriptCode(SourceUnit sourceUnit)
            : base(sourceUnit)
        {
        }
        public override object Run(Scope scope)
        {
            Console.WriteLine("Hello, World");
            return null;
        }
    }

Objects of this class will run a simple “Hello, World”. Note that it receives a SourceUnit, something that has the source code to compile. But it will be ignored in this simple example.

Then, the class that manage the HelloScriptCode:

    public class HelloContext : LanguageContext
    {
        public HelloContext(ScriptDomainManager domainManager,
            IDictionary<string, object> options)
            : base(domainManager)
        {
        }
        public override ScriptCode CompileSourceCode(SourceUnit sourceUnit, 
            CompilerOptions options, ErrorSink errorSink)
        {
            return new HelloScriptCode(sourceUnit);
        }
    }

Its main responsability: given a SourceUnit, produce an ScriptCode object.

DLR can host a language, providing a REPL for it. I wrote a class inheriting ConsoleHost:

    public class HelloConsole : ConsoleHost
    {
        protected override Type Provider
        {
            get
            {
                return typeof(HelloContext);
            }
        }
    }

The simple main is:

    class Program
    {
        static void Main(string[] args)
        {
            (new HelloConsole()).Run(args);
        }
    }

 

The output could be boring 😉 :

I should study and understand the involved pieces in this example (host options, source unit, language context, script code). Next steps: research on compiling simple expressions and commands.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Create a free website or blog at WordPress.com.