module Language.Fortran.Transformer ( transform, transformWithModFiles
                                    , Transformation(..) ) where

import Data.Maybe (fromJust)
import Data.Map (empty)
import Data.Data

import Language.Fortran.Util.ModFile
import Language.Fortran.Transformation.TransformMonad (Transform, runTransform)
import Language.Fortran.Transformation.Disambiguation.Function
import Language.Fortran.Transformation.Disambiguation.Intrinsic
import Language.Fortran.Transformation.Grouping
import Language.Fortran.AST (ProgramFile)

data Transformation =
    GroupForall
  | GroupIf
  | GroupCase
  | GroupDo
  | GroupLabeledDo
  | DisambiguateFunction
  | DisambiguateIntrinsic
  deriving (Transformation -> Transformation -> Bool
(Transformation -> Transformation -> Bool)
-> (Transformation -> Transformation -> Bool) -> Eq Transformation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Transformation -> Transformation -> Bool
$c/= :: Transformation -> Transformation -> Bool
== :: Transformation -> Transformation -> Bool
$c== :: Transformation -> Transformation -> Bool
Eq)

transformationMapping :: Data a => [ (Transformation, Transform a ()) ]
transformationMapping :: [(Transformation, Transform a ())]
transformationMapping =
  [ (Transformation
GroupForall, Transform a ()
forall a. Data a => Transform a ()
groupForall)
  , (Transformation
GroupIf, Transform a ()
forall a. Data a => Transform a ()
groupIf)
  , (Transformation
GroupCase, Transform a ()
forall a. Data a => Transform a ()
groupCase)
  , (Transformation
GroupDo, Transform a ()
forall a. Data a => Transform a ()
groupDo)
  , (Transformation
GroupLabeledDo, Transform a ()
forall a. Data a => Transform a ()
groupLabeledDo)
  , (Transformation
DisambiguateFunction, Transform a ()
forall a. Data a => Transform a ()
disambiguateFunction)
  , (Transformation
DisambiguateIntrinsic, Transform a ()
forall a. Data a => Transform a ()
disambiguateIntrinsic)
  ]

transformWithModFiles :: Data a => ModFiles -> [ Transformation ] -> ProgramFile a -> ProgramFile a
transformWithModFiles :: ModFiles -> [Transformation] -> ProgramFile a -> ProgramFile a
transformWithModFiles ModFiles
mods [Transformation]
trs = TypeEnv
-> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
forall a.
Data a =>
TypeEnv
-> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
runTransform (ModFiles -> TypeEnv
combinedTypeEnv ModFiles
mods) (ModFiles -> ModuleMap
combinedModuleMap ModFiles
mods) Transform a ()
trans
  where
    trans :: Transform a ()
trans = (Transformation -> Transform a ())
-> [Transformation] -> Transform a ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\Transformation
t -> Maybe (Transform a ()) -> Transform a ()
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (Transform a ()) -> Transform a ())
-> Maybe (Transform a ()) -> Transform a ()
forall a b. (a -> b) -> a -> b
$ Transformation
-> [(Transformation, Transform a ())] -> Maybe (Transform a ())
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Transformation
t [(Transformation, Transform a ())]
forall a. Data a => [(Transformation, Transform a ())]
transformationMapping) [Transformation]
trs

transform :: Data a => [ Transformation ] -> ProgramFile a -> ProgramFile a
transform :: [Transformation] -> ProgramFile a -> ProgramFile a
transform [Transformation]
trs = TypeEnv
-> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
forall a.
Data a =>
TypeEnv
-> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
runTransform TypeEnv
forall k a. Map k a
empty ModuleMap
forall k a. Map k a
empty Transform a ()
trans
  where
    trans :: Transform a ()
trans = (Transformation -> Transform a ())
-> [Transformation] -> Transform a ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\Transformation
t -> Maybe (Transform a ()) -> Transform a ()
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (Transform a ()) -> Transform a ())
-> Maybe (Transform a ()) -> Transform a ()
forall a b. (a -> b) -> a -> b
$ Transformation
-> [(Transformation, Transform a ())] -> Maybe (Transform a ())
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Transformation
t [(Transformation, Transform a ())]
forall a. Data a => [(Transformation, Transform a ())]
transformationMapping) [Transformation]
trs