{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Futhark.Script
(
ScriptServer,
withScriptServer,
Func (..),
Exp (..),
parseExp,
varsInExp,
ScriptValueType (..),
ScriptValue (..),
scriptValueType,
ExpValue,
EvalBuiltin,
evalExp,
getExpValue,
evalExpToGround,
valueToExp,
freeValue,
)
where
import Control.Monad.Except
import qualified Data.Binary as Bin
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Char
import Data.Foldable (toList)
import Data.IORef
import Data.List (intersperse)
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Text as T
import Data.Traversable
import Data.Void
import Futhark.Server
import qualified Futhark.Test.Values as V
import qualified Futhark.Test.Values.Parser as V
import Futhark.Util (nubOrd)
import Futhark.Util.Pretty hiding (float, line, sep, string, (</>), (<|>))
import System.IO
import System.IO.Temp
import Text.Megaparsec
import Text.Megaparsec.Char.Lexer (charLiteral)
data ScriptServer = ScriptServer Server (IORef Int)
withScriptServer :: FilePath -> [FilePath] -> (ScriptServer -> IO a) -> IO a
withScriptServer :: forall a. FilePath -> [FilePath] -> (ScriptServer -> IO a) -> IO a
withScriptServer FilePath
prog [FilePath]
options ScriptServer -> IO a
f = FilePath -> [FilePath] -> (Server -> IO a) -> IO a
forall a. FilePath -> [FilePath] -> (Server -> IO a) -> IO a
withServer FilePath
prog [FilePath]
options ((Server -> IO a) -> IO a) -> (Server -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Server
server -> do
IORef Int
counter <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
ScriptServer -> IO a
f (ScriptServer -> IO a) -> ScriptServer -> IO a
forall a b. (a -> b) -> a -> b
$ Server -> IORef Int -> ScriptServer
ScriptServer Server
server IORef Int
counter
data Func = FuncFut EntryName | FuncBuiltin T.Text
deriving (Int -> Func -> ShowS
[Func] -> ShowS
Func -> FilePath
(Int -> Func -> ShowS)
-> (Func -> FilePath) -> ([Func] -> ShowS) -> Show Func
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [Func] -> ShowS
$cshowList :: [Func] -> ShowS
show :: Func -> FilePath
$cshow :: Func -> FilePath
showsPrec :: Int -> Func -> ShowS
$cshowsPrec :: Int -> Func -> ShowS
Show)
data Exp
= Call Func [Exp]
| Const V.Value
| Tuple [Exp]
| Record [(T.Text, Exp)]
| StringLit T.Text
|
ServerVar TypeName VarName
deriving (Int -> Exp -> ShowS
[Exp] -> ShowS
Exp -> FilePath
(Int -> Exp -> ShowS)
-> (Exp -> FilePath) -> ([Exp] -> ShowS) -> Show Exp
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [Exp] -> ShowS
$cshowList :: [Exp] -> ShowS
show :: Exp -> FilePath
$cshow :: Exp -> FilePath
showsPrec :: Int -> Exp -> ShowS
$cshowsPrec :: Int -> Exp -> ShowS
Show)
instance Pretty Func where
ppr :: Func -> Doc
ppr (FuncFut EntryName
f) = EntryName -> Doc
forall a. Pretty a => a -> Doc
ppr EntryName
f
ppr (FuncBuiltin EntryName
f) = Doc
"$" Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> EntryName -> Doc
forall a. Pretty a => a -> Doc
ppr EntryName
f
instance Pretty Exp where
ppr :: Exp -> Doc
ppr = Int -> Exp -> Doc
forall a. Pretty a => Int -> a -> Doc
pprPrec Int
0
pprPrec :: Int -> Exp -> Doc
pprPrec Int
_ (ServerVar EntryName
_ EntryName
v) = Doc
"$" Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> EntryName -> Doc
forall a. Pretty a => a -> Doc
ppr EntryName
v
pprPrec Int
_ (Const Value
v) = Value -> Doc
forall a. Pretty a => a -> Doc
ppr Value
v
pprPrec Int
_ (Call Func
v []) = Func -> Doc
forall a. Pretty a => a -> Doc
ppr Func
v
pprPrec Int
i (Call Func
v [Exp]
args) =
Bool -> Doc -> Doc
parensIf (Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Func -> Doc
forall a. Pretty a => a -> Doc
ppr Func
v Doc -> Doc -> Doc
<+> [Doc] -> Doc
spread ((Exp -> Doc) -> [Exp] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Exp -> Doc
forall a. Pretty a => Int -> a -> Doc
pprPrec Int
1) [Exp]
args)
pprPrec Int
_ (Tuple [Exp]
vs) =
Doc -> Doc
parens (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
commasep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (Exp -> Doc) -> [Exp] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Exp -> Doc
forall a. Pretty a => a -> Doc
ppr [Exp]
vs
pprPrec Int
_ (StringLit EntryName
s) = FilePath -> Doc
forall a. Pretty a => a -> Doc
ppr (FilePath -> Doc) -> FilePath -> Doc
forall a b. (a -> b) -> a -> b
$ EntryName -> FilePath
forall a. Show a => a -> FilePath
show EntryName
s
pprPrec Int
_ (Record [(EntryName, Exp)]
m) = Doc -> Doc
braces (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
commasep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ ((EntryName, Exp) -> Doc) -> [(EntryName, Exp)] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (EntryName, Exp) -> Doc
forall {a} {a}. (Pretty a, Pretty a) => (a, a) -> Doc
field [(EntryName, Exp)]
m
where
field :: (a, a) -> Doc
field (a
k, a
v) = a -> Doc
forall a. Pretty a => a -> Doc
ppr a
k Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> Doc
equals Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> a -> Doc
forall a. Pretty a => a -> Doc
ppr a
v
type Parser = Parsec Void T.Text
lexeme :: Parser () -> Parser a -> Parser a
lexeme :: forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep Parser a
p = Parser a
p Parser a -> Parser () -> Parser a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
sep
inParens :: Parser () -> Parser a -> Parser a
inParens :: forall a. Parser () -> Parser a -> Parser a
inParens Parser ()
sep = ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity a
-> ParsecT Void EntryName Identity a
forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between (Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
"(") (Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
")")
inBraces :: Parser () -> Parser a -> Parser a
inBraces :: forall a. Parser () -> Parser a -> Parser a
inBraces Parser ()
sep = ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity a
-> ParsecT Void EntryName Identity a
forall (m :: * -> *) open close a.
Applicative m =>
m open -> m close -> m a -> m a
between (Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
"{") (Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
"}")
parseExp :: Parser () -> Parser Exp
parseExp :: Parser () -> Parser Exp
parseExp Parser ()
sep =
[Parser Exp] -> Parser Exp
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice
[ Parser () -> Parser Exp -> Parser Exp
forall a. Parser () -> Parser a -> Parser a
inParens Parser ()
sep ([Exp] -> Exp
mkTuple ([Exp] -> Exp)
-> ParsecT Void EntryName Identity [Exp] -> Parser Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser () -> Parser Exp
parseExp Parser ()
sep Parser Exp
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity [Exp]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
`sepBy` ParsecT Void EntryName Identity EntryName
pComma)),
Parser () -> Parser Exp -> Parser Exp
forall a. Parser () -> Parser a -> Parser a
inBraces Parser ()
sep ([(EntryName, Exp)] -> Exp
Record ([(EntryName, Exp)] -> Exp)
-> ParsecT Void EntryName Identity [(EntryName, Exp)] -> Parser Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ParsecT Void EntryName Identity (EntryName, Exp)
pField ParsecT Void EntryName Identity (EntryName, Exp)
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity [(EntryName, Exp)]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
`sepBy` ParsecT Void EntryName Identity EntryName
pComma)),
Func -> [Exp] -> Exp
Call (Func -> [Exp] -> Exp)
-> ParsecT Void EntryName Identity Func
-> ParsecT Void EntryName Identity ([Exp] -> Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ()
-> ParsecT Void EntryName Identity Func
-> ParsecT Void EntryName Identity Func
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity Func
parseFunc ParsecT Void EntryName Identity ([Exp] -> Exp)
-> ParsecT Void EntryName Identity [Exp] -> Parser Exp
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Exp -> ParsecT Void EntryName Identity [Exp]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many (Parser () -> Parser Exp
parseExp Parser ()
sep),
PrimValue -> Parser Exp
forall {m :: * -> *} {t}. (MonadFail m, PutValue t) => t -> m Exp
constV (PrimValue -> Parser Exp)
-> ParsecT Void EntryName Identity PrimValue -> Parser Exp
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Parser ()
-> ParsecT Void EntryName Identity PrimValue
-> ParsecT Void EntryName Identity PrimValue
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity PrimValue
V.parsePrimValue,
EntryName -> Exp
StringLit (EntryName -> Exp) -> (FilePath -> EntryName) -> FilePath -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> EntryName
T.pack (FilePath -> Exp)
-> ParsecT Void EntryName Identity FilePath -> Parser Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ()
-> ParsecT Void EntryName Identity FilePath
-> ParsecT Void EntryName Identity FilePath
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep (ParsecT Void EntryName Identity EntryName
"\"" ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity FilePath
-> ParsecT Void EntryName Identity FilePath
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void EntryName Identity Char
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity FilePath
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
manyTill ParsecT Void EntryName Identity Char
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m Char
charLiteral ParsecT Void EntryName Identity EntryName
"\"")
]
where
pField :: ParsecT Void EntryName Identity (EntryName, Exp)
pField = (,) (EntryName -> Exp -> (EntryName, Exp))
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity (Exp -> (EntryName, Exp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
parseEntryName ParsecT Void EntryName Identity (Exp -> (EntryName, Exp))
-> Parser Exp -> ParsecT Void EntryName Identity (EntryName, Exp)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (ParsecT Void EntryName Identity EntryName
pEquals ParsecT Void EntryName Identity EntryName
-> Parser Exp -> Parser Exp
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser () -> Parser Exp
parseExp Parser ()
sep)
pEquals :: ParsecT Void EntryName Identity EntryName
pEquals = Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
"="
pComma :: ParsecT Void EntryName Identity EntryName
pComma = Parser ()
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall a. Parser () -> Parser a -> Parser a
lexeme Parser ()
sep ParsecT Void EntryName Identity EntryName
","
mkTuple :: [Exp] -> Exp
mkTuple [Exp
v] = Exp
v
mkTuple [Exp]
vs = [Exp] -> Exp
Tuple [Exp]
vs
parseFunc :: ParsecT Void EntryName Identity Func
parseFunc =
[ParsecT Void EntryName Identity Func]
-> ParsecT Void EntryName Identity Func
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice
[ EntryName -> Func
FuncBuiltin (EntryName -> Func)
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity Func
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ParsecT Void EntryName Identity EntryName
"$" ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity EntryName
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void EntryName Identity EntryName
parseEntryName),
EntryName -> Func
FuncFut (EntryName -> Func)
-> ParsecT Void EntryName Identity EntryName
-> ParsecT Void EntryName Identity Func
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void EntryName Identity EntryName
parseEntryName
]
parseEntryName :: ParsecT Void EntryName Identity EntryName
parseEntryName =
(FilePath -> EntryName)
-> ParsecT Void EntryName Identity FilePath
-> ParsecT Void EntryName Identity EntryName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap FilePath -> EntryName
T.pack (ParsecT Void EntryName Identity FilePath
-> ParsecT Void EntryName Identity EntryName)
-> ParsecT Void EntryName Identity FilePath
-> ParsecT Void EntryName Identity EntryName
forall a b. (a -> b) -> a -> b
$ (:) (Char -> ShowS)
-> ParsecT Void EntryName Identity Char
-> ParsecT Void EntryName Identity ShowS
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Token EntryName -> Bool)
-> ParsecT Void EntryName Identity (Token EntryName)
forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy Char -> Bool
Token EntryName -> Bool
isAlpha ParsecT Void EntryName Identity ShowS
-> ParsecT Void EntryName Identity FilePath
-> ParsecT Void EntryName Identity FilePath
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Void EntryName Identity Char
-> ParsecT Void EntryName Identity FilePath
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many ((Token EntryName -> Bool)
-> ParsecT Void EntryName Identity (Token EntryName)
forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy Char -> Bool
Token EntryName -> Bool
constituent)
where
constituent :: Char -> Bool
constituent Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_'
constV :: t -> m Exp
constV t
v =
m Exp -> (Value -> m Exp) -> Maybe Value -> m Exp
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (FilePath -> m Exp
forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail FilePath
"invalid value read") (Exp -> m Exp
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp -> m Exp) -> (Value -> Exp) -> Value -> m Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Exp
Const) (Maybe Value -> m Exp) -> Maybe Value -> m Exp
forall a b. (a -> b) -> a -> b
$ t -> Maybe Value
forall t. PutValue t => t -> Maybe Value
V.putValue t
v
prettyFailure :: CmdFailure -> T.Text
prettyFailure :: CmdFailure -> EntryName
prettyFailure (CmdFailure [EntryName]
bef [EntryName]
aft) =
[EntryName] -> EntryName
T.unlines ([EntryName] -> EntryName) -> [EntryName] -> EntryName
forall a b. (a -> b) -> a -> b
$ [EntryName]
bef [EntryName] -> [EntryName] -> [EntryName]
forall a. [a] -> [a] -> [a]
++ [EntryName]
aft
cmdMaybe :: (MonadError T.Text m, MonadIO m) => IO (Maybe CmdFailure) -> m ()
cmdMaybe :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
IO (Maybe CmdFailure) -> m ()
cmdMaybe IO (Maybe CmdFailure)
m = m () -> (CmdFailure -> m ()) -> Maybe CmdFailure -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (EntryName -> m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m ())
-> (CmdFailure -> EntryName) -> CmdFailure -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CmdFailure -> EntryName
prettyFailure) (Maybe CmdFailure -> m ()) -> m (Maybe CmdFailure) -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Maybe CmdFailure) -> m (Maybe CmdFailure)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (Maybe CmdFailure)
m
cmdEither :: (MonadError T.Text m, MonadIO m) => IO (Either CmdFailure a) -> m a
cmdEither :: forall (m :: * -> *) a.
(MonadError EntryName m, MonadIO m) =>
IO (Either CmdFailure a) -> m a
cmdEither IO (Either CmdFailure a)
m = (CmdFailure -> m a) -> (a -> m a) -> Either CmdFailure a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (EntryName -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m a)
-> (CmdFailure -> EntryName) -> CmdFailure -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CmdFailure -> EntryName
prettyFailure) a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either CmdFailure a -> m a) -> m (Either CmdFailure a) -> m a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Either CmdFailure a) -> m (Either CmdFailure a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (Either CmdFailure a)
m
readVar :: (MonadError T.Text m, MonadIO m) => Server -> VarName -> m V.Value
readVar :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
Server -> EntryName -> m Value
readVar Server
server EntryName
v =
(EntryName -> m Value)
-> (Value -> m Value) -> Either EntryName Value -> m Value
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either EntryName -> m Value
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError Value -> m Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either EntryName Value -> m Value)
-> (IO (Either EntryName Value) -> m (Either EntryName Value))
-> IO (Either EntryName Value)
-> m Value
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< IO (Either EntryName Value) -> m (Either EntryName Value)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either EntryName Value) -> m Value)
-> IO (Either EntryName Value) -> m Value
forall a b. (a -> b) -> a -> b
$
FilePath
-> (FilePath -> Handle -> IO (Either EntryName Value))
-> IO (Either EntryName Value)
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
FilePath -> (FilePath -> Handle -> m a) -> m a
withSystemTempFile FilePath
"futhark-server-read" ((FilePath -> Handle -> IO (Either EntryName Value))
-> IO (Either EntryName Value))
-> (FilePath -> Handle -> IO (Either EntryName Value))
-> IO (Either EntryName Value)
forall a b. (a -> b) -> a -> b
$ \FilePath
tmpf Handle
tmpf_h -> do
Handle -> IO ()
hClose Handle
tmpf_h
Maybe CmdFailure
store_res <- Server -> FilePath -> [EntryName] -> IO (Maybe CmdFailure)
cmdStore Server
server FilePath
tmpf [EntryName
v]
case Maybe CmdFailure
store_res of
Just CmdFailure
err -> Either EntryName Value -> IO (Either EntryName Value)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either EntryName Value -> IO (Either EntryName Value))
-> Either EntryName Value -> IO (Either EntryName Value)
forall a b. (a -> b) -> a -> b
$ EntryName -> Either EntryName Value
forall a b. a -> Either a b
Left (EntryName -> Either EntryName Value)
-> EntryName -> Either EntryName Value
forall a b. (a -> b) -> a -> b
$ CmdFailure -> EntryName
prettyFailure CmdFailure
err
Maybe CmdFailure
Nothing -> do
ByteString
s <- FilePath -> IO ByteString
LBS.readFile FilePath
tmpf
case ByteString -> Maybe [Value]
V.readValues ByteString
s of
Just [Value
val] -> Either EntryName Value -> IO (Either EntryName Value)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either EntryName Value -> IO (Either EntryName Value))
-> Either EntryName Value -> IO (Either EntryName Value)
forall a b. (a -> b) -> a -> b
$ Value -> Either EntryName Value
forall a b. b -> Either a b
Right Value
val
Just [] -> Either EntryName Value -> IO (Either EntryName Value)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either EntryName Value -> IO (Either EntryName Value))
-> Either EntryName Value -> IO (Either EntryName Value)
forall a b. (a -> b) -> a -> b
$ EntryName -> Either EntryName Value
forall a b. a -> Either a b
Left EntryName
"Cannot read opaque value from Futhark server."
Maybe [Value]
_ -> Either EntryName Value -> IO (Either EntryName Value)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either EntryName Value -> IO (Either EntryName Value))
-> Either EntryName Value -> IO (Either EntryName Value)
forall a b. (a -> b) -> a -> b
$ EntryName -> Either EntryName Value
forall a b. a -> Either a b
Left EntryName
"Invalid data file produced by Futhark server."
writeVar :: (MonadError T.Text m, MonadIO m) => Server -> VarName -> V.Value -> m ()
writeVar :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
Server -> EntryName -> Value -> m ()
writeVar Server
server EntryName
v Value
val =
IO (Maybe CmdFailure) -> m ()
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
IO (Maybe CmdFailure) -> m ()
cmdMaybe (IO (Maybe CmdFailure) -> m ())
-> ((FilePath -> Handle -> IO (Maybe CmdFailure))
-> IO (Maybe CmdFailure))
-> (FilePath -> Handle -> IO (Maybe CmdFailure))
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Maybe CmdFailure) -> IO (Maybe CmdFailure)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe CmdFailure) -> IO (Maybe CmdFailure))
-> ((FilePath -> Handle -> IO (Maybe CmdFailure))
-> IO (Maybe CmdFailure))
-> (FilePath -> Handle -> IO (Maybe CmdFailure))
-> IO (Maybe CmdFailure)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> (FilePath -> Handle -> IO (Maybe CmdFailure))
-> IO (Maybe CmdFailure)
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
FilePath -> (FilePath -> Handle -> m a) -> m a
withSystemTempFile FilePath
"futhark-server-write" ((FilePath -> Handle -> IO (Maybe CmdFailure)) -> m ())
-> (FilePath -> Handle -> IO (Maybe CmdFailure)) -> m ()
forall a b. (a -> b) -> a -> b
$ \FilePath
tmpf Handle
tmpf_h -> do
Handle -> ByteString -> IO ()
LBS.hPutStr Handle
tmpf_h (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Value -> ByteString
forall a. Binary a => a -> ByteString
Bin.encode Value
val
Handle -> IO ()
hClose Handle
tmpf_h
let V.ValueType [Int]
dims PrimType
t = Value -> ValueType
V.valueType Value
val
t' :: EntryName
t' = [EntryName] -> EntryName
forall a. Monoid a => [a] -> a
mconcat ((Int -> EntryName) -> [Int] -> [EntryName]
forall a b. (a -> b) -> [a] -> [b]
map (EntryName -> Int -> EntryName
forall a b. a -> b -> a
const EntryName
"[]") [Int]
dims) EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> PrimType -> EntryName
forall a. Pretty a => a -> EntryName
prettyText PrimType
t
Server
-> FilePath -> [(EntryName, EntryName)] -> IO (Maybe CmdFailure)
cmdRestore Server
server FilePath
tmpf [(EntryName
v, EntryName
t')]
data ScriptValue v
= SValue TypeName v
|
SFun EntryName [TypeName] [TypeName] [ScriptValue v]
instance Functor ScriptValue where
fmap :: forall a b. (a -> b) -> ScriptValue a -> ScriptValue b
fmap = (a -> b) -> ScriptValue a -> ScriptValue b
forall (t :: * -> *) a b. Traversable t => (a -> b) -> t a -> t b
fmapDefault
instance Foldable ScriptValue where
foldMap :: forall m a. Monoid m => (a -> m) -> ScriptValue a -> m
foldMap = (a -> m) -> ScriptValue a -> m
forall (t :: * -> *) m a.
(Traversable t, Monoid m) =>
(a -> m) -> t a -> m
foldMapDefault
instance Traversable ScriptValue where
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ScriptValue a -> f (ScriptValue b)
traverse a -> f b
f (SValue EntryName
t a
v) = EntryName -> b -> ScriptValue b
forall v. EntryName -> v -> ScriptValue v
SValue EntryName
t (b -> ScriptValue b) -> f b -> f (ScriptValue b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
v
traverse a -> f b
f (SFun EntryName
fname [EntryName]
ins [EntryName]
outs [ScriptValue a]
vs) =
EntryName
-> [EntryName] -> [EntryName] -> [ScriptValue b] -> ScriptValue b
forall v.
EntryName
-> [EntryName] -> [EntryName] -> [ScriptValue v] -> ScriptValue v
SFun EntryName
fname [EntryName]
ins [EntryName]
outs ([ScriptValue b] -> ScriptValue b)
-> f [ScriptValue b] -> f (ScriptValue b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ScriptValue a -> f (ScriptValue b))
-> [ScriptValue a] -> f [ScriptValue b]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((a -> f b) -> ScriptValue a -> f (ScriptValue b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f) [ScriptValue a]
vs
data ScriptValueType
= STValue TypeName
|
STFun [TypeName] [TypeName]
deriving (ScriptValueType -> ScriptValueType -> Bool
(ScriptValueType -> ScriptValueType -> Bool)
-> (ScriptValueType -> ScriptValueType -> Bool)
-> Eq ScriptValueType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ScriptValueType -> ScriptValueType -> Bool
$c/= :: ScriptValueType -> ScriptValueType -> Bool
== :: ScriptValueType -> ScriptValueType -> Bool
$c== :: ScriptValueType -> ScriptValueType -> Bool
Eq, Int -> ScriptValueType -> ShowS
[ScriptValueType] -> ShowS
ScriptValueType -> FilePath
(Int -> ScriptValueType -> ShowS)
-> (ScriptValueType -> FilePath)
-> ([ScriptValueType] -> ShowS)
-> Show ScriptValueType
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [ScriptValueType] -> ShowS
$cshowList :: [ScriptValueType] -> ShowS
show :: ScriptValueType -> FilePath
$cshow :: ScriptValueType -> FilePath
showsPrec :: Int -> ScriptValueType -> ShowS
$cshowsPrec :: Int -> ScriptValueType -> ShowS
Show)
instance Pretty ScriptValueType where
ppr :: ScriptValueType -> Doc
ppr (STValue EntryName
t) = EntryName -> Doc
forall a. Pretty a => a -> Doc
ppr EntryName
t
ppr (STFun [EntryName]
ins [EntryName]
outs) =
[Doc] -> Doc
spread ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ Doc -> [Doc] -> [Doc]
forall a. a -> [a] -> [a]
intersperse Doc
"->" ((EntryName -> Doc) -> [EntryName] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map EntryName -> Doc
forall a. Pretty a => a -> Doc
ppr [EntryName]
ins [Doc] -> [Doc] -> [Doc]
forall a. [a] -> [a] -> [a]
++ [Doc
outs'])
where
outs' :: Doc
outs' = case [EntryName]
outs of
[EntryName
out] -> EntryName -> Doc
strictText EntryName
out
[EntryName]
_ -> Doc -> Doc
parens (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
commasep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (EntryName -> Doc) -> [EntryName] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map EntryName -> Doc
strictText [EntryName]
outs
data ValOrVar = VVal V.Value | VVar VarName
deriving (Int -> ValOrVar -> ShowS
[ValOrVar] -> ShowS
ValOrVar -> FilePath
(Int -> ValOrVar -> ShowS)
-> (ValOrVar -> FilePath) -> ([ValOrVar] -> ShowS) -> Show ValOrVar
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [ValOrVar] -> ShowS
$cshowList :: [ValOrVar] -> ShowS
show :: ValOrVar -> FilePath
$cshow :: ValOrVar -> FilePath
showsPrec :: Int -> ValOrVar -> ShowS
$cshowsPrec :: Int -> ValOrVar -> ShowS
Show)
type ExpValue = V.Compound (ScriptValue ValOrVar)
scriptValueType :: ScriptValue v -> ScriptValueType
scriptValueType :: forall v. ScriptValue v -> ScriptValueType
scriptValueType (SValue EntryName
t v
_) = EntryName -> ScriptValueType
STValue EntryName
t
scriptValueType (SFun EntryName
_ [EntryName]
ins [EntryName]
outs [ScriptValue v]
_) = [EntryName] -> [EntryName] -> ScriptValueType
STFun [EntryName]
ins [EntryName]
outs
serverVarsInValue :: ExpValue -> S.Set VarName
serverVarsInValue :: ExpValue -> Set EntryName
serverVarsInValue = [EntryName] -> Set EntryName
forall a. Ord a => [a] -> Set a
S.fromList ([EntryName] -> Set EntryName)
-> (ExpValue -> [EntryName]) -> ExpValue -> Set EntryName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScriptValue ValOrVar -> [EntryName])
-> [ScriptValue ValOrVar] -> [EntryName]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ScriptValue ValOrVar -> [EntryName]
isVar ([ScriptValue ValOrVar] -> [EntryName])
-> (ExpValue -> [ScriptValue ValOrVar]) -> ExpValue -> [EntryName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExpValue -> [ScriptValue ValOrVar]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
where
isVar :: ScriptValue ValOrVar -> [EntryName]
isVar (SValue EntryName
_ (VVar EntryName
x)) = [EntryName
x]
isVar (SValue EntryName
_ (VVal Value
_)) = []
isVar (SFun EntryName
_ [EntryName]
_ [EntryName]
_ [ScriptValue ValOrVar]
closure) = (ScriptValue ValOrVar -> [EntryName])
-> [ScriptValue ValOrVar] -> [EntryName]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ScriptValue ValOrVar -> [EntryName]
isVar ([ScriptValue ValOrVar] -> [EntryName])
-> [ScriptValue ValOrVar] -> [EntryName]
forall a b. (a -> b) -> a -> b
$ [ScriptValue ValOrVar] -> [ScriptValue ValOrVar]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList [ScriptValue ValOrVar]
closure
valueToExp :: ExpValue -> Exp
valueToExp :: ExpValue -> Exp
valueToExp (V.ValueAtom (SValue EntryName
t (VVar EntryName
v))) =
EntryName -> EntryName -> Exp
ServerVar EntryName
t EntryName
v
valueToExp (V.ValueAtom (SValue EntryName
_ (VVal Value
v))) =
Value -> Exp
Const Value
v
valueToExp (V.ValueAtom (SFun EntryName
fname [EntryName]
_ [EntryName]
_ [ScriptValue ValOrVar]
closure)) =
Func -> [Exp] -> Exp
Call (EntryName -> Func
FuncFut EntryName
fname) ([Exp] -> Exp) -> [Exp] -> Exp
forall a b. (a -> b) -> a -> b
$ (ScriptValue ValOrVar -> Exp) -> [ScriptValue ValOrVar] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map (ExpValue -> Exp
valueToExp (ExpValue -> Exp)
-> (ScriptValue ValOrVar -> ExpValue)
-> ScriptValue ValOrVar
-> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScriptValue ValOrVar -> ExpValue
forall v. v -> Compound v
V.ValueAtom) [ScriptValue ValOrVar]
closure
valueToExp (V.ValueRecord Map EntryName ExpValue
fs) =
[(EntryName, Exp)] -> Exp
Record ([(EntryName, Exp)] -> Exp) -> [(EntryName, Exp)] -> Exp
forall a b. (a -> b) -> a -> b
$ Map EntryName Exp -> [(EntryName, Exp)]
forall k a. Map k a -> [(k, a)]
M.toList (Map EntryName Exp -> [(EntryName, Exp)])
-> Map EntryName Exp -> [(EntryName, Exp)]
forall a b. (a -> b) -> a -> b
$ (ExpValue -> Exp) -> Map EntryName ExpValue -> Map EntryName Exp
forall a b k. (a -> b) -> Map k a -> Map k b
M.map ExpValue -> Exp
valueToExp Map EntryName ExpValue
fs
valueToExp (V.ValueTuple [ExpValue]
fs) =
[Exp] -> Exp
Tuple ([Exp] -> Exp) -> [Exp] -> Exp
forall a b. (a -> b) -> a -> b
$ (ExpValue -> Exp) -> [ExpValue] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map ExpValue -> Exp
valueToExp [ExpValue]
fs
type EvalBuiltin m = T.Text -> [V.CompoundValue] -> m V.CompoundValue
evalExp ::
forall m.
(MonadError T.Text m, MonadIO m) =>
EvalBuiltin m ->
ScriptServer ->
Exp ->
m ExpValue
evalExp :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
EvalBuiltin m -> ScriptServer -> Exp -> m ExpValue
evalExp EvalBuiltin m
builtin (ScriptServer Server
server IORef Int
counter) Exp
top_level_e = do
IORef [EntryName]
vars <- IO (IORef [EntryName]) -> m (IORef [EntryName])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef [EntryName]) -> m (IORef [EntryName]))
-> IO (IORef [EntryName]) -> m (IORef [EntryName])
forall a b. (a -> b) -> a -> b
$ [EntryName] -> IO (IORef [EntryName])
forall a. a -> IO (IORef a)
newIORef []
let newVar :: EntryName -> m EntryName
newVar EntryName
base = IO EntryName -> m EntryName
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO EntryName -> m EntryName) -> IO EntryName -> m EntryName
forall a b. (a -> b) -> a -> b
$ do
Int
x <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
counter
IORef Int -> (Int -> Int) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef Int
counter (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
let v :: EntryName
v = EntryName
base EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> Int -> EntryName
forall a. Pretty a => a -> EntryName
prettyText Int
x
IORef [EntryName] -> ([EntryName] -> [EntryName]) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef [EntryName]
vars (EntryName
v EntryName -> [EntryName] -> [EntryName]
forall a. a -> [a] -> [a]
:)
EntryName -> IO EntryName
forall (f :: * -> *) a. Applicative f => a -> f a
pure EntryName
v
toVal :: ValOrVar -> m V.Value
toVal :: ValOrVar -> m Value
toVal (VVal Value
v) = Value -> m Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure Value
v
toVal (VVar EntryName
v) = Server -> EntryName -> m Value
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
Server -> EntryName -> m Value
readVar Server
server EntryName
v
toVar :: ValOrVar -> m VarName
toVar :: ValOrVar -> m EntryName
toVar (VVar EntryName
v) = EntryName -> m EntryName
forall (f :: * -> *) a. Applicative f => a -> f a
pure EntryName
v
toVar (VVal Value
val) = do
EntryName
v <- EntryName -> m EntryName
forall {m :: * -> *}. MonadIO m => EntryName -> m EntryName
newVar EntryName
"const"
Server -> EntryName -> Value -> m ()
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
Server -> EntryName -> Value -> m ()
writeVar Server
server EntryName
v Value
val
EntryName -> m EntryName
forall (f :: * -> *) a. Applicative f => a -> f a
pure EntryName
v
scriptValueToValOrVar :: ScriptValue a -> m a
scriptValueToValOrVar (SFun EntryName
f [EntryName]
_ [EntryName]
_ [ScriptValue a]
_) =
EntryName -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m a) -> EntryName -> m a
forall a b. (a -> b) -> a -> b
$ EntryName
"Function " EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
f EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
" not fully applied."
scriptValueToValOrVar (SValue EntryName
_ a
v) =
a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
v
scriptValueToVal :: ScriptValue ValOrVar -> m V.Value
scriptValueToVal :: ScriptValue ValOrVar -> m Value
scriptValueToVal = ValOrVar -> m Value
toVal (ValOrVar -> m Value)
-> (ScriptValue ValOrVar -> m ValOrVar)
-> ScriptValue ValOrVar
-> m Value
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< ScriptValue ValOrVar -> m ValOrVar
forall {m :: * -> *} {a}.
MonadError EntryName m =>
ScriptValue a -> m a
scriptValueToValOrVar
scriptValueToVar :: ScriptValue ValOrVar -> m VarName
scriptValueToVar :: ScriptValue ValOrVar -> m EntryName
scriptValueToVar = ValOrVar -> m EntryName
toVar (ValOrVar -> m EntryName)
-> (ScriptValue ValOrVar -> m ValOrVar)
-> ScriptValue ValOrVar
-> m EntryName
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< ScriptValue ValOrVar -> m ValOrVar
forall {m :: * -> *} {a}.
MonadError EntryName m =>
ScriptValue a -> m a
scriptValueToValOrVar
interValToVal :: ExpValue -> m V.CompoundValue
interValToVal :: ExpValue -> m CompoundValue
interValToVal = (ScriptValue ValOrVar -> m Value) -> ExpValue -> m CompoundValue
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ScriptValue ValOrVar -> m Value
scriptValueToVal
interValToVar :: ExpValue -> m VarName
interValToVar :: ExpValue -> m EntryName
interValToVar (V.ValueAtom ScriptValue ValOrVar
v) = ScriptValue ValOrVar -> m EntryName
scriptValueToVar ScriptValue ValOrVar
v
interValToVar ExpValue
_ = EntryName -> m EntryName
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError EntryName
"Unexpected tuple or record value."
valToInterVal :: V.CompoundValue -> ExpValue
valToInterVal :: CompoundValue -> ExpValue
valToInterVal = (Value -> ScriptValue ValOrVar) -> CompoundValue -> ExpValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Value -> ScriptValue ValOrVar) -> CompoundValue -> ExpValue)
-> (Value -> ScriptValue ValOrVar) -> CompoundValue -> ExpValue
forall a b. (a -> b) -> a -> b
$ \Value
v ->
EntryName -> ValOrVar -> ScriptValue ValOrVar
forall v. EntryName -> v -> ScriptValue v
SValue (ValueType -> EntryName
V.prettyValueTypeNoDims (Value -> ValueType
V.valueType Value
v)) (ValOrVar -> ScriptValue ValOrVar)
-> ValOrVar -> ScriptValue ValOrVar
forall a b. (a -> b) -> a -> b
$ Value -> ValOrVar
VVal Value
v
simpleType :: Compound ScriptValueType -> Bool
simpleType (V.ValueAtom (STValue EntryName
_)) = Bool
True
simpleType Compound ScriptValueType
_ = Bool
False
evalExp' :: Exp -> m ExpValue
evalExp' :: Exp -> m ExpValue
evalExp' (ServerVar EntryName
t EntryName
v) =
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExpValue -> m ExpValue) -> ExpValue -> m ExpValue
forall a b. (a -> b) -> a -> b
$ ScriptValue ValOrVar -> ExpValue
forall v. v -> Compound v
V.ValueAtom (ScriptValue ValOrVar -> ExpValue)
-> ScriptValue ValOrVar -> ExpValue
forall a b. (a -> b) -> a -> b
$ EntryName -> ValOrVar -> ScriptValue ValOrVar
forall v. EntryName -> v -> ScriptValue v
SValue EntryName
t (ValOrVar -> ScriptValue ValOrVar)
-> ValOrVar -> ScriptValue ValOrVar
forall a b. (a -> b) -> a -> b
$ EntryName -> ValOrVar
VVar EntryName
v
evalExp' (Call (FuncBuiltin EntryName
name) [Exp]
es) = do
CompoundValue
v <- EvalBuiltin m
builtin EntryName
name ([CompoundValue] -> m CompoundValue)
-> m [CompoundValue] -> m CompoundValue
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Exp -> m CompoundValue) -> [Exp] -> m [CompoundValue]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (ExpValue -> m CompoundValue
interValToVal (ExpValue -> m CompoundValue)
-> (Exp -> m ExpValue) -> Exp -> m CompoundValue
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Exp -> m ExpValue
evalExp') [Exp]
es
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExpValue -> m ExpValue) -> ExpValue -> m ExpValue
forall a b. (a -> b) -> a -> b
$ CompoundValue -> ExpValue
valToInterVal CompoundValue
v
evalExp' (Call (FuncFut EntryName
name) [Exp]
es) = do
[EntryName]
in_types <- IO (Either CmdFailure [EntryName]) -> m [EntryName]
forall (m :: * -> *) a.
(MonadError EntryName m, MonadIO m) =>
IO (Either CmdFailure a) -> m a
cmdEither (IO (Either CmdFailure [EntryName]) -> m [EntryName])
-> IO (Either CmdFailure [EntryName]) -> m [EntryName]
forall a b. (a -> b) -> a -> b
$ Server -> EntryName -> IO (Either CmdFailure [EntryName])
cmdInputs Server
server EntryName
name
[EntryName]
out_types <- IO (Either CmdFailure [EntryName]) -> m [EntryName]
forall (m :: * -> *) a.
(MonadError EntryName m, MonadIO m) =>
IO (Either CmdFailure a) -> m a
cmdEither (IO (Either CmdFailure [EntryName]) -> m [EntryName])
-> IO (Either CmdFailure [EntryName]) -> m [EntryName]
forall a b. (a -> b) -> a -> b
$ Server -> EntryName -> IO (Either CmdFailure [EntryName])
cmdOutputs Server
server EntryName
name
[ExpValue]
es' <- (Exp -> m ExpValue) -> [Exp] -> m [ExpValue]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Exp -> m ExpValue
evalExp' [Exp]
es
let es_types :: [Compound ScriptValueType]
es_types = (ExpValue -> Compound ScriptValueType)
-> [ExpValue] -> [Compound ScriptValueType]
forall a b. (a -> b) -> [a] -> [b]
map ((ScriptValue ValOrVar -> ScriptValueType)
-> ExpValue -> Compound ScriptValueType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ScriptValue ValOrVar -> ScriptValueType
forall v. ScriptValue v -> ScriptValueType
scriptValueType) [ExpValue]
es'
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((Compound ScriptValueType -> Bool)
-> [Compound ScriptValueType] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Compound ScriptValueType -> Bool
simpleType [Compound ScriptValueType]
es_types) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
EntryName -> m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m ()) -> EntryName -> m ()
forall a b. (a -> b) -> a -> b
$
EntryName
"Literate Futhark does not support passing script-constructed records, tuples, or functions to entry points.\n"
EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
"Create a Futhark wrapper function."
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> [Bool] -> Bool
forall a b. (a -> b) -> a -> b
$ (Compound ScriptValueType -> Compound ScriptValueType -> Bool)
-> [Compound ScriptValueType]
-> [Compound ScriptValueType]
-> [Bool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Compound ScriptValueType -> Compound ScriptValueType -> Bool
forall a. Eq a => a -> a -> Bool
(==) [Compound ScriptValueType]
es_types ((EntryName -> Compound ScriptValueType)
-> [EntryName] -> [Compound ScriptValueType]
forall a b. (a -> b) -> [a] -> [b]
map (ScriptValueType -> Compound ScriptValueType
forall v. v -> Compound v
V.ValueAtom (ScriptValueType -> Compound ScriptValueType)
-> (EntryName -> ScriptValueType)
-> EntryName
-> Compound ScriptValueType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EntryName -> ScriptValueType
STValue) [EntryName]
in_types)) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
EntryName -> m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m ()) -> EntryName -> m ()
forall a b. (a -> b) -> a -> b
$
EntryName
"Function \"" EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
name EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
"\" expects arguments of types:\n"
EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> Compound (Compound EntryName) -> EntryName
forall a. Pretty a => a -> EntryName
prettyText ([Compound EntryName] -> Compound (Compound EntryName)
forall v. [v] -> Compound v
V.mkCompound ([Compound EntryName] -> Compound (Compound EntryName))
-> [Compound EntryName] -> Compound (Compound EntryName)
forall a b. (a -> b) -> a -> b
$ (EntryName -> Compound EntryName)
-> [EntryName] -> [Compound EntryName]
forall a b. (a -> b) -> [a] -> [b]
map EntryName -> Compound EntryName
forall v. v -> Compound v
V.ValueAtom [EntryName]
in_types)
EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
"\nBut called with arguments of types:\n"
EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> Compound (Compound (Compound ScriptValueType)) -> EntryName
forall a. Pretty a => a -> EntryName
prettyText ([Compound (Compound ScriptValueType)]
-> Compound (Compound (Compound ScriptValueType))
forall v. [v] -> Compound v
V.mkCompound ([Compound (Compound ScriptValueType)]
-> Compound (Compound (Compound ScriptValueType)))
-> [Compound (Compound ScriptValueType)]
-> Compound (Compound (Compound ScriptValueType))
forall a b. (a -> b) -> a -> b
$ (Compound ScriptValueType -> Compound (Compound ScriptValueType))
-> [Compound ScriptValueType]
-> [Compound (Compound ScriptValueType)]
forall a b. (a -> b) -> [a] -> [b]
map Compound ScriptValueType -> Compound (Compound ScriptValueType)
forall v. v -> Compound v
V.ValueAtom [Compound ScriptValueType]
es_types)
[EntryName]
ins <- (Exp -> m EntryName) -> [Exp] -> m [EntryName]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (ExpValue -> m EntryName
interValToVar (ExpValue -> m EntryName)
-> (Exp -> m ExpValue) -> Exp -> m EntryName
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Exp -> m ExpValue
evalExp') [Exp]
es
if [EntryName] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EntryName]
in_types Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [EntryName] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EntryName]
ins
then do
[EntryName]
outs <- Int -> m EntryName -> m [EntryName]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([EntryName] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EntryName]
out_types) (m EntryName -> m [EntryName]) -> m EntryName -> m [EntryName]
forall a b. (a -> b) -> a -> b
$ EntryName -> m EntryName
forall {m :: * -> *}. MonadIO m => EntryName -> m EntryName
newVar EntryName
"out"
m [EntryName] -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m [EntryName] -> m ()) -> m [EntryName] -> m ()
forall a b. (a -> b) -> a -> b
$ IO (Either CmdFailure [EntryName]) -> m [EntryName]
forall (m :: * -> *) a.
(MonadError EntryName m, MonadIO m) =>
IO (Either CmdFailure a) -> m a
cmdEither (IO (Either CmdFailure [EntryName]) -> m [EntryName])
-> IO (Either CmdFailure [EntryName]) -> m [EntryName]
forall a b. (a -> b) -> a -> b
$ Server
-> EntryName
-> [EntryName]
-> [EntryName]
-> IO (Either CmdFailure [EntryName])
cmdCall Server
server EntryName
name [EntryName]
outs [EntryName]
ins
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExpValue -> m ExpValue) -> ExpValue -> m ExpValue
forall a b. (a -> b) -> a -> b
$ [ScriptValue ValOrVar] -> ExpValue
forall v. [v] -> Compound v
V.mkCompound ([ScriptValue ValOrVar] -> ExpValue)
-> [ScriptValue ValOrVar] -> ExpValue
forall a b. (a -> b) -> a -> b
$ (EntryName -> ValOrVar -> ScriptValue ValOrVar)
-> [EntryName] -> [ValOrVar] -> [ScriptValue ValOrVar]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith EntryName -> ValOrVar -> ScriptValue ValOrVar
forall v. EntryName -> v -> ScriptValue v
SValue [EntryName]
out_types ([ValOrVar] -> [ScriptValue ValOrVar])
-> [ValOrVar] -> [ScriptValue ValOrVar]
forall a b. (a -> b) -> a -> b
$ (EntryName -> ValOrVar) -> [EntryName] -> [ValOrVar]
forall a b. (a -> b) -> [a] -> [b]
map EntryName -> ValOrVar
VVar [EntryName]
outs
else
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExpValue -> m ExpValue)
-> ([ScriptValue ValOrVar] -> ExpValue)
-> [ScriptValue ValOrVar]
-> m ExpValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScriptValue ValOrVar -> ExpValue
forall v. v -> Compound v
V.ValueAtom (ScriptValue ValOrVar -> ExpValue)
-> ([ScriptValue ValOrVar] -> ScriptValue ValOrVar)
-> [ScriptValue ValOrVar]
-> ExpValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EntryName
-> [EntryName]
-> [EntryName]
-> [ScriptValue ValOrVar]
-> ScriptValue ValOrVar
forall v.
EntryName
-> [EntryName] -> [EntryName] -> [ScriptValue v] -> ScriptValue v
SFun EntryName
name [EntryName]
in_types [EntryName]
out_types ([ScriptValue ValOrVar] -> m ExpValue)
-> [ScriptValue ValOrVar] -> m ExpValue
forall a b. (a -> b) -> a -> b
$
(EntryName -> ValOrVar -> ScriptValue ValOrVar)
-> [EntryName] -> [ValOrVar] -> [ScriptValue ValOrVar]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith EntryName -> ValOrVar -> ScriptValue ValOrVar
forall v. EntryName -> v -> ScriptValue v
SValue [EntryName]
in_types ([ValOrVar] -> [ScriptValue ValOrVar])
-> [ValOrVar] -> [ScriptValue ValOrVar]
forall a b. (a -> b) -> a -> b
$ (EntryName -> ValOrVar) -> [EntryName] -> [ValOrVar]
forall a b. (a -> b) -> [a] -> [b]
map EntryName -> ValOrVar
VVar [EntryName]
ins
evalExp' (StringLit EntryName
s) =
case EntryName -> Maybe Value
forall t. PutValue t => t -> Maybe Value
V.putValue EntryName
s of
Just Value
s' ->
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExpValue -> m ExpValue) -> ExpValue -> m ExpValue
forall a b. (a -> b) -> a -> b
$ ScriptValue ValOrVar -> ExpValue
forall v. v -> Compound v
V.ValueAtom (ScriptValue ValOrVar -> ExpValue)
-> ScriptValue ValOrVar -> ExpValue
forall a b. (a -> b) -> a -> b
$ EntryName -> ValOrVar -> ScriptValue ValOrVar
forall v. EntryName -> v -> ScriptValue v
SValue (ValueType -> EntryName
forall a. Pretty a => a -> EntryName
prettyText (Value -> ValueType
V.valueType Value
s')) (ValOrVar -> ScriptValue ValOrVar)
-> ValOrVar -> ScriptValue ValOrVar
forall a b. (a -> b) -> a -> b
$ Value -> ValOrVar
VVal Value
s'
Maybe Value
Nothing -> FilePath -> m ExpValue
forall a. HasCallStack => FilePath -> a
error (FilePath -> m ExpValue) -> FilePath -> m ExpValue
forall a b. (a -> b) -> a -> b
$ FilePath
"Unable to write value " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ EntryName -> FilePath
forall a. Pretty a => a -> FilePath
pretty EntryName
s
evalExp' (Const Value
val) =
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExpValue -> m ExpValue) -> ExpValue -> m ExpValue
forall a b. (a -> b) -> a -> b
$ ScriptValue ValOrVar -> ExpValue
forall v. v -> Compound v
V.ValueAtom (ScriptValue ValOrVar -> ExpValue)
-> ScriptValue ValOrVar -> ExpValue
forall a b. (a -> b) -> a -> b
$ EntryName -> ValOrVar -> ScriptValue ValOrVar
forall v. EntryName -> v -> ScriptValue v
SValue (ValueType -> EntryName
V.prettyValueTypeNoDims (Value -> ValueType
V.valueType Value
val)) (ValOrVar -> ScriptValue ValOrVar)
-> ValOrVar -> ScriptValue ValOrVar
forall a b. (a -> b) -> a -> b
$ Value -> ValOrVar
VVal Value
val
evalExp' (Tuple [Exp]
es) =
[ExpValue] -> ExpValue
forall v. [Compound v] -> Compound v
V.ValueTuple ([ExpValue] -> ExpValue) -> m [ExpValue] -> m ExpValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Exp -> m ExpValue) -> [Exp] -> m [ExpValue]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Exp -> m ExpValue
evalExp' [Exp]
es
evalExp' e :: Exp
e@(Record [(EntryName, Exp)]
m) = do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([EntryName] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([EntryName] -> [EntryName]
forall a. Ord a => [a] -> [a]
nubOrd (((EntryName, Exp) -> EntryName)
-> [(EntryName, Exp)] -> [EntryName]
forall a b. (a -> b) -> [a] -> [b]
map (EntryName, Exp) -> EntryName
forall a b. (a, b) -> a
fst [(EntryName, Exp)]
m)) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [EntryName] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (((EntryName, Exp) -> EntryName)
-> [(EntryName, Exp)] -> [EntryName]
forall a b. (a -> b) -> [a] -> [b]
map (EntryName, Exp) -> EntryName
forall a b. (a, b) -> a
fst [(EntryName, Exp)]
m)) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
EntryName -> m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m ()) -> EntryName -> m ()
forall a b. (a -> b) -> a -> b
$ EntryName
"Record " EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> Exp -> EntryName
forall a. Pretty a => a -> EntryName
prettyText Exp
e EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
" has duplicate fields."
Map EntryName ExpValue -> ExpValue
forall v. Map EntryName (Compound v) -> Compound v
V.ValueRecord (Map EntryName ExpValue -> ExpValue)
-> m (Map EntryName ExpValue) -> m ExpValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Exp -> m ExpValue)
-> Map EntryName Exp -> m (Map EntryName ExpValue)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Exp -> m ExpValue
evalExp' ([(EntryName, Exp)] -> Map EntryName Exp
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(EntryName, Exp)]
m)
let freeNonresultVars :: ExpValue -> m ExpValue
freeNonresultVars ExpValue
v = do
let v_vars :: Set EntryName
v_vars = ExpValue -> Set EntryName
serverVarsInValue ExpValue
v
[EntryName]
to_free <- IO [EntryName] -> m [EntryName]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [EntryName] -> m [EntryName])
-> IO [EntryName] -> m [EntryName]
forall a b. (a -> b) -> a -> b
$ (EntryName -> Bool) -> [EntryName] -> [EntryName]
forall a. (a -> Bool) -> [a] -> [a]
filter (EntryName -> Set EntryName -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.notMember` Set EntryName
v_vars) ([EntryName] -> [EntryName]) -> IO [EntryName] -> IO [EntryName]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef [EntryName] -> IO [EntryName]
forall a. IORef a -> IO a
readIORef IORef [EntryName]
vars
IO (Maybe CmdFailure) -> m ()
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
IO (Maybe CmdFailure) -> m ()
cmdMaybe (IO (Maybe CmdFailure) -> m ()) -> IO (Maybe CmdFailure) -> m ()
forall a b. (a -> b) -> a -> b
$ Server -> [EntryName] -> IO (Maybe CmdFailure)
cmdFree Server
server [EntryName]
to_free
ExpValue -> m ExpValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure ExpValue
v
freeVarsOnError :: e -> m b
freeVarsOnError e
e = do
m (Maybe CmdFailure) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Maybe CmdFailure) -> m ()) -> m (Maybe CmdFailure) -> m ()
forall a b. (a -> b) -> a -> b
$ IO (Maybe CmdFailure) -> m (Maybe CmdFailure)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe CmdFailure) -> m (Maybe CmdFailure))
-> IO (Maybe CmdFailure) -> m (Maybe CmdFailure)
forall a b. (a -> b) -> a -> b
$ Server -> [EntryName] -> IO (Maybe CmdFailure)
cmdFree Server
server ([EntryName] -> IO (Maybe CmdFailure))
-> IO [EntryName] -> IO (Maybe CmdFailure)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef [EntryName] -> IO [EntryName]
forall a. IORef a -> IO a
readIORef IORef [EntryName]
vars
e -> m b
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError e
e
(ExpValue -> m ExpValue
forall {m :: * -> *}.
(MonadIO m, MonadError EntryName m) =>
ExpValue -> m ExpValue
freeNonresultVars (ExpValue -> m ExpValue) -> m ExpValue -> m ExpValue
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Exp -> m ExpValue
evalExp' Exp
top_level_e) m ExpValue -> (EntryName -> m ExpValue) -> m ExpValue
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` EntryName -> m ExpValue
forall {m :: * -> *} {e} {b}.
(MonadIO m, MonadError e m) =>
e -> m b
freeVarsOnError
getExpValue ::
(MonadError T.Text m, MonadIO m) => ScriptServer -> ExpValue -> m V.CompoundValue
getExpValue :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
ScriptServer -> ExpValue -> m CompoundValue
getExpValue (ScriptServer Server
server IORef Int
_) ExpValue
e =
(ScriptValue Value -> m Value)
-> Compound (ScriptValue Value) -> m CompoundValue
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ScriptValue Value -> m Value
forall {m :: * -> *} {a}.
MonadError EntryName m =>
ScriptValue a -> m a
toGround (Compound (ScriptValue Value) -> m CompoundValue)
-> m (Compound (ScriptValue Value)) -> m CompoundValue
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (ScriptValue ValOrVar -> m (ScriptValue Value))
-> ExpValue -> m (Compound (ScriptValue Value))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((ValOrVar -> m Value)
-> ScriptValue ValOrVar -> m (ScriptValue Value)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ValOrVar -> m Value
forall {m :: * -> *}.
(MonadError EntryName m, MonadIO m) =>
ValOrVar -> m Value
onLeaf) ExpValue
e
where
onLeaf :: ValOrVar -> m Value
onLeaf (VVar EntryName
v) = Server -> EntryName -> m Value
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
Server -> EntryName -> m Value
readVar Server
server EntryName
v
onLeaf (VVal Value
v) = Value -> m Value
forall (f :: * -> *) a. Applicative f => a -> f a
pure Value
v
toGround :: ScriptValue a -> m a
toGround (SFun EntryName
fname [EntryName]
_ [EntryName]
_ [ScriptValue a]
_) =
EntryName -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (EntryName -> m a) -> EntryName -> m a
forall a b. (a -> b) -> a -> b
$ EntryName
"Function " EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
fname EntryName -> EntryName -> EntryName
forall a. Semigroup a => a -> a -> a
<> EntryName
" not fully applied."
toGround (SValue EntryName
_ a
v) = a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
v
evalExpToGround ::
(MonadError T.Text m, MonadIO m) =>
EvalBuiltin m ->
ScriptServer ->
Exp ->
m (Either (V.Compound ScriptValueType) V.CompoundValue)
evalExpToGround :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
EvalBuiltin m
-> ScriptServer
-> Exp
-> m (Either (Compound ScriptValueType) CompoundValue)
evalExpToGround EvalBuiltin m
builtin ScriptServer
server Exp
e = do
ExpValue
v <- EvalBuiltin m -> ScriptServer -> Exp -> m ExpValue
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
EvalBuiltin m -> ScriptServer -> Exp -> m ExpValue
evalExp EvalBuiltin m
builtin ScriptServer
server Exp
e
(CompoundValue -> Either (Compound ScriptValueType) CompoundValue
forall a b. b -> Either a b
Right (CompoundValue -> Either (Compound ScriptValueType) CompoundValue)
-> m CompoundValue
-> m (Either (Compound ScriptValueType) CompoundValue)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ScriptServer -> ExpValue -> m CompoundValue
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
ScriptServer -> ExpValue -> m CompoundValue
getExpValue ScriptServer
server ExpValue
v)
m (Either (Compound ScriptValueType) CompoundValue)
-> (EntryName
-> m (Either (Compound ScriptValueType) CompoundValue))
-> m (Either (Compound ScriptValueType) CompoundValue)
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` m (Either (Compound ScriptValueType) CompoundValue)
-> EntryName -> m (Either (Compound ScriptValueType) CompoundValue)
forall a b. a -> b -> a
const (Either (Compound ScriptValueType) CompoundValue
-> m (Either (Compound ScriptValueType) CompoundValue)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either (Compound ScriptValueType) CompoundValue
-> m (Either (Compound ScriptValueType) CompoundValue))
-> Either (Compound ScriptValueType) CompoundValue
-> m (Either (Compound ScriptValueType) CompoundValue)
forall a b. (a -> b) -> a -> b
$ Compound ScriptValueType
-> Either (Compound ScriptValueType) CompoundValue
forall a b. a -> Either a b
Left (Compound ScriptValueType
-> Either (Compound ScriptValueType) CompoundValue)
-> Compound ScriptValueType
-> Either (Compound ScriptValueType) CompoundValue
forall a b. (a -> b) -> a -> b
$ (ScriptValue ValOrVar -> ScriptValueType)
-> ExpValue -> Compound ScriptValueType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ScriptValue ValOrVar -> ScriptValueType
forall v. ScriptValue v -> ScriptValueType
scriptValueType ExpValue
v)
varsInExp :: Exp -> S.Set EntryName
varsInExp :: Exp -> Set EntryName
varsInExp ServerVar {} = Set EntryName
forall a. Monoid a => a
mempty
varsInExp (Call (FuncFut EntryName
v) [Exp]
es) = EntryName -> Set EntryName -> Set EntryName
forall a. Ord a => a -> Set a -> Set a
S.insert EntryName
v (Set EntryName -> Set EntryName) -> Set EntryName -> Set EntryName
forall a b. (a -> b) -> a -> b
$ (Exp -> Set EntryName) -> [Exp] -> Set EntryName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> Set EntryName
varsInExp [Exp]
es
varsInExp (Call (FuncBuiltin EntryName
_) [Exp]
es) = (Exp -> Set EntryName) -> [Exp] -> Set EntryName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> Set EntryName
varsInExp [Exp]
es
varsInExp (Tuple [Exp]
es) = (Exp -> Set EntryName) -> [Exp] -> Set EntryName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> Set EntryName
varsInExp [Exp]
es
varsInExp (Record [(EntryName, Exp)]
fs) = ((EntryName, Exp) -> Set EntryName)
-> [(EntryName, Exp)] -> Set EntryName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ((Exp -> Set EntryName) -> (EntryName, Exp) -> Set EntryName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> Set EntryName
varsInExp) [(EntryName, Exp)]
fs
varsInExp Const {} = Set EntryName
forall a. Monoid a => a
mempty
varsInExp StringLit {} = Set EntryName
forall a. Monoid a => a
mempty
freeValue :: (MonadError T.Text m, MonadIO m) => ScriptServer -> ExpValue -> m ()
freeValue :: forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
ScriptServer -> ExpValue -> m ()
freeValue (ScriptServer Server
server IORef Int
_) =
IO (Maybe CmdFailure) -> m ()
forall (m :: * -> *).
(MonadError EntryName m, MonadIO m) =>
IO (Maybe CmdFailure) -> m ()
cmdMaybe (IO (Maybe CmdFailure) -> m ())
-> (ExpValue -> IO (Maybe CmdFailure)) -> ExpValue -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Server -> [EntryName] -> IO (Maybe CmdFailure)
cmdFree Server
server ([EntryName] -> IO (Maybe CmdFailure))
-> (ExpValue -> [EntryName]) -> ExpValue -> IO (Maybe CmdFailure)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set EntryName -> [EntryName]
forall a. Set a -> [a]
S.toList (Set EntryName -> [EntryName])
-> (ExpValue -> Set EntryName) -> ExpValue -> [EntryName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExpValue -> Set EntryName
serverVarsInValue