module Language.Drasil.Code.Imperative.FunctionCalls (
  genAllInputCalls, genAllInputCallsProc, genInputCall, genInputCallProc,
  genDerivedCall, genDerivedCallProc, genConstraintCall, genConstraintCallProc,
  genCalcCall, genCalcCallProc, genOutputCall, genOutputCallProc
) where

import Language.Drasil.Code.Imperative.GenerateGOOL (fApp, fAppProc, fAppInOut,
  fAppInOutProc)
import Language.Drasil.Code.Imperative.Helpers (convScope)
import Language.Drasil.Code.Imperative.Import (codeType, mkVal, mkValProc,
  mkVar, mkVarProc)
import Language.Drasil.Code.Imperative.Logging (maybeLog)
import Language.Drasil.Code.Imperative.Parameters (getCalcParams,
  getConstraintParams, getDerivedIns, getDerivedOuts, getInputFormatIns,
  getInputFormatOuts, getOutputParams)
import Language.Drasil.Code.Imperative.DrasilState (GenState, DrasilState(..),
  genICName)
import Language.Drasil.Chunk.Code (CodeIdea(codeName), CodeVarChunk, quantvar)
import Language.Drasil.Chunk.CodeDefinition (CodeDefinition)
import Language.Drasil.Mod (Name)
import Language.Drasil.Choices (InternalConcept(..))

import Drasil.GOOL (VSType, SValue, MSStatement, SharedProg, OOProg,
  TypeSym(..), VariableValue(..), StatementSym(..), DeclStatement(..),
  convType, convTypeOO)

import Data.List ((\\), intersect)
import qualified Data.Map as Map (lookup)
import Data.Maybe (catMaybes)
import Control.Applicative ((<|>))
import Control.Monad.State (get)

-- | Generates calls to all of the input-related functions. First is the call to
-- the function for reading inputs, then the function for calculating derived
-- inputs, then the function for checking input constraints.
genAllInputCalls :: (OOProg r) => GenState [MSStatement r]
genAllInputCalls :: forall (r :: * -> *). OOProg r => GenState [MSStatement r]
genAllInputCalls = do
  Maybe (MSStatement r)
gi <- GenState (Maybe (MSStatement r))
forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genInputCall
  Maybe (MSStatement r)
dv <- GenState (Maybe (MSStatement r))
forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genDerivedCall
  Maybe (MSStatement r)
ic <- GenState (Maybe (MSStatement r))
forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genConstraintCall
  [MSStatement r] -> GenState [MSStatement r]
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ([MSStatement r] -> GenState [MSStatement r])
-> [MSStatement r] -> GenState [MSStatement r]
forall a b. (a -> b) -> a -> b
$ [Maybe (MSStatement r)] -> [MSStatement r]
forall a. [Maybe a] -> [a]
catMaybes [Maybe (MSStatement r)
gi, Maybe (MSStatement r)
dv, Maybe (MSStatement r)
ic]

-- | Generates a call to the function for reading inputs from a file.
genInputCall :: (OOProg r) => GenState (Maybe (MSStatement r))
genInputCall :: forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genInputCall = do
  Name
giName <- InternalConcept -> GenState Name
genICName InternalConcept
GetInput
  Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
forall (r :: * -> *).
OOProg r =>
Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
genInOutCall Name
giName GenState [CodeVarChunk]
getInputFormatIns GenState [CodeVarChunk]
getInputFormatOuts

-- | Generates a call to the function for calculating derived inputs.
genDerivedCall :: (OOProg r) => GenState (Maybe (MSStatement r))
genDerivedCall :: forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genDerivedCall = do
  Name
dvName <- InternalConcept -> GenState Name
genICName InternalConcept
DerivedValuesFn
  Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
forall (r :: * -> *).
OOProg r =>
Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
genInOutCall Name
dvName GenState [CodeVarChunk]
getDerivedIns GenState [CodeVarChunk]
getDerivedOuts

