{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
module Camfort.Transformation.EquivalenceElim
( refactorEquivalences
) where
import Camfort.Analysis
import Camfort.Analysis.Annotations
import Camfort.Helpers.Syntax
import Camfort.Transformation.DeadCode
import Control.Monad.State.Lazy hiding (ap)
import Data.Generics.Uniplate.Operations
import Data.List
import qualified Data.Map as M
import Data.Void (Void)
import qualified Language.Fortran.AST as F
import qualified Language.Fortran.Analysis as FA
import qualified Language.Fortran.Analysis.Renaming as FAR
import qualified Language.Fortran.Analysis.Types as FAT (analyseTypes, TypeEnv)
import qualified Language.Fortran.Util.Position as FU
type EquivalenceRefactoring = PureAnalysis Void Void
type A1 = FA.Analysis Annotation
type RmEqState = ([[F.Expression A1]], Int)
refactorEquivalences :: F.ProgramFile A -> EquivalenceRefactoring (F.ProgramFile A)
refactorEquivalences :: ProgramFile A -> EquivalenceRefactoring (ProgramFile A)
refactorEquivalences ProgramFile A
pf = do
let
pf' :: ProgramFile (Analysis A)
pf' = ProgramFile (Analysis A) -> ProgramFile (Analysis A)
forall a.
Data a =>
ProgramFile (Analysis a) -> ProgramFile (Analysis a)
FAR.analyseRenames (ProgramFile (Analysis A) -> ProgramFile (Analysis A))
-> (ProgramFile A -> ProgramFile (Analysis A))
-> ProgramFile A
-> ProgramFile (Analysis A)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> ProgramFile (Analysis A)
forall (b :: * -> *) a. Functor b => b a -> b (Analysis a)
FA.initAnalysis (ProgramFile A -> ProgramFile (Analysis A))
-> ProgramFile A -> ProgramFile (Analysis A)
forall a b. (a -> b) -> a -> b
$ ProgramFile A
pf
(ProgramFile (Analysis A)
pf'', TypeEnv
typeEnv) = ProgramFile (Analysis A) -> (ProgramFile (Analysis A), TypeEnv)
forall a.
Data a =>
ProgramFile (Analysis a) -> (ProgramFile (Analysis a), TypeEnv)
FAT.analyseTypes ProgramFile (Analysis A)
pf'
ProgramFile (Analysis A)
pf''' <- TypeEnv
-> ProgramFile (Analysis A)
-> EquivalenceRefactoring (ProgramFile (Analysis A))
refactoring TypeEnv
typeEnv ProgramFile (Analysis A)
pf''
Bool -> ProgramFile A -> EquivalenceRefactoring (ProgramFile A)
deadCode Bool
True ((Analysis A -> A) -> ProgramFile (Analysis A) -> ProgramFile A
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Analysis A -> A
forall a. Analysis a -> a
FA.prevAnnotation ProgramFile (Analysis A)
pf''')
where
refactoring
:: FAT.TypeEnv -> F.ProgramFile A1
-> EquivalenceRefactoring (F.ProgramFile A1)
refactoring :: TypeEnv
-> ProgramFile (Analysis A)
-> EquivalenceRefactoring (ProgramFile (Analysis A))
refactoring TypeEnv
tenv ProgramFile (Analysis A)
pf' = do
(ProgramFile (Analysis A)
pf'', RmEqState
_) <- StateT RmEqState EquivalenceRefactoring (ProgramFile (Analysis A))
-> RmEqState
-> EquivalenceRefactoring (ProgramFile (Analysis A), RmEqState)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT StateT RmEqState EquivalenceRefactoring (ProgramFile (Analysis A))
equiv ([], Int
0)
ProgramFile (Analysis A)
-> EquivalenceRefactoring (ProgramFile (Analysis A))
forall (m :: * -> *) a. Monad m => a -> m a
return ProgramFile (Analysis A)
pf''
where
equiv :: StateT RmEqState EquivalenceRefactoring (ProgramFile (Analysis A))
equiv = do ProgramFile (Analysis A)
pf'' <- (Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Block (Analysis A)))
-> ProgramFile (Analysis A)
-> StateT
RmEqState EquivalenceRefactoring (ProgramFile (Analysis A))
forall (m :: * -> *) from to.
(Monad m, Applicative m, Biplate from to) =>
(to -> m to) -> from -> m from
transformBiM Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Block (Analysis A))
perBlockRmEquiv ProgramFile (Analysis A)
pf'
([Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)])
-> ProgramFile (Analysis A)
-> StateT
RmEqState EquivalenceRefactoring (ProgramFile (Analysis A))
forall from to (m :: * -> *).
(Biplate from to, Applicative m) =>
(to -> m to) -> from -> m from
descendBiM (TypeEnv
-> [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
addCopysPerBlockGroup TypeEnv
tenv) ProgramFile (Analysis A)
pf''
addCopysPerBlockGroup
:: FAT.TypeEnv -> [F.Block A1]
-> StateT RmEqState EquivalenceRefactoring [F.Block A1]
addCopysPerBlockGroup :: TypeEnv
-> [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
addCopysPerBlockGroup TypeEnv
tenv [Block (Analysis A)]
blocks = do
[[Block (Analysis A)]]
blockss <- (Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)])
-> [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [[Block (Analysis A)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TypeEnv
-> Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
addCopysPerBlock TypeEnv
tenv) [Block (Analysis A)]
blocks
[Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)])
-> [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
forall a b. (a -> b) -> a -> b
$ [[Block (Analysis A)]] -> [Block (Analysis A)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Block (Analysis A)]]
blockss
addCopysPerBlock
:: FAT.TypeEnv -> F.Block A1
-> StateT RmEqState EquivalenceRefactoring [F.Block A1]
addCopysPerBlock :: TypeEnv
-> Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
addCopysPerBlock TypeEnv
tenv b :: Block (Analysis A)
b@(F.BlStatement Analysis A
_ SrcSpan
_ Maybe (Expression (Analysis A))
_
(F.StExpressionAssign Analysis A
a sp :: SrcSpan
sp@(FU.SrcSpan Position
s1 Position
_) Expression (Analysis A)
dstE Expression (Analysis A)
_))
| Bool -> Bool
not (A -> Bool
pRefactored (A -> Bool) -> A -> Bool
forall a b. (a -> b) -> a -> b
$ Analysis A -> A
forall a. Analysis a -> a
FA.prevAnnotation Analysis A
a) = do
[Expression (Analysis A)]
eqs <- Expression (Analysis A)
-> StateT
RmEqState EquivalenceRefactoring [Expression (Analysis A)]
equivalentsToExpr Expression (Analysis A)
dstE
if [Expression (Analysis A)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expression (Analysis A)]
eqs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
then [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
forall (m :: * -> *) a. Monad m => a -> m a
return [Block (Analysis A)
b]
else do
([[Expression (Analysis A)]]
equivs, Int
n) <- StateT RmEqState EquivalenceRefactoring RmEqState
forall s (m :: * -> *). MonadState s m => m s
get
let eqs' :: [Expression (Analysis A)]
eqs' = (Expression (Analysis A) -> Expression (Analysis A) -> Bool)
-> Expression (Analysis A)
-> [Expression (Analysis A)]
-> [Expression (Analysis A)]
forall a. (a -> a -> Bool) -> a -> [a] -> [a]
deleteBy (\ Expression (Analysis A)
x Expression (Analysis A)
y -> Expression (Analysis A) -> AnnotationFree (Expression (Analysis A))
forall t. t -> AnnotationFree t
af Expression (Analysis A)
x AnnotationFree (Expression (Analysis A))
-> AnnotationFree (Expression (Analysis A)) -> Bool
forall a. Eq a => a -> a -> Bool
== Expression (Analysis A) -> AnnotationFree (Expression (Analysis A))
forall t. t -> AnnotationFree t
af Expression (Analysis A)
y) Expression (Analysis A)
dstE [Expression (Analysis A)]
eqs
let pos :: Position
pos = SrcSpan -> Position
afterAligned SrcSpan
sp
let copies :: [Block (Analysis A)]
copies = (Expression (Analysis A) -> Block (Analysis A))
-> [Expression (Analysis A)] -> [Block (Analysis A)]
forall a b. (a -> b) -> [a] -> [b]
map (TypeEnv
-> Position
-> Expression (Analysis A)
-> Expression (Analysis A)
-> Block (Analysis A)
mkCopy TypeEnv
tenv Position
pos Expression (Analysis A)
dstE) [Expression (Analysis A)]
eqs'
let (FU.Position Int
ao Int
c Int
l String
f Maybe (Int, String)
p) = Position
s1
reportSpan :: Int -> SrcSpan
reportSpan Int
i =
let pos' :: Position
pos' = Int -> Int -> Int -> String -> Maybe (Int, String) -> Position
FU.Position (Int
ao Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i) Int
c (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i) String
f Maybe (Int, String)
p
in (Position -> Position -> SrcSpan
FU.SrcSpan Position
pos' Position
pos')
[Int]
-> (Int -> StateT RmEqState EquivalenceRefactoring ())
-> StateT RmEqState EquivalenceRefactoring ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
n..(Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Block (Analysis A)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Block (Analysis A)]
copies Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)] ((Int -> StateT RmEqState EquivalenceRefactoring ())
-> StateT RmEqState EquivalenceRefactoring ())
-> (Int -> StateT RmEqState EquivalenceRefactoring ())
-> StateT RmEqState EquivalenceRefactoring ()
forall a b. (a -> b) -> a -> b
$ \Int
i -> do
Origin
origin <- SrcSpan -> StateT RmEqState EquivalenceRefactoring Origin
forall e w (m :: * -> *) a.
(MonadLogger e w m, Spanned a) =>
a -> m Origin
atSpanned (Int -> SrcSpan
reportSpan Int
i)
Origin -> Text -> StateT RmEqState EquivalenceRefactoring ()
forall e w (m :: * -> *).
MonadLogger e w m =>
Origin -> Text -> m ()
logInfo Origin
origin (Text -> StateT RmEqState EquivalenceRefactoring ())
-> Text -> StateT RmEqState EquivalenceRefactoring ()
forall a b. (a -> b) -> a -> b
$ Text
"added copy due to refactored equivalence"
RmEqState -> StateT RmEqState EquivalenceRefactoring ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put ([[Expression (Analysis A)]]
equivs, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Expression (Analysis A)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expression (Analysis A)]
eqs')
[Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)])
-> [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
forall a b. (a -> b) -> a -> b
$ Block (Analysis A)
b Block (Analysis A) -> [Block (Analysis A)] -> [Block (Analysis A)]
forall a. a -> [a] -> [a]
: [Block (Analysis A)]
copies
addCopysPerBlock TypeEnv
tenv Block (Analysis A)
x = do
Block (Analysis A)
x' <- ([Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)])
-> Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Block (Analysis A))
forall from to (m :: * -> *).
(Biplate from to, Applicative m) =>
(to -> m to) -> from -> m from
descendBiM (TypeEnv
-> [Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
addCopysPerBlockGroup TypeEnv
tenv) Block (Analysis A)
x
[Block (Analysis A)]
-> StateT RmEqState EquivalenceRefactoring [Block (Analysis A)]
forall (m :: * -> *) a. Monad m => a -> m a
return [Block (Analysis A)
x']
equalTypes :: FAT.TypeEnv -> F.Expression A1 -> F.Expression A1 -> Maybe FA.IDType
equalTypes :: TypeEnv
-> Expression (Analysis A)
-> Expression (Analysis A)
-> Maybe IDType
equalTypes TypeEnv
tenv Expression (Analysis A)
e Expression (Analysis A)
e' = do
String
v1 <- Expression (Analysis A) -> Maybe String
forall a. Expression a -> Maybe String
extractVariable Expression (Analysis A)
e
String
v2 <- Expression (Analysis A) -> Maybe String
forall a. Expression a -> Maybe String
extractVariable Expression (Analysis A)
e'
IDType
t1 <- String -> TypeEnv -> Maybe IDType
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup String
v1 TypeEnv
tenv
IDType
t2 <- String -> TypeEnv -> Maybe IDType
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup String
v2 TypeEnv
tenv
if IDType
t1 IDType -> IDType -> Bool
forall a. Eq a => a -> a -> Bool
== IDType
t2 then IDType -> Maybe IDType
forall a. a -> Maybe a
Just IDType
t1 else Maybe IDType
forall a. Maybe a
Nothing
mkCopy :: FAT.TypeEnv
-> FU.Position
-> F.Expression A1 -> F.Expression A1 -> F.Block A1
mkCopy :: TypeEnv
-> Position
-> Expression (Analysis A)
-> Expression (Analysis A)
-> Block (Analysis A)
mkCopy TypeEnv
tenv Position
pos Expression (Analysis A)
srcE Expression (Analysis A)
dstE = Block A -> Block (Analysis A)
forall (b :: * -> *) a. Functor b => b a -> b (Analysis a)
FA.initAnalysis (Block A -> Block (Analysis A)) -> Block A -> Block (Analysis A)
forall a b. (a -> b) -> a -> b
$
A -> SrcSpan -> Maybe (Expression A) -> Statement A -> Block A
forall a.
a -> SrcSpan -> Maybe (Expression a) -> Statement a -> Block a
F.BlStatement A
a SrcSpan
sp Maybe (Expression A)
forall a. Maybe a
Nothing (Statement A -> Block A) -> Statement A -> Block A
forall a b. (a -> b) -> a -> b
$
case TypeEnv
-> Expression (Analysis A)
-> Expression (Analysis A)
-> Maybe IDType
equalTypes TypeEnv
tenv Expression (Analysis A)
srcE Expression (Analysis A)
dstE of
Maybe IDType
Nothing -> A -> SrcSpan -> Expression A -> Expression A -> Statement A
forall a.
a -> SrcSpan -> Expression a -> Expression a -> Statement a
F.StExpressionAssign A
a SrcSpan
sp Expression A
dstE' Expression A
call
where
call :: Expression A
call = A
-> SrcSpan
-> Expression A
-> Maybe (AList Argument A)
-> Expression A
forall a.
a
-> SrcSpan
-> Expression a
-> Maybe (AList Argument a)
-> Expression a
F.ExpFunctionCall A
a SrcSpan
sp Expression A
transf Maybe (AList Argument A)
argst
transf :: Expression A
transf = A -> SrcSpan -> Value A -> Expression A
forall a. a -> SrcSpan -> Value a -> Expression a
F.ExpValue A
a SrcSpan
sp (String -> Value A
forall a. String -> Value a
F.ValVariable String
"transfer")
argst :: Maybe (AList Argument A)
argst = AList Argument A -> Maybe (AList Argument A)
forall a. a -> Maybe a
Just (A -> SrcSpan -> [Argument A] -> AList Argument A
forall (t :: * -> *) a. a -> SrcSpan -> [t a] -> AList t a
F.AList A
a SrcSpan
sp [Argument A]
args)
args :: [Argument A]
args = (Expression A -> Argument A) -> [Expression A] -> [Argument A]
forall a b. (a -> b) -> [a] -> [b]
map (A -> SrcSpan -> Maybe String -> Expression A -> Argument A
forall a.
a -> SrcSpan -> Maybe String -> Expression a -> Argument a
F.Argument A
a SrcSpan
sp Maybe String
forall a. Maybe a
Nothing) [Expression A
srcE', Expression A
dstE']
Just IDType
_ -> A -> SrcSpan -> Expression A -> Expression A -> Statement A
forall a.
a -> SrcSpan -> Expression a -> Expression a -> Statement a
F.StExpressionAssign A
a SrcSpan
sp Expression A
dstE' Expression A
srcE'
where
sp :: SrcSpan
sp = Position -> Position -> SrcSpan
FU.SrcSpan (Position -> Position
toCol0 Position
pos) (Position -> Position
toCol0 Position
pos)
a :: A
a = A
unitAnnotation { refactored :: Maybe Position
refactored = Position -> Maybe Position
forall a. a -> Maybe a
Just Position
pos, newNode :: Bool
newNode = Bool
True }
dstE' :: Expression A
dstE' = Expression (Analysis A) -> Expression A
forall (b :: * -> *) a. Functor b => b (Analysis a) -> b a
FA.stripAnalysis Expression (Analysis A)
dstE
srcE' :: Expression A
srcE' = Expression (Analysis A) -> Expression A
forall (b :: * -> *) a. Functor b => b (Analysis a) -> b a
FA.stripAnalysis Expression (Analysis A)
srcE
perBlockRmEquiv :: F.Block A1 -> StateT RmEqState EquivalenceRefactoring (F.Block A1)
perBlockRmEquiv :: Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Block (Analysis A))
perBlockRmEquiv = (Statement (Analysis A)
-> StateT
RmEqState EquivalenceRefactoring (Statement (Analysis A)))
-> Block (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Block (Analysis A))
forall (m :: * -> *) from to.
(Monad m, Applicative m, Biplate from to) =>
(to -> m to) -> from -> m from
transformBiM Statement (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Statement (Analysis A))
perStatementRmEquiv
perStatementRmEquiv
:: F.Statement A1
-> StateT RmEqState EquivalenceRefactoring (F.Statement A1)
perStatementRmEquiv :: Statement (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Statement (Analysis A))
perStatementRmEquiv (F.StEquivalence Analysis A
a sp :: SrcSpan
sp@(FU.SrcSpan Position
spL Position
_) AList (AList Expression) (Analysis A)
equivs) = do
([[Expression (Analysis A)]]
ess, Int
n) <- StateT RmEqState EquivalenceRefactoring RmEqState
forall s (m :: * -> *). MonadState s m => m s
get
let spL' :: SrcSpan
spL' = Position -> Position -> SrcSpan
FU.SrcSpan Position
spL Position
spL
SrcSpan -> Text -> StateT RmEqState EquivalenceRefactoring ()
forall e w (m :: * -> *) a.
(MonadLogger e w m, Spanned a) =>
a -> Text -> m ()
logInfo' SrcSpan
spL' (Text -> StateT RmEqState EquivalenceRefactoring ())
-> Text -> StateT RmEqState EquivalenceRefactoring ()
forall a b. (a -> b) -> a -> b
$ Text
"removed equivalence"
RmEqState -> StateT RmEqState EquivalenceRefactoring ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put ((((AList Expression (Analysis A) -> [Expression (Analysis A)])
-> [AList Expression (Analysis A)] -> [[Expression (Analysis A)]]
forall a b. (a -> b) -> [a] -> [b]
map AList Expression (Analysis A) -> [Expression (Analysis A)]
forall (t :: * -> *) a. AList t a -> [t a]
F.aStrip) ([AList Expression (Analysis A)] -> [[Expression (Analysis A)]])
-> (AList (AList Expression) (Analysis A)
-> [AList Expression (Analysis A)])
-> AList (AList Expression) (Analysis A)
-> [[Expression (Analysis A)]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AList (AList Expression) (Analysis A)
-> [AList Expression (Analysis A)]
forall (t :: * -> *) a. AList t a -> [t a]
F.aStrip (AList (AList Expression) (Analysis A)
-> [[Expression (Analysis A)]])
-> AList (AList Expression) (Analysis A)
-> [[Expression (Analysis A)]]
forall a b. (a -> b) -> a -> b
$ AList (AList Expression) (Analysis A)
equivs) [[Expression (Analysis A)]]
-> [[Expression (Analysis A)]] -> [[Expression (Analysis A)]]
forall a. [a] -> [a] -> [a]
++ [[Expression (Analysis A)]]
ess, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
let a' :: Analysis A
a' = (A -> A) -> Analysis A -> Analysis A
forall a. (a -> a) -> Analysis a -> Analysis a
onPrev (\A
ap -> A
ap {refactored :: Maybe Position
refactored = Position -> Maybe Position
forall a. a -> Maybe a
Just Position
spL, deleteNode :: Bool
deleteNode = Bool
True}) Analysis A
a
Statement (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Statement (Analysis A))
forall (m :: * -> *) a. Monad m => a -> m a
return (Analysis A
-> SrcSpan
-> AList (AList Expression) (Analysis A)
-> Statement (Analysis A)
forall a. a -> SrcSpan -> AList (AList Expression) a -> Statement a
F.StEquivalence Analysis A
a' (SrcSpan -> SrcSpan
deleteLine SrcSpan
sp) AList (AList Expression) (Analysis A)
equivs)
perStatementRmEquiv Statement (Analysis A)
f = Statement (Analysis A)
-> StateT RmEqState EquivalenceRefactoring (Statement (Analysis A))
forall (m :: * -> *) a. Monad m => a -> m a
return Statement (Analysis A)
f
equivalentsToExpr
:: F.Expression A1
-> StateT RmEqState EquivalenceRefactoring [F.Expression A1]
equivalentsToExpr :: Expression (Analysis A)
-> StateT
RmEqState EquivalenceRefactoring [Expression (Analysis A)]
equivalentsToExpr Expression (Analysis A)
y = do
([[Expression (Analysis A)]]
equivs, Int
_) <- StateT RmEqState EquivalenceRefactoring RmEqState
forall s (m :: * -> *). MonadState s m => m s
get
[Expression (Analysis A)]
-> StateT
RmEqState EquivalenceRefactoring [Expression (Analysis A)]
forall (m :: * -> *) a. Monad m => a -> m a
return (Expression (Analysis A)
-> [[Expression (Analysis A)]] -> [Expression (Analysis A)]
forall t. Eq (AnnotationFree t) => t -> [[t]] -> [t]
inGroup Expression (Analysis A)
y [[Expression (Analysis A)]]
equivs)
where
inGroup :: t -> [[t]] -> [t]
inGroup t
_ [] = []
inGroup t
x ([t]
xs:[[t]]
xss) =
if t -> AnnotationFree t
forall t. t -> AnnotationFree t
AnnotationFree t
x AnnotationFree t -> [AnnotationFree t] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (t -> AnnotationFree t) -> [t] -> [AnnotationFree t]
forall a b. (a -> b) -> [a] -> [b]
map t -> AnnotationFree t
forall t. t -> AnnotationFree t
AnnotationFree [t]
xs
then [t]
xs
else t -> [[t]] -> [t]
inGroup t
x [[t]]
xss