Я использовал абстрактное синтаксическое дерево (AST) Language.C library для модификации программ на C с использованием общих преобразований SYB library. Этот АСТ имеет разные типы узлов (типы данных), каждый из которых представляет собой конструкцию С, т. Е. Выражения, утверждения, определения и т. Д. Мне нужно теперь как-то увеличить информацию, которую содержат данные, т. Е. Аннотировать их. Я должен (возможно я ошибаюсь), что я не могу изменить или переопределить исходный тип данных, поэтому я хотел бы иметь что-то вроде этого:Укомплектовать сложным типом данных в общем виде в Haskell
annotateAST anns =
everywhere (mkT (annotateAST_ anns))
annotateAST_ astnode anns
| isStmt astnode = AnnStmt astnode (getAnn astnode anns)
| otherwise = astnode
Таким образом, я должен был бы новый AST с аннотированными заявлениями вместо первоначального. Конечно, GHC собирается жаловаться, потому что everywhere
должен возвращать тот же самый тип, который он получает, и это не то, что здесь происходит.
В заключение, мне нужно в общих чертах аннотировать AST без изменения исходных типов данных и таким образом, чтобы было легко вернуться к исходной структуре данных. Я думал о разных решениях этой проблемы, но не убежден ни в одном из них, поэтому решил поделиться ею здесь.
P.S. Мне сказали, что библиотека SYB не очень эффективна. Принимая во внимание, что AST of Language.C выводит только данные, есть ли у меня более эффективная альтернатива общему обходу и модификации АСТ?
Спасибо @chi! Я знал, что AST для библиотеки Language.C была подготовлена для аннотаций пользователей. Хотя все типы узлов разделяли одни и те же аннотации, это не было проблемой для меня, но, как вы предлагаете, может быть хорошим улучшением. Используя предоставленную функциональность, мне понадобится путь от АСТ, созданного синтаксическим анализатором (его тип - «CTranslationUnit NodeInfo') к пользовательскому аннотированному AST (« CTranslationUnit AnnotatedNodeInfo »). Поэтому мне нужно будет использовать функцию, подобную «annotateAST» в вопросе, но, конечно, выполнение ограничений типов. –
@SalvadorTamarit Вы можете использовать 'fmap fromNodeInfoToAnnotatedNodeInfo' для выполнения этого, хотя новая аннотация таким образом не может зависеть ни от чего другого, кроме старой аннотации. Если для новой аннотации есть разумный «по умолчанию», этого может быть достаточно, чтобы определить ваш 'fromNodeInfo ...'. После этого преобразования вы можете использовать SYB для изменения новых аннотаций, чтобы они зависели от фактических данных. (Может быть, есть лучший подход, но это все, что я вижу) – chi
Еще раз спасибо @chi. Ваше предложение работает. 'fmap' может здесь хорошо справиться. Спасибо за вашу помощь. –