-- | Generates a call to the function for checking constraints on the input.
genConstraintCall :: (OOProg r) => GenState (Maybe (MSStatement r))
genConstraintCall :: forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genConstraintCall = do
  Name
icName <- InternalConcept -> GenState Name
genICName InternalConcept
InputConstraintsFn
  Maybe (VS (r (Value r)))
val <- Name
-> VSType r
-> GenState [CodeVarChunk]
-> StateT DrasilState Identity (Maybe (VS (r (Value r))))
forall (r :: * -> *).
OOProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCall Name
icName VSType r
forall (r :: * -> *). TypeSym r => VSType r
void GenState [CodeVarChunk]
getConstraintParams
  Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MSStatement r) -> GenState (Maybe (MSStatement r)))
-> Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a b. (a -> b) -> a -> b
$ (VS (r (Value r)) -> MSStatement r)
-> Maybe (VS (r (Value r))) -> Maybe (MSStatement r)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VS (r (Value r)) -> MSStatement r
forall (r :: * -> *). StatementSym r => SValue r -> MSStatement r
valStmt Maybe (VS (r (Value r)))
val

-- | Generates a call to a calculation function, given the 'CodeDefinition' for the
-- value being calculated.
genCalcCall :: (OOProg r) => CodeDefinition -> GenState (Maybe (MSStatement r))
genCalcCall :: forall (r :: * -> *).
OOProg r =>
CodeDefinition -> GenState (Maybe (MSStatement r))
genCalcCall CodeDefinition
c = do
  DrasilState
g <- StateT DrasilState Identity DrasilState
forall s (m :: * -> *). MonadState s m => m s
get
  let scp :: r (Scope r)
scp = ScopeType -> r (Scope r)
forall (r :: * -> *). SharedProg r => ScopeType -> r (Scope r)
convScope (ScopeType -> r (Scope r)) -> ScopeType -> r (Scope r)
forall a b. (a -> b) -> a -> b
$ DrasilState -> ScopeType
currentScope DrasilState
g
  CodeType
t <- CodeDefinition -> GenState CodeType
forall c. HasSpace c => c -> GenState CodeType
codeType CodeDefinition
c
  Maybe (VS (r (Value r)))
val <- Name
-> VSType r
-> GenState [CodeVarChunk]
-> StateT DrasilState Identity (Maybe (VS (r (Value r))))
forall (r :: * -> *).
OOProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCall (CodeDefinition -> Name
forall c. CodeIdea c => c -> Name
codeName CodeDefinition
c) (CodeType -> VSType r
forall (r :: * -> *). OOTypeSym r => CodeType -> VSType r
convTypeOO CodeType
t) (CodeDefinition -> GenState [CodeVarChunk]
getCalcParams CodeDefinition
c)
  VS (r (Variable r))
v <- CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
OOProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVar (CodeDefinition -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar CodeDefinition
c)
  [MSStatement r]
l <- VS (r (Variable r)) -> StateT DrasilState Identity [MSStatement r]
forall (r :: * -> *).
SharedProg r =>
SVariable r -> GenState [MSStatement r]
maybeLog VS (r (Variable r))
v
  Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MSStatement r) -> GenState (Maybe (MSStatement r)))
-> Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a b. (a -> b) -> a -> b
$ (VS (r (Value r)) -> MSStatement r)
-> Maybe (VS (r (Value r))) -> Maybe (MSStatement r)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([MSStatement r] -> MSStatement r
forall (r :: * -> *).
StatementSym r =>
[MSStatement r] -> MSStatement r
multi ([MSStatement r] -> MSStatement r)
-> (VS (r (Value r)) -> [MSStatement r])
-> VS (r (Value r))
-> MSStatement r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MSStatement r -> [MSStatement r] -> [MSStatement r]
forall a. a -> [a] -> [a]
: [MSStatement r]
l) (MSStatement r -> [MSStatement r])
-> (VS (r (Value r)) -> MSStatement r)
-> VS (r (Value r))
-> [MSStatement r]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VS (r (Variable r))
-> r (Scope r) -> VS (r (Value r)) -> MSStatement r
forall (r :: * -> *).
DeclStatement r =>
SVariable r -> r (Scope r) -> SValue r -> MSStatement r
varDecDef VS (r (Variable r))
v r (Scope r)
scp) Maybe (VS (r (Value r)))
val

