HaRe-0.6: refactorer/RefacGenFold.hs
module RefacGenFold where
import PFE0
import HsTokens
import TypeCheck
import PrettyPrint
import PosSyntax
import HsName
import HsLexerPass1
import AbstractIO
import Maybe
import TypedIds
import UniqueNames hiding (srcLoc)
import PNT
import TiPNT
import List
import RefacUtils hiding (getParams)
import PFE0 (findFile, allFiles, allModules)
import MUtils (( # ))
import RefacLocUtils
import System
import IO
import Relations
import Ents
import Data.Set (toList)
import Data.List
import System.IO.Unsafe
import System.Cmd
import LocalSettings
import RefacSimplify
import StateMT(WithState,withSt,withStS,getSt,setSt,updSt,updSt_)
import qualified Control.Exception as CE (catch)
import EditorCommands
-- | An argument list for a function which of course is a list of paterns.
type FunctionPats = [HsPatP]
-- | A list of declarations used to represent a where or let clause.
type WhereDecls = [HsDeclP]
data PatFun = Mat | Patt | Er deriving (Eq, Show)
genFold args
= do
let fileName = ghead "fileName'" args
beginRow = read (args!!1)::Int
beginCol = read (args!!2)::Int
endRow = read (args!!3)::Int
endCol = read (args!!4)::Int
AbstractIO.putStrLn "genFold"
modName <-fileNameToModName fileName
let modName1 = convertModName modName
(inscps, exps, mod, tokList)<-parseSourceFile fileName
let subExp = locToExp (beginRow, beginCol) (endRow, endCol) tokList mod
let (ty, pnt, pats, wh)
= findDefNameAndExp tokList
(beginRow, beginCol)
(endRow, endCol)
mod
((_,m), (newToks, (newMod, e))) <- applyRefac (addCommentDec pnt) (Just (inscps, exps, mod, tokList)) fileName
writeRefactoredFiles False [((fileName, m), (newToks, newMod))]
(inscps', exps', mod', tokList') <- parseSourceFile fileName
((_,m'), (newToks', (newMod',parsed))) <- applyRefac (retrieveDecAndRemove pnt e)
(Just (inscps', exps', mod', tokList')) fileName
let pnt' = declToPNT parsed
-- undo the added entry!
undoLatestInHistory
(inscps2, exps2, mod2, tokList2)<-parseSourceFile fileName
((_,m'''), (newToks''', newMod''')) <- applyRefac (changeExpression pnt pnt' parsed subExp)
(Just (inscps2, exps2, mod2, tokList2)) fileName
writeRefactoredFiles False [((fileName, m'''), (newToks''', newMod'''))]
AbstractIO.putStrLn "Completed.\n"
addCommentDec pnt (_,_,t)
= do
tks <- extractComment (pNTtoPN pnt) t
let tksString = concatMap getName tks
let commentDef = dropWhile (==' ') (parseComment (reverse tksString))
if '=' `elem` commentDef
then do
mod <- insertTerm (dropWhile (==' ') (reverse commentDef)) (pNTtoPN pnt) t
return (mod, (dropWhile (==' ') (reverse commentDef)))
else do
error "Please define an equation within a comment above the definition under scrutiny."
retrieveDecAndRemove pnt e (_,_,t)
= do
let parsedDec = retrieveDec pnt e t
-- mod <- removeDec e t
return (t, parsedDec)
retrieveDec pnt exp t
= fromMaybe (error ("Previous record of definition not found! " ++ exp))
(applyTU (once_tdTU (failTU `adhocTU` inDec)) t)
where
inDec d@(Dec (HsPatBind _ _ _ _))
| (render.ppi) d == exp
= Just d
inDec d@(Dec (HsFunBind l matches))
| rendered matches exp
= do
let x = rendered2 matches exp
Just (Dec (HsFunBind l [x]))
inDec d = Nothing
rendered [] _ = False
rendered (m:ms) e
| rmLine ( rmToks ((render.ppi) m)) == rmLine ( rmToks e ) = True
| otherwise = rendered ms e
rendered2 [] _ = error "Error in rendered2"
rendered2 (m:ms) e
| rmLine ( rmToks ((render.ppi) m)) == rmLine ( rmToks e ) = m
| otherwise = rendered2 ms e
rmToks x = (rmRBracket.rmLBracket.rmLine.rmSpace) x
rmSpace x = filter (/=' ') x
rmLine x = filter (/='\n') x
rmLBracket x = filter (/='(') x
rmRBracket x = filter (/=')') x
removeDec exp t
= applyTP (stop_tdTP (idTP `adhocTP` inDec)) t
where
inDec (d::HsDeclP)
| (render.ppi) d == exp
= do
rmDecl (declToPName2 d) True [d]
return d
inDec d = return d
parseComment :: String -> String
parseComment [] = []
parseComment ('}':('-':xs)) = parseComment' xs
parseComment (x:xs) = parseComment xs
parseComment' :: String -> String
parseComment' [] = []
parseComment' ('-':('{':xs)) = ""
parseComment' (x:xs) = x : (parseComment' xs)
getName :: PosToken -> String
getName (_, ((Pos _ _ _), s)) = s
changeExpression pnt pntComment d exp (_,_,t)
= do
mod <- changeExpression' pnt pntComment d exp t
return mod
changeExpression' pnt pntComment d exp t
= applyTP (stop_tdTP (failTP `adhocTP` (inExp d exp))) t
where
inExp (Dec (HsPatBind _ p (HsBody e2) ds)) exp (e::HsExpP)
| sameOccurrence exp e
= do
if rmAllLocs e2 == rmAllLocs e
then do
res <- update e (nameToExp (pNTtoName (patToPNT p))) e
return res
else do
mzero
inExp (dec@(Dec (HsFunBind s matches))::HsDeclP) exp (e::HsExpP)
| sameOccurrence exp e
= do
let match@(HsMatch loc name pats (HsBody e2) ds) = getMatch pntComment matches
let newExp = searchForRHS pnt exp t
let (pred, newParams) = rewriteExp pats newExp e2
if pred
then do
-- let patsConverd = map (render.ppi) newPats
res <- update e (createFunc pntComment (map patToExp newParams)) e
return res
else do
mzero
inExp d exp e = mzero
rewriteExp :: [HsPatP] -> HsExpP -> HsExpP -> (Bool, [HsPatP])
rewriteExp pats (Exp (HsParen e)) e2 = rewriteExp pats e e2
rewriteExp pats e (Exp (HsParen e2)) = rewriteExp pats e e2
rewriteExp pats (Exp (HsLit s x)) (Exp (HsLit s1 x2))
| x == x2 = (True, pats)
rewriteExp pats (Exp (HsId (HsCon x))) (Exp (HsId (HsCon y)))
| x == y = (True, pats)
rewriteExp pats n m@(Exp (HsId (HsVar i2)))
| checkPNTInPat pats i2 = (True, getPatFromPats pats n i2)
rewriteExp pats n@(Exp (HsId (HsVar i1))) (Exp (HsId (HsVar i2)))
| (pNTtoName i1) /= (pNTtoName i2) && checkPNTInPat pats i2 = (True, getPatFromPats pats n i2)
| (pNTtoName i1) == (pNTtoName i2) = (True, pats)
| isLocalPNT i1 && isLocalPNT i2 = (True, pats)
| otherwise = (False, pats)
rewriteExp pats a@(Exp (HsApp e1 e2)) b@(Exp (HsApp e3 e4))
| pred1 == True && pred2 == True = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e3
(pred2, pats2) = rewriteExp pats1 e2 e4
rewriteExp pats a@(Exp (HsInfixApp e1 o1 e2)) b@(Exp (HsInfixApp e3 o2 e4))
| o1 == o2 && (pred1 && pred2) = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e3
(pred2, pats2) = rewriteExp pats1 e2 e4
rewriteExp pats a@(Exp (HsTuple e1)) b@(Exp (HsTuple e2))
| length e1 == length e2 && pred = (True, pats2)
| otherwise = (False, pats)
where
(pred, pats2) = checkList pats e1 e2
rewriteExp pats a@(Exp (HsList e1)) b@(Exp (HsList e2))
| length e1 == length e2 = (True, pats2)
| otherwise = (False, pats)
where
(pred, pats2) = checkList pats e1 e2
rewriteExp pats a@(Exp (HsLeftSection e1 i1)) b@(Exp (HsLeftSection e2 i2))
| i1 == i2 && pred1 = (True, pats1)
where
(pred1, pats1) = rewriteExp pats e1 e2
rewriteExp pats a@(Exp (HsRightSection i1 e1)) b@(Exp (HsRightSection i2 e2))
| i1 == i2 && pred1 = (True, pats1)
where
(pred1, pats1) = rewriteExp pats e1 e2
rewriteExp pats a@(Exp (HsEnumFrom e1)) b@(Exp (HsEnumFrom e2))
| pred1 = (True, pats1)
where
(pred1, pats1) = rewriteExp pats e1 e2
rewriteExp pats a@(Exp (HsEnumFromTo e1 e2)) b@(Exp (HsEnumFromTo e3 e4))
| pred1 && pred2 = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e3
(pred2, pats2) = rewriteExp pats1 e2 e4
rewriteExp pats a@(Exp (HsEnumFromThen e1 e2)) b2@(Exp (HsEnumFromThen e3 e4))
| pred1 && pred2 = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e3
(pred2, pats2) = rewriteExp pats1 e2 e4
rewriteExp pats a@(Exp (HsEnumFromThenTo e1 e2 e3)) b@(Exp (HsEnumFromThenTo e4 e5 e6))
| pred1 && pred2 && pred3 = (True, pats3)
where
(pred1, pats1) = rewriteExp pats e1 e4
(pred2, pats2) = rewriteExp pats1 e2 e5
(pred3, pats3) = rewriteExp pats2 e3 e6
rewriteExp pats a@(Exp (HsIf e1 e2 e3)) b@(Exp (HsIf e4 e5 e6))
| pred1 && pred2 && pred3 = (True, pats3)
where
(pred1, pats1) = rewriteExp pats e1 e4
(pred2, pats2) = rewriteExp pats1 e2 e5
(pred3, pats3) = rewriteExp pats2 e3 e6
rewriteExp pats a@(Exp (HsNegApp s e)) b@(Exp (HsNegApp s2 e2))
| pred = (True, pats1)
where
(pred, pats1) = rewriteExp pats e e2
rewriteExp pats a@(Exp (HsListComp stmts1)) b@(Exp (HsListComp stmts2))
| pred = (True, pats1)
where
(pred, pats1) = rewriteExpStmts pats stmts1 stmts2
rewriteExp pats (Exp (HsDo stmts1)) (Exp (HsDo stmts2))
| pred = (True, pats1)
where
(pred, pats1) = rewriteExpStmts pats stmts1 stmts2
rewriteExp pats a@(Exp (HsLambda ps e1)) b@(Exp (HsLambda ps2 e2))
| wildCardAllPNs ps == wildCardAllPNs ps2 && pred = (True, pats1)
where
(pred, pats1) = rewriteExp pats e1 (localRewriteExp e2 (localRewritePats ps ps2))
localRewritePats [] ps = []
localRewritePats ps [] = []
localRewritePats (p1:p1s) (p2:p2s)
= (rewritePat p2 p1) : (localRewritePats p1s p2s)
localRewriteExp e [] = e
localRewriteExp e (p1:p1s)
= let e1' = rewritePatsInExp p1 e in localRewriteExp e1' p1s
rewriteExp pats a@(Exp (HsRecConstr s i fields1)) b@(Exp (HsRecConstr s2 i2 fields2))
| i == i2 && pred = (True, pats1)
where
(pred, pats1) = rewriteExpFields pats fields1 fields2
rewriteExp pats a@(Exp (HsRecUpdate s1 e1 fields1)) b@(Exp (HsRecUpdate s2 e2 fields2))
| pred1 && pred2 = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e2
(pred2, pats2) = rewriteExpFields pats1 fields1 fields2
rewriteExp pats a@(Exp (HsCase e1 alts1)) b@(Exp (HsCase e2 alts2))
| pred1 && pred2 = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e2
(pred2, pats2) = rewriteExpAlts pats1 alts1 alts2
-- rewriteExp pats e1 e2 = error $ ">" ++ (show (pats, e1, e2))
rewriteExp pats e1 e2 = (False, pats) -- error $ ">" ++ (show (pats, e1, e2))
rewriteExpFields pats [] _ = (True, pats)
rewriteExpFields pats _ [] = (True, pats)
rewriteExpFields pats ((HsField i1 e1):f1) ((HsField i2 e2):f2)
| pred && (i1 == i2 && pred2) = (True, pats2)
| otherwise = (False, pats)
where
(pred, pats1) = rewriteExp pats e1 e2
(pred2, pats2) = rewriteExpFields pats1 f1 f2
rewriteExpAlts pats [] _ = (True, pats)
rewriteExpAlts pats _ [] = (True, pats)
rewriteExpAlts pats ((HsAlt _ p1 (HsBody e1) ds1):alts1) ((HsAlt _ p2 (HsBody e2) ds2):alts2)
| pred && (wildCardAllPNs p1 == wildCardAllPNs p2 && pred2) = (True, pats2)
| otherwise = (False, pats)
where
(pred, pats1) = rewriteExp pats e1 (rewritePatsInExp (rewritePat p2 p1) e2)
(pred2, pats2) = rewriteExpAlts pats1 alts1 alts2
rewriteExpAlts pats ((HsAlt _ p1 (HsGuard gs1) ds1):alts1) ((HsAlt _ p2 (HsGuard gs2) ds2):alts2)
| (wildCardAllPNs p1 == wildCardAllPNs p2 && pred2) = (True, pats2)
| otherwise = (False, pats)
where
-- (pred, pats1) = rewriteExp pats e1 e2
(pred2, pats2) = rewriteExpGuards pats gs1 res
res = (rewritePatsInGuard (rewritePat p2 p1) gs2)
rewriteExpAlts pats _ _ = (False, pats)
rewriteExpGuards pats [] _ = (True, pats)
rewriteExpGuards pats _ [] = (True, pats)
rewriteExpGuards pats ((_ ,e1,e2):gs1) ((_, e3, e4):gs2)
| pred1 && pred2 && pred3 = (True, pats3)
where
(pred1, pats1) = rewriteExp pats e1 e3
(pred2, pats2) = rewriteExp pats1 e2 e4
(pred3, pats3) = rewriteExpGuards pats2 gs1 gs2
rewriteExpStmts pats s1@(HsGenerator _ p1 e1 m1) s2@(HsGenerator _ p2 e2 m2)
| wildCardAllPNs p1 == wildCardAllPNs p2 && pred1 && pred2 = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e2
(pred2, pats2) = rewriteExpStmts pats1 m1 m2
rewriteExpStmts pats (HsLast e1) (HsLast e2)
| wildCardAllPNs e1 == wildCardAllPNs e2 = (True, pats)
-- = error $ show $ rewriteExp pats e1 e2
rewriteExpStmts pats (HsQualifier e1 stmts) (HsQualifier e2 stmts2)
| pred1 && pred2 = (True, pats2)
where
(pred1, pats1) = rewriteExp pats e1 e2
(pred2, pats2) = rewriteExpStmts pats1 stmts stmts2
rewriteExpStmts pats (HsLetStmt ds1 stmts) (HsLetStmt ds2 stmts2)
= rewriteExpStmts pats stmts stmts2
rewriteExpStmts pats s1 s2 = (False, pats)
changeAllNames :: PNT -> PNT -> PNT
changeAllNames pnt t =runIdentity (applyTP (full_buTP (idTP `adhocTP` l)) t)
where
l ((PN (UnQual n) s))
| n /= (pNTtoName pnt) = return ((PN (UnQual (pNTtoName pnt)) s))
| otherwise = return ((PN (UnQual n) s))
rewritePat :: HsPatP -> HsPatP -> HsPatP
rewritePat a@(Pat (HsPId (HsVar x))) b@(Pat (HsPId (HsVar y)))
= (Pat (HsPId (HsVar (changeAllNames y x))))
rewritePat a@(Pat (HsPId (HsCon x))) b@(Pat (HsPId (HsCon y)))
= a
rewritePat a@(Pat (HsPLit _ _)) b@(Pat (HsPLit _ _))
= a
rewritePat a@(Pat (HsPNeg _ _)) b@(Pat (HsPNeg _ _))
= a
rewritePat a@(Pat (HsPSucc _ _ _)) b@(Pat (HsPSucc _ _ _))
= a
rewritePat a@(Pat (HsPInfixApp p1 i p2)) b@(Pat (HsPInfixApp p3 i2 p4))
= (Pat (HsPInfixApp (rewritePat p1 p3) i (rewritePat p2 p4)))
rewritePat a@(Pat (HsPApp i ps)) b@(Pat (HsPApp i2 ps2))
= (Pat (HsPApp i (rewritePat' ps ps2)))
rewritePat a@(Pat (HsPTuple s ps)) b@(Pat (HsPTuple s2 ps2))
= (Pat (HsPTuple s (rewritePat' ps ps2)))
rewritePat a@(Pat (HsPList s ps)) b@(Pat (HsPList s2 ps2))
= (Pat (HsPList s (rewritePat' ps ps2)))
rewritePat a@(Pat (HsPParen p1)) b@(Pat (HsPParen p2))
= (Pat (HsPParen (rewritePat p1 p2)))
rewritePat a@(Pat (HsPAsPat i p1)) b@(Pat (HsPAsPat i2 p2))
= (Pat (HsPAsPat i (rewritePat p1 p2)))
rewritePat a@(Pat (HsPWildCard)) b@(Pat (HsPWildCard))
= a
rewritePat a@(Pat (HsPIrrPat p1)) b@(Pat (HsPIrrPat p2))
= Pat (HsPIrrPat (rewritePat p1 p2))
rewritePat a b = a
rewritePat' :: [HsPatP] -> [HsPatP] -> [HsPatP]
rewritePat' [] _ = []
rewritePat' x [] = x
rewritePat' (x:xs) (y:ys)
= rewritePat x y : rewritePat' xs ys
rewritePatsInExp :: HsPatP -> HsExpP -> HsExpP
rewritePatsInExp p a@(Exp (HsId (HsVar x)))
| isTopLevelPNT x = a
| otherwise
= (Exp (HsId (HsVar newPNT)))
where
newPNT = grabPNT x (hsPNTs p)
rewritePatsInExp p (Exp (HsInfixApp e1 o e2))
= (Exp (HsInfixApp e1' o e2'))
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
rewritePatsInExp p (Exp (HsApp e1 e2))
= (Exp (HsApp e1' e2'))
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
rewritePatsInExp p (Exp (HsNegApp s e))
= (Exp (HsNegApp s e'))
where
e' = rewritePatsInExp p e
rewritePatsInExp p (Exp (HsLambda ps e))
= (Exp (HsLambda ps e'))
where
e' = rewritePatsInExp p e
rewritePatsInExp p (Exp (HsLet ds e))
= (Exp (HsLet ds e'))
where
e' = rewritePatsInExp p e
rewritePatsInExp p (Exp (HsIf e1 e2 e3))
= (Exp (HsIf e1' e2' e3'))
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
e3' = rewritePatsInExp p e3
rewritePatsInExp p (Exp (HsCase e alts))
= (Exp (HsCase e' alts'))
where
e' = rewritePatsInExp p e
alts' = rewritePatsInAlts p alts
rewritePatsInExp p (Exp (HsDo stmts))
= (Exp (HsDo stmts'))
where
stmts' = rewritePatsInStmts p stmts
rewritePatsInExp p (Exp (HsTuple es))
= (Exp (HsTuple es'))
where
es' = map (rewritePatsInExp p) es
rewritePatsInExp p (Exp (HsList es))
= (Exp (HsList es'))
where
es' = map (rewritePatsInExp p) es
rewritePatsInExp p (Exp (HsParen e))
= (Exp (HsParen (rewritePatsInExp p e)))
rewritePatsInExp p (Exp (HsLeftSection e (HsVar x)))
= (Exp (HsLeftSection e' (HsVar newPNT)))
where
e' = rewritePatsInExp p e'
newPNT = grabPNT x (hsPNTs p)
rewritePatsInExp p (Exp (HsRightSection (HsVar x) e))
= (Exp (HsRightSection (HsVar newPNT) e'))
where
e' = rewritePatsInExp p e'
newPNT = grabPNT x (hsPNTs p)
rewritePatsInExp p (Exp (HsRecConstr s i fields))
= (Exp (HsRecConstr s newPNT fields'))
where
newPNT = grabPNT i (hsPNTs p)
fields' = rewritePatsInFields p fields
rewritePatsInExp p (Exp (HsRecUpdate s e fields))
= (Exp (HsRecUpdate s e' fields'))
where
e' = rewritePatsInExp p e
fields' = rewritePatsInFields p fields
rewritePatsInExp p (Exp (HsEnumFrom e))
= (Exp (HsEnumFrom e'))
where
e' = rewritePatsInExp p e
rewritePatsInExp p (Exp (HsEnumFromTo e1 e2))
= (Exp (HsEnumFromTo e1' e2'))
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
rewritePatsInExp p (Exp (HsEnumFromThen e1 e2))
= (Exp (HsEnumFromThen e1' e2'))
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
rewritePatsInExp p (Exp (HsEnumFromThenTo e1 e2 e3))
= (Exp (HsEnumFromThenTo e1' e2' e3'))
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
e3' = rewritePatsInExp p e3
rewritePatsInExp p (Exp (HsListComp stmts))
= (Exp (HsListComp stmts'))
where
stmts' = rewritePatsInStmts p stmts
rewritePatsInExp p e = e
rewritePatsInStmts :: HsPatP -> HsStmtP -> HsStmtP
rewritePatsInStmts p (HsGenerator s p2 e stmts)
= (HsGenerator s p2 e' stmts')
where
e' = rewritePatsInExp p e
stmts' = rewritePatsInStmts p stmts
rewritePatsInStmts p (HsQualifier e stmts)
= (HsQualifier e' stmts')
where
e' = rewritePatsInExp p e
stmts' = rewritePatsInStmts p stmts
rewritePatsInStmts p (HsLetStmt ds stmts)
= (HsLetStmt ds stmts')
where
stmts' = rewritePatsInStmts p stmts
rewritePatsInStmts p (HsLast e)
= (HsLast e')
where
e' = rewritePatsInExp p e
rewritePatsInFields :: HsPatP -> [HsFieldP] -> [HsFieldP]
rewritePatsInFields p [] = []
rewritePatsInFields p ((HsField i e):fs)
= (HsField newPNT e') : (rewritePatsInFields p fs)
where
newPNT = grabPNT i (hsPNTs e)
e' = rewritePatsInExp p e
rewritePatsInAlts :: HsPatP -> [HsAltP] -> [HsAltP]
rewritePatsInAlts p [] = []
rewritePatsInAlts p ((HsAlt s p2 (HsBody e) ds):alts)
= (HsAlt s p2 (HsBody e') ds) : (rewritePatsInAlts p alts)
where
e' = rewritePatsInExp p e
rewritePatsInAlts p ((HsAlt s p2 (HsGuard gs) ds):alts)
= (HsAlt s p2 (HsGuard gs') ds) : (rewritePatsInAlts p alts)
where
gs' = rewritePatsInGuard p gs
rewritePatsInGuard :: HsPatP -> [(SrcLoc, HsExpP, HsExpP)] -> [(SrcLoc, HsExpP, HsExpP)]
rewritePatsInGuard p [] = []
rewritePatsInGuard p ((s, e1, e2):gs)
= (s, e1', e2') : (rewritePatsInGuard p gs)
where
e1' = rewritePatsInExp p e1
e2' = rewritePatsInExp p e2
grabPNT :: PNT -> [PNT] -> PNT
grabPNT x [] = x
grabPNT x (y:ys)
| defineLoc x == defineLoc y = y
| otherwise = grabPNT x ys
checkList :: [HsPatP] -> [HsExpP] -> [HsExpP] -> (Bool, [HsPatP])
checkList pats [] [] = (True, pats)
checkList pats [e] [l] = rewriteExp pats e l
checkList pats (e:es) (l:ls)
| pred = checkList pats' es ls
| otherwise = (False, pats')
where
(pred, pats') = rewriteExp pats e l
checkPNTInPat :: [HsPatP] -> PNT -> Bool
checkPNTInPat [] _ = False
checkPNTInPat (p:ps) i
| defineLoc i == (SrcLoc "__unknown__" 0 0 0) = False
| defineLoc i == defineLoc (patToPNT p) = True
| otherwise = checkPNTInPat ps i
getPatFromPats :: [HsPatP] -> HsExpP -> PNT -> [HsPatP]
getPatFromPats [] _ _ = []
getPatFromPats (p:pats) e i2
| defineLoc i2 == (SrcLoc "__unknown__" 0 0 0) = p : (getPatFromPats pats e i2)
| defineLoc i2 == defineLoc (patToPNT p) = (expToPat e) ++ (getPatFromPats pats e i2)
| otherwise = p : (getPatFromPats pats e i2)
patToExp :: HsPatP -> HsExpP
patToExp (Pat (HsPId x)) = (Exp (HsId x))
patToExp (Pat (HsPLit s l)) = (Exp (HsLit s l))
patToExp (Pat (HsPInfixApp p1 i p2)) = (Exp (HsInfixApp (patToExp p1) (HsCon i) (patToExp p2)))
patToExp (Pat (HsPApp pnt p2)) = (Exp (HsApp (nameToExp (pNTtoName pnt)) (cApp p2)))
where
cApp :: [HsPatP] -> HsExpP
cApp [p] = patToExp p
cApp (p:ps) = Exp (HsApp (cApp (init (p:ps))) (patToExp (last ps)))
patToExp (Pat (HsPTuple s ps)) = (Exp (HsTuple (map patToExp ps)))
patToExp (Pat (HsPList s ps)) = (Exp (HsList (map patToExp ps)))
patToExp (Pat (HsPParen p1)) = (Exp (HsParen (patToExp p1)))
patToExp (Pat (HsPAsPat pnt pat)) = (Exp (HsId (HsVar pnt)))
patToExp (Pat (HsPIrrPat p)) = patToExp p
patToExp (Pat (HsPWildCard)) = nameToExp "undefined"
expToPat :: HsExpP -> [HsPatP]
expToPat (Exp (HsId x)) = [Pat (HsPId x)]
expToPat (Exp (HsLit s l)) = [Pat (HsPLit s l)]
expToPat (Exp (HsInfixApp e1 (HsVar i) e2)) = [Pat (HsPInfixApp (ghead "expToPat" $ expToPat e1)
i (ghead "expToPat" $ expToPat e2))]
expToPat (Exp (HsInfixApp e1 (HsCon i) e2)) = [Pat (HsPInfixApp (ghead "expToPat" $ expToPat e1)
i (ghead "expToPat" $ expToPat e2))]
expToPat e@(Exp (HsApp e1 e2)) = [Pat (HsPApp (nameToPNT " ")
(concatMap expToPat exps))]
where
exps = flatternApp e
expToPat (Exp (HsLambda ps e)) = ps
expToPat (Exp (HsTuple es)) = concatMap expToPat es --[Pat (HsPTuple loc0 (concatMap expToPat es))]
expToPat (Exp (HsList es)) = concatMap expToPat es
expToPat (Exp (HsParen e1)) = [Pat (HsPParen (ghead "expToPat" $ expToPat e1))]
expToPat e = []
flatternApp :: HsExpP -> [HsExpP]
flatternApp (Exp (HsApp e1 e2)) = flatternApp e1 ++ flatternApp e2
flatternApp (Exp (HsParen e)) = flatternApp e
flatternApp x = [x]
searchForRHS pnt exp t
= (fromMaybe (error "Could not find the right hand side for the commented definition!"))
(applyTU (once_tdTU (failTU `adhocTU` (inDec exp))) t)
where
inDec e (pat@(Dec (HsPatBind loc1 ps rhs@(HsBody e2) ds))::HsDeclP)
| findEntity e e2
= do
let newExp = symbolicallyTie exp e2 []
Just newExp
inDec e (dec@(Dec (HsFunBind s matches))::HsDeclP)
| findPNT pnt matches
= do
let match@(HsMatch loc name pats rhs ds) = getMatch pnt matches
if findEntity e (extractRHS e rhs)
then do
let newExp = symbolicallyTie exp (extractRHS e rhs) pats
Just newExp
else do
mzero
inDec _ d = mzero
findGuard e [] = error "Cannot find highlight expression!"
findGuard e ((_,_,x):xs)
| findEntity e x = x
| otherwise = findGuard e xs
extractRHS e (HsBody x) = x
extractRHS e (HsGuard gs) = findGuard e gs
symbolicallyTie exp (Exp (HsParen e)) pats = symbolicallyTie exp e pats
symbolicallyTie exp n@(Exp (HsCase e alts)) pats
= symbolicallyTie' alts -- (Exp (HsCase e [symbolicallyTie' alts]))
where
symbolicallyTie' [] = error "Error in symbolic evaluation: expression does not occur on the RHS!"
symbolicallyTie' (a@(HsAlt l p (HsGuard gs) ds):as)
| findEntity exp gs
= zipPatExp e n a' pats
| findEntity exp ds -- selected definition is in where clause of a case alt.
= zipPatExp e n a' pats
where
a' = (HsAlt l p (HsBody exp) ds)
symbolicallyTie' (a@(HsAlt l p (HsBody e2) ds):as)
| findEntity exp e2
= zipPatExp e n a' pats
| findEntity exp ds -- selected definition is in where clause of a case alt.
= zipPatExp e n a' pats
| otherwise = symbolicallyTie' as
where
a' = (HsAlt l p (HsBody exp) ds)
symbolicallyTie exp e pats = exp
-- utility functions
getMatch :: PNT -> [HsMatchP] -> HsMatchP
getMatch _ [] = error "Please select a case in top-level expression scope!"
getMatch pnt (match@(HsMatch loc name pats rhs ds):ms)
| useLoc pnt == useLoc name = match
| otherwise = getMatch pnt ms
convertModName (PlainModule s) = s
convertModName m@(MainModule f) = modNameToStr m
{-|
Takes the position of the highlighted code and returns
the function name, the list of arguments, the expression that has been
highlighted by the user, and any where\/let clauses associated with the
function.
-}
findDefNameAndExp :: Term t => [PosToken] -- ^ The token stream for the
-- file to be
-- refactored.
-> (Int, Int) -- ^ The beginning position of the highlighting.
-> (Int, Int) -- ^ The end position of the highlighting.
-> t -- ^ The abstract syntax tree.
-> (PatFun, PNT, FunctionPats, WhereDecls) -- ^ A tuple of,
-- (the function name, the list of arguments,
-- the expression highlighted, any where\/let clauses
-- associated with the function).
findDefNameAndExp toks beginPos endPos t
= fromMaybe (Er, defaultPNT, [], [])
(applyTU (once_buTU (failTU `adhocTU` inMatch `adhocTU` inPat)) t)
where
--The selected sub-expression is in the rhs of a match
inMatch (match@(HsMatch loc1 pnt pats rhs@(HsBody e) ds)::HsMatchP)
| locToExp beginPos endPos toks rhs /= defaultExp
= Just (Mat, pnt, pats, ds)
inMatch (match@(HsMatch loc1 pnt pats rhs@(HsGuard e) ds)::HsMatchP)
| locToExp beginPos endPos toks rhs /= defaultExp
= Just (Mat, pnt, pats, ds)
inMatch _ = Nothing
--The selected sub-expression is in the rhs of a pattern-binding
inPat (pat@(Dec (HsPatBind loc1 ps rhs ds))::HsDeclP)
| locToExp beginPos endPos toks rhs /= defaultExp
= if isSimplePatBind pat
then Just (Patt, patToPNT ps, [], ds)
else Just (Patt, pnt, pats, ds)
where
(_, pnt, pats, ds') = findDefining pat t
findDefining pats t
= fromMaybe (error "Error: the selected entity is a top level complex pattern binding!")
(applyTU (once_buTU (failTU `adhocTU` inMatch')) t)
inMatch' (match@(HsMatch loc1 pnt pats rhs@(HsBody e) ds)::HsMatchP)
| pat `elem` ds = Just (Mat, pnt, pats, ds)
| findEntity pat e = Just (Mat, pnt, pats, ds)
inMatch' (match@(HsMatch loc1 pnt pats rhs@(HsGuard e) ds)::HsMatchP)
| pat `elem` ds = Just (Mat, pnt, pats, ds)
| findEntity pat e = Just (Mat, pnt, pats, ds)
inMatch' _ = Nothing
inPat _ = Nothing