воскресенье, 24 января 2010 г.

Expression trees: продолжаем писать компилятор

Обычно компилятор состоит из двух частей: парсер и генератор. Как быстро и легко написать парсер я уже писал LINQ: интересный подход к написанию парсеров.
Теперь займемся генератором. Вернее подход будет несколько другим. Я разрабатывал внутренний язык, который будет использоваться внутри .NET приложения, т.е. необходимо выполнить  инструкцию написанную на этом языке. И тут к нам на помощь придут Expression trees. Теперь подробнее...

Expression trees - это объектное представление языкового кода, например 2 + 2 дерево состоит из корня операции + и двух дочерних численных узлов 2. Лямбда выражение в .NET тоже expression tree. Например уже приведенное лямбда выражение, которое принимает параметр 2, выглядит вот так:
  1. Expression<Func<intint>> expression = argument => argument + argument;  
Но это же выражение мы можем построить в динамике :)
  1. ParameterExpression argument = Expression.Parameter(typeof(int), "argument");  
  2. BinaryExpression summ = Expression.Add(argument, argument);  
  3. Expression<Func<intint>> expression = Expression.Lambda<Func<intint>>(summ, new[] { argument });  
Готово, а прелесть в том, что мы можем его скомпилировать в делегат Func и хранить например набор таких функций скомпилированных по выражениям нашего DSL, и выполнять по запросу, вот так:
  1. Func<intint> func = expression.Compile();  
  2. Console.WriteLine(func(2));  

В целом, я действительно проторчал от Expression trees в .NET, очень классная штука, на заметку всем, кто хочет использовать какой-нибудь внутренний dsl язык в своём приложении.

Комментариев нет:

Отправить комментарий