-- | Generates a call to the function for printing outputs.
genOutputCall :: (OOProg r) => GenState (Maybe (MSStatement r))
genOutputCall :: forall (r :: * -> *). OOProg r => GenState (Maybe (MSStatement r))
genOutputCall = do
  Name
woName <- InternalConcept -> GenState Name
genICName InternalConcept
WriteOutput
  Maybe (VS (r (Value r)))
val <- Name
-> VSType r
-> GenState [CodeVarChunk]
-> StateT DrasilState Identity (Maybe (VS (r (Value r))))
forall (r :: * -> *).
OOProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCall Name
woName VSType r
forall (r :: * -> *). TypeSym r => VSType r
void GenState [CodeVarChunk]
getOutputParams
  Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MSStatement r) -> GenState (Maybe (MSStatement r)))
-> Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a b. (a -> b) -> a -> b
$ (VS (r (Value r)) -> MSStatement r)
-> Maybe (VS (r (Value r))) -> Maybe (MSStatement r)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VS (r (Value r)) -> MSStatement r
forall (r :: * -> *). StatementSym r => SValue r -> MSStatement r
valStmt Maybe (VS (r (Value r)))
val

-- | Generates a function call given the name, return type, and arguments to
-- the function.
genFuncCall :: (OOProg r) => Name -> VSType r ->
  GenState [CodeVarChunk] -> GenState (Maybe (SValue r))
genFuncCall :: forall (r :: * -> *).
OOProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCall Name
n VSType r
t GenState [CodeVarChunk]
funcPs = do
  Maybe Name
mm <- Name -> GenState (Maybe Name)
genCall Name
n
  let genFuncCall' :: Maybe Name -> GenState (Maybe (SValue r))
