metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-08-12 11:49 am

Опять кодогенерация, шаблонизаторы vs AST

Кодогенератор-шаблонизатор T4 оказался весьма удобной вещью, на которой кодогенераторы пишутся и расширяются просто со страшной скоростью.

И поначалу это гораздо понятнее, чем кодогенератор с использованием AST целевого языка и претти-принтингом оного AST в исходники.
Но есть одно НО.
Результат без подсветки синтаксиса и автоформатирования к поддержке практически непригоден. Исходник представляет собой смесь C# кода, который выполняется и C# кода который генерируется, с разделителями вида <#,<#=,<#+ и #>. Без заточенного под это дело редактора после определенного уровня сложности кодогенератора в этом понять ничего невозможно.

Например, я, упившись крепким чаем, в припадке безумия таки реализовал свою старую идею - генерацию из простой модели иммутабельных сущностей и методов сохранения и загрузки оных сущностей в простой XML, где полям-значениям соответствуют атрибуты, полям-объектам - элементы, полям-спискам(List<>) - элементы с вложенными списками. Т.е. вариант XML, в котором это дело наиболее читабельно глазами. Если не боитесь пауков - можете глянуть на этот мрак.
По мере расширения этого кодогенератора (простые сущности-записи -> сущности с полями-списками -> поддержка enum -> поддержка полей-вложенных объектов -> поддержка memo-полей (строки в которых длинный текст с переносами)) это все понемногу превратилось в жопный ад. 10 кб текста, 300 строк, в которых даже я с трудом ориентируюсь уже.
Использовать это очень просто, расширять дальше - уже сложно.

Кроме того, во всей этой кодогенерации очень бесит необходимость постоянно расширять систему типов. Т.к. один и тот же string в целевой проге - это может быть и коротенькое имя, и текст SQL запроса и RTF-документ. А при показе поля с датой пользователю может быть необходимо использовать culture-invariant формат (например я для служебных данных и для себя пользуюсь везде только им, чтобы не вспоминать "на какой локали я сижу") а может и формат из текущей локали.
В общем, если делать классическими дотнетовскими средствами, как положено, то на каждое поле или проперть в POCO-сущности навешивается еще 5-10 атрибутов, и по всему коду расползается анализ этих атрибутов, т.е. фактически мало того, что мы расширяем систему типов дополнительными описаниями, так еще и всю их обработку делаем в рунтайме, как с какой-то динамической типизацией.



PS: Во, вспомнил еще идею, которая мне насчет T4 в голову пришла.
Частенько в C# не хватает ADT, но их можно сымитировать, сделав базовый класс и унаследовав от него все варианты ADT с нужными полями. Чтобы сделать pattern matching поверх этого, нужно написать в базовом классе метод, в который передается в качестве параметров по одному делегату на каждый вариант ADT и он анализирует текущий тип объекта, вызывая соответствующий делегат, подставляя поля варианта в качестве параметров делегату.

Руками такое писать очевидно влом. Но можно сделать на T4 мелкий шаблончик, который из описания ADT в привычном виде сгенерит все классы, конструктора, прототипы делегатов и метод для pattern matching.

[identity profile] metaclass.livejournal.com 2010-08-12 07:08 pm (UTC)(link)
Не, не, я не представляю, как ЭТО отлаживать.

[identity profile] metaclass.livejournal.com 2010-08-12 07:16 pm (UTC)(link)
Ну в отладчике пройтись по тому, что макрос нагенерил, можно?
И чтобы сообщения об ошибках показывали все места, откуда в месте ошибки взялся код.

[identity profile] theiced.livejournal.com 2010-08-12 07:18 pm (UTC)(link)
конечно. в случае коммонлиспа (а надо брать именно его для реальных задач, увы) есть слайм - который всё расскажет и покажет.

[identity profile] theiced.livejournal.com 2010-08-12 07:23 pm (UTC)(link)
http://www.guba.com/watch/3000054867 - зафтыкайте на сон грядущий.

[identity profile] metaclass.livejournal.com 2010-08-12 07:26 pm (UTC)(link)
А это у коммон лиспа вроде заморочки с связыванием переменных по имени? Т.е. что он свободную переменную в теле чего-нибудь ищет не там где это что-нибудь объявлено, а там где это что-нибудь вызывают?

[identity profile] theiced.livejournal.com 2010-08-12 07:37 pm (UTC)(link)
продолжим совращение - http://code.google.com/p/uabcl/

[identity profile] theiced.livejournal.com 2010-08-12 07:40 pm (UTC)(link)
http://ironscheme.codeplex.com/documentation - ой вэй - и схема есть вже.

[identity profile] metaclass.livejournal.com 2010-08-12 07:37 pm (UTC)(link)
А, вроде эта шиза - dynamic scoping в emacs lisp