Jaa


現在のDLRにTreeCompilerは存在するのか

以前のDLRのASTのみを使うというエントリでTreeCompilerを使う方法を説明しました。最近のDLRでは、どうなったでしょうか。結論から云えば、IronPython 2.0 ベータ4ではTreeCompilerは無くなっています。その代わりに、以下のような方法を使うことでDLRのASTのみを使うことができます。

 using System;
using System.Collections.Generic;
using System.Text;

using System.Linq.Expressions;
using Microsoft.Scripting.Ast;

namespace AstTest
{
  class Program
  {
    delegate void MyFunc();

    static void Main(string[] args)
    {
      LambdaBuilder lambdaBuilder = Utils.Lambda(
                    typeof(void), "MyFunc", Annotations.Empty);

      var helper = typeof(Console).GetMethod("WriteLine",
                                    new[] {typeof(string)});

      // 1行の場合
       //lambdaBuilder.Body = Expression.Call(
      //       helper, Expression.Constant("Hello, world"));
      // 複数行の場合
       lambdaBuilder.Body = Expression.Block(
             Expression.Call(helper, 
                        Expression.Constant("Hello, world")),
             Expression.Call(helper,
                        Expression.Constant("Hello, world")),
             Expression.Call(helper,
                        Expression.Constant("Hello, world")));

      LambdaExpression lambdExpression = lambdaBuilder.MakeLambda();
      // 型パラメータを作成したコードブロックに一致させる
       MyFunc myFunc = lambdExpression.Compile<MyFunc>();
      myFunc();

      Console.ReadKey();
    }
  }
}

これにMicrosoft.Scripting.dllとMicrosoft.Scripting.Core.dllへ参照を追加し実行すれば、「Hello, world」の文字列が3回コンソールに出力されます。

この内容からDLRのASTの基本的な使い方を理解することができます。それは、以下のようなことです。

  • LambdaBuilder:戻り値型やメソッド名などを指定する。
  • LambdaBuilder.Body:Expressionクラス(ASTによって作成される式)のインスタンス。
  • MakeLambdaメソッド:MakeLambdaメソッドによって、LambdaExpressionを作成する。
  • LambdaExpression.Compileメソッド:LambdaExpressionをコンパイルして、結果をデリゲートのインスタンスとして返す。
  • デリゲートを呼び出す。

この使い方を理解できれば、If文やループなどに応用することができます。

追記:Naitoさんよりフィードバックを頂きました。正確にはBeta4でCompile<T>()メソッドが削除されていて、Beta5に含まれています。このためNaitoさんのご指摘通り、Compile()メソッドを使って、Microsoft.Actionクラスを受け取り、DynamicInvokeメソッドで実行することができます。

Comments