genFuncCall' Maybe Name
Nothing = Maybe (SValue r) -> GenState (Maybe (SValue r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (SValue r)
forall a. Maybe a
Nothing
      genFuncCall' (Just Name
m) = do
        [CodeVarChunk]
cs <- GenState [CodeVarChunk]
funcPs
        [SValue r]
pvals <- (CodeVarChunk -> StateT DrasilState Identity (SValue r))
-> [CodeVarChunk] -> StateT DrasilState Identity [SValue r]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (SValue r)
forall (r :: * -> *).
OOProg r =>
CodeVarChunk -> GenState (SValue r)
mkVal [CodeVarChunk]
cs
        SValue r
val <- Name
-> Name
-> VSType r
-> [SValue r]
-> NamedArgs r
-> StateT DrasilState Identity (SValue r)
forall (r :: * -> *).
OOProg r =>
Name
-> Name
-> VSType r
-> [SValue r]
-> NamedArgs r
-> GenState (SValue r)
fApp Name
m Name
n VSType r
t [SValue r]
pvals []
        Maybe (SValue r) -> GenState (Maybe (SValue r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (SValue r) -> GenState (Maybe (SValue r)))
-> Maybe (SValue r) -> GenState (Maybe (SValue r))
forall a b. (a -> b) -> a -> b
$ SValue r -> Maybe (SValue r)
forall a. a -> Maybe a
Just SValue r
val
  Maybe Name -> GenState (Maybe (SValue r))
genFuncCall' Maybe Name
mm

-- | Generates a function call given the name, inputs, and outputs for the
-- function.
genInOutCall :: (OOProg r) => Name -> GenState [CodeVarChunk] ->
  GenState [CodeVarChunk] -> GenState (Maybe (MSStatement r))
genInOutCall :: forall (r :: * -> *).
OOProg r =>
Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
genInOutCall Name
n GenState [CodeVarChunk]
inFunc GenState [CodeVarChunk]
outFunc = do
  Maybe Name
mm <- Name -> GenState (Maybe Name)
genCall Name
n
  let genInOutCall' :: Maybe Name
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
genInOutCall' Maybe Name
Nothing = Maybe (MS (r (Statement r)))
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (MS (r (Statement r)))
forall a. Maybe a
Nothing
      genInOutCall' (Just Name
m) = do
        [CodeVarChunk]
ins' <- GenState [CodeVarChunk]
inFunc
        [CodeVarChunk]
outs' <- GenState [CodeVarChunk]
outFunc
        [VS (r (Variable r))]
ins <- (CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r))))
-> [CodeVarChunk]
-> StateT DrasilState Identity [VS (r (Variable r))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
OOProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVar ([CodeVarChunk]
ins' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk]
outs')
        [VS (r (Variable r))]
outs <- (CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r))))
-> [CodeVarChunk]
-> StateT DrasilState Identity [VS (r (Variable r))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
OOProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVar ([CodeVarChunk]
outs' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk]
ins')
        [VS (r (Variable r))]
both <- (CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r))))
-> [CodeVarChunk]
-> StateT DrasilState Identity [VS (r (Variable r))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
OOProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVar ([CodeVarChunk]
ins' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
`intersect` [CodeVarChunk]
outs')
        MS (r (Statement r))
stmt <- Name
-> Name
-> [SValue r]
-> [VS (r (Variable r))]
-> [VS (r (Variable r))]
-> StateT DrasilState Identity (MS (r (Statement r)))
forall (r :: * -> *).
OOProg r =>
Name
-> Name
-> [SValue r]
-> [SVariable r]
-> [SVariable r]
-> GenState (MSStatement r)
fAppInOut Name
m Name
n ((VS (r (Variable r)) -> SValue r)
-> [VS (r (Variable r))] -> [SValue r]
forall a b. (a -> b) -> [a] -> [b]
map VS (r (Variable r)) -> SValue r
forall (r :: * -> *). VariableValue r => SVariable r -> SValue r
valueOf [VS (r (Variable r))]
ins) [VS (r (Variable r))]
outs [VS (r (Variable r))]
both
        Maybe (MS (r (Statement r)))
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MS (r (Statement r)))
 -> StateT DrasilState Identity (Maybe (MS (r (Statement r)))))
-> Maybe (MS (r (Statement r)))
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
forall a b. (a -> b) -> a -> b
$ MS (r (Statement r)) -> Maybe (MS (r (Statement r)))
forall a. a -> Maybe a
Just MS (r (Statement r))
stmt
  Maybe Name -> GenState (Maybe (MSStatement r))
forall {r :: * -> *}.
OOProg r =>
Maybe Name
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
genInOutCall' Maybe Name
mm

-- | Gets the name of the module containing the function being called.
-- If the function is not in either the module export map or class definition map,
--   return 'Nothing'.
-- If the function is not in module export map but is in the class definition map,
-- that means it is a private function, so return 'Nothing' unless it is in the
-- current class.
genCall :: Name -> GenState (Maybe Name)
genCall :: Name -> GenState (Maybe Name)
genCall Name
n = do
  DrasilState
g <- StateT DrasilState Identity DrasilState
forall s (m :: * -> *). MonadState s m => m s
get
  let currc :: Name
currc = DrasilState -> Name
currentClass DrasilState
g
      genCallExported :: Maybe Name -> m (Maybe Name)
genCallExported Maybe Name
Nothing = Maybe Name -> m (Maybe Name)
forall {m :: * -> *}. Monad m => Maybe Name -> m (Maybe Name)
genCallInClass (Name -> Map Name Name -> Maybe Name
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
n (Map Name Name -> Maybe Name) -> Map Name Name -> Maybe Name
forall a b. (a -> b) -> a -> b
$ DrasilState -> Map Name Name
clsMap DrasilState
g)
      genCallExported Maybe Name
