2015-08-02 1 views
0

У меня есть AST, представляющая программу Haskell и список bitvector/Ий, представляющее присутствие строгости аннотации на Pattern с в примере order.For, 1000 представляет собой программу с 4-х Pat, где первым из них a BangPat. Есть ли способ, который я могу включить и выключить аннотации в AST согласно списку?почтового АСТ со списком BOOL

- EDIT: дополнительно уточнить, что я хочу editBang сделать

На основании ответа user5042 в: 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 местами, которые могут появиться !

+0

Ответ обновляется с рабочим примером. – ErikR

+0

Обратите внимание, что '! Xs' не разрешено. У вас есть ваша работа, вырезанная для вас, так как во многих местах разрешены запреты, которые вы не рассматриваете, например. '! []' и '! [! x]', но они не допускаются в определениях верхнего уровня, например. '! main = ...' не допускается, хотя 'main' является шаблоном. В следующий раз будьте более откровенными о том, что вы хотите. – ErikR

ответ

3

В качестве первого шага, вот как использовать 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 [email protected](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" 
+0

Большое спасибо, я не ожидал такого полного ответа. Примите, как только я заработаю. – rem