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