m = Maybe Name -> m (Maybe Name)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Name
m
      genCallInClass :: Maybe Name -> m (Maybe Name)
genCallInClass Maybe Name
Nothing = Maybe Name -> m (Maybe Name)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Name
forall a. Maybe a
Nothing
      genCallInClass (Just Name
c) = if Name
c Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
currc then Maybe Name -> m (Maybe Name)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Name -> m (Maybe Name)) -> Maybe Name -> m (Maybe Name)
forall a b. (a -> b) -> a -> b
$ Name -> Map Name Name -> Maybe Name
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
c (DrasilState -> Map Name Name
eMap
        DrasilState
g) Maybe Name -> Maybe Name -> Maybe Name
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Name -> Maybe Name
forall a. HasCallStack => Name -> a
error (Name
c Name -> Name -> Name
forall a. [a] -> [a] -> [a]
++ Name
" class missing from export map")
        else Maybe Name -> m (Maybe Name)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Name
forall a. Maybe a
Nothing
  Maybe Name -> GenState (Maybe Name)
forall {m :: * -> *}. Monad m => Maybe Name -> m (Maybe Name)
genCallExported (Maybe Name -> GenState (Maybe Name))
-> Maybe Name -> GenState (Maybe Name)
forall a b. (a -> b) -> a -> b
$ Name -> Map Name Name -> Maybe Name
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
n (DrasilState -> Map Name Name
eMap DrasilState
g)

-- Procedural Versions --

-- | Generates calls to all of the input-related functions. First is the call to
-- the function for reading inputs, then the function for calculating derived
-- inputs, then the function for checking input constraints.
genAllInputCallsProc :: (SharedProg r) => GenState [MSStatement r]
genAllInputCallsProc :: forall (r :: * -> *). SharedProg r => GenState [MSStatement r]
genAllInputCallsProc = do
  Maybe (MSStatement r)
gi <- GenState (Maybe (MSStatement r))
forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genInputCallProc
  Maybe (MSStatement r)
dv <- GenState (Maybe (MSStatement r))
forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genDerivedCallProc
  Maybe (MSStatement r)
ic <- GenState (Maybe (MSStatement r))
forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genConstraintCallProc
  [MSStatement r] -> GenState [MSStatement r]
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ([MSStatement r] -> GenState [MSStatement r])
-> [MSStatement r] -> GenState [MSStatement r]
forall a b. (a -> b) -> a -> b
$ [Maybe (MSStatement r)] -> [MSStatement r]
forall a. [Maybe a] -> [a]
catMaybes [Maybe (MSStatement r)
gi, Maybe (MSStatement r)
dv, Maybe (MSStatement r)
ic]

-- | Generates a call to the function for reading inputs from a file.
genInputCallProc:: (SharedProg r) => GenState (Maybe (MSStatement r))
genInputCallProc :: forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genInputCallProc = do
  Name
giName <- InternalConcept -> GenState Name
genICName InternalConcept
GetInput
  Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
forall (r :: * -> *).
SharedProg r =>
Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
genInOutCallProc Name
giName GenState [CodeVarChunk]
getInputFormatIns GenState [CodeVarChunk]
getInputFormatOuts

-- | Generates a call to the function for calculating derived inputs.
genDerivedCallProc :: (SharedProg r) => GenState (Maybe (MSStatement r))
genDerivedCallProc :: forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genDerivedCallProc = do
  Name
dvName <- InternalConcept -> GenState Name
genICName InternalConcept
DerivedValuesFn
  Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
forall (r :: * -> *).
SharedProg r =>
Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
genInOutCallProc Name
dvName GenState [CodeVarChunk]
getDerivedIns GenState [CodeVarChunk]
getDerivedOuts

-- | Generates a call to the function for checking constraints on the input.
genConstraintCallProc :: (SharedProg r) => GenState (Maybe (MSStatement r))
genConstraintCallProc :: forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genConstraintCallProc = do
  Name
icName <- InternalConcept -> GenState Name
genICName InternalConcept
InputConstraintsFn
  Maybe (VS (r (Value r)))
val <- Name
-> VSType r
-> GenState [CodeVarChunk]
-> StateT DrasilState Identity (Maybe (VS (r (Value r))))
forall (r :: * -> *).
SharedProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCallProc Name
icName VSType r
forall (r :: * -> *). TypeSym r => VSType r
void GenState [CodeVarChunk]
getConstraintParams
  Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MSStatement r) -> GenState (Maybe (MSStatement r)))
-> Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a b. (a -> b) -> a -> b
$ (VS (r (Value r)) -> MSStatement r)
-> Maybe (VS (r (Value r))) -> Maybe (MSStatement r)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VS (r (Value r)) -> MSStatement r
forall (r :: * -> *). StatementSym r => SValue r -> MSStatement r
valStmt Maybe (VS (r (Value r)))
val

-- | Generates a call to a calculation function, given the 'CodeDefinition' for the
-- value being calculated.
genCalcCallProc :: (SharedProg r) => CodeDefinition ->
  GenState (Maybe (MSStatement r))
genCalcCallProc :: forall (r :: * -> *).
SharedProg r =>
CodeDefinition -> GenState (Maybe (MSStatement r))
genCalcCallProc CodeDefinition
c = do
  DrasilState
g <- StateT DrasilState Identity DrasilState
forall s (m :: * -> *). MonadState s m => m s
get
  let scp :: r (Scope r)
scp = ScopeType -> r (Scope r)
forall (r :: * -> *). SharedProg r => ScopeType -> r (Scope r)
convScope (ScopeType -> r (Scope r)) -> ScopeType -> r (Scope r)
forall a b. (a -> b) -> a -> b
$ DrasilState -> ScopeType
currentScope DrasilState
g
  CodeType
t <- CodeDefinition -> GenState CodeType
forall c. HasSpace c => c -> GenState CodeType
codeType CodeDefinition
c
  Maybe (VS (r (Value r)))
val <- Name
-> VSType r
-> GenState [CodeVarChunk]
-> StateT DrasilState Identity (Maybe (VS (r (Value r))))
forall (r :: * -> *).
SharedProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCallProc (CodeDefinition -> Name
forall c. CodeIdea c => c -> Name
codeName CodeDefinition
c) (CodeType -> VSType r
forall (r :: * -> *). TypeSym r => CodeType -> VSType r
convType CodeType
t) (CodeDefinition -> GenState [CodeVarChunk]
getCalcParams CodeDefinition
c)
  VS (r (Variable r))
v <- CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
SharedProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVarProc (CodeDefinition -> CodeVarChunk
forall c. (Quantity c, MayHaveUnit c) => c -> CodeVarChunk
quantvar CodeDefinition
c)
  [MSStatement r]
l <- VS (r (Variable r)) -> StateT DrasilState Identity [MSStatement r]
forall (r :: * -> *).
SharedProg r =>
SVariable r -> GenState [MSStatement r]
maybeLog VS (r (Variable r))
v
  Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MSStatement r) -> GenState (Maybe (MSStatement r)))
-> Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a b. (a -> b) -> a -> b
$ (VS (r (Value r)) -> MSStatement r)
-> Maybe (VS (r (Value r))) -> Maybe (MSStatement r)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([MSStatement r] -> MSStatement r
forall (r :: * -> *).
StatementSym r =>
[MSStatement r] -> MSStatement r
multi ([MSStatement r] -> MSStatement r)
-> (VS (r (Value r)) -> [MSStatement r])
-> VS (r (Value r))
-> MSStatement r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MSStatement r -> [MSStatement r] -> [MSStatement r]
forall a. a -> [a] -> [a]
: [MSStatement r]
l) (MSStatement r -> [MSStatement r])
-> (VS (r (Value r)) -> MSStatement r)
-> VS (r (Value r))
-> [MSStatement r]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VS (r (Variable r))
-> r (Scope r) -> VS (r (Value r)) -> MSStatement r
forall (r :: * -> *).
DeclStatement r =>
SVariable r -> r (Scope r) -> SValue r -> MSStatement r
`varDecDef` r (Scope r)
scp) VS (r (Variable r))
v) Maybe (VS (r (Value r)))
val

-- | Generates a call to the function for printing outputs.
genOutputCallProc :: (SharedProg r) => GenState (Maybe (MSStatement r))
genOutputCallProc :: forall (r :: * -> *).
SharedProg r =>
GenState (Maybe (MSStatement r))
genOutputCallProc = do
  Name
woName <- InternalConcept -> GenState Name
genICName InternalConcept
WriteOutput
  Maybe (VS (r (Value r)))
val <- Name
-> VSType r
-> GenState [CodeVarChunk]
-> StateT DrasilState Identity (Maybe (VS (r (Value r))))
forall (r :: * -> *).
SharedProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCallProc Name
woName VSType r
forall (r :: * -> *). TypeSym r => VSType r
void GenState [CodeVarChunk]
getOutputParams
  Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MSStatement r) -> GenState (Maybe (MSStatement r)))
-> Maybe (MSStatement r) -> GenState (Maybe (MSStatement r))
forall a b. (a -> b) -> a -> b
$ (VS (r (Value r)) -> MSStatement r)
-> Maybe (VS (r (Value r))) -> Maybe (MSStatement r)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VS (r (Value r)) -> MSStatement r
forall (r :: * -> *). StatementSym r => SValue r -> MSStatement r
valStmt Maybe (VS (r (Value r)))
val

-- | Generates a function call given the name, return type, and arguments to
-- the function.
genFuncCallProc :: (SharedProg r) => Name -> VSType r ->
  GenState [CodeVarChunk] -> GenState (Maybe (SValue r))
genFuncCallProc :: forall (r :: * -> *).
SharedProg r =>
Name
-> VSType r
-> GenState [CodeVarChunk]
-> GenState (Maybe (SValue r))
genFuncCallProc Name
n VSType r
t GenState [CodeVarChunk]
funcPs = do
  Maybe Name
mm <- Name -> GenState (Maybe Name)
genCall Name
n
  let genFuncCall' :: Maybe Name -> GenState (Maybe (SValue r))
genFuncCall' Maybe Name
Nothing = Maybe (SValue r) -> GenState (Maybe (SValue r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (SValue r)
forall a. Maybe a
Nothing
      genFuncCall' (Just Name
m) = do
        [CodeVarChunk]
cs <- GenState [CodeVarChunk]
funcPs
        [SValue r]
pvals <- (CodeVarChunk -> StateT DrasilState Identity (SValue r))
-> [CodeVarChunk] -> StateT DrasilState Identity [SValue r]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (SValue r)
forall (r :: * -> *).
SharedProg r =>
CodeVarChunk -> GenState (SValue r)
mkValProc [CodeVarChunk]
cs
        SValue r
val <- Name
-> Name
-> VSType r
-> [SValue r]
-> NamedArgs r
-> StateT DrasilState Identity (SValue r)
forall (r :: * -> *).
SharedProg r =>
Name
-> Name
-> VSType r
-> [SValue r]
-> NamedArgs r
-> GenState (SValue r)
fAppProc Name
m Name
n VSType r
t [SValue r]
pvals []
        Maybe (SValue r) -> GenState (Maybe (SValue r))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (SValue r) -> GenState (Maybe (SValue r)))
-> Maybe (SValue r) -> GenState (Maybe (SValue r))
forall a b. (a -> b) -> a -> b
$ SValue r -> Maybe (SValue r)
forall a. a -> Maybe a
Just SValue r
val
  Maybe Name -> GenState (Maybe (SValue r))
genFuncCall' Maybe Name
mm

-- | Generates a function call given the name, inputs, and outputs for the
-- function.
genInOutCallProc :: (SharedProg r) => Name -> GenState [CodeVarChunk] ->
  GenState [CodeVarChunk] -> GenState (Maybe (MSStatement r))
genInOutCallProc :: forall (r :: * -> *).
SharedProg r =>
Name
-> GenState [CodeVarChunk]
-> GenState [CodeVarChunk]
-> GenState (Maybe (MSStatement r))
genInOutCallProc Name
n GenState [CodeVarChunk]
inFunc GenState [CodeVarChunk]
outFunc = do
  Maybe Name
mm <- Name -> GenState (Maybe Name)
genCall Name
n
  let genInOutCall' :: Maybe Name
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
genInOutCall' Maybe Name
Nothing = Maybe (MS (r (Statement r)))
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (MS (r (Statement r)))
forall a. Maybe a
Nothing
      genInOutCall' (Just Name
m) = do
        [CodeVarChunk]
ins' <- GenState [CodeVarChunk]
inFunc
        [CodeVarChunk]
outs' <- GenState [CodeVarChunk]
outFunc
        [VS (r (Variable r))]
ins <- (CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r))))
-> [CodeVarChunk]
-> StateT DrasilState Identity [VS (r (Variable r))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
SharedProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVarProc ([CodeVarChunk]
ins' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk]
outs')
        [VS (r (Variable r))]
outs <- (CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r))))
-> [CodeVarChunk]
-> StateT DrasilState Identity [VS (r (Variable r))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
SharedProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVarProc ([CodeVarChunk]
outs' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk]
ins')
        [VS (r (Variable r))]
both <- (CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r))))
-> [CodeVarChunk]
-> StateT DrasilState Identity [VS (r (Variable r))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM CodeVarChunk -> StateT DrasilState Identity (VS (r (Variable r)))
forall (r :: * -> *).
SharedProg r =>
CodeVarChunk -> GenState (SVariable r)
mkVarProc ([CodeVarChunk]
ins' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
`intersect` [CodeVarChunk]
outs')
        MS (r (Statement r))
stmt <- Name
-> Name
-> [SValue r]
-> [VS (r (Variable r))]
-> [VS (r (Variable r))]
-> StateT DrasilState Identity (MS (r (Statement r)))
forall (r :: * -> *).
SharedProg r =>
Name
-> Name
-> [SValue r]
-> [SVariable r]
-> [SVariable r]
-> GenState (MSStatement r)
fAppInOutProc Name
m Name
n ((VS (r (Variable r)) -> SValue r)
-> [VS (r (Variable r))] -> [SValue r]
forall a b. (a -> b) -> [a] -> [b]
map VS (r (Variable r)) -> SValue r
forall (r :: * -> *). VariableValue r => SVariable r -> SValue r
valueOf [VS (r (Variable r))]
ins) [VS (r (Variable r))]
outs [VS (r (Variable r))]
both
        Maybe (MS (r (Statement r)))
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
forall a. a -> StateT DrasilState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MS (r (Statement r)))
 -> StateT DrasilState Identity (Maybe (MS (r (Statement r)))))
-> Maybe (MS (r (Statement r)))
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
forall a b. (a -> b) -> a -> b
$ MS (r (Statement r)) -> Maybe (MS (r (Statement r)))
forall a. a -> Maybe a
Just MS (r (Statement r))
stmt
  Maybe Name -> GenState (Maybe (MSStatement r))
forall {r :: * -> *}.
SharedProg r =>
Maybe Name
-> StateT DrasilState Identity (Maybe (MS (r (Statement r))))
genInOutCall' Maybe Name
mm