module Language.Fortran.Vars.Dummy
  ( undefineDummyArguments
  )
where

import           Language.Fortran.Extras
                                                ( allPUS )
import           Data.Data                      ( Data )
import           Data.List                      ( foldl' )
import qualified Data.Map                      as M
import           Language.Fortran.Analysis      ( Analysis
                                                , srcName
                                                )
import           Language.Fortran.AST           ( AList
                                                , aStrip
                                                , Value(..)
                                                , Expression(..)
                                                , ProgramUnit(..)
                                                , Statement(..)
                                                )

import           Language.Fortran.Vars.Types
                                                ( SymbolTableEntry(..)
                                                , SymbolTable
                                                )

dummyArgInProcedure
  :: Data a => SymbolTable -> ProgramUnit (Analysis a) -> SymbolTable
dummyArgInProcedure :: forall a.
Data a =>
SymbolTable -> ProgramUnit (Analysis a) -> SymbolTable
dummyArgInProcedure SymbolTable
symt (PUSubroutine Analysis a
_ SrcSpan
_ PrefixSuffix (Analysis a)
_ Name
_ Maybe (AList Expression (Analysis a))
args [Block (Analysis a)]
_ Maybe [ProgramUnit (Analysis a)]
_) = SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
forall a.
Data a =>
SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
dummyArgs SymbolTable
symt Maybe (AList Expression (Analysis a))
args
dummyArgInProcedure SymbolTable
symt (PUFunction Analysis a
_ SrcSpan
_ Maybe (TypeSpec (Analysis a))
_ PrefixSuffix (Analysis a)
_ Name
_ Maybe (AList Expression (Analysis a))
args Maybe (Expression (Analysis a))
_ [Block (Analysis a)]
_ Maybe [ProgramUnit (Analysis a)]
_) =
  SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
forall a.
Data a =>
SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
dummyArgs SymbolTable
symt Maybe (AList Expression (Analysis a))
args
dummyArgInProcedure SymbolTable
symt ProgramUnit (Analysis a)
_ = SymbolTable
symt

dummyArgInStmtFunction
  :: Data a => SymbolTable -> Statement (Analysis a) -> SymbolTable
dummyArgInStmtFunction :: forall a.
Data a =>
SymbolTable -> Statement (Analysis a) -> SymbolTable
dummyArgInStmtFunction SymbolTable
symt (StFunction Analysis a
_ SrcSpan
_ Expression (Analysis a)
_ AList Expression (Analysis a)
args Expression (Analysis a)
_) =
  SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
forall a.
Data a =>
SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
dummyArgs SymbolTable
symt (AList Expression (Analysis a)
-> Maybe (AList Expression (Analysis a))
forall a. a -> Maybe a
Just AList Expression (Analysis a)
args)
dummyArgInStmtFunction SymbolTable
symt Statement (Analysis a)
_ = SymbolTable
symt

dummyArgs
  :: Data a
  => SymbolTable
  -> Maybe (AList Expression (Analysis a))
  -> SymbolTable
dummyArgs :: forall a.
Data a =>
SymbolTable -> Maybe (AList Expression (Analysis a)) -> SymbolTable
dummyArgs SymbolTable
symt Maybe (AList Expression (Analysis a))
maybeArgs = case Maybe (AList Expression (Analysis a))
maybeArgs of
  Just AList Expression (Analysis a)
args -> (SymbolTable -> Expression (Analysis a) -> SymbolTable)
-> SymbolTable -> [Expression (Analysis a)] -> SymbolTable
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' SymbolTable -> Expression (Analysis a) -> SymbolTable
forall a.
Data a =>
SymbolTable -> Expression (Analysis a) -> SymbolTable
undefineDummyArg SymbolTable
symt (AList Expression (Analysis a) -> [Expression (Analysis a)]
forall (t :: * -> *) a. AList t a -> [t a]
aStrip AList Expression (Analysis a)
args)
  Maybe (AList Expression (Analysis a))
Nothing   -> SymbolTable
symt

undefineDummyArg
  :: Data a => SymbolTable -> Expression (Analysis a) -> SymbolTable
undefineDummyArg :: forall a.
Data a =>
SymbolTable -> Expression (Analysis a) -> SymbolTable
undefineDummyArg SymbolTable
symt (ExpValue Analysis a
_ SrcSpan
_ Value (Analysis a)
ValStar) = SymbolTable
symt
undefineDummyArg SymbolTable
symt Expression (Analysis a)
varExp =
  let symbol :: Name
symbol = Expression (Analysis a) -> Name
forall a. Expression (Analysis a) -> Name
srcName Expression (Analysis a)
varExp
  in  case Name -> SymbolTable -> Maybe SymbolTableEntry
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Name
symbol SymbolTable
symt of
        Just ve :: SymbolTableEntry
ve@SVariable{} -> Name -> SymbolTableEntry -> SymbolTable -> SymbolTable
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Name
symbol (SymbolTableEntry -> SymbolTableEntry
variableToDummy SymbolTableEntry
ve) SymbolTable
symt
        Just SParameter{} ->
          Name -> SymbolTable
forall a. HasCallStack => Name -> a
error (Name
symbol Name -> Name -> Name
forall a. [a] -> [a] -> [a]
++ Name
"is a parameter, invalid fortran syntax.")
        Maybe SymbolTableEntry
_ -> SymbolTable
symt

variableToDummy :: SymbolTableEntry -> SymbolTableEntry
variableToDummy :: SymbolTableEntry -> SymbolTableEntry
variableToDummy (SVariable Type
ty Location
_) = Type -> SymbolTableEntry
SDummy Type
ty
variableToDummy SymbolTableEntry
_ =
  Name -> SymbolTableEntry
forall a. HasCallStack => Name -> a
error Name
"Only VariableEntry might be transformed to DummyEntry."

-- | Since FORTRAN parameters to functions can only have their memory allocation determined
-- at runtime, given a 'ProgramUnit' and a 'SymbolTable', return a new 'SymbolTable' where
-- all of the parameters have their 'DenotedVal' set to 'Undefined'
undefineDummyArguments
  :: Data a => ProgramUnit (Analysis a) -> SymbolTable -> SymbolTable
undefineDummyArguments :: forall a.
Data a =>
ProgramUnit (Analysis a) -> SymbolTable -> SymbolTable
undefineDummyArguments ProgramUnit (Analysis a)
pu SymbolTable
symTable =
  let symTable1 :: SymbolTable
symTable1 = SymbolTable -> ProgramUnit (Analysis a) -> SymbolTable
forall a.
Data a =>
SymbolTable -> ProgramUnit (Analysis a) -> SymbolTable
dummyArgInProcedure SymbolTable
symTable ProgramUnit (Analysis a)
pu
  in  (SymbolTable -> Statement (Analysis a) -> SymbolTable)
-> SymbolTable -> [Statement (Analysis a)] -> SymbolTable
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' SymbolTable -> Statement (Analysis a) -> SymbolTable
forall a.
Data a =>
SymbolTable -> Statement (Analysis a) -> SymbolTable
dummyArgInStmtFunction SymbolTable
symTable1 ([Statement (Analysis a)] -> SymbolTable)
-> [Statement (Analysis a)] -> SymbolTable
forall a b. (a -> b) -> a -> b
$ ProgramUnit (Analysis a) -> [Statement (Analysis a)]
forall a. Data a => ProgramUnit a -> [Statement a]
allPUS ProgramUnit (Analysis a)
pu