packages feed

HaRe-0.6: refactorer/RefacInstantiate.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  RefacInstantiate
-- Copyright   :  (c) Christopher Brown 2007
--
-- Maintainer  :  cmb21@kent.ac.uk
-- Stability   :  provisional
-- Portability :  portable
--
-- This module contains a transformation for HaRe.
-- Instantiating Patterns


module RefacInstantiate where


import System.IO.Unsafe
import PrettyPrint
import RefacTypeSyn
import RefacLocUtils
-- import GHC (Session)
import Data.Char
import GHC.Unicode
import AbstractIO
import Maybe
import List
import RefacUtils
import RefacRedunDec
import SlicingUtils
import Directory
import LocalSettings

refacInstantiate args
  = do 
       let fileName     = args!!0
           begin        = read (args!!1)::Int
           end          = read (args!!2)::Int
           instantPatt  = drop 3 args
       AbstractIO.putStrLn "refacInstantiate"
       (inscps, exps, mod, tokList) <- parseSourceFile fileName
       case findMatch fileName begin end mod of
         Nothing -> do error "You can only instantiate patterns on the LHS of a match!"
         Just (decl, pats) ->
           do              
              let pairedPats = pairPatWithInstance pats instantPatt              
              res <- findAndReplaceAllPat decl pairedPats
              case checkCursor fileName begin end mod of
               Left errMsg -> do error errMsg
               Right fun ->
                 do
                  let newFun = addMatch fun res
                  ((_,m), (newToks, newMod)) <- applyRefac (addNewPat fun newFun) (Just (inscps, exps, mod, tokList)) fileName
                  writeRefactoredFiles False [((fileName, m), (newToks, newMod))]           
                  AbstractIO.putStrLn "Completed.\n"
                  
addMatch :: HsDeclP -> HsMatchP -> HsDeclP
addMatch (Dec (HsFunBind x ms) ) m = (Dec (HsFunBind x (m : ms)))
addMatch x _ = error "You can only instantiate patterns on the LHS of a match!"

addNewPat fun newFun (_, _, mod) 
 = do
     newMod <- update fun newFun mod
     return newMod             

pairPatWithInstance :: [HsPatP] -> [ String ] -> [ (HsPatP, String) ]
pairPatWithInstance [] _ = []
pairPatWithInstance _ [] = []
pairPatWithInstance ((Pat (HsPLit _ x)):_) (s:ss)
  | convert x /= s && s /= "_" = error "Can only instantiate an identifier!"
pairPatWithInstance (p:ps) (s:ss) = (p, s) : pairPatWithInstance ps ss

convert ::HsLiteral -> String
convert (HsInt x) = show x
convert (HsChar x) = show x
convert (HsString x) = x
convert (HsFrac x) = show x
convert (HsCharPrim x) = show x
convert (HsStringPrim x) = show x
convert (HsIntPrim x) = show x
convert (HsFloatPrim x) = show x
convert (HsDoublePrim x) = show x
convertt (HsLitLit x ) = x

findAndReplaceAllPat :: (Term t, Monad m) => t -> [ (HsPatP, String) ] -> m t
findAndReplaceAllPat t [] = return t
findAndReplaceAllPat t (x:xs)
 = do
      res <- findAndReplacePat t x
      rest <- findAndReplaceAllPat res xs
      return rest

findAndReplacePat :: (Term t, Monad m) => t -> (HsPatP, String) -> m t
findAndReplacePat t (p,s) 
  = applyTP (full_tdTP (idTP `adhocTP` inRhs)) t
  where
   inRhs (pnt::PNT) 
    | (patToPNT p) == pnt 
       = do return (nameToPNT s)
   inRhs x = return x
findMatch :: Term t => String -> Int -> Int -> t -> Maybe (HsMatchP, [HsPatP])
findMatch fileName row col mod
  = applyTU (once_tdTU (failTU `adhocTU` inMatch)) mod
    where
      --The selected sub-expression is in the rhs of a match
      inMatch (match@(HsMatch loc1  pnt pats (rhs@(HsBody e)) ds)::HsMatchP)
        | useLoc (locToPNT fileName (row, col) mod) == useLoc pnt
          = Just (match, pats)
      inMatch _ = Nothing

checkCursor :: String -> Int -> Int -> HsModuleP -> Either String HsDeclP
checkCursor fileName row col mod
 = case locToPName of
     Nothing -> Left ("Invalid cursor position. Please place cursor at the beginning of the definition!")
     Just decl -> Right decl
    where
        locToPName 
         = case res of 
             Nothing -> find (definesPNT (locToPNT fileName (row, col) mod)) (hsDecls mod)
             _ -> res
        res =  find (defines (locToPN fileName (row, col) mod)) (concat (map hsDecls (hsModDecls mod)))
        
        definesPNT pnt d@(Dec (HsPatBind loc p e ds))
         = findPNT pnt d
        definesPNT pnt d@(Dec (HsFunBind loc ms)) 
         = findPNT pnt d
        definesPNT _ _ = False