Почтовый индекс с списком бул
У меня есть AST
представляет программу на Haskell и список bitvector/bool, представляющий наличие аннотаций строгости на Pattern
с по порядку. Например, 1000
представляет программу с 4 Pat
где первый BangPat
, Есть ли способ, которым я могу включать и выключать аннотации в AST
по списку?
- РЕДАКТИРОВАТЬ: уточнить, что я хочу editBang
сделать
На основании ответа пользователя 5042: Simple.hs :=
main = do
case args of
[] -> error "blah"
[!x] -> putStrLn "one"
(!x : xs) -> putStrLn "many"
И я хочу editBang "Simple.hs" [True, True, True, True]
производить
main = do
case args of
[] -> error "blah"
[!x] -> putStrLn "one"
(!(!x : !xs)) -> putStrLn "many"
Учитывая, что выше только 4 места, которые !
может появиться
1 ответ
В качестве первого шага, вот как использовать transformBi
:
import Data.Data
import Control.Monad
import Data.Generics.Uniplate.Data
import Language.Haskell.Exts
import Text.Show.Pretty (ppShow)
changeNames x = transformBi change x
where change (Ident str) = Ident ("foo_" ++ str)
change x = x
test2 = do
content <- readFile "Simple.hs"
case parseModule content of
ParseFailed _ e -> error e
ParseOk a -> do
let a' = changeNames a
putStrLn $ ppShow a'
changeNames
Функция находит все вхождения Ident s
и заменяет его Ident ("foo_"++s)
в исходном дереве.
Существует монадическая версия под названием transformBiM
что позволяет функции замены быть монадической, что позволит вам использовать элементы из вашего списка Bools, когда вы находите шаблоны взрыва.
Вот полный рабочий пример:
import Control.Monad
import Data.Generics.Uniplate.Data
import Language.Haskell.Exts
import Text.Show.Pretty (ppShow)
import Control.Monad.State.Strict
parseHaskell path = do
content <- readFile path
let mode = ParseMode path Haskell2010 [EnableExtension BangPatterns] False False Nothing
case parseModuleWithMode mode content of
ParseFailed _ e -> error $ path ++ ": " ++ e
ParseOk a -> return a
changeBangs bools x = runState (transformBiM go x) bools
where go pp@(PBangPat p) = do
(b:bs) <- get
put bs
if b
then return p
else return pp
go x = return x
test = do
a <- parseHaskell "Simple.hs"
putStrLn $ unlines . map ("before: " ++) . lines $ ppShow a
let a' = changeBangs [True,False] a
putStrLn $ unlines . map ("after : " ++) . lines $ ppShow a'
Вы также можете посмотреть на использование rewriteBiM
,
Файл Simple.hs
:
main = do
case args of
[] -> error "blah"
[!x] -> putStrLn "one"
(!x : xs) -> putStrLn "many"