never executed always true always false
    1 module Conjure.UI.TranslateSolution ( translateSolution ) where
    2 
    3 -- conjure
    4 import Conjure.Prelude
    5 import Conjure.Bug
    6 import Conjure.Language.Definition
    7 import Conjure.Language.Type ( TypeCheckerMode(..) )
    8 import Conjure.Language.Constant ( normaliseConstant )
    9 import Conjure.Language.Pretty
   10 import Conjure.Language.Instantiate
   11 import Conjure.Process.Enums ( removeEnumsFromParam, addEnumsAndUnnamedsBack )
   12 import Conjure.Process.Enumerate ( EnumerateDomain )
   13 import Conjure.UI.TranslateParameter ( translateParameter )
   14 import Conjure.Representations ( up )
   15 
   16 -- text
   17 import qualified Data.Text as T ( pack, stripPrefix )
   18 
   19 -- unordered-containers
   20 import qualified Data.HashMap.Strict as M
   21 
   22 
   23 translateSolution ::
   24     MonadFailDoc m =>
   25     MonadLog m =>
   26     NameGen m =>
   27     EnumerateDomain m =>
   28     MonadIO m =>
   29     (?typeCheckerMode :: TypeCheckerMode) =>
   30     Model ->      -- eprime model
   31     Model ->      -- essence param
   32     Model ->      -- eprime solution
   33     m Model       -- essence solution
   34 
   35 translateSolution (undoUnderscores -> eprimeModel) (undoUnderscores -> essenceParam') (undoUnderscores -> eprimeSolution) = do
   36 
   37     eprimeParam <- translateParameter False eprimeModel essenceParam'
   38     (_, essenceParam) <- removeEnumsFromParam eprimeModel essenceParam'
   39 
   40     let eprimeLettingsForEnums =
   41             [ (nm, fromInt (genericLength vals))
   42             | nm1                                          <- eprimeModel |> mInfo |> miEnumGivens
   43             , Declaration (LettingDomainDefnEnum nm2 vals) <- essenceParam' |> mStatements
   44             , nm1 == nm2
   45             , let nm = nm1 `mappend` "_EnumSize"
   46             ]
   47 
   48     let eprimeLettings0 = extractLettings essenceParam ++
   49                           extractLettings eprimeParam ++
   50                           extractLettings eprimeSolution ++
   51                           extractLettings eprimeModel ++
   52                           (eprimeModel |> mInfo |> miLettings) ++
   53                           eprimeLettingsForEnums
   54     let essenceFindNames = eprimeModel |> mInfo |> miFinds
   55     let essenceFinds     = eprimeModel |> mInfo |> miRepresentations
   56                                        |> filter (\ (n,_) -> n `elem` essenceFindNames )
   57 
   58     -- the right hand sides of these lettings may be expressions (as opposed to constants)
   59     -- that will make evaluation unnecessarily slower
   60     let eprimeLettings =
   61             [ (name, maybe val Constant (e2c val))
   62             | (name, val) <- eprimeLettings0
   63             ]
   64 
   65     eprimeLettings' <- forM eprimeLettings $ \ (name, val) -> do
   66         constant <- instantiateExpression eprimeLettings val
   67         return (name, constant)
   68 
   69     essenceFinds' <- forM essenceFinds $ \ (name, dom) -> do
   70         constant <- instantiateDomain eprimeLettings dom
   71         return (name, constant)
   72 
   73     essenceLettings <- forM essenceFinds' $ \ (name, domain) -> do
   74         (_, constant) <- up eprimeLettings' (name, domain)
   75         let origDomain = eprimeModel
   76                 |> mInfo |> miOriginalDomains
   77                 |> lookup name
   78                 |> fromMaybe (bug ("Missing original domain for:" <+> pretty name))
   79         return (name, origDomain, constant)
   80 
   81     let
   82         intToEnumConstant :: M.HashMap (Integer, Name) Constant
   83         intToEnumConstant = M.fromList $ concat
   84             [ [ ((i,ename), ConstantEnum ename vals v)
   85               | (i,v) <- zip allNats vals
   86               ]
   87             | Declaration (LettingDomainDefnEnum ename vals)
   88                     <- mStatements essenceParam'
   89                     ++ eprimeModel |> mInfo |> miEnumLettings |> map Declaration
   90             ]
   91 
   92     let
   93         unnameds :: [(Name, Expression)]
   94         unnameds = eprimeModel |> mInfo |> miUnnameds
   95 
   96     unnamedsAsEnumDomains <- forM unnameds $ \ (n, s') -> do
   97         s <- instantiateExpression eprimeLettings s'
   98         case s of
   99             ConstantInt _ size -> return $
  100                 let nms = [ mconcat [n, "_", Name (T.pack (show i))]
  101                           | i <- [1 .. size]
  102                           ]
  103                 in  Declaration (LettingDomainDefnEnum n nms)
  104             _ -> failDoc $ vcat [ "Expecting an integer value for" <+> pretty n
  105                              , "But got:" <+> pretty s
  106                              ]
  107 
  108     let outStmts =
  109             unnamedsAsEnumDomains ++
  110             sortNub
  111                 [ Declaration (Letting n (Constant (normaliseConstant y)))
  112                 | (n, d, x) <- essenceLettings
  113                 , let y = addEnumsAndUnnamedsBack
  114                                 (map fst unnameds)
  115                                 intToEnumConstant
  116                                 d x
  117                 ]
  118 
  119     let undefs = [ u | u@ConstantUndefined{} <- universeBi outStmts ]
  120 
  121     if null undefs
  122         then return def { mStatements = outStmts }
  123         else bug $ vcat
  124             [ "Undefined values in the output:" <++> vcat (map pretty undefs)
  125             , ""
  126             , "Complete output would have been the following."
  127             , ""
  128             , pretty $ def { mStatements = outStmts }
  129             ]
  130 
  131 undoUnderscores :: Model -> Model
  132 undoUnderscores model =
  133     let
  134         -- SR doesn't support identifiers that start with _
  135         -- we replaced them with UNDERSCORE__ in prologue
  136         -- undo that here
  137         onName :: Name -> Name
  138         onName (Name t) =
  139             case T.stripPrefix "UNDERSCORE__" t of
  140                 Nothing -> Name t
  141                 Just t' -> Name (mappend "_" t')
  142         onName n = n
  143 
  144     in
  145         transformBi onName model
  146