Здравствуйте, ·, Вы писали:
·>Ок. На самом деле на входе не Program.cs, а его AST. Ну тогда байткод, конечно сложнее будет анализировать (ибо он даже к яп не привязан). Впрочем подменить вызов метода на какой-то другой — довольно просто и в байткоде.
Это-то как раз да, но для начала нужно этот новый метод откуда-то взять. И вот получить его из AST на порядок проще, чем синтезировать из байт-кода. Я вот в своём проекте начинал как раз со сшивки байт-кода, но быстро упёрся в неразрешимые проблемы. А с AST всё получилось как надо. ·>Тут будет вопрос как можно будет анализировать и преобразовывать аргументы вызова метода. Отличить простую лямду от непростой и что потом с ней делать. Но это всё нерелевантно. Тут вопрос не в том как можно анализировать и генерировать код, а накой результат всего этого описывать в виде патча файл/строка/позиция, и т.п., притом только с возможностью делать подмену вызова метода, вместо того, чтобы просто получить произвольный результирующий код и его компилировать как обычно.
Да, выглядит это пока феерически криво. Я думаю, что парни пытаются нащупать способ дать ровно столько гибкости, сколько необходимо. Произвольные манипуляции AST чреваты тем, что новое AST не удастся скомпилировать в байт-код — и даже диагностику причин толком провести будет невозможно. Им же нужно сделать так, чтобы ошибки в коде "расширений компилятора" диагностировались, и ломали только расширения — а не сам компилятор.
Ну вот пока сделали вот такую залипуху — на конкретной фазе компиляции подтягиваем набор "патчей" и применяем их.
Так-то и SG тоже выглядят немножко странно — зачем нам порождать какие-то файлы, с каким-то текстом, когда мы работаем с AST? Не проще ли было бы сразу породить в памяти нужное AST и отдать компилятору?
·>Ну раз есть AST, то "распарсить Program.cs а AST", "заменить в AST вызов source.Where(n=>n%2==0) на вызов EnumerableHelper.Where2314234235569567(source)", "сохранить в Program_modified.cs вместе с реализацией Where2314234235569567 как приватного метода", "скомпилировать".
Ну, это примерно то же самое, вид сбоку. Только придётся делать плюс-минус каждый раз, как происходит компиляция. А SG и Interceptors срабатывают однократно. Ну, и в вашем предложении получается удвоение объёма кода на ровном месте — ведь придётся хранить полный клон всего Program.cs, который отличается только одной строчкой.
А в нынешнем подходе хранится "набор патчей" в виде списка атрибутов InterceptsLocation.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.