{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
module Command.Diagram
( diagram
, DiagramOptions(..)
, DiagramFormat(..)
, DiagramMode(..)
, DiagramPropFormat(..)
, ErrorCode
)
where
import Control.Exception as E
import Control.Monad.Except (runExceptT)
import Data.Aeson (object, (.=))
import Data.Char (toLower)
import Data.Foldable (for_)
import Data.Text.Lazy (pack)
import System.FilePath ((</>))
import System.Directory.Extra ( copyTemplate )
import Command.Errors (ErrorTriplet (..))
import Command.Result (Result (..))
import Data.Diagram.Parser (DiagramFormat (..), readDiagram)
import Data.ExprPair (ExprPair (..), ExprPairT (..))
import qualified Data.ExprPair
import Data.Location (Location (..))
import Paths_ogma_core (getDataDir)
import Language.Trans.Diagram2Copilot (DiagramMode (..), diagram2CopilotSpec)
diagram :: FilePath
-> DiagramOptions
-> IO (Result ErrorCode)
diagram :: [Char] -> DiagramOptions -> IO (Result Int)
diagram [Char]
fp DiagramOptions
options = do
(SomeException -> IO (Result Int))
-> IO (Result Int) -> IO (Result Int)
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
E.handle (Result Int -> IO (Result Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result Int -> IO (Result Int))
-> (SomeException -> Result Int)
-> SomeException
-> IO (Result Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> SomeException -> Result Int
diagramTemplateError [Char]
fp) (IO (Result Int) -> IO (Result Int))
-> IO (Result Int) -> IO (Result Int)
forall a b. (a -> b) -> a -> b
$ do
let functions :: ExprPair
functions = DiagramPropFormat -> ExprPair
exprPair (DiagramOptions -> DiagramPropFormat
diagramPropFormat DiagramOptions
options)
copilotSpecElems <- [Char]
-> DiagramOptions
-> ExprPair
-> IO (Either [Char] ([Char], [Char]))
diagram' [Char]
fp DiagramOptions
options ExprPair
functions
let (mOutput, result) = diagramResult fp copilotSpecElems
for_ mOutput $ \([Char]
streamDefs, [Char]
triggers) -> do
let subst :: Value
subst = [Pair] -> Value
object
[ Key
"streamDefs" Key -> Text -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Char] -> Text
pack [Char]
streamDefs
, Key
"specName" Key -> Text -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Char] -> Text
pack (DiagramOptions -> [Char]
diagramFilename DiagramOptions
options)
, Key
"input" Key -> Text -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Char] -> Text
pack (DiagramOptions -> [Char]
diagramInputVar DiagramOptions
options)
, Key
"state" Key -> Text -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Char] -> Text
pack (DiagramOptions -> [Char]
diagramStateVar DiagramOptions
options)
, Key
"triggers" Key -> Text -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Char] -> Text
pack [Char]
triggers
]
templateDir <- case DiagramOptions -> Maybe [Char]
diagramTemplateDir DiagramOptions
options of
Just [Char]
x -> [Char] -> IO [Char]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
x
Maybe [Char]
Nothing -> do
dataDir <- IO [Char]
getDataDir
return $ dataDir </> "templates" </> "diagram"
let targetDir = DiagramOptions -> [Char]
diagramTargetDir DiagramOptions
options
copyTemplate templateDir subst targetDir
return result
diagram' :: FilePath
-> DiagramOptions
-> ExprPair
-> IO (Either String (String, String))
diagram' :: [Char]
-> DiagramOptions
-> ExprPair
-> IO (Either [Char] ([Char], [Char]))
diagram' [Char]
fp DiagramOptions
options ExprPair
exprP = do
diagramE <- ExceptT ErrorTriplet IO Diagram -> IO (Either ErrorTriplet Diagram)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT ErrorTriplet IO Diagram
-> IO (Either ErrorTriplet Diagram))
-> ExceptT ErrorTriplet IO Diagram
-> IO (Either ErrorTriplet Diagram)
forall a b. (a -> b) -> a -> b
$ [Char]
-> DiagramFormat -> ExprPair -> ExceptT ErrorTriplet IO Diagram
readDiagram [Char]
fp (DiagramOptions -> DiagramFormat
diagramFormat DiagramOptions
options) ExprPair
exprP
case diagramE of
Left (ErrorTriplet Int
_ec [Char]
msg Location
_loc) -> Either [Char] ([Char], [Char])
-> IO (Either [Char] ([Char], [Char]))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either [Char] ([Char], [Char])
-> IO (Either [Char] ([Char], [Char])))
-> Either [Char] ([Char], [Char])
-> IO (Either [Char] ([Char], [Char]))
forall a b. (a -> b) -> a -> b
$ [Char] -> Either [Char] ([Char], [Char])
forall a b. a -> Either a b
Left [Char]
msg
Right Diagram
diagramR ->
Either [Char] ([Char], [Char])
-> IO (Either [Char] ([Char], [Char]))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either [Char] ([Char], [Char])
-> IO (Either [Char] ([Char], [Char])))
-> Either [Char] ([Char], [Char])
-> IO (Either [Char] ([Char], [Char]))
forall a b. (a -> b) -> a -> b
$ ([Char], [Char]) -> Either [Char] ([Char], [Char])
forall a b. b -> Either a b
Right (([Char], [Char]) -> Either [Char] ([Char], [Char]))
-> ([Char], [Char]) -> Either [Char] ([Char], [Char])
forall a b. (a -> b) -> a -> b
$ Diagram -> DiagramMode -> ([Char], [Char])
diagram2CopilotSpec Diagram
diagramR (DiagramOptions -> DiagramMode
diagramMode DiagramOptions
options)
data DiagramOptions = DiagramOptions
{ DiagramOptions -> [Char]
diagramTargetDir :: FilePath
, DiagramOptions -> Maybe [Char]
diagramTemplateDir :: Maybe FilePath
, DiagramOptions -> DiagramFormat
diagramFormat :: DiagramFormat
, DiagramOptions -> DiagramPropFormat
diagramPropFormat :: DiagramPropFormat
, DiagramOptions -> [Char]
diagramFilename :: String
, DiagramOptions -> DiagramMode
diagramMode :: DiagramMode
, DiagramOptions -> [Char]
diagramStateVar :: String
, DiagramOptions -> [Char]
diagramInputVar :: String
}
data DiagramPropFormat = Lustre
| Inputs
| Literal
| SMV
deriving (DiagramPropFormat -> DiagramPropFormat -> Bool
(DiagramPropFormat -> DiagramPropFormat -> Bool)
-> (DiagramPropFormat -> DiagramPropFormat -> Bool)
-> Eq DiagramPropFormat
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DiagramPropFormat -> DiagramPropFormat -> Bool
== :: DiagramPropFormat -> DiagramPropFormat -> Bool
$c/= :: DiagramPropFormat -> DiagramPropFormat -> Bool
/= :: DiagramPropFormat -> DiagramPropFormat -> Bool
Eq, Int -> DiagramPropFormat -> [Char] -> [Char]
[DiagramPropFormat] -> [Char] -> [Char]
DiagramPropFormat -> [Char]
(Int -> DiagramPropFormat -> [Char] -> [Char])
-> (DiagramPropFormat -> [Char])
-> ([DiagramPropFormat] -> [Char] -> [Char])
-> Show DiagramPropFormat
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
$cshowsPrec :: Int -> DiagramPropFormat -> [Char] -> [Char]
showsPrec :: Int -> DiagramPropFormat -> [Char] -> [Char]
$cshow :: DiagramPropFormat -> [Char]
show :: DiagramPropFormat -> [Char]
$cshowList :: [DiagramPropFormat] -> [Char] -> [Char]
showList :: [DiagramPropFormat] -> [Char] -> [Char]
Show)
type ErrorCode = Int
ecDiagramError :: ErrorCode
ecDiagramError :: Int
ecDiagramError = Int
1
ecDiagramTemplateError :: ErrorCode
ecDiagramTemplateError :: Int
ecDiagramTemplateError = Int
2
diagramResult :: FilePath
-> Either String a
-> (Maybe a, Result ErrorCode)
diagramResult :: forall a. [Char] -> Either [Char] a -> (Maybe a, Result Int)
diagramResult [Char]
fp Either [Char] a
result = case Either [Char] a
result of
Left [Char]
msg -> (Maybe a
forall a. Maybe a
Nothing, Int -> [Char] -> Location -> Result Int
forall a. a -> [Char] -> Location -> Result a
Error Int
ecDiagramError [Char]
msg ([Char] -> Location
LocationFile [Char]
fp))
Right a
t -> (a -> Maybe a
forall a. a -> Maybe a
Just a
t, Result Int
forall a. Result a
Success)
diagramTemplateError :: FilePath
-> E.SomeException
-> Result ErrorCode
diagramTemplateError :: [Char] -> SomeException -> Result Int
diagramTemplateError [Char]
fp SomeException
exception =
Int -> [Char] -> Location -> Result Int
forall a. a -> [Char] -> Location -> Result a
Error Int
ecDiagramTemplateError [Char]
msg ([Char] -> Location
LocationFile [Char]
fp)
where
msg :: [Char]
msg =
[Char]
"Diagram monitor generation failed during copy/write operation. Check"
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" that there's free space in the disk and that you have the necessary"
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" permissions to write in the destination directory. "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ SomeException -> [Char]
forall a. Show a => a -> [Char]
show SomeException
exception
exprPair :: DiagramPropFormat -> ExprPair
exprPair :: DiagramPropFormat -> ExprPair
exprPair DiagramPropFormat
Inputs = ExprPairT Int -> ExprPair
forall a. ExprPairT a -> ExprPair
ExprPair (ExprPairT Int -> ExprPair) -> ExprPairT Int -> ExprPair
forall a b. (a -> b) -> a -> b
$
([Char] -> Either [Char] Int)
-> ([([Char], [Char])] -> Int -> Int)
-> (Int -> [Char])
-> (Int -> [[Char]])
-> Int
-> ExprPairT Int
forall a.
([Char] -> Either [Char] a)
-> ([([Char], [Char])] -> a -> a)
-> (a -> [Char])
-> (a -> [[Char]])
-> a
-> ExprPairT a
ExprPairT
((Int -> Either [Char] Int
forall a b. b -> Either a b
Right (Int -> Either [Char] Int)
-> ([Char] -> Int) -> [Char] -> Either [Char] Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Int
forall a. Read a => [Char] -> a
read) :: String -> Either String Int)
(\[([Char], [Char])]
_ -> Int -> Int
forall a. a -> a
id)
(\Int
x -> [Char]
"input == " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
x)
([[Char]] -> Int -> [[Char]]
forall a b. a -> b -> a
const [])
(-Int
1)
exprPair DiagramPropFormat
f = [Char] -> ExprPair
Data.ExprPair.exprPair (DiagramPropFormat -> [Char]
formatName DiagramPropFormat
f)
where
formatName :: DiagramPropFormat -> [Char]
formatName = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower ([Char] -> [Char])
-> (DiagramPropFormat -> [Char]) -> DiagramPropFormat -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiagramPropFormat -> [Char]
forall a. Show a => a -> [Char]
show