{-# LANGUAGE GADTs, TemplateHaskell #-}
{-# LANGUAGE InstanceSigs #-}
-- | Defines the CodeSpec structure and related functions.
module Language.Drasil.CodeSpec (
  -- * Types
  Input, Output, Const, Derived, ConstantMap,
  CodeSpec,
  -- * Typeclasses
  HasCodeSpec(..),
  -- * Constructors
  mkCodeSpec,
  -- * ODEs
  getODE, mapODE,
  -- * Hacks
  asVC, funcUID, getDerivedInputs, getConstraints, constraintvars
) where

import Prelude hiding (const)
import Control.Lens ((^.), makeClassy, set)
import Data.List (nub, (\\))
import qualified Data.Map as Map
import Data.Maybe (mapMaybe)
import qualified Data.List.NonEmpty as NE

import Drasil.FileHandling.Legacy (RelativeFile)
import Language.Drasil hiding (None)
import Language.Drasil.Display (Symbol(Variable))
import Drasil.Database (ChunkDB, UID, HasUID(..), insertAll, mkUid)
import Drasil.Code.CodeExpr.Development (expr, eNamesRI, eDep)
import qualified Drasil.SRS as S
import Drasil.System (HasSystemMeta(..))
import Drasil.SRS (HasSmithEtAlSRS(..))
import Theory.Drasil (DataDefinition, qdEFromDD, getEqModQdsFromIm)
import Data.List.Extras (subsetOf)

import Drasil.Code.CodeVar (CodeVarChunk, quantvar)
import Language.Drasil.Chunk.ConstraintMap (ConstraintCEMap, ConstraintCE, constraintMap)
import Language.Drasil.Chunk.CodeDefinition (CodeDefinition, qtov, qtoc, odeDef)
import Language.Drasil.Choices (Choices(..), Maps(..), ODE(..), ExtLib(..),
  odeLibReqs, odeInfoReqs)
import Language.Drasil.Chunk.CodeBase (codevars, varResolve)
import Language.Drasil.Mod (Func(..), FuncData(..), FuncDef(..), Mod(..))
import Language.Drasil.ICOSolutionSearch (Def, solveExecOrder)

-- | Program input.
type Input = CodeVarChunk
-- | Program output.
type Output = CodeVarChunk
-- | Constants in the problem.
type Const = CodeDefinition
-- | Derived inputs.
type Derived = CodeDefinition
-- | Maps constants to their respective 'CodeDefinition'.
type ConstantMap = Map.Map UID CodeDefinition

-- | Code Specification. Holds system information and options.
data CodeSpec = CS {
  CodeSpec -> SmithEtAlSRS
_srs :: S.SmithEtAlSRS,
  -- | All inputs.
  CodeSpec -> [Input]
_inputs :: [Input],
  -- | Explicit inputs (values to be supplied by a file).
  CodeSpec -> [Input]
_extInputs :: [Input],
  -- | Derived inputs (each calculated from explicit inputs in a single step).
  CodeSpec -> [Const]
_derivedInputs :: [Derived],
  -- | All outputs.
  CodeSpec -> [Input]
_outputs :: [Output],
  -- | List of files that must be in same directory for running the executable.
  CodeSpec -> [RelativeFile]
_configFiles :: [RelativeFile],
  -- | Mathematical definitions, ordered so that they form a path from inputs to
  -- outputs.
  CodeSpec -> [Const]
_execOrder :: [Def],
  -- | Map from 'UID's to constraints for all constrained chunks used in the problem.
  CodeSpec -> ConstraintCEMap
_cMap :: ConstraintCEMap,
  -- | List of all constants used in the problem.
  CodeSpec -> [Const]
_constDefns :: [Const],
  -- | Map containing all constants used in the problem.
  CodeSpec -> ConstantMap
_constMap :: ConstantMap,
  -- | Additional modules required in the generated code, which Drasil cannot yet
  -- automatically define.
  CodeSpec -> [Mod]
_mods :: [Mod]  -- medium hack
}
makeClassy ''CodeSpec

instance HasSmithEtAlSRS CodeSpec where
  smithEtAlSRS :: Lens' CodeSpec SmithEtAlSRS
smithEtAlSRS = (SmithEtAlSRS -> f SmithEtAlSRS) -> CodeSpec -> f CodeSpec
forall c. HasCodeSpec c => Lens' c SmithEtAlSRS
Lens' CodeSpec SmithEtAlSRS
srs

instance HasSystemMeta CodeSpec where
  systemMeta :: Lens' CodeSpec SystemMeta
systemMeta = (SmithEtAlSRS -> f SmithEtAlSRS) -> CodeSpec -> f CodeSpec
forall c. HasCodeSpec c => Lens' c SmithEtAlSRS
Lens' CodeSpec SmithEtAlSRS
srs ((SmithEtAlSRS -> f SmithEtAlSRS) -> CodeSpec -> f CodeSpec)
-> ((SystemMeta -> f SystemMeta) -> SmithEtAlSRS -> f SmithEtAlSRS)
-> (SystemMeta -> f SystemMeta)
-> CodeSpec
-> f CodeSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SystemMeta -> f SystemMeta) -> SmithEtAlSRS -> f SmithEtAlSRS
forall c. HasSystemMeta c => Lens' c SystemMeta
Lens' SmithEtAlSRS SystemMeta
systemMeta

-- | Converts a list of chunks that have 'UID's to a Map from 'UID' to the associated chunk.
assocToMap :: HasUID a => [a] -> Map.Map UID a
assocToMap :: forall a. HasUID a => [a] -> Map UID a
assocToMap = [(UID, a)] -> Map UID a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(UID, a)] -> Map UID a)
-> ([a] -> [(UID, a)]) -> [a] -> Map UID a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> (UID, a)) -> [a] -> [(UID, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\a
x -> (a
x a -> Getting UID a UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID a UID
forall c. HasUID c => Getter c UID
Getter a UID
uid, a
x))

-- | Get ODE from ExtLib
getODE :: [ExtLib] -> Maybe ODE
getODE :: [ExtLib] -> Maybe ODE
getODE [] = Maybe ODE
forall a. Maybe a
Nothing
getODE (Math ODE
ode: [ExtLib]
_) = ODE -> Maybe ODE
forall a. a -> Maybe a
Just ODE
ode
-- getODE (_:xs) = getODE xs

-- | Maps ODE to their respective 'CodeDefinition'.
mapODE :: Maybe ODE -> [CodeDefinition]
mapODE :: Maybe ODE -> [Const]
mapODE Maybe ODE
Nothing = []
mapODE (Just ODE
ode) = (ODEInfo -> Const) -> [ODEInfo] -> [Const]
forall a b. (a -> b) -> [a] -> [b]
map ODEInfo -> Const
odeDef ([ODEInfo] -> [Const]) -> [ODEInfo] -> [Const]
forall a b. (a -> b) -> a -> b
$ ODE -> [ODEInfo]
odeInfo ODE
ode

-- | Creates a 'CodeSpec' using the provided 'System', 'Choices', and 'Mod's.
mkCodeSpec :: S.SmithEtAlSRS -> Choices -> CodeSpec
mkCodeSpec :: SmithEtAlSRS -> Choices -> CodeSpec
mkCodeSpec si :: SmithEtAlSRS
si@S.ICO{ _inputs :: ()
S._inputs = NonEmpty h
ins
                    , _outputs :: ()
S._outputs = NonEmpty i
outs
                    , _constraints :: ()
S._constraints = [j]
cs
                    , _constants :: SmithEtAlSRS -> [ConstQDef]
S._constants = [ConstQDef]
cnsts } Choices
chs =
  let els :: [ExtLib]
els = Choices -> [ExtLib]
extLibs Choices
chs
      libReqs :: [DefinedQuantityDict]
libReqs = (ExtLib -> [DefinedQuantityDict])
-> [ExtLib] -> [DefinedQuantityDict]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ExtLib -> [DefinedQuantityDict]
odeLibReqs [ExtLib]
els
      infoReqs :: [DefinedQuantityDict]
infoReqs = (ExtLib -> [DefinedQuantityDict])
-> [ExtLib] -> [DefinedQuantityDict]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ExtLib -> [DefinedQuantityDict]
odeInfoReqs [ExtLib]
els
      db' :: ChunkDB
db' = [DefinedQuantityDict] -> ChunkDB -> ChunkDB
forall a. TypeableChunk a => [a] -> ChunkDB -> ChunkDB
insertAll ([DefinedQuantityDict]
libReqs [DefinedQuantityDict]
-> [DefinedQuantityDict] -> [DefinedQuantityDict]
forall a. [a] -> [a] -> [a]
++ [DefinedQuantityDict]
infoReqs) (ChunkDB -> ChunkDB) -> ChunkDB -> ChunkDB
forall a b. (a -> b) -> a -> b
$ SmithEtAlSRS
si SmithEtAlSRS -> Getting ChunkDB SmithEtAlSRS ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB SmithEtAlSRS ChunkDB
forall c. HasSystemMeta c => Lens' c ChunkDB
Lens' SmithEtAlSRS ChunkDB
systemdb
      sys :: SmithEtAlSRS
sys = ASetter SmithEtAlSRS SmithEtAlSRS ChunkDB ChunkDB
-> ChunkDB -> SmithEtAlSRS -> SmithEtAlSRS
forall s t a b. ASetter s t a b -> b -> s -> t
set ASetter SmithEtAlSRS SmithEtAlSRS ChunkDB ChunkDB
forall c. HasSystemMeta c => Lens' c ChunkDB
Lens' SmithEtAlSRS ChunkDB
systemdb ChunkDB
db' SmithEtAlSRS
si
      ddefs :: [DataDefinition]
ddefs = SmithEtAlSRS
sys SmithEtAlSRS
-> Getting [DataDefinition] SmithEtAlSRS [DataDefinition]
-> [DataDefinition]
forall s a. s -> Getting a s a -> a
^. Getting [DataDefinition] SmithEtAlSRS [DataDefinition]
forall c. HasSmithEtAlSRS c => Lens' c [DataDefinition]
Lens' SmithEtAlSRS [DataDefinition]
dataDefns
      db :: ChunkDB
db = SmithEtAlSRS
sys SmithEtAlSRS -> Getting ChunkDB SmithEtAlSRS ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB SmithEtAlSRS ChunkDB
forall c. HasSystemMeta c => Lens' c ChunkDB
Lens' SmithEtAlSRS ChunkDB
systemdb
      inputs' :: [Input]
inputs' = (h -> Input) -> [h] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map h -> Input
forall c. (Quantity c, MayHaveUnit c, Concept c) => c -> Input
quantvar ([h] -> [Input]) -> [h] -> [Input]
forall a b. (a -> b) -> a -> b
$ NonEmpty h -> [h]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty h
ins
      const' :: [Const]
const' = (ConstQDef -> Const) -> [ConstQDef] -> [Const]
forall a b. (a -> b) -> [a] -> [b]
map ConstQDef -> Const
forall e. CanGenCode e => QDefinition e -> Const
qtov ((ConstQDef -> Bool) -> [ConstQDef] -> [ConstQDef]
forall a. (a -> Bool) -> [a] -> [a]
filter ((UID -> Map UID [CodeConcept] -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.notMember` Maps -> Map UID [CodeConcept]
conceptMatch (Choices -> Maps
maps Choices
chs)) (UID -> Bool) -> (ConstQDef -> UID) -> ConstQDef -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ConstQDef -> Getting UID ConstQDef UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID ConstQDef UID
forall c. HasUID c => Getter c UID
Getter ConstQDef UID
uid))
        [ConstQDef]
cnsts)
      derived :: [Const]
derived = (QDefinition Expr -> Const) -> [QDefinition Expr] -> [Const]
forall a b. (a -> b) -> [a] -> [b]
map QDefinition Expr -> Const
forall e. CanGenCode e => QDefinition e -> Const
qtov ([QDefinition Expr] -> [Const]) -> [QDefinition Expr] -> [Const]
forall a b. (a -> b) -> a -> b
$ [DataDefinition]
-> [Input] -> [Const] -> ChunkDB -> [QDefinition Expr]
getDerivedInputs [DataDefinition]
ddefs [Input]
inputs' [Const]
const' ChunkDB
db
      rels :: [Const]
rels = ((QDefinition Expr -> Const) -> [QDefinition Expr] -> [Const]
forall a b. (a -> b) -> [a] -> [b]
map QDefinition Expr -> Const
forall (q :: * -> *).
(Quantity (q Expr), MayHaveUnit (q Expr), DefiningExpr q,
 Concept (q Expr)) =>
q Expr -> Const
qtoc ([InstanceModel] -> [QDefinition Expr]
getEqModQdsFromIm (SmithEtAlSRS
sys SmithEtAlSRS
-> Getting [InstanceModel] SmithEtAlSRS [InstanceModel]
-> [InstanceModel]
forall s a. s -> Getting a s a -> a
^. Getting [InstanceModel] SmithEtAlSRS [InstanceModel]
forall c. HasSmithEtAlSRS c => Lens' c [InstanceModel]
Lens' SmithEtAlSRS [InstanceModel]
instModels) [QDefinition Expr] -> [QDefinition Expr] -> [QDefinition Expr]
forall a. [a] -> [a] -> [a]
++ (DataDefinition -> Maybe (QDefinition Expr))
-> [DataDefinition] -> [QDefinition Expr]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DataDefinition -> Maybe (QDefinition Expr)
qdEFromDD [DataDefinition]
ddefs) [Const] -> [Const] -> [Const]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Const]
derived)
        [Const] -> [Const] -> [Const]
forall a. [a] -> [a] -> [a]
++ Maybe ODE -> [Const]
mapODE ([ExtLib] -> Maybe ODE
getODE ([ExtLib] -> Maybe ODE) -> [ExtLib] -> Maybe ODE
forall a b. (a -> b) -> a -> b
$ Choices -> [ExtLib]
extLibs Choices
chs)
        [Const] -> [Const] -> [Const]
forall a. [a] -> [a] -> [a]
++ (QDefinition Expr -> Const) -> [QDefinition Expr] -> [Const]
forall a b. (a -> b) -> [a] -> [b]
map QDefinition Expr -> Const
forall (q :: * -> *).
(Quantity (q Expr), MayHaveUnit (q Expr), DefiningExpr q,
 Concept (q Expr)) =>
q Expr -> Const
qtoc (Choices -> [QDefinition Expr]
handWiredDefs Choices
chs)
      -- TODO: When we have better DEModels, we should be deriving our ODE information
      --       directly from the instance models (ims) instead of directly from the choices.
      outs' :: [Input]
outs' = (i -> Input) -> [i] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map i -> Input
forall c. (Quantity c, MayHaveUnit c, Concept c) => c -> Input
quantvar ([i] -> [Input]) -> [i] -> [Input]
forall a b. (a -> b) -> a -> b
$ NonEmpty i -> [i]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty i
outs
      allInputs :: [Input]
allInputs = [Input]
inputs' [Input] -> [Input] -> [Input]
forall a. [a] -> [a] -> [a]
++ (Const -> Input) -> [Const] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map Const -> Input
forall c. (Quantity c, MayHaveUnit c, Concept c) => c -> Input
quantvar [Const]
derived
      exOrder :: [Const]
exOrder = [Const] -> [Input] -> [Input] -> ChunkDB -> [Const]
solveExecOrder [Const]
rels ([Input]
allInputs [Input] -> [Input] -> [Input]
forall a. [a] -> [a] -> [a]
++ (ConstQDef -> Input) -> [ConstQDef] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map ConstQDef -> Input
forall c. (Quantity c, MayHaveUnit c, Concept c) => c -> Input
quantvar [ConstQDef]
cnsts) [Input]
outs' ChunkDB
db
  in CS {
        _srs :: SmithEtAlSRS
_srs = SmithEtAlSRS
sys,
        _inputs :: [Input]
_inputs = [Input]
allInputs,
        _extInputs :: [Input]
_extInputs = [Input]
inputs',
        _derivedInputs :: [Const]
_derivedInputs = [Const]
derived,
        _outputs :: [Input]
_outputs = [Input]
outs',
        _configFiles :: [RelativeFile]
_configFiles = Choices -> [RelativeFile]
defaultConfigFiles Choices
chs,
        _execOrder :: [Const]
_execOrder = [Const]
exOrder,
        _cMap :: ConstraintCEMap
_cMap = [j] -> ConstraintCEMap
forall c. (HasUID c, Constrained c) => [c] -> ConstraintCEMap
constraintMap [j]
cs,
        _constDefns :: [Const]
_constDefns = [Const]
const',
        _constMap :: ConstantMap
_constMap = [Const] -> ConstantMap
forall a. HasUID a => [a] -> Map UID a
assocToMap [Const]
const',
        _mods :: [Mod]
_mods = Choices -> [Mod]
extraMods Choices
chs
      }

-- medium hacks ---

-- | Convert a 'Func' to an implementation-stage 'DefinedQuantityDict' representing the
-- function.
asVC :: Func -> DefinedQuantityDict
asVC :: Func -> DefinedQuantityDict
asVC (FDef (FuncDef String
n String
d [ParameterChunk]
_ Space
_ Maybe String
_ [FuncStmt]
_)) = UID -> NP -> Sentence -> Symbol -> Space -> DefinedQuantityDict
quantNoUnit (String -> UID
mkUid String
n) (String -> NP
nounPhraseSP String
n) (String -> Sentence
S String
d) (String -> Symbol
Variable String
n) Space
Real
asVC (FDef (CtorDef String
n String
d [ParameterChunk]
_ [Initializer]
_ [FuncStmt]
_))   = UID -> NP -> Sentence -> Symbol -> Space -> DefinedQuantityDict
quantNoUnit (String -> UID
mkUid String
n) (String -> NP
nounPhraseSP String
n) (String -> Sentence
S String
d) (String -> Symbol
Variable String
n) Space
Real
asVC (FData (FuncData String
n String
d DataDesc
_))     = UID -> NP -> Sentence -> Symbol -> Space -> DefinedQuantityDict
quantNoUnit (String -> UID
mkUid String
n) (String -> NP
nounPhraseSP String
n) (String -> Sentence
S String
d) (String -> Symbol
Variable String
n) Space
Real

-- | Get a 'UID' of a chunk corresponding to a 'Func'.
funcUID :: Func -> UID
funcUID :: Func -> UID
funcUID Func
f = Func -> DefinedQuantityDict
asVC Func
f DefinedQuantityDict -> Getting UID DefinedQuantityDict UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID DefinedQuantityDict UID
forall c. HasUID c => Getter c UID
Getter DefinedQuantityDict UID
uid

-- | Determines the derived inputs, which can be immediately calculated from the
-- knowns (inputs and constants). If there are DDs, the derived inputs will
-- come from those. If there are none, then the 'QDefinition's are used instead.
getDerivedInputs :: [DataDefinition] -> [Input] -> [Const] ->
  ChunkDB -> [SimpleQDef]
getDerivedInputs :: [DataDefinition]
-> [Input] -> [Const] -> ChunkDB -> [QDefinition Expr]
getDerivedInputs [DataDefinition]
ddefs [Input]
ins [Const]
cnsts ChunkDB
sm =
  (QDefinition Expr -> Bool)
-> [QDefinition Expr] -> [QDefinition Expr]
forall a. (a -> Bool) -> [a] -> [a]
filter (([Input] -> [Input] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`subsetOf` [Input]
refSet) ([Input] -> Bool)
-> (QDefinition Expr -> [Input]) -> QDefinition Expr -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CodeExpr -> ChunkDB -> [Input]) -> ChunkDB -> CodeExpr -> [Input]
forall a b c. (a -> b -> c) -> b -> a -> c
flip CodeExpr -> ChunkDB -> [Input]
codevars ChunkDB
sm (CodeExpr -> [Input])
-> (QDefinition Expr -> CodeExpr) -> QDefinition Expr -> [Input]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> CodeExpr
expr (Expr -> CodeExpr)
-> (QDefinition Expr -> Expr) -> QDefinition Expr -> CodeExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (QDefinition Expr -> Getting Expr (QDefinition Expr) Expr -> Expr
forall s a. s -> Getting a s a -> a
^. Getting Expr (QDefinition Expr) Expr
forall e. Lens' (QDefinition e) e
forall (c :: * -> *) e. DefiningExpr c => Lens' (c e) e
defnExpr)) ((DataDefinition -> Maybe (QDefinition Expr))
-> [DataDefinition] -> [QDefinition Expr]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DataDefinition -> Maybe (QDefinition Expr)
qdEFromDD [DataDefinition]
ddefs)
  where refSet :: [Input]
refSet = [Input]
ins [Input] -> [Input] -> [Input]
forall a. [a] -> [a] -> [a]
++ (Const -> Input) -> [Const] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map Const -> Input
forall c. (Quantity c, MayHaveUnit c, Concept c) => c -> Input
quantvar [Const]
cnsts

-- | Get a list of 'Constraint's for a list of 'CodeChunk's.
getConstraints :: (HasUID c) => ConstraintCEMap -> [c] -> [ConstraintCE]
getConstraints :: forall c. HasUID c => ConstraintCEMap -> [c] -> [ConstraintCE]
getConstraints ConstraintCEMap
cm [c]
cs = [[ConstraintCE]] -> [ConstraintCE]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ConstraintCE]] -> [ConstraintCE])
-> [[ConstraintCE]] -> [ConstraintCE]
forall a b. (a -> b) -> a -> b
$ (c -> Maybe [ConstraintCE]) -> [c] -> [[ConstraintCE]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\c
c -> UID -> ConstraintCEMap -> Maybe [ConstraintCE]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (c
c c -> Getting UID c UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID c UID
forall c. HasUID c => Getter c UID
Getter c UID
uid) ConstraintCEMap
cm) [c]
cs

-- | Get a list of 'CodeVarChunk's from a constraint.
constraintvars :: ConstraintCE -> ChunkDB -> [CodeVarChunk]
constraintvars :: ConstraintCE -> ChunkDB -> [Input]
constraintvars (Range ConstraintReason
_ RealInterval CodeExpr CodeExpr
ri) ChunkDB
m = (UID -> Input) -> [UID] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map (ChunkDB -> UID -> Input
varResolve ChunkDB
m) ([UID] -> [Input]) -> [UID] -> [Input]
forall a b. (a -> b) -> a -> b
$ [UID] -> [UID]
forall a. Eq a => [a] -> [a]
nub ([UID] -> [UID]) -> [UID] -> [UID]
forall a b. (a -> b) -> a -> b
$ RealInterval CodeExpr CodeExpr -> [UID]
eNamesRI RealInterval CodeExpr CodeExpr
ri
constraintvars (Elem ConstraintReason
_ CodeExpr
ri)  ChunkDB
m = (UID -> Input) -> [UID] -> [Input]
forall a b. (a -> b) -> [a] -> [b]
map (ChunkDB -> UID -> Input
varResolve ChunkDB
m) ([UID] -> [Input]) -> [UID] -> [Input]
forall a b. (a -> b) -> a -> b
$ CodeExpr -> [UID]
eDep CodeExpr
ri