module Language.Drasil.ICOSolutionSearch where
    
import Language.Drasil (CodeVarChunk, showUID, DefiningCodeExpr(codeExpr))
import Language.Drasil.Chunk.CodeDefinition (CodeDefinition, auxExprs)
import Database.Drasil (ChunkDB)
import Utils.Drasil (subsetOf)
import Language.Drasil.Chunk.CodeBase (codevars', quantvar)
import Data.List ((\\), intercalate)
import Control.Lens ((^.))
type Def = CodeDefinition
type Known = CodeVarChunk
type Need  = CodeVarChunk
getExecOrder :: [Def] -> [Known] -> [Need] -> ChunkDB -> [Def]
getExecOrder :: [Def] -> [CodeVarChunk] -> [CodeVarChunk] -> ChunkDB -> [Def]
getExecOrder [Def]
d [CodeVarChunk]
k' [CodeVarChunk]
n' ChunkDB
sm  = [Def] -> [Def] -> [CodeVarChunk] -> [CodeVarChunk] -> [Def]
getExecOrder' [] [Def]
d [CodeVarChunk]
k' ([CodeVarChunk]
n' [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk]
k')
  where getExecOrder' :: [Def] -> [Def] -> [CodeVarChunk] -> [CodeVarChunk] -> [Def]
getExecOrder' [Def]
ord [Def]
_ [CodeVarChunk]
_ []   = [Def]
ord
        getExecOrder' [Def]
ord [Def]
defs' [CodeVarChunk]
k [CodeVarChunk]
n =
          let new :: [Def]
new  = (Def -> Bool) -> [Def] -> [Def]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Def
def -> ([CodeVarChunk] -> [CodeVarChunk] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`subsetOf` [CodeVarChunk]
k) ((CodeExpr -> [CodeVarChunk]) -> [CodeExpr] -> [CodeVarChunk]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (CodeExpr -> ChunkDB -> [CodeVarChunk]
`codevars'` ChunkDB
sm)
                (Def
def Def -> Getting CodeExpr Def CodeExpr -> CodeExpr
forall s a. s -> Getting a s a -> a
^. Getting CodeExpr Def CodeExpr
forall c. DefiningCodeExpr c => Lens' c CodeExpr
Lens' Def CodeExpr
codeExpr CodeExpr -> [CodeExpr] -> [CodeExpr]
forall a. a -> [a] -> [a]
: Def
def Def -> Getting [CodeExpr] Def [CodeExpr] -> [CodeExpr]
forall s a. s -> Getting a s a -> a
^. Getting [CodeExpr] Def [CodeExpr]
Lens' Def [CodeExpr]
auxExprs) [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Def -> CodeVarChunk
forall c.
(Quantity c, MayHaveUnit c, Concept c) =>
c -> CodeVarChunk
quantvar Def
def])) [Def]
defs'
              cnew :: [CodeVarChunk]
cnew = (Def -> CodeVarChunk) -> [Def] -> [CodeVarChunk]
forall a b. (a -> b) -> [a] -> [b]
map Def -> CodeVarChunk
forall c.
(Quantity c, MayHaveUnit c, Concept c) =>
c -> CodeVarChunk
quantvar [Def]
new
              kNew :: [CodeVarChunk]
kNew = [CodeVarChunk]
k [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. [a] -> [a] -> [a]
++ [CodeVarChunk]
cnew
              nNew :: [CodeVarChunk]
nNew = [CodeVarChunk]
n [CodeVarChunk] -> [CodeVarChunk] -> [CodeVarChunk]
forall a. Eq a => [a] -> [a] -> [a]
\\ [CodeVarChunk]
cnew
          in  if [Def] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Def]
new
              then [Char] -> [Def]
forall a. HasCallStack => [Char] -> a
error ([Char]
"The following outputs cannot be computed: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                       [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " ((CodeVarChunk -> [Char]) -> [CodeVarChunk] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map CodeVarChunk -> [Char]
forall a. HasUID a => a -> [Char]
showUID [CodeVarChunk]
n) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n"
                     [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"Unused definitions are: "
                       [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " ((Def -> [Char]) -> [Def] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Def -> [Char]
forall a. HasUID a => a -> [Char]
showUID [Def]
defs') [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n"
                     [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"Known values are: "
                       [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " ((CodeVarChunk -> [Char]) -> [CodeVarChunk] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map CodeVarChunk -> [Char]
forall a. HasUID a => a -> [Char]
showUID [CodeVarChunk]
k))
              else [Def] -> [Def] -> [CodeVarChunk] -> [CodeVarChunk] -> [Def]
getExecOrder' ([Def]
ord [Def] -> [Def] -> [Def]
forall a. [a] -> [a] -> [a]
++ [Def]
new) ([Def]
defs' [Def] -> [Def] -> [Def]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Def]
new) [CodeVarChunk]
kNew [CodeVarChunk]
nNew