{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | High-level translation of Copilot Core into C99.
module Copilot.Compile.C99.CodeGen where

import Control.Monad.State  (runState)
import Data.List            (union, unzip4)
import Data.Typeable        (Typeable)

import qualified Language.C99.Simple as C

import Copilot.Core
import Copilot.Compile.C99.Util
import Copilot.Compile.C99.External
import Copilot.Compile.C99.Translate

-- | Write a declaration for a generator function.
gendecln :: String -> Type a -> C.Decln
gendecln :: String -> Type a -> Decln
gendecln String
name Type a
ty = Maybe StorageSpec -> Type -> String -> [Param] -> Decln
C.FunDecln Maybe StorageSpec
forall a. Maybe a
Nothing Type
cty String
name [] where
  cty :: Type
cty = Type -> Type
C.decay (Type -> Type) -> Type -> Type
forall a b. (a -> b) -> a -> b
$ Type a -> Type
forall a. Type a -> Type
transtype Type a
ty

-- | Write a generator function for a stream.
genfun :: String -> Expr a -> Type a -> C.FunDef
genfun :: String -> Expr a -> Type a -> FunDef
genfun String
name Expr a
expr Type a
ty = Type -> String -> [Param] -> [Decln] -> [Stmt] -> FunDef
C.FunDef Type
cty String
name [] [Decln]
cvars [Maybe Expr -> Stmt
C.Return (Maybe Expr -> Stmt) -> Maybe Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ Expr -> Maybe Expr
forall a. a -> Maybe a
Just Expr
cexpr] where
  cty :: Type
cty = Type -> Type
C.decay (Type -> Type) -> Type -> Type
forall a b. (a -> b) -> a -> b
$ Type a -> Type
forall a. Type a -> Type
transtype Type a
ty
  (Expr
cexpr, ([Decln]
cvars, [String]
_)) = State ([Decln], [String]) Expr
-> ([Decln], [String]) -> (Expr, ([Decln], [String]))
forall s a. State s a -> s -> (a, s)
runState (Expr a -> State ([Decln], [String]) Expr
forall a. Expr a -> State ([Decln], [String]) Expr
transexpr Expr a
expr) ([Decln], [String])
forall a. Monoid a => a
mempty

-- | Make a extern declaration of a variable.
mkextdecln :: External -> C.Decln
mkextdecln :: External -> Decln
mkextdecln (External String
name String
_ Type a
ty) = Decln
decln where
  decln :: Decln
decln = Maybe StorageSpec -> Type -> String -> Maybe Init -> Decln
C.VarDecln (StorageSpec -> Maybe StorageSpec
forall a. a -> Maybe a
Just StorageSpec
C.Extern) Type
cty String
name Maybe Init
forall a. Maybe a
Nothing
  cty :: Type
cty   = Type a -> Type
forall a. Type a -> Type
transtype Type a
ty

-- | Make a declaration for a copy of an external variable.
mkextcpydecln :: External -> C.Decln
mkextcpydecln :: External -> Decln
mkextcpydecln (External String
name String
cpyname Type a
ty) = Decln
decln where
  cty :: Type
cty   = Type a -> Type
forall a. Type a -> Type
transtype Type a
ty
  decln :: Decln
decln = Maybe StorageSpec -> Type -> String -> Maybe Init -> Decln
C.VarDecln (StorageSpec -> Maybe StorageSpec
forall a. a -> Maybe a
Just StorageSpec
C.Static) Type
cty String
cpyname Maybe Init
forall a. Maybe a
Nothing

-- | Make a C buffer variable and initialise it with the stream buffer.
mkbuffdecln :: Id -> Type a -> [a] -> C.Decln
mkbuffdecln :: Id -> Type a -> [a] -> Decln
mkbuffdecln Id
sid Type a
ty [a]
xs = Maybe StorageSpec -> Type -> String -> Maybe Init -> Decln
C.VarDecln (StorageSpec -> Maybe StorageSpec
forall a. a -> Maybe a
Just StorageSpec
C.Static) Type
cty String
name Maybe Init
initvals where
  name :: String
name     = Id -> String
streamname Id
sid
  cty :: Type
cty      = Type -> Maybe Expr -> Type
C.Array (Type a -> Type
forall a. Type a -> Type
transtype Type a
ty) (Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> Expr -> Maybe Expr
forall a b. (a -> b) -> a -> b
$ Integer -> Expr
C.LitInt (Integer -> Expr) -> Integer -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Id
buffsize)
  buffsize :: Id
buffsize = [a] -> Id
forall (t :: * -> *) a. Foldable t => t a -> Id
length [a]
xs
  initvals :: Maybe Init
initvals = Init -> Maybe Init
forall a. a -> Maybe a
Just (Init -> Maybe Init) -> Init -> Maybe Init
forall a b. (a -> b) -> a -> b
$ [Init] -> Init
C.InitArray ([Init] -> Init) -> [Init] -> Init
forall a b. (a -> b) -> a -> b
$ (a -> Init) -> [a] -> [Init]
forall a b. (a -> b) -> [a] -> [b]
map (Expr -> Init
C.InitExpr (Expr -> Init) -> (a -> Expr) -> a -> Init
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type a -> a -> Expr
forall a. Type a -> a -> Expr
constty Type a
ty) [a]
xs

-- | Make a C index variable and initialise it to 0.
mkindexdecln :: Id -> C.Decln
mkindexdecln :: Id -> Decln
mkindexdecln Id
sid = Maybe StorageSpec -> Type -> String -> Maybe Init -> Decln
C.VarDecln (StorageSpec -> Maybe StorageSpec
forall a. a -> Maybe a
Just StorageSpec
C.Static) Type
cty String
name Maybe Init
initval where
  name :: String
name    = Id -> String
indexname Id
sid
  cty :: Type
cty     = TypeSpec -> Type
C.TypeSpec (TypeSpec -> Type) -> TypeSpec -> Type
forall a b. (a -> b) -> a -> b
$ String -> TypeSpec
C.TypedefName String
"size_t"
  initval :: Maybe Init
initval = Init -> Maybe Init
forall a. a -> Maybe a
Just (Init -> Maybe Init) -> Init -> Maybe Init
forall a b. (a -> b) -> a -> b
$ Expr -> Init
C.InitExpr (Expr -> Init) -> Expr -> Init
forall a b. (a -> b) -> a -> b
$ Integer -> Expr
C.LitInt Integer
0

-- | Writes the step function, that updates all streams.
mkstep :: [Stream] -> [Trigger] -> [External] -> C.FunDef
mkstep :: [Stream] -> [Trigger] -> [External] -> FunDef
mkstep [Stream]
streams [Trigger]
triggers [External]
exts = Type -> String -> [Param] -> [Decln] -> [Stmt] -> FunDef
C.FunDef Type
void String
"step" [] [Decln]
declns [Stmt]
stmts where
  void :: Type
void = TypeSpec -> Type
C.TypeSpec TypeSpec
C.Void
  stmts :: [Stmt]
stmts  =  (External -> Stmt) -> [External] -> [Stmt]
forall a b. (a -> b) -> [a] -> [b]
map External -> Stmt
mkexcopy [External]
exts
         [Stmt] -> [Stmt] -> [Stmt]
forall a. [a] -> [a] -> [a]
++ (Trigger -> Stmt) -> [Trigger] -> [Stmt]
forall a b. (a -> b) -> [a] -> [b]
map Trigger -> Stmt
mktriggercheck [Trigger]
triggers
         [Stmt] -> [Stmt] -> [Stmt]
forall a. [a] -> [a] -> [a]
++ [Stmt]
tmpassigns
         [Stmt] -> [Stmt] -> [Stmt]
forall a. [a] -> [a] -> [a]
++ [Stmt]
bufferupdates
         [Stmt] -> [Stmt] -> [Stmt]
forall a. [a] -> [a] -> [a]
++ [Stmt]
indexupdates
  ([Decln]
declns, [Stmt]
tmpassigns, [Stmt]
bufferupdates, [Stmt]
indexupdates) =
    [(Decln, Stmt, Stmt, Stmt)] -> ([Decln], [Stmt], [Stmt], [Stmt])
forall a b c d. [(a, b, c, d)] -> ([a], [b], [c], [d])
unzip4 ([(Decln, Stmt, Stmt, Stmt)] -> ([Decln], [Stmt], [Stmt], [Stmt]))
-> [(Decln, Stmt, Stmt, Stmt)] -> ([Decln], [Stmt], [Stmt], [Stmt])
forall a b. (a -> b) -> a -> b
$ (Stream -> (Decln, Stmt, Stmt, Stmt))
-> [Stream] -> [(Decln, Stmt, Stmt, Stmt)]
forall a b. (a -> b) -> [a] -> [b]
map Stream -> (Decln, Stmt, Stmt, Stmt)
mkupdateglobals [Stream]
streams

  -- Write code to update global stream buffers and index.
  mkupdateglobals :: Stream -> (C.Decln, C.Stmt, C.Stmt, C.Stmt)
  mkupdateglobals :: Stream -> (Decln, Stmt, Stmt, Stmt)
mkupdateglobals (Stream Id
sid [a]
buff Expr a
expr Type a
ty) =
    (Decln
tmpdecln, Stmt
tmpassign, Stmt
bufferupdate, Stmt
indexupdate)
      where
        tmpdecln :: Decln
tmpdecln = Maybe StorageSpec -> Type -> String -> Maybe Init -> Decln
C.VarDecln Maybe StorageSpec
forall a. Maybe a
Nothing Type
cty String
tmp_var Maybe Init
forall a. Maybe a
Nothing

        tmpassign :: Stmt
tmpassign = case Type a
ty of
          Array Type t
_ -> Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr -> Expr
memcpy (String -> Expr
C.Ident String
tmp_var) Expr
val Expr
size
            where
              size :: Expr
size = Integer -> Expr
C.LitInt (Integer -> Expr) -> Integer -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Id -> Integer) -> Id -> Integer
forall a b. (a -> b) -> a -> b
$ Type (Array n t) -> Id
forall (n :: Nat) t. KnownNat n => Type (Array n t) -> Id
tysize Type a
Type (Array n t)
ty
          Type a
_       -> Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ String -> Expr
C.Ident String
tmp_var Expr -> Expr -> Expr
C..= Expr
val

        bufferupdate :: Stmt
bufferupdate = case Type a
ty of
          Array Type t
_ -> Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr -> Expr
memcpy Expr
dest (String -> Expr
C.Ident String
tmp_var) Expr
size
            where
              dest :: Expr
dest = Expr -> Expr -> Expr
C.Index Expr
buff_var Expr
index_var
              size :: Expr
size = Integer -> Expr
C.LitInt (Integer -> Expr) -> Integer -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Id -> Integer) -> Id -> Integer
forall a b. (a -> b) -> a -> b
$ Type (Array n t) -> Id
forall (n :: Nat) t. KnownNat n => Type (Array n t) -> Id
tysize Type a
Type (Array n t)
ty
          Type a
_       -> Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr
C.Index Expr
buff_var Expr
index_var Expr -> Expr -> Expr
C..= (String -> Expr
C.Ident String
tmp_var)

        indexupdate :: Stmt
indexupdate = Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ Expr
index_var Expr -> Expr -> Expr
C..= (Expr
incindex Expr -> Expr -> Expr
C..% Expr
bufflength)
          where
            bufflength :: Expr
bufflength = Integer -> Expr
C.LitInt (Integer -> Expr) -> Integer -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Id -> Integer) -> Id -> Integer
forall a b. (a -> b) -> a -> b
$ [a] -> Id
forall (t :: * -> *) a. Foldable t => t a -> Id
length [a]
buff
            incindex :: Expr
incindex   = Expr
index_var Expr -> Expr -> Expr
C..+ Integer -> Expr
C.LitInt Integer
1

        tmp_var :: String
tmp_var   = Id -> String
streamname Id
sid String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_tmp"
        buff_var :: Expr
buff_var  = String -> Expr
C.Ident (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> String
streamname Id
sid
        index_var :: Expr
index_var = String -> Expr
C.Ident (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> String
indexname Id
sid
        val :: Expr
val       = Expr -> [Expr] -> Expr
C.Funcall (String -> Expr
C.Ident (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> String
generatorname Id
sid) []
        cty :: Type
cty       = Type a -> Type
forall a. Type a -> Type
transtype Type a
ty

  -- Make code that copies an external variable to its local one.
  mkexcopy :: External -> C.Stmt
  mkexcopy :: External -> Stmt
mkexcopy (External String
name String
cpyname Type a
ty) = Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ case Type a
ty of
    Array Type t
_ -> Expr -> Expr -> Expr -> Expr
memcpy Expr
exvar Expr
locvar Expr
size where
                 exvar :: Expr
exvar  = String -> Expr
C.Ident String
cpyname
                 locvar :: Expr
locvar = String -> Expr
C.Ident String
name
                 size :: Expr
size   = Integer -> Expr
C.LitInt (Integer -> Expr) -> Integer -> Expr
forall a b. (a -> b) -> a -> b
$ Id -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Id -> Integer) -> Id -> Integer
forall a b. (a -> b) -> a -> b
$ Type (Array n t) -> Id
forall (n :: Nat) t. KnownNat n => Type (Array n t) -> Id
tysize Type a
Type (Array n t)
ty
    Type a
_       -> String -> Expr
C.Ident String
cpyname Expr -> Expr -> Expr
C..= String -> Expr
C.Ident String
name

  -- Make if-statement to check the guard, call the trigger if necessary.
  mktriggercheck :: Trigger -> C.Stmt
  mktriggercheck :: Trigger -> Stmt
mktriggercheck (Trigger String
name Expr Bool
guard [UExpr]
args) = Expr -> [Stmt] -> Stmt
C.If Expr
guard' [Stmt]
firetrigger where
    guard' :: Expr
guard'      = Expr -> [Expr] -> Expr
C.Funcall (String -> Expr
C.Ident (String -> Expr) -> String -> Expr
forall a b. (a -> b) -> a -> b
$ String -> String
guardname String
name) []
    firetrigger :: [Stmt]
firetrigger = [Expr -> Stmt
C.Expr (Expr -> Stmt) -> Expr -> Stmt
forall a b. (a -> b) -> a -> b
$ Expr -> [Expr] -> Expr
C.Funcall (String -> Expr
C.Ident String
name) [Expr]
args'] where
      args' :: [Expr]
args'        = Id -> [Expr] -> [Expr]
forall a. Id -> [a] -> [a]
take ([UExpr] -> Id
forall (t :: * -> *) a. Foldable t => t a -> Id
length [UExpr]
args) ((String -> Expr) -> [String] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map String -> Expr
argcall (String -> [String]
argnames String
name))
      argcall :: String -> Expr
argcall String
name = Expr -> [Expr] -> Expr
C.Funcall (String -> Expr
C.Ident String
name) []

  -- Write a call to the memcpy function.
  memcpy :: C.Expr -> C.Expr -> C.Expr -> C.Expr
  memcpy :: Expr -> Expr -> Expr -> Expr
memcpy Expr
dest Expr
src Expr
size = Expr -> [Expr] -> Expr
C.Funcall (String -> Expr
C.Ident String
"memcpy") [Expr
dest, Expr
src, Expr
size]


-- | Write a struct declaration based on its definition.
mkstructdecln :: Struct a => Type a -> C.Decln
mkstructdecln :: Type a -> Decln
mkstructdecln (Struct a
x) = Type -> Decln
C.TypeDecln Type
struct where
  struct :: Type
struct = TypeSpec -> Type
C.TypeSpec (TypeSpec -> Type) -> TypeSpec -> Type
forall a b. (a -> b) -> a -> b
$ Maybe String -> [FieldDecln] -> TypeSpec
C.StructDecln (String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ a -> String
forall a. Struct a => a -> String
typename a
x) [FieldDecln]
fields
  fields :: [FieldDecln]
fields = (Value a -> FieldDecln) -> [Value a] -> [FieldDecln]
forall a b. (a -> b) -> [a] -> [b]
map Value a -> FieldDecln
forall a. Value a -> FieldDecln
mkfield (a -> [Value a]
forall a. Struct a => a -> [Value a]
toValues a
x)

  mkfield :: Value a -> C.FieldDecln
  mkfield :: Value a -> FieldDecln
mkfield (Value Type t
ty Field s t
field) = Type -> String -> FieldDecln
C.FieldDecln (Type t -> Type
forall a. Type a -> Type
transtype Type t
ty) (Field s t -> String
forall (s :: Symbol) t. KnownSymbol s => Field s t -> String
fieldname Field s t
field)

-- | Write a forward struct declaration.
mkstructforwdecln :: Struct a => Type a -> C.Decln
mkstructforwdecln :: Type a -> Decln
mkstructforwdecln (Struct a
x) = Type -> Decln
C.TypeDecln Type
struct where
  struct :: Type
struct = TypeSpec -> Type
C.TypeSpec (TypeSpec -> Type) -> TypeSpec -> Type
forall a b. (a -> b) -> a -> b
$ String -> TypeSpec
C.Struct (a -> String
forall a. Struct a => a -> String
typename a
x)

-- | List all types of an expression, returns items uniquely.
exprtypes :: Typeable a => Expr a -> [UType]
exprtypes :: Expr a -> [UType]
exprtypes Expr a
e = case Expr a
e of
  Const Type a
ty a
_            -> Type a -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a
ty
  Local Type a1
ty1 Type a
ty2 String
_ Expr a1
e1 Expr a
e2 -> Type a1 -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a1
ty1 [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Type a -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a
ty2
                           [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Expr a1 -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr a1
e1 [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Expr a -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr a
e2
  Var Type a
ty String
_              -> Type a -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a
ty
  Drop Type a
ty DropIdx
_ Id
_           -> Type a -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a
ty
  ExternVar Type a
ty String
_ Maybe [a]
_      -> Type a -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a
ty
  Op1 Op1 a1 a
_ Expr a1
e1              -> Expr a1 -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr a1
e1
  Op2 Op2 a1 b a
_ Expr a1
e1 Expr b
e2           -> Expr a1 -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr a1
e1 [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Expr b -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr b
e2
  Op3 Op3 a1 b c a
_ Expr a1
e1 Expr b
e2 Expr c
e3        -> Expr a1 -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr a1
e1 [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Expr b -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr b
e2 [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Expr c -> [UType]
forall a. Typeable a => Expr a -> [UType]
exprtypes Expr c
e3
  Label Type a
ty String
_ Expr a
_          -> Type a -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type a
ty

-- | List all types of a type, returns items uniquely.
typetypes :: Typeable a => Type a -> [UType]
typetypes :: Type a -> [UType]
typetypes Type a
ty = case Type a
ty of
  Array Type t
ty' -> [Type a -> UType
forall a. Typeable a => Type a -> UType
UType Type a
ty] [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` Type t -> [UType]
forall a. Typeable a => Type a -> [UType]
typetypes Type t
ty'
  Struct a
x  -> [Type a -> UType
forall a. Typeable a => Type a -> UType
UType Type a
ty] [UType] -> [UType] -> [UType]
forall a. Eq a => [a] -> [a] -> [a]
`union` (Value a -> UType) -> [Value a] -> [UType]
forall a b. (a -> b) -> [a] -> [b]
map (\(Value Type t
ty' Field s t
_) -> Type t -> UType
forall a. Typeable a => Type a -> UType
UType Type t
ty') (a -> [Value a]
forall a. Struct a => a -> [Value a]
toValues a
x)
  Type a
_         -> [Type a -> UType
forall a. Typeable a => Type a -> UType
UType Type a
ty]

-- | Collect all expression of a list of streams and triggers and wrap them
-- into an UEXpr.
gatherexprs :: [Stream] -> [Trigger] -> [UExpr]
gatherexprs :: [Stream] -> [Trigger] -> [UExpr]
gatherexprs [Stream]
streams [Trigger]
triggers =  (Stream -> UExpr) -> [Stream] -> [UExpr]
forall a b. (a -> b) -> [a] -> [b]
map Stream -> UExpr
streamexpr [Stream]
streams
                             [UExpr] -> [UExpr] -> [UExpr]
forall a. [a] -> [a] -> [a]
++ (Trigger -> [UExpr]) -> [Trigger] -> [UExpr]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Trigger -> [UExpr]
triggerexpr [Trigger]
triggers where
  streamexpr :: Stream -> UExpr
streamexpr  (Stream Id
_ [a]
_ Expr a
expr Type a
ty)   = Type a -> Expr a -> UExpr
forall a. Typeable a => Type a -> Expr a -> UExpr
UExpr Type a
ty Expr a
expr
  triggerexpr :: Trigger -> [UExpr]
triggerexpr (Trigger String
_ Expr Bool
guard [UExpr]
args) = Type Bool -> Expr Bool -> UExpr
forall a. Typeable a => Type a -> Expr a -> UExpr
UExpr Type Bool
Bool Expr Bool
guard UExpr -> [UExpr] -> [UExpr]
forall a. a -> [a] -> [a]
: [UExpr]
args