Почтовый индекс с списком бул

У меня есть 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"
Другие вопросы по тегам