DLRのASTのみを使う


簡単な言語を作るシリーズでNyaRuRuさんがDLRのASTだけを使った方法というのを解説していると取り上げました。DLRのソースコードを使わないで、DLRのASTだけを扱う方法を以下に示します。

using System;
using System.Collections.Generic;

using Microsoft.Scripting;
using Microsoft.Scripting.Ast;

namespace AstTest
{
delegate void MyFunc();

class Program
{
static void Main(string[] args)
{
var helper = typeof(Console).GetMethod(“WriteLine”,
new[] {typeof(string)});
// コードブロックが、関数名の一種と考えれば良い
CodeBlock cb = Ast.CodeBlock(“MyFunc”, typeof(void));
cb.Body =
Ast.Block(
Ast.Call(helper, Ast.Constant(“Hello, World”)),
Ast.Call(helper, Ast.Constant(“Hello, World”)),
Ast.Call(helper, Ast.Constant(“Hello, World”))
);
// 型パラメータを作成したコードブロックに一致させる
MyFunc myFunc = TreeCompiler.CompileBlock<myfunc>(cb);
myFunc();

Console.ReadKey();
}
}
}



このプログラムにMicrosft.Scripting.dllへの参照を追加して実行すれば、「Hello, World」の文字列が3回コンソールに出力されます。このコードが何をしているかと云えば、以下のようなことです。



  • CodeBlock定義:一種の関数定義と思っていただければ良いと思います。第一引数にブロック(関数)名、第二引数に戻り値の型を指定します。
  • Body定義:何を実行するかを定義します。この場合で云えば、Console.WriteLineメソッド呼び出しに、Hello, Worldという定数を引き渡します。
  • TreeCompiler:Microsoft.Scripting.Ast.TreeCompilerクラスのComipleBlockメソッドでコードブロックをコンパイルして、結果をデリゲートインスタンスとして返します。ここで指定している型パラメータは、作成したコードブロック(関数のようなもの)に合わせます。
  • 作成したデリゲートを呼び出します。

これで作成したDLRのASTが無事に実行されるのです。この例では、戻り値の無いMyFuncというコードブロックを作成するために、「delegate void MyFunc()」というデリゲートを定義しています。戻り値や引数がある場合は、Funcデリゲートを流用しても良いでしょう。


 この例以外に引数を取るブロックやループなどが出来るのは、NyaRuRuさんのエントリーの通りです。他の言語を使用するまでも無く、ちょっとしたロジックを自分でASTを組み立てて実行したい時などに利用することができるでしょう。

Comments (3)

  1. Microsoft.Scripting.Ast.TreeCompiler 『C#, DLR AST, meta programming』で「DLR AST の直接コンパイルは public クラスからはできない」と書きましたが,誤報でした.すみません. 荒井さんのエントリ『DLRのASTのみを使う』にあるように,TreeCompiler クラスのスタティ

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

Skip to main content