{-# LANGUAGE TemplateHaskell, Rank2Types, ScopedTypeVariables  #-}
-- | Defines types and functions for General Definitions.
module Theory.Drasil.GenDefn (
  -- * Type
  GenDefn,
  -- * Constructors
  gd, gdNoRefs,
  -- * Functions
  getEqModQdsFromGd) where

import Language.Drasil
import Language.Drasil.Development (showUID)
import Data.Drasil.TheoryConcepts (genDefn)
import Theory.Drasil.ModelKinds (ModelKind, getEqModQds)

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

-- | A general definition is a 'ModelKind' that may have units, a derivation,
-- references (as 'DecRef's), a shortname, a reference address, and notes.
data GenDefn = GD { GenDefn -> ModelKind ModelExpr
_mk    :: ModelKind ModelExpr
                  , GenDefn -> Maybe UnitDefn
gdUnit :: Maybe UnitDefn -- TODO: Should be derived from the ModelKinds
                  , GenDefn -> Maybe Derivation
_deri  :: Maybe Derivation
                  , GenDefn -> [DecRef]
_rf    :: [DecRef]
                  , GenDefn -> ShortName
_sn    :: ShortName
                  , GenDefn -> String
_ra    :: String -- RefAddr
                  , GenDefn -> [Sentence]
_notes :: [Sentence]
                  }
makeLenses ''GenDefn

-- | Finds the 'UID' of a 'GenDefn'.
instance HasUID             GenDefn where uid :: Lens' GenDefn UID
uid         = Lens' GenDefn (ModelKind ModelExpr)
mk forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. HasUID c => Lens' c UID
uid
-- | Finds the term ('NP') of the 'GenDefn'.
instance NamedIdea          GenDefn where term :: Lens' GenDefn NP
term        = Lens' GenDefn (ModelKind ModelExpr)
mk forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'GenDefn'.
instance Idea               GenDefn where getA :: GenDefn -> Maybe String
getA        = forall c. Idea c => c -> Maybe String
getA forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall s a. s -> Getting a s a -> a
^. Lens' GenDefn (ModelKind ModelExpr)
mk)
-- | Finds the definition of the 'GenDefn'.
instance Definition         GenDefn where defn :: Lens' GenDefn Sentence
defn        = Lens' GenDefn (ModelKind ModelExpr)
mk forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. Definition c => Lens' c Sentence
defn
-- | Finds the domain of the 'GenDefn'.
instance ConceptDomain      GenDefn where cdom :: GenDefn -> [UID]
cdom        = forall c. ConceptDomain c => c -> [UID]
cdom forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall s a. s -> Getting a s a -> a
^. Lens' GenDefn (ModelKind ModelExpr)
mk)
-- | Converts the 'GenDefn's related expression into a 'ModelExpr'.
instance Express            GenDefn where express :: GenDefn -> ModelExpr
express     = forall c. Express c => c -> ModelExpr
express forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall s a. s -> Getting a s a -> a
^. Lens' GenDefn (ModelKind ModelExpr)
mk)
-- | Finds the derivation of the 'GenDefn'. May contain Nothing.
instance MayHaveDerivation  GenDefn where derivations :: Lens' GenDefn (Maybe Derivation)
derivations = Lens' GenDefn (Maybe Derivation)
deri
{-- | Finds 'Reference's contained in the 'GenDefn'.
instance HasReference       GenDefn where getReferences = rf-}
-- | Finds 'DecRef's contained in the 'GenDefn'.
instance HasDecRef          GenDefn where getDecRefs :: Lens' GenDefn [DecRef]
getDecRefs  = Lens' GenDefn [DecRef]
rf
-- | Finds the 'ShortName' of the 'GenDefn'.
instance HasShortName       GenDefn where shortname :: GenDefn -> ShortName
shortname     = forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' GenDefn ShortName
sn
-- | Finds the reference address of the 'GenDefn'.
instance HasRefAddress      GenDefn where getRefAdd :: GenDefn -> LblType
getRefAdd GenDefn
l = IRefProg -> String -> LblType
RP (String -> IRefProg
prepend forall a b. (a -> b) -> a -> b
$ forall c. CommonIdea c => c -> String
abrv GenDefn
l) (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' GenDefn String
ra GenDefn
l)
-- | Finds the units of the 'GenDefn'.
instance HasAdditionalNotes GenDefn where getNotes :: Lens' GenDefn [Sentence]
getNotes    = Lens' GenDefn [Sentence]
notes
-- | Finds the units of the 'GenDefn'.
instance MayHaveUnit        GenDefn where getUnit :: GenDefn -> Maybe UnitDefn
getUnit     = GenDefn -> Maybe UnitDefn
gdUnit
-- | Finds the idea of a 'GenDefn' (abbreviation).
instance CommonIdea         GenDefn where abrv :: GenDefn -> String
abrv GenDefn
_      = forall c. CommonIdea c => c -> String
abrv CI
genDefn
-- | Finds the reference address of a 'GenDefn'.
instance Referable          GenDefn where
  refAdd :: GenDefn -> String
refAdd      = forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Lens' GenDefn String
ra
  renderRef :: GenDefn -> LblType
renderRef GenDefn
l = IRefProg -> String -> LblType
RP (String -> IRefProg
prepend forall a b. (a -> b) -> a -> b
$ forall c. CommonIdea c => c -> String
abrv GenDefn
l) (forall s. Referable s => s -> String
refAdd GenDefn
l)

-- | Smart constructor for general definitions.
gd :: IsUnit u => ModelKind ModelExpr -> Maybe u ->
  Maybe Derivation -> [DecRef] -> String -> [Sentence] -> GenDefn
gd :: forall u.
IsUnit u =>
ModelKind ModelExpr
-> Maybe u
-> Maybe Derivation
-> [DecRef]
-> String
-> [Sentence]
-> GenDefn
gd ModelKind ModelExpr
mkind Maybe u
_   Maybe Derivation
_     []   String
_  = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Source field of " forall a. [a] -> [a] -> [a]
++ forall a. HasUID a => a -> String
showUID ModelKind ModelExpr
mkind forall a. [a] -> [a] -> [a]
++ String
" is empty"
gd ModelKind ModelExpr
mkind Maybe u
u Maybe Derivation
derivs [DecRef]
refs String
sn_ = 
  ModelKind ModelExpr
-> Maybe UnitDefn
-> Maybe Derivation
-> [DecRef]
-> ShortName
-> String
-> [Sentence]
-> GenDefn
GD ModelKind ModelExpr
mkind (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall u. IsUnit u => u -> UnitDefn
unitWrapper Maybe u
u) Maybe Derivation
derivs [DecRef]
refs (Sentence -> ShortName
shortname' forall a b. (a -> b) -> a -> b
$ String -> Sentence
S String
sn_) (forall c. CommonIdea c => c -> String -> String
prependAbrv CI
genDefn String
sn_)

-- | Smart constructor for general definitions with no references.
gdNoRefs :: IsUnit u => ModelKind ModelExpr -> Maybe u ->
  Maybe Derivation -> String -> [Sentence] -> GenDefn
gdNoRefs :: forall u.
IsUnit u =>
ModelKind ModelExpr
-> Maybe u -> Maybe Derivation -> String -> [Sentence] -> GenDefn
gdNoRefs ModelKind ModelExpr
mkind Maybe u
u Maybe Derivation
derivs String
sn_ = 
  ModelKind ModelExpr
-> Maybe UnitDefn
-> Maybe Derivation
-> [DecRef]
-> ShortName
-> String
-> [Sentence]
-> GenDefn
GD ModelKind ModelExpr
mkind (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall u. IsUnit u => u -> UnitDefn
unitWrapper Maybe u
u) Maybe Derivation
derivs [] (Sentence -> ShortName
shortname' forall a b. (a -> b) -> a -> b
$ String -> Sentence
S String
sn_) (forall c. CommonIdea c => c -> String -> String
prependAbrv CI
genDefn String
sn_)

-- | Grab all related 'QDefinitions' from a list of general definitions.
getEqModQdsFromGd :: [GenDefn] -> [ModelQDef]
getEqModQdsFromGd :: [GenDefn] -> [ModelQDef]
getEqModQdsFromGd = forall e. [ModelKind e] -> [QDefinition e]
getEqModQds forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map GenDefn -> ModelKind ModelExpr
_mk