module Language.Fortran.Transformation.Monad
  ( getProgramFile
  , putProgramFile
  , modifyProgramFile
  , runTransform
  , Transform
  ) where

import Prelude hiding (lookup)
import Control.Monad.State.Lazy hiding (state)
import Data.Data

import Language.Fortran.Analysis
import Language.Fortran.Analysis.Types
import Language.Fortran.Analysis.Renaming
import Language.Fortran.AST (ProgramFile)

data TransformationState a = TransformationState
  { forall a. TransformationState a -> ProgramFile (Analysis a)
transProgramFile :: ProgramFile (Analysis a) }

type Transform a = State (TransformationState a)

runTransform
    :: Data a
    => TypeEnv -> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
runTransform :: forall a.
Data a =>
TypeEnv
-> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
runTransform TypeEnv
env ModuleMap
mmap Transform a ()
trans ProgramFile a
pf =
    ProgramFile (Analysis a) -> ProgramFile a
forall (b :: * -> *) a. Functor b => b (Analysis a) -> b a
stripAnalysis (ProgramFile (Analysis a) -> ProgramFile a)
-> (TransformationState a -> ProgramFile (Analysis a))
-> TransformationState a
-> ProgramFile a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TransformationState a -> ProgramFile (Analysis a)
forall a. TransformationState a -> ProgramFile (Analysis a)
transProgramFile (TransformationState a -> ProgramFile (Analysis a))
-> (TransformationState a -> TransformationState a)
-> TransformationState a
-> ProgramFile (Analysis a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transform a () -> TransformationState a -> TransformationState a
forall s a. State s a -> s -> s
execState Transform a ()
trans (TransformationState a -> ProgramFile a)
-> TransformationState a -> ProgramFile a
forall a b. (a -> b) -> a -> b
$ TransformationState a
initState
  where
    (ProgramFile (Analysis a)
pf', TypeEnv
_) = TypeEnv
-> ProgramFile (Analysis a) -> (ProgramFile (Analysis a), TypeEnv)
forall a.
Data a =>
TypeEnv
-> ProgramFile (Analysis a) -> (ProgramFile (Analysis a), TypeEnv)
analyseTypesWithEnv TypeEnv
env (ProgramFile (Analysis a) -> (ProgramFile (Analysis a), TypeEnv))
-> (ProgramFile a -> ProgramFile (Analysis a))
-> ProgramFile a
-> (ProgramFile (Analysis a), TypeEnv)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleMap -> ProgramFile (Analysis a) -> ProgramFile (Analysis a)
forall a.
Data a =>
ModuleMap -> ProgramFile (Analysis a) -> ProgramFile (Analysis a)
analyseRenamesWithModuleMap ModuleMap
mmap (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)
initAnalysis (ProgramFile a -> (ProgramFile (Analysis a), TypeEnv))
-> ProgramFile a -> (ProgramFile (Analysis a), TypeEnv)
forall a b. (a -> b) -> a -> b
$ ProgramFile a
pf
    initState :: TransformationState a
initState = TransformationState
      { transProgramFile :: ProgramFile (Analysis a)
transProgramFile = ProgramFile (Analysis a)
pf' }

getProgramFile :: Transform a (ProgramFile (Analysis a))
getProgramFile :: forall a. Transform a (ProgramFile (Analysis a))
getProgramFile = (TransformationState a -> ProgramFile (Analysis a))
-> StateT
     (TransformationState a) Identity (ProgramFile (Analysis a))
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets TransformationState a -> ProgramFile (Analysis a)
forall a. TransformationState a -> ProgramFile (Analysis a)
transProgramFile

putProgramFile :: ProgramFile (Analysis a) -> Transform a ()
putProgramFile :: forall a. ProgramFile (Analysis a) -> Transform a ()
putProgramFile ProgramFile (Analysis a)
pf = do
  TransformationState a
state <- StateT (TransformationState a) Identity (TransformationState a)
forall s (m :: * -> *). MonadState s m => m s
get
  TransformationState a -> Transform a ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (TransformationState a -> Transform a ())
-> TransformationState a -> Transform a ()
forall a b. (a -> b) -> a -> b
$ TransformationState a
state { transProgramFile :: ProgramFile (Analysis a)
transProgramFile = ProgramFile (Analysis a)
pf }

modifyProgramFile :: (ProgramFile (Analysis a) -> ProgramFile (Analysis a)) -> Transform a ()
modifyProgramFile :: forall a.
(ProgramFile (Analysis a) -> ProgramFile (Analysis a))
-> Transform a ()
modifyProgramFile ProgramFile (Analysis a) -> ProgramFile (Analysis a)
f = (TransformationState a -> TransformationState a)
-> StateT (TransformationState a) Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((TransformationState a -> TransformationState a)
 -> StateT (TransformationState a) Identity ())
-> (TransformationState a -> TransformationState a)
-> StateT (TransformationState a) Identity ()
forall a b. (a -> b) -> a -> b
$ \ TransformationState a
s -> TransformationState a
s { transProgramFile :: ProgramFile (Analysis a)
transProgramFile = ProgramFile (Analysis a) -> ProgramFile (Analysis a)
f (TransformationState a -> ProgramFile (Analysis a)
forall a. TransformationState a -> ProgramFile (Analysis a)
transProgramFile TransformationState a
s) }