{-# LANGUAGE TemplateHaskell #-}
module Language.Drasil.Chunk.Parameter (
  PassBy(..), ParameterChunk(..), pcAuto, pcVal
) where

import Language.Drasil hiding (Ref, CodeIdea(..), CodeChunk)
import Language.Drasil.Chunk.Code (CodeIdea(..), CodeChunk)

import Control.Lens ((^.), makeLenses, view)

-- | Determines whether a parameter is passed by value or by reference.
data PassBy = Val | Ref

-- | Chunk representing a parameter.
data ParameterChunk = PC {ParameterChunk -> CodeChunk
_pcc :: CodeChunk
                         , ParameterChunk -> PassBy
passBy :: PassBy}
makeLenses ''ParameterChunk

-- | Finds the 'UID' of the 'CodeChunk' used to make the 'ParameterChunk'.
instance HasUID      ParameterChunk where uid :: Lens' ParameterChunk UID
uid = Lens' ParameterChunk CodeChunk
pcc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. HasUID c => Lens' c UID
uid
-- | Finds the term ('NP') of the 'CodeChunk' used to make the 'ParameterChunk'.
instance NamedIdea   ParameterChunk where term :: Lens' ParameterChunk NP
term = Lens' ParameterChunk CodeChunk
pcc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'CodeChunk' used to make the 'ParameterChunk'.
instance Idea        ParameterChunk where getA :: ParameterChunk -> Maybe String
getA = forall c. Idea c => c -> Maybe String
getA forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' ParameterChunk CodeChunk
pcc
-- | Finds the 'Space' of the 'CodeChunk' used to make the 'ParameterChunk'.
instance HasSpace    ParameterChunk where typ :: Getter ParameterChunk Space
typ = Lens' ParameterChunk CodeChunk
pcc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. HasSpace c => Getter c Space
typ
-- | Finds the 'Stage' dependent 'Symbol' of the 'CodeChunk' used to make the 'ParameterChunk'.
instance HasSymbol   ParameterChunk where symbol :: ParameterChunk -> Stage -> Symbol
symbol = forall c. HasSymbol c => c -> Stage -> Symbol
symbol forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' ParameterChunk CodeChunk
pcc
-- | 'ParameterChunk's have a 'Quantity'.
instance Quantity    ParameterChunk
-- | Finds the code name and 'CodeChunk' of a 'ParameterChunk'.
instance CodeIdea    ParameterChunk where
  codeName :: ParameterChunk -> String
codeName = forall c. CodeIdea c => c -> String
codeName forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' ParameterChunk CodeChunk
pcc
  codeChunk :: ParameterChunk -> CodeChunk
codeChunk = forall c. CodeIdea c => c -> CodeChunk
codeChunk forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' ParameterChunk CodeChunk
pcc
-- | Equal if 'UID's are equal.
instance Eq          ParameterChunk where ParameterChunk
c1 == :: ParameterChunk -> ParameterChunk -> Bool
== ParameterChunk
c2 = (ParameterChunk
c1 forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid) forall a. Eq a => a -> a -> Bool
== (ParameterChunk
c2 forall s a. s -> Getting a s a -> a
^. forall c. HasUID c => Lens' c UID
uid)
-- | Finds the units of the 'CodeChunk' used to make the 'ParameterChunk'.
instance MayHaveUnit ParameterChunk where getUnit :: ParameterChunk -> Maybe UnitDefn
getUnit = forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' ParameterChunk CodeChunk
pcc

-- | Automatically chooses 'PassBy' based on 'Space' ('Vect'ors and 'Actor's passed by reference).
pcAuto :: (CodeIdea c) => c -> ParameterChunk
pcAuto :: forall c. CodeIdea c => c -> ParameterChunk
pcAuto c
c = CodeChunk -> PassBy -> ParameterChunk
PC CodeChunk
cdch (Space -> PassBy
choosePB forall a b. (a -> b) -> a -> b
$ CodeChunk
cdch forall s a. s -> Getting a s a -> a
^. forall c. HasSpace c => Getter c Space
typ)
  where cdch :: CodeChunk
cdch = forall c. CodeIdea c => c -> CodeChunk
codeChunk c
c
        choosePB :: Space -> PassBy
choosePB (Vect Space
_) = PassBy
Ref
        choosePB (Actor String
_) = PassBy
Ref
        choosePB Space
_ = PassBy
Val

-- | Constructs a pass-by-value parameter.
pcVal :: (CodeIdea c) => c -> ParameterChunk
pcVal :: forall c. CodeIdea c => c -> ParameterChunk
pcVal c
c = CodeChunk -> PassBy -> ParameterChunk
PC (forall c. CodeIdea c => c -> CodeChunk
codeChunk c
c) PassBy
Val