AST в рантайме
От: Ziaw Россия  
Дата: 18.08.11 05:23
Оценка:
Метапрограммирование в немерле на высоте, но пока только в компайл тайме. Это конечно более эффективно, но и требует большего скачка для перехода. Предлагаю сделать удобным метапрограммирование в рантайме, для тех, кто хочет его использовать, но не хочет вникать в сложности компилятора.

Сначала код:
Main()
{
  F(1, x => x + 1); // компиляция выражений конструктор дерева вместо кода
  F(1, x => x * 10);
}

F(val : int, expr : Expr[int -> int]) : int
{
  match (expr)
  {
    | <[ (x) => x + $y ]> => WriteLine($"x + $y expression") // PM по дереву выражений
    | x => WriteLine("other expression $x");
  }
  def lambda = expr.Compile(); // компиляция выражения в код
  lambda(val);
}


Дополнительно можно сделать макрос, который умеет создавать перегруженную функцию для того, чтобы такие методы можно было использовать из C#:
F(val : int, expression : System.Linq.Expressions.Expression[int -> int]) : int
{
  def expr = expression.ToExpr(); // преобразование Expression из фреймворка в наш аст для квазицитирования и PM
  F(val, expr)
}


Что требуется от компилятора для реализации этой фичи (все это уже есть, но в несколько других сценаоиях):
0. Умение создавать AST вместо кода в зависимости от типа аргумента. (реализовано в linq)
1. типизированный expression AST (реализовано, но я не знаю насколько подойдет)
2. квазицитирование и PM по нему (не реализовано, тут будут основные сложности)
3. компиляция expresison в рантайме (не реализовано, но требуется всего лишь поднять компилятор и пропустить фазу парсера и типизации, дав уже типизированный код)

Дополнительные юзкейсы:
def expr = fun(x) { x + 1 } : Expr; // вывод типов позволяет не указывать тип дженерика
def expr = try {
    any(valid(expression))
  } finally {
    allowed(here)
  } : Expr; // используются любые выражения, не только лямбды это будет Expr[void -> _]
def otherExpr = <[
    repeat (10)
      $expr
  ]> : Expr; // можно конструировать их по месту



Главный поинт: Это сильно проще и привычнее. Для использования метапрограммирования (пусть и в рантайме), не требуется весь проект переводить на nemerle, достаточно на нем написать именно задачу требующую МП. Мне все чаще приходится метапрограммировать через expression tree, это АДЪ. Такая прослойка могла бы мне помочь с легким сердцем использовать nemerle для создания одной сборки внутри проекта. Я бы мог писать простой и понятный код анализа и обработки и конструирования C# expressions на nemerle, но это все оставалось бы внутри одной сборки и снаружи использовалось бы точно так же как тот код, который пишу сейчас я.

Основная проблема сложных макросов (типизация и раличные фазы) тут не стоит, все работает уже с типизированным AST.

К сожалению, "снаружи" сделать это не получится. Требуется поддержка именно компилятора.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.