{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE Strict #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}

-- | = Definition of the Futhark core language IR
--
-- For actually /constructing/ ASTs, see "Futhark.Construct".
--
-- == Types and values
--
-- The core language type system is much more restricted than the core
-- language.  This is a theme that repeats often.  The only types that
-- are supported in the core language are various primitive types
-- t'PrimType' which can be combined in arrays (ignore v'Mem' for
-- now).  Types are represented as t'TypeBase', which is parameterised
-- by the shape of the array and whether we keep uniqueness
-- information.  The t'Type' alias, which is the most commonly used,
-- uses t'Shape' and t'NoUniqueness'.
--
-- This means that the records, tuples, and sum types of the source
-- language are represented merely as collections of primitives and
-- arrays.  This is implemented in "Futhark.Internalise", but the
-- specifics are not important for writing passes on the core
-- language.  What /is/ important is that many constructs that
-- conceptually return tuples instead return /multiple values/.  This
-- is not merely syntactic sugar for a tuple: each of those values are
-- eventually bound to distinct variables.  The prettyprinter for the
-- IR will typically print such collections of values or types in
-- curly braces.
--
-- The system of primitive types is interesting in itself.  See
-- "Futhark.IR.Primitive".
--
-- == Overall AST design
--
-- Internally, the Futhark compiler core intermediate representation
-- resembles a traditional compiler for an imperative language more
-- than it resembles, say, a Haskell or ML compiler.  All functions
-- are monomorphic (except for sizes), first-order, and defined at the
-- top level.  Notably, the IR does /not/ use continuation-passing
-- style (CPS) at any time.  Instead it uses Administrative Normal
-- Form (ANF), where all subexpressions t'SubExp' are either
-- constants 'PrimValue' or variables 'VName'.  Variables are
-- represented as a human-readable t'Name' (which doesn't matter to
-- the compiler) as well as a numeric /tag/, which is what the
-- compiler actually looks at.  All variable names when prettyprinted
-- are of the form @foo_123@.  Function names are just t'Name's,
-- though.
--
-- The body of a function ('FunDef') is a t'Body', which consists of
-- a sequence of statements ('Stms') and a t'Result'.  Execution of a
-- t'Body' consists of executing all of the statements, then returning
-- the values of the variables indicated by the result.
--
-- A statement ('Stm') consists of a t'Pat' alongside an
-- expression 'ExpT'.  A pattern is a sequence of name/type pairs.
--
-- For example, the source language expression @let z = x + y - 1 in
-- z@ would in the core language be represented (in prettyprinted
-- form) as something like:
--
-- @
-- let {a_12} = x_10 + y_11
-- let {b_13} = a_12 - 1
-- in {b_13}
-- @
--
-- == Representations
--
-- Most AST types ('Stm', 'ExpT', t'Prog', etc) are parameterised by a
-- type parameter @rep@.  The representation specifies how to fill out
-- various polymorphic parts of the AST.  For example, 'ExpT' has a
-- constructor v'Op' whose payload depends on @rep@, via the use of a
-- type family called t'Op' (a kind of type-level function) which is
-- applied to the @rep@.  The SOACS representation
-- ("Futhark.IR.SOACS") thus uses a rep called @SOACS@, and defines
-- that @Op SOACS@ is a SOAC, while the Kernels representation
-- ("Futhark.IR.Kernels") defines @Op Kernels@ as some kind of kernel
-- construct.  Similarly, various other decorations (e.g. what
-- information we store in a t'PatElemT') are also type families.
--
-- The full list of possible decorations is defined as part of the
-- type class 'RepTypes' (although other type families are also
-- used elsewhere in the compiler on an ad hoc basis).
--
-- Essentially, the @rep@ type parameter functions as a kind of
-- proxy, saving us from having to parameterise the AST type with all
-- the different forms of decorations that we desire (it would easily
-- become a type with a dozen type parameters).
--
-- Defining a new representation (or /rep/) thus requires you to
-- define an empty datatype and implement a handful of type class
-- instances for it.  See the source of "Futhark.IR.Seq"
-- for what is likely the simplest example.
module Futhark.IR.Syntax
  ( module Language.Futhark.Core,
    pretty,
    module Futhark.IR.Rep,
    module Futhark.IR.Syntax.Core,

    -- * Types
    Uniqueness (..),
    NoUniqueness (..),
    Rank (..),
    ArrayShape (..),
    Space (..),
    TypeBase (..),
    Diet (..),

    -- * Attributes
    Attr (..),
    Attrs (..),
    oneAttr,
    inAttrs,
    withoutAttrs,

    -- * Abstract syntax tree
    Ident (..),
    SubExp (..),
    PatElem,
    PatElemT (..),
    PatT (..),
    Pat,
    StmAux (..),
    Stm (..),
    Stms,
    SubExpRes (..),
    Result,
    BodyT (..),
    Body,
    BasicOp (..),
    UnOp (..),
    BinOp (..),
    CmpOp (..),
    ConvOp (..),
    OpaqueOp (..),
    DimChange (..),
    ShapeChange,
    ExpT (..),
    Exp,
    LoopForm (..),
    IfDec (..),
    IfSort (..),
    Safety (..),
    LambdaT (..),
    Lambda,

    -- * Definitions
    Param (..),
    FParam,
    LParam,
    FunDef (..),
    EntryPoint,
    EntryParam (..),
    EntryPointType (..),
    Prog (..),

    -- * Utils
    oneStm,
    stmsFromList,
    stmsToList,
    stmsHead,
    subExpRes,
    subExpsRes,
    varRes,
    varsRes,
  )
where

import Control.Category
import Data.Foldable
import qualified Data.Sequence as Seq
import qualified Data.Set as S
import Data.String
import Data.Traversable (fmapDefault, foldMapDefault)
import Futhark.IR.Rep
import Futhark.IR.Syntax.Core
import Futhark.Util.Pretty (pretty)
import Language.Futhark.Core
import Prelude hiding (id, (.))

-- | A single attribute.
data Attr
  = AttrAtom Name
  | AttrComp Name [Attr]
  deriving (Eq Attr
Eq Attr
-> (Attr -> Attr -> Ordering)
-> (Attr -> Attr -> Bool)
-> (Attr -> Attr -> Bool)
-> (Attr -> Attr -> Bool)
-> (Attr -> Attr -> Bool)
-> (Attr -> Attr -> Attr)
-> (Attr -> Attr -> Attr)
-> Ord Attr
Attr -> Attr -> Bool
Attr -> Attr -> Ordering
Attr -> Attr -> Attr
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Attr -> Attr -> Attr
$cmin :: Attr -> Attr -> Attr
max :: Attr -> Attr -> Attr
$cmax :: Attr -> Attr -> Attr
>= :: Attr -> Attr -> Bool
$c>= :: Attr -> Attr -> Bool
> :: Attr -> Attr -> Bool
$c> :: Attr -> Attr -> Bool
<= :: Attr -> Attr -> Bool
$c<= :: Attr -> Attr -> Bool
< :: Attr -> Attr -> Bool
$c< :: Attr -> Attr -> Bool
compare :: Attr -> Attr -> Ordering
$ccompare :: Attr -> Attr -> Ordering
$cp1Ord :: Eq Attr
Ord, Int -> Attr -> ShowS
[Attr] -> ShowS
Attr -> String
(Int -> Attr -> ShowS)
-> (Attr -> String) -> ([Attr] -> ShowS) -> Show Attr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Attr] -> ShowS
$cshowList :: [Attr] -> ShowS
show :: Attr -> String
$cshow :: Attr -> String
showsPrec :: Int -> Attr -> ShowS
$cshowsPrec :: Int -> Attr -> ShowS
Show, Attr -> Attr -> Bool
(Attr -> Attr -> Bool) -> (Attr -> Attr -> Bool) -> Eq Attr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Attr -> Attr -> Bool
$c/= :: Attr -> Attr -> Bool
== :: Attr -> Attr -> Bool
$c== :: Attr -> Attr -> Bool
Eq)

instance IsString Attr where
  fromString :: String -> Attr
fromString = Name -> Attr
AttrAtom (Name -> Attr) -> (String -> Name) -> String -> Attr
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Name
forall a. IsString a => String -> a
fromString

-- | Every statement is associated with a set of attributes, which can
-- have various effects throughout the compiler.
newtype Attrs = Attrs {Attrs -> Set Attr
unAttrs :: S.Set Attr}
  deriving (Eq Attrs
Eq Attrs
-> (Attrs -> Attrs -> Ordering)
-> (Attrs -> Attrs -> Bool)
-> (Attrs -> Attrs -> Bool)
-> (Attrs -> Attrs -> Bool)
-> (Attrs -> Attrs -> Bool)
-> (Attrs -> Attrs -> Attrs)
-> (Attrs -> Attrs -> Attrs)
-> Ord Attrs
Attrs -> Attrs -> Bool
Attrs -> Attrs -> Ordering
Attrs -> Attrs -> Attrs
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Attrs -> Attrs -> Attrs
$cmin :: Attrs -> Attrs -> Attrs
max :: Attrs -> Attrs -> Attrs
$cmax :: Attrs -> Attrs -> Attrs
>= :: Attrs -> Attrs -> Bool
$c>= :: Attrs -> Attrs -> Bool
> :: Attrs -> Attrs -> Bool
$c> :: Attrs -> Attrs -> Bool
<= :: Attrs -> Attrs -> Bool
$c<= :: Attrs -> Attrs -> Bool
< :: Attrs -> Attrs -> Bool
$c< :: Attrs -> Attrs -> Bool
compare :: Attrs -> Attrs -> Ordering
$ccompare :: Attrs -> Attrs -> Ordering
$cp1Ord :: Eq Attrs
Ord, Int -> Attrs -> ShowS
[Attrs] -> ShowS
Attrs -> String
(Int -> Attrs -> ShowS)
-> (Attrs -> String) -> ([Attrs] -> ShowS) -> Show Attrs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Attrs] -> ShowS
$cshowList :: [Attrs] -> ShowS
show :: Attrs -> String
$cshow :: Attrs -> String
showsPrec :: Int -> Attrs -> ShowS
$cshowsPrec :: Int -> Attrs -> ShowS
Show, Attrs -> Attrs -> Bool
(Attrs -> Attrs -> Bool) -> (Attrs -> Attrs -> Bool) -> Eq Attrs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Attrs -> Attrs -> Bool
$c/= :: Attrs -> Attrs -> Bool
== :: Attrs -> Attrs -> Bool
$c== :: Attrs -> Attrs -> Bool
Eq, Semigroup Attrs
Attrs
Semigroup Attrs
-> Attrs
-> (Attrs -> Attrs -> Attrs)
-> ([Attrs] -> Attrs)
-> Monoid Attrs
[Attrs] -> Attrs
Attrs -> Attrs -> Attrs
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Attrs] -> Attrs
$cmconcat :: [Attrs] -> Attrs
mappend :: Attrs -> Attrs -> Attrs
$cmappend :: Attrs -> Attrs -> Attrs
mempty :: Attrs
$cmempty :: Attrs
$cp1Monoid :: Semigroup Attrs
Monoid, b -> Attrs -> Attrs
NonEmpty Attrs -> Attrs
Attrs -> Attrs -> Attrs
(Attrs -> Attrs -> Attrs)
-> (NonEmpty Attrs -> Attrs)
-> (forall b. Integral b => b -> Attrs -> Attrs)
-> Semigroup Attrs
forall b. Integral b => b -> Attrs -> Attrs
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Attrs -> Attrs
$cstimes :: forall b. Integral b => b -> Attrs -> Attrs
sconcat :: NonEmpty Attrs -> Attrs
$csconcat :: NonEmpty Attrs -> Attrs
<> :: Attrs -> Attrs -> Attrs
$c<> :: Attrs -> Attrs -> Attrs
Semigroup)

-- | Construct 'Attrs' from a single 'Attr'.
oneAttr :: Attr -> Attrs
oneAttr :: Attr -> Attrs
oneAttr = Set Attr -> Attrs
Attrs (Set Attr -> Attrs) -> (Attr -> Set Attr) -> Attr -> Attrs
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Attr -> Set Attr
forall a. a -> Set a
S.singleton

-- | Is the given attribute to be found in the attribute set?
inAttrs :: Attr -> Attrs -> Bool
inAttrs :: Attr -> Attrs -> Bool
inAttrs Attr
attr (Attrs Set Attr
attrs) = Attr
attr Attr -> Set Attr -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.member` Set Attr
attrs

-- | @x `withoutAttrs` y@ gives @x@ except for any attributes also in @y@.
withoutAttrs :: Attrs -> Attrs -> Attrs
withoutAttrs :: Attrs -> Attrs -> Attrs
withoutAttrs (Attrs Set Attr
x) (Attrs Set Attr
y) = Set Attr -> Attrs
Attrs (Set Attr -> Attrs) -> Set Attr -> Attrs
forall a b. (a -> b) -> a -> b
$ Set Attr
x Set Attr -> Set Attr -> Set Attr
forall a. Ord a => Set a -> Set a -> Set a
`S.difference` Set Attr
y

-- | A type alias for namespace control.
type PatElem rep = PatElemT (LetDec rep)

-- | A pattern is conceptually just a list of names and their types.
newtype PatT dec = Pat {PatT dec -> [PatElemT dec]
patElems :: [PatElemT dec]}
  deriving (Eq (PatT dec)
Eq (PatT dec)
-> (PatT dec -> PatT dec -> Ordering)
-> (PatT dec -> PatT dec -> Bool)
-> (PatT dec -> PatT dec -> Bool)
-> (PatT dec -> PatT dec -> Bool)
-> (PatT dec -> PatT dec -> Bool)
-> (PatT dec -> PatT dec -> PatT dec)
-> (PatT dec -> PatT dec -> PatT dec)
-> Ord (PatT dec)
PatT dec -> PatT dec -> Bool
PatT dec -> PatT dec -> Ordering
PatT dec -> PatT dec -> PatT dec
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall dec. Ord dec => Eq (PatT dec)
forall dec. Ord dec => PatT dec -> PatT dec -> Bool
forall dec. Ord dec => PatT dec -> PatT dec -> Ordering
forall dec. Ord dec => PatT dec -> PatT dec -> PatT dec
min :: PatT dec -> PatT dec -> PatT dec
$cmin :: forall dec. Ord dec => PatT dec -> PatT dec -> PatT dec
max :: PatT dec -> PatT dec -> PatT dec
$cmax :: forall dec. Ord dec => PatT dec -> PatT dec -> PatT dec
>= :: PatT dec -> PatT dec -> Bool
$c>= :: forall dec. Ord dec => PatT dec -> PatT dec -> Bool
> :: PatT dec -> PatT dec -> Bool
$c> :: forall dec. Ord dec => PatT dec -> PatT dec -> Bool
<= :: PatT dec -> PatT dec -> Bool
$c<= :: forall dec. Ord dec => PatT dec -> PatT dec -> Bool
< :: PatT dec -> PatT dec -> Bool
$c< :: forall dec. Ord dec => PatT dec -> PatT dec -> Bool
compare :: PatT dec -> PatT dec -> Ordering
$ccompare :: forall dec. Ord dec => PatT dec -> PatT dec -> Ordering
$cp1Ord :: forall dec. Ord dec => Eq (PatT dec)
Ord, Int -> PatT dec -> ShowS
[PatT dec] -> ShowS
PatT dec -> String
(Int -> PatT dec -> ShowS)
-> (PatT dec -> String) -> ([PatT dec] -> ShowS) -> Show (PatT dec)
forall dec. Show dec => Int -> PatT dec -> ShowS
forall dec. Show dec => [PatT dec] -> ShowS
forall dec. Show dec => PatT dec -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PatT dec] -> ShowS
$cshowList :: forall dec. Show dec => [PatT dec] -> ShowS
show :: PatT dec -> String
$cshow :: forall dec. Show dec => PatT dec -> String
showsPrec :: Int -> PatT dec -> ShowS
$cshowsPrec :: forall dec. Show dec => Int -> PatT dec -> ShowS
Show, PatT dec -> PatT dec -> Bool
(PatT dec -> PatT dec -> Bool)
-> (PatT dec -> PatT dec -> Bool) -> Eq (PatT dec)
forall dec. Eq dec => PatT dec -> PatT dec -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PatT dec -> PatT dec -> Bool
$c/= :: forall dec. Eq dec => PatT dec -> PatT dec -> Bool
== :: PatT dec -> PatT dec -> Bool
$c== :: forall dec. Eq dec => PatT dec -> PatT dec -> Bool
Eq)

instance Semigroup (PatT dec) where
  Pat [PatElemT dec]
xs <> :: PatT dec -> PatT dec -> PatT dec
<> Pat [PatElemT dec]
ys = [PatElemT dec] -> PatT dec
forall dec. [PatElemT dec] -> PatT dec
Pat ([PatElemT dec]
xs [PatElemT dec] -> [PatElemT dec] -> [PatElemT dec]
forall a. Semigroup a => a -> a -> a
<> [PatElemT dec]
ys)

instance Monoid (PatT dec) where
  mempty :: PatT dec
mempty = [PatElemT dec] -> PatT dec
forall dec. [PatElemT dec] -> PatT dec
Pat [PatElemT dec]
forall a. Monoid a => a
mempty

instance Functor PatT where
  fmap :: (a -> b) -> PatT a -> PatT b
fmap = (a -> b) -> PatT a -> PatT b
forall (t :: * -> *) a b. Traversable t => (a -> b) -> t a -> t b
fmapDefault

instance Foldable PatT where
  foldMap :: (a -> m) -> PatT a -> m
foldMap = (a -> m) -> PatT a -> m
forall (t :: * -> *) m a.
(Traversable t, Monoid m) =>
(a -> m) -> t a -> m
foldMapDefault

instance Traversable PatT where
  traverse :: (a -> f b) -> PatT a -> f (PatT b)
traverse a -> f b
f (Pat [PatElemT a]
xs) =
    [PatElemT b] -> PatT b
forall dec. [PatElemT dec] -> PatT dec
Pat ([PatElemT b] -> PatT b) -> f [PatElemT b] -> f (PatT b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (PatElemT a -> f (PatElemT b)) -> [PatElemT a] -> f [PatElemT b]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((a -> f b) -> PatElemT a -> f (PatElemT b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f) [PatElemT a]
xs

-- | A type alias for namespace control.
type Pat rep = PatT (LetDec rep)

-- | Auxilliary Information associated with a statement.
data StmAux dec = StmAux
  { StmAux dec -> Certs
stmAuxCerts :: !Certs,
    StmAux dec -> Attrs
stmAuxAttrs :: Attrs,
    StmAux dec -> dec
stmAuxDec :: dec
  }
  deriving (Eq (StmAux dec)
Eq (StmAux dec)
-> (StmAux dec -> StmAux dec -> Ordering)
-> (StmAux dec -> StmAux dec -> Bool)
-> (StmAux dec -> StmAux dec -> Bool)
-> (StmAux dec -> StmAux dec -> Bool)
-> (StmAux dec -> StmAux dec -> Bool)
-> (StmAux dec -> StmAux dec -> StmAux dec)
-> (StmAux dec -> StmAux dec -> StmAux dec)
-> Ord (StmAux dec)
StmAux dec -> StmAux dec -> Bool
StmAux dec -> StmAux dec -> Ordering
StmAux dec -> StmAux dec -> StmAux dec
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall dec. Ord dec => Eq (StmAux dec)
forall dec. Ord dec => StmAux dec -> StmAux dec -> Bool
forall dec. Ord dec => StmAux dec -> StmAux dec -> Ordering
forall dec. Ord dec => StmAux dec -> StmAux dec -> StmAux dec
min :: StmAux dec -> StmAux dec -> StmAux dec
$cmin :: forall dec. Ord dec => StmAux dec -> StmAux dec -> StmAux dec
max :: StmAux dec -> StmAux dec -> StmAux dec
$cmax :: forall dec. Ord dec => StmAux dec -> StmAux dec -> StmAux dec
>= :: StmAux dec -> StmAux dec -> Bool
$c>= :: forall dec. Ord dec => StmAux dec -> StmAux dec -> Bool
> :: StmAux dec -> StmAux dec -> Bool
$c> :: forall dec. Ord dec => StmAux dec -> StmAux dec -> Bool
<= :: StmAux dec -> StmAux dec -> Bool
$c<= :: forall dec. Ord dec => StmAux dec -> StmAux dec -> Bool
< :: StmAux dec -> StmAux dec -> Bool
$c< :: forall dec. Ord dec => StmAux dec -> StmAux dec -> Bool
compare :: StmAux dec -> StmAux dec -> Ordering
$ccompare :: forall dec. Ord dec => StmAux dec -> StmAux dec -> Ordering
$cp1Ord :: forall dec. Ord dec => Eq (StmAux dec)
Ord, Int -> StmAux dec -> ShowS
[StmAux dec] -> ShowS
StmAux dec -> String
(Int -> StmAux dec -> ShowS)
-> (StmAux dec -> String)
-> ([StmAux dec] -> ShowS)
-> Show (StmAux dec)
forall dec. Show dec => Int -> StmAux dec -> ShowS
forall dec. Show dec => [StmAux dec] -> ShowS
forall dec. Show dec => StmAux dec -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StmAux dec] -> ShowS
$cshowList :: forall dec. Show dec => [StmAux dec] -> ShowS
show :: StmAux dec -> String
$cshow :: forall dec. Show dec => StmAux dec -> String
showsPrec :: Int -> StmAux dec -> ShowS
$cshowsPrec :: forall dec. Show dec => Int -> StmAux dec -> ShowS
Show, StmAux dec -> StmAux dec -> Bool
(StmAux dec -> StmAux dec -> Bool)
-> (StmAux dec -> StmAux dec -> Bool) -> Eq (StmAux dec)
forall dec. Eq dec => StmAux dec -> StmAux dec -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StmAux dec -> StmAux dec -> Bool
$c/= :: forall dec. Eq dec => StmAux dec -> StmAux dec -> Bool
== :: StmAux dec -> StmAux dec -> Bool
$c== :: forall dec. Eq dec => StmAux dec -> StmAux dec -> Bool
Eq)

instance Semigroup dec => Semigroup (StmAux dec) where
  StmAux Certs
cs1 Attrs
attrs1 dec
dec1 <> :: StmAux dec -> StmAux dec -> StmAux dec
<> StmAux Certs
cs2 Attrs
attrs2 dec
dec2 =
    Certs -> Attrs -> dec -> StmAux dec
forall dec. Certs -> Attrs -> dec -> StmAux dec
StmAux (Certs
cs1 Certs -> Certs -> Certs
forall a. Semigroup a => a -> a -> a
<> Certs
cs2) (Attrs
attrs1 Attrs -> Attrs -> Attrs
forall a. Semigroup a => a -> a -> a
<> Attrs
attrs2) (dec
dec1 dec -> dec -> dec
forall a. Semigroup a => a -> a -> a
<> dec
dec2)

-- | A local variable binding.
data Stm rep = Let
  { -- | Pat.
    Stm rep -> Pat rep
stmPat :: Pat rep,
    -- | Auxiliary information statement.
    Stm rep -> StmAux (ExpDec rep)
stmAux :: StmAux (ExpDec rep),
    -- | Expression.
    Stm rep -> Exp rep
stmExp :: Exp rep
  }

deriving instance RepTypes rep => Ord (Stm rep)

deriving instance RepTypes rep => Show (Stm rep)

deriving instance RepTypes rep => Eq (Stm rep)

-- | A sequence of statements.
type Stms rep = Seq.Seq (Stm rep)

-- | A single statement.
oneStm :: Stm rep -> Stms rep
oneStm :: Stm rep -> Stms rep
oneStm = Stm rep -> Stms rep
forall a. a -> Seq a
Seq.singleton

-- | Convert a statement list to a statement sequence.
stmsFromList :: [Stm rep] -> Stms rep
stmsFromList :: [Stm rep] -> Stms rep
stmsFromList = [Stm rep] -> Stms rep
forall a. [a] -> Seq a
Seq.fromList

-- | Convert a statement sequence to a statement list.
stmsToList :: Stms rep -> [Stm rep]
stmsToList :: Stms rep -> [Stm rep]
stmsToList = Stms rep -> [Stm rep]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

-- | The first statement in the sequence, if any.
stmsHead :: Stms rep -> Maybe (Stm rep, Stms rep)
stmsHead :: Stms rep -> Maybe (Stm rep, Stms rep)
stmsHead Stms rep
stms = case Stms rep -> ViewL (Stm rep)
forall a. Seq a -> ViewL a
Seq.viewl Stms rep
stms of
  Stm rep
stm Seq.:< Stms rep
stms' -> (Stm rep, Stms rep) -> Maybe (Stm rep, Stms rep)
forall a. a -> Maybe a
Just (Stm rep
stm, Stms rep
stms')
  ViewL (Stm rep)
Seq.EmptyL -> Maybe (Stm rep, Stms rep)
forall a. Maybe a
Nothing

-- | A pairing of a subexpression and some certificates.
data SubExpRes = SubExpRes
  { SubExpRes -> Certs
resCerts :: Certs,
    SubExpRes -> SubExp
resSubExp :: SubExp
  }
  deriving (SubExpRes -> SubExpRes -> Bool
(SubExpRes -> SubExpRes -> Bool)
-> (SubExpRes -> SubExpRes -> Bool) -> Eq SubExpRes
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubExpRes -> SubExpRes -> Bool
$c/= :: SubExpRes -> SubExpRes -> Bool
== :: SubExpRes -> SubExpRes -> Bool
$c== :: SubExpRes -> SubExpRes -> Bool
Eq, Eq SubExpRes
Eq SubExpRes
-> (SubExpRes -> SubExpRes -> Ordering)
-> (SubExpRes -> SubExpRes -> Bool)
-> (SubExpRes -> SubExpRes -> Bool)
-> (SubExpRes -> SubExpRes -> Bool)
-> (SubExpRes -> SubExpRes -> Bool)
-> (SubExpRes -> SubExpRes -> SubExpRes)
-> (SubExpRes -> SubExpRes -> SubExpRes)
-> Ord SubExpRes
SubExpRes -> SubExpRes -> Bool
SubExpRes -> SubExpRes -> Ordering
SubExpRes -> SubExpRes -> SubExpRes
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SubExpRes -> SubExpRes -> SubExpRes
$cmin :: SubExpRes -> SubExpRes -> SubExpRes
max :: SubExpRes -> SubExpRes -> SubExpRes
$cmax :: SubExpRes -> SubExpRes -> SubExpRes
>= :: SubExpRes -> SubExpRes -> Bool
$c>= :: SubExpRes -> SubExpRes -> Bool
> :: SubExpRes -> SubExpRes -> Bool
$c> :: SubExpRes -> SubExpRes -> Bool
<= :: SubExpRes -> SubExpRes -> Bool
$c<= :: SubExpRes -> SubExpRes -> Bool
< :: SubExpRes -> SubExpRes -> Bool
$c< :: SubExpRes -> SubExpRes -> Bool
compare :: SubExpRes -> SubExpRes -> Ordering
$ccompare :: SubExpRes -> SubExpRes -> Ordering
$cp1Ord :: Eq SubExpRes
Ord, Int -> SubExpRes -> ShowS
[SubExpRes] -> ShowS
SubExpRes -> String
(Int -> SubExpRes -> ShowS)
-> (SubExpRes -> String)
-> ([SubExpRes] -> ShowS)
-> Show SubExpRes
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubExpRes] -> ShowS
$cshowList :: [SubExpRes] -> ShowS
show :: SubExpRes -> String
$cshow :: SubExpRes -> String
showsPrec :: Int -> SubExpRes -> ShowS
$cshowsPrec :: Int -> SubExpRes -> ShowS
Show)

-- | Construct a 'SubExpRes' with no certificates.
subExpRes :: SubExp -> SubExpRes
subExpRes :: SubExp -> SubExpRes
subExpRes = Certs -> SubExp -> SubExpRes
SubExpRes Certs
forall a. Monoid a => a
mempty

-- | Construct a 'SubExpRes' from a variable name.
varRes :: VName -> SubExpRes
varRes :: VName -> SubExpRes
varRes = SubExp -> SubExpRes
subExpRes (SubExp -> SubExpRes) -> (VName -> SubExp) -> VName -> SubExpRes
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. VName -> SubExp
Var

-- | Construct a 'Result' from subexpressions.
subExpsRes :: [SubExp] -> Result
subExpsRes :: [SubExp] -> [SubExpRes]
subExpsRes = (SubExp -> SubExpRes) -> [SubExp] -> [SubExpRes]
forall a b. (a -> b) -> [a] -> [b]
map SubExp -> SubExpRes
subExpRes

-- | Construct a 'Result' from variable names.
varsRes :: [VName] -> Result
varsRes :: [VName] -> [SubExpRes]
varsRes = (VName -> SubExpRes) -> [VName] -> [SubExpRes]
forall a b. (a -> b) -> [a] -> [b]
map VName -> SubExpRes
varRes

-- | The result of a body is a sequence of subexpressions.
type Result = [SubExpRes]

-- | A body consists of a number of bindings, terminating in a result
-- (essentially a tuple literal).
data BodyT rep = Body
  { BodyT rep -> BodyDec rep
bodyDec :: BodyDec rep,
    BodyT rep -> Stms rep
bodyStms :: Stms rep,
    BodyT rep -> [SubExpRes]
bodyResult :: Result
  }

deriving instance RepTypes rep => Ord (BodyT rep)

deriving instance RepTypes rep => Show (BodyT rep)

deriving instance RepTypes rep => Eq (BodyT rep)

-- | Type alias for namespace reasons.
type Body = BodyT

-- | The new dimension in a 'Reshape'-like operation.  This allows us to
-- disambiguate "real" reshapes, that change the actual shape of the
-- array, from type coercions that are just present to make the types
-- work out.  The two constructors are considered equal for purposes of 'Eq'.
data DimChange d
  = -- | The new dimension is guaranteed to be numerically
    -- equal to the old one.
    DimCoercion d
  | -- | The new dimension is not necessarily numerically
    -- equal to the old one.
    DimNew d
  deriving (Eq (DimChange d)
Eq (DimChange d)
-> (DimChange d -> DimChange d -> Ordering)
-> (DimChange d -> DimChange d -> Bool)
-> (DimChange d -> DimChange d -> Bool)
-> (DimChange d -> DimChange d -> Bool)
-> (DimChange d -> DimChange d -> Bool)
-> (DimChange d -> DimChange d -> DimChange d)
-> (DimChange d -> DimChange d -> DimChange d)
-> Ord (DimChange d)
DimChange d -> DimChange d -> Bool
DimChange d -> DimChange d -> Ordering
DimChange d -> DimChange d -> DimChange d
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall d. Ord d => Eq (DimChange d)
forall d. Ord d => DimChange d -> DimChange d -> Bool
forall d. Ord d => DimChange d -> DimChange d -> Ordering
forall d. Ord d => DimChange d -> DimChange d -> DimChange d
min :: DimChange d -> DimChange d -> DimChange d
$cmin :: forall d. Ord d => DimChange d -> DimChange d -> DimChange d
max :: DimChange d -> DimChange d -> DimChange d
$cmax :: forall d. Ord d => DimChange d -> DimChange d -> DimChange d
>= :: DimChange d -> DimChange d -> Bool
$c>= :: forall d. Ord d => DimChange d -> DimChange d -> Bool
> :: DimChange d -> DimChange d -> Bool
$c> :: forall d. Ord d => DimChange d -> DimChange d -> Bool
<= :: DimChange d -> DimChange d -> Bool
$c<= :: forall d. Ord d => DimChange d -> DimChange d -> Bool
< :: DimChange d -> DimChange d -> Bool
$c< :: forall d. Ord d => DimChange d -> DimChange d -> Bool
compare :: DimChange d -> DimChange d -> Ordering
$ccompare :: forall d. Ord d => DimChange d -> DimChange d -> Ordering
$cp1Ord :: forall d. Ord d => Eq (DimChange d)
Ord, Int -> DimChange d -> ShowS
[DimChange d] -> ShowS
DimChange d -> String
(Int -> DimChange d -> ShowS)
-> (DimChange d -> String)
-> ([DimChange d] -> ShowS)
-> Show (DimChange d)
forall d. Show d => Int -> DimChange d -> ShowS
forall d. Show d => [DimChange d] -> ShowS
forall d. Show d => DimChange d -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DimChange d] -> ShowS
$cshowList :: forall d. Show d => [DimChange d] -> ShowS
show :: DimChange d -> String
$cshow :: forall d. Show d => DimChange d -> String
showsPrec :: Int -> DimChange d -> ShowS
$cshowsPrec :: forall d. Show d => Int -> DimChange d -> ShowS
Show)

instance Eq d => Eq (DimChange d) where
  DimCoercion d
x == :: DimChange d -> DimChange d -> Bool
== DimNew d
y = d
x d -> d -> Bool
forall a. Eq a => a -> a -> Bool
== d
y
  DimCoercion d
x == DimCoercion d
y = d
x d -> d -> Bool
forall a. Eq a => a -> a -> Bool
== d
y
  DimNew d
x == DimCoercion d
y = d
x d -> d -> Bool
forall a. Eq a => a -> a -> Bool
== d
y
  DimNew d
x == DimNew d
y = d
x d -> d -> Bool
forall a. Eq a => a -> a -> Bool
== d
y

instance Functor DimChange where
  fmap :: (a -> b) -> DimChange a -> DimChange b
fmap a -> b
f (DimCoercion a
d) = b -> DimChange b
forall d. d -> DimChange d
DimCoercion (b -> DimChange b) -> b -> DimChange b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
d
  fmap a -> b
f (DimNew a
d) = b -> DimChange b
forall d. d -> DimChange d
DimNew (b -> DimChange b) -> b -> DimChange b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
d

instance Foldable DimChange where
  foldMap :: (a -> m) -> DimChange a -> m
foldMap a -> m
f (DimCoercion a
d) = a -> m
f a
d
  foldMap a -> m
f (DimNew a
d) = a -> m
f a
d

instance Traversable DimChange where
  traverse :: (a -> f b) -> DimChange a -> f (DimChange b)
traverse a -> f b
f (DimCoercion a
d) = b -> DimChange b
forall d. d -> DimChange d
DimCoercion (b -> DimChange b) -> f b -> f (DimChange b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
d
  traverse a -> f b
f (DimNew a
d) = b -> DimChange b
forall d. d -> DimChange d
DimNew (b -> DimChange b) -> f b -> f (DimChange b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
d

-- | A list of 'DimChange's, indicating the new dimensions of an array.
type ShapeChange d = [DimChange d]

-- | Apart from being Opaque, what else is going on here?
data OpaqueOp
  = -- | No special operation.
    OpaqueNil
  | -- | Print the argument, prefixed by this string.
    OpaqueTrace String
  deriving (OpaqueOp -> OpaqueOp -> Bool
(OpaqueOp -> OpaqueOp -> Bool)
-> (OpaqueOp -> OpaqueOp -> Bool) -> Eq OpaqueOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OpaqueOp -> OpaqueOp -> Bool
$c/= :: OpaqueOp -> OpaqueOp -> Bool
== :: OpaqueOp -> OpaqueOp -> Bool
$c== :: OpaqueOp -> OpaqueOp -> Bool
Eq, Eq OpaqueOp
Eq OpaqueOp
-> (OpaqueOp -> OpaqueOp -> Ordering)
-> (OpaqueOp -> OpaqueOp -> Bool)
-> (OpaqueOp -> OpaqueOp -> Bool)
-> (OpaqueOp -> OpaqueOp -> Bool)
-> (OpaqueOp -> OpaqueOp -> Bool)
-> (OpaqueOp -> OpaqueOp -> OpaqueOp)
-> (OpaqueOp -> OpaqueOp -> OpaqueOp)
-> Ord OpaqueOp
OpaqueOp -> OpaqueOp -> Bool
OpaqueOp -> OpaqueOp -> Ordering
OpaqueOp -> OpaqueOp -> OpaqueOp
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: OpaqueOp -> OpaqueOp -> OpaqueOp
$cmin :: OpaqueOp -> OpaqueOp -> OpaqueOp
max :: OpaqueOp -> OpaqueOp -> OpaqueOp
$cmax :: OpaqueOp -> OpaqueOp -> OpaqueOp
>= :: OpaqueOp -> OpaqueOp -> Bool
$c>= :: OpaqueOp -> OpaqueOp -> Bool
> :: OpaqueOp -> OpaqueOp -> Bool
$c> :: OpaqueOp -> OpaqueOp -> Bool
<= :: OpaqueOp -> OpaqueOp -> Bool
$c<= :: OpaqueOp -> OpaqueOp -> Bool
< :: OpaqueOp -> OpaqueOp -> Bool
$c< :: OpaqueOp -> OpaqueOp -> Bool
compare :: OpaqueOp -> OpaqueOp -> Ordering
$ccompare :: OpaqueOp -> OpaqueOp -> Ordering
$cp1Ord :: Eq OpaqueOp
Ord, Int -> OpaqueOp -> ShowS
[OpaqueOp] -> ShowS
OpaqueOp -> String
(Int -> OpaqueOp -> ShowS)
-> (OpaqueOp -> String) -> ([OpaqueOp] -> ShowS) -> Show OpaqueOp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OpaqueOp] -> ShowS
$cshowList :: [OpaqueOp] -> ShowS
show :: OpaqueOp -> String
$cshow :: OpaqueOp -> String
showsPrec :: Int -> OpaqueOp -> ShowS
$cshowsPrec :: Int -> OpaqueOp -> ShowS
Show)

-- | A primitive operation that returns something of known size and
-- does not itself contain any bindings.
data BasicOp
  = -- | A variable or constant.
    SubExp SubExp
  | -- | Semantically and operationally just identity, but is
    -- invisible/impenetrable to optimisations (hopefully).  This
    -- partially a hack to avoid optimisation (so, to work around
    -- compiler limitations), but is also used to implement tracing
    -- and other operations that are semantically invisible, but have
    -- some sort of effect (brrr).
    Opaque OpaqueOp SubExp
  | -- | Array literals, e.g., @[ [1+x, 3], [2, 1+4] ]@.
    -- Second arg is the element type of the rows of the array.
    ArrayLit [SubExp] Type
  | -- | Unary operation.
    UnOp UnOp SubExp
  | -- | Binary operation.
    BinOp BinOp SubExp SubExp
  | -- | Comparison - result type is always boolean.
    CmpOp CmpOp SubExp SubExp
  | -- | Conversion "casting".
    ConvOp ConvOp SubExp
  | -- | Turn a boolean into a certificate, halting the program with the
    -- given error message if the boolean is false.
    Assert SubExp (ErrorMsg SubExp) (SrcLoc, [SrcLoc])
  | -- Primitive array operations

    -- | The certificates for bounds-checking are part of the 'Stm'.
    Index VName (Slice SubExp)
  | -- | An in-place update of the given array at the given position.
    -- Consumes the array.  If 'Safe', perform a run-time bounds check
    -- and ignore the write if out of bounds (like @Scatter@).
    Update Safety VName (Slice SubExp) SubExp
  | FlatIndex VName (FlatSlice SubExp)
  | FlatUpdate VName (FlatSlice SubExp) VName
  | -- | @concat@0([1],[2, 3, 4]) = [1, 2, 3, 4]@.
    Concat Int VName [VName] SubExp
  | -- | Copy the given array.  The result will not alias anything.
    Copy VName
  | -- | Manifest an array with dimensions represented in the given
    -- order.  The result will not alias anything.
    Manifest [Int] VName
  | -- Array construction.

    -- | @iota(n, x, s) = [x,x+s,..,x+(n-1)*s]@.
    --
    -- The t'IntType' indicates the type of the array returned and the
    -- offset/stride arguments, but not the length argument.
    Iota SubExp SubExp SubExp IntType
  | -- | @replicate([3][2],1) = [[1,1], [1,1], [1,1]]@
    Replicate Shape SubExp
  | -- | Create array of given type and shape, with undefined elements.
    Scratch PrimType [SubExp]
  | -- Array index space transformation.

    -- | 1st arg is the new shape, 2nd arg is the input array *)
    Reshape (ShapeChange SubExp) VName
  | -- | Permute the dimensions of the input array.  The list
    -- of integers is a list of dimensions (0-indexed), which
    -- must be a permutation of @[0,n-1]@, where @n@ is the
    -- number of dimensions in the input array.
    Rearrange [Int] VName
  | -- | Rotate the dimensions of the input array.  The list of
    -- subexpressions specify how much each dimension is rotated.  The
    -- length of this list must be equal to the rank of the array.
    Rotate [SubExp] VName
  | -- | Update an accumulator at the given index with the given value.
    -- Consumes the accumulator and produces a new one.
    UpdateAcc VName [SubExp] [SubExp]
  deriving (BasicOp -> BasicOp -> Bool
(BasicOp -> BasicOp -> Bool)
-> (BasicOp -> BasicOp -> Bool) -> Eq BasicOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BasicOp -> BasicOp -> Bool
$c/= :: BasicOp -> BasicOp -> Bool
== :: BasicOp -> BasicOp -> Bool
$c== :: BasicOp -> BasicOp -> Bool
Eq, Eq BasicOp
Eq BasicOp
-> (BasicOp -> BasicOp -> Ordering)
-> (BasicOp -> BasicOp -> Bool)
-> (BasicOp -> BasicOp -> Bool)
-> (BasicOp -> BasicOp -> Bool)
-> (BasicOp -> BasicOp -> Bool)
-> (BasicOp -> BasicOp -> BasicOp)
-> (BasicOp -> BasicOp -> BasicOp)
-> Ord BasicOp
BasicOp -> BasicOp -> Bool
BasicOp -> BasicOp -> Ordering
BasicOp -> BasicOp -> BasicOp
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BasicOp -> BasicOp -> BasicOp
$cmin :: BasicOp -> BasicOp -> BasicOp
max :: BasicOp -> BasicOp -> BasicOp
$cmax :: BasicOp -> BasicOp -> BasicOp
>= :: BasicOp -> BasicOp -> Bool
$c>= :: BasicOp -> BasicOp -> Bool
> :: BasicOp -> BasicOp -> Bool
$c> :: BasicOp -> BasicOp -> Bool
<= :: BasicOp -> BasicOp -> Bool
$c<= :: BasicOp -> BasicOp -> Bool
< :: BasicOp -> BasicOp -> Bool
$c< :: BasicOp -> BasicOp -> Bool
compare :: BasicOp -> BasicOp -> Ordering
$ccompare :: BasicOp -> BasicOp -> Ordering
$cp1Ord :: Eq BasicOp
Ord, Int -> BasicOp -> ShowS
[BasicOp] -> ShowS
BasicOp -> String
(Int -> BasicOp -> ShowS)
-> (BasicOp -> String) -> ([BasicOp] -> ShowS) -> Show BasicOp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BasicOp] -> ShowS
$cshowList :: [BasicOp] -> ShowS
show :: BasicOp -> String
$cshow :: BasicOp -> String
showsPrec :: Int -> BasicOp -> ShowS
$cshowsPrec :: Int -> BasicOp -> ShowS
Show)

-- | The root Futhark expression type.  The v'Op' constructor contains
-- a rep-specific operation.  Do-loops, branches and function calls
-- are special.  Everything else is a simple t'BasicOp'.
data ExpT rep
  = -- | A simple (non-recursive) operation.
    BasicOp BasicOp
  | Apply Name [(SubExp, Diet)] [RetType rep] (Safety, SrcLoc, [SrcLoc])
  | If SubExp (BodyT rep) (BodyT rep) (IfDec (BranchType rep))
  | -- | @loop {a} = {v} (for i < n|while b) do b@.
    DoLoop [(FParam rep, SubExp)] (LoopForm rep) (BodyT rep)
  | -- | Create accumulators backed by the given arrays (which are
    -- consumed) and pass them to the lambda, which must return the
    -- updated accumulators and possibly some extra values.  The
    -- accumulators are turned back into arrays.  The t'Shape' is the
    -- write index space.  The corresponding arrays must all have this
    -- shape outermost.  This construct is not part of t'BasicOp'
    -- because we need the @rep@ parameter.
    WithAcc [(Shape, [VName], Maybe (Lambda rep, [SubExp]))] (Lambda rep)
  | Op (Op rep)

deriving instance RepTypes rep => Eq (ExpT rep)

deriving instance RepTypes rep => Show (ExpT rep)

deriving instance RepTypes rep => Ord (ExpT rep)

-- | For-loop or while-loop?
data LoopForm rep
  = ForLoop VName IntType SubExp [(LParam rep, VName)]
  | WhileLoop VName

deriving instance RepTypes rep => Eq (LoopForm rep)

deriving instance RepTypes rep => Show (LoopForm rep)

deriving instance RepTypes rep => Ord (LoopForm rep)

-- | Data associated with a branch.
data IfDec rt = IfDec
  { IfDec rt -> [rt]
ifReturns :: [rt],
    IfDec rt -> IfSort
ifSort :: IfSort
  }
  deriving (IfDec rt -> IfDec rt -> Bool
(IfDec rt -> IfDec rt -> Bool)
-> (IfDec rt -> IfDec rt -> Bool) -> Eq (IfDec rt)
forall rt. Eq rt => IfDec rt -> IfDec rt -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IfDec rt -> IfDec rt -> Bool
$c/= :: forall rt. Eq rt => IfDec rt -> IfDec rt -> Bool
== :: IfDec rt -> IfDec rt -> Bool
$c== :: forall rt. Eq rt => IfDec rt -> IfDec rt -> Bool
Eq, Int -> IfDec rt -> ShowS
[IfDec rt] -> ShowS
IfDec rt -> String
(Int -> IfDec rt -> ShowS)
-> (IfDec rt -> String) -> ([IfDec rt] -> ShowS) -> Show (IfDec rt)
forall rt. Show rt => Int -> IfDec rt -> ShowS
forall rt. Show rt => [IfDec rt] -> ShowS
forall rt. Show rt => IfDec rt -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IfDec rt] -> ShowS
$cshowList :: forall rt. Show rt => [IfDec rt] -> ShowS
show :: IfDec rt -> String
$cshow :: forall rt. Show rt => IfDec rt -> String
showsPrec :: Int -> IfDec rt -> ShowS
$cshowsPrec :: forall rt. Show rt => Int -> IfDec rt -> ShowS
Show, Eq (IfDec rt)
Eq (IfDec rt)
-> (IfDec rt -> IfDec rt -> Ordering)
-> (IfDec rt -> IfDec rt -> Bool)
-> (IfDec rt -> IfDec rt -> Bool)
-> (IfDec rt -> IfDec rt -> Bool)
-> (IfDec rt -> IfDec rt -> Bool)
-> (IfDec rt -> IfDec rt -> IfDec rt)
-> (IfDec rt -> IfDec rt -> IfDec rt)
-> Ord (IfDec rt)
IfDec rt -> IfDec rt -> Bool
IfDec rt -> IfDec rt -> Ordering
IfDec rt -> IfDec rt -> IfDec rt
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall rt. Ord rt => Eq (IfDec rt)
forall rt. Ord rt => IfDec rt -> IfDec rt -> Bool
forall rt. Ord rt => IfDec rt -> IfDec rt -> Ordering
forall rt. Ord rt => IfDec rt -> IfDec rt -> IfDec rt
min :: IfDec rt -> IfDec rt -> IfDec rt
$cmin :: forall rt. Ord rt => IfDec rt -> IfDec rt -> IfDec rt
max :: IfDec rt -> IfDec rt -> IfDec rt
$cmax :: forall rt. Ord rt => IfDec rt -> IfDec rt -> IfDec rt
>= :: IfDec rt -> IfDec rt -> Bool
$c>= :: forall rt. Ord rt => IfDec rt -> IfDec rt -> Bool
> :: IfDec rt -> IfDec rt -> Bool
$c> :: forall rt. Ord rt => IfDec rt -> IfDec rt -> Bool
<= :: IfDec rt -> IfDec rt -> Bool
$c<= :: forall rt. Ord rt => IfDec rt -> IfDec rt -> Bool
< :: IfDec rt -> IfDec rt -> Bool
$c< :: forall rt. Ord rt => IfDec rt -> IfDec rt -> Bool
compare :: IfDec rt -> IfDec rt -> Ordering
$ccompare :: forall rt. Ord rt => IfDec rt -> IfDec rt -> Ordering
$cp1Ord :: forall rt. Ord rt => Eq (IfDec rt)
Ord)

-- | What kind of branch is this?  This has no semantic meaning, but
-- provides hints to simplifications.
data IfSort
  = -- | An ordinary branch.
    IfNormal
  | -- | A branch where the "true" case is what we are
    -- actually interested in, and the "false" case is only
    -- present as a fallback for when the true case cannot
    -- be safely evaluated.  The compiler is permitted to
    -- optimise away the branch if the true case contains
    -- only safe statements.
    IfFallback
  | -- | Both of these branches are semantically equivalent,
    -- and it is fine to eliminate one if it turns out to
    -- have problems (e.g. contain things we cannot generate
    -- code for).
    IfEquiv
  deriving (IfSort -> IfSort -> Bool
(IfSort -> IfSort -> Bool)
-> (IfSort -> IfSort -> Bool) -> Eq IfSort
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IfSort -> IfSort -> Bool
$c/= :: IfSort -> IfSort -> Bool
== :: IfSort -> IfSort -> Bool
$c== :: IfSort -> IfSort -> Bool
Eq, Int -> IfSort -> ShowS
[IfSort] -> ShowS
IfSort -> String
(Int -> IfSort -> ShowS)
-> (IfSort -> String) -> ([IfSort] -> ShowS) -> Show IfSort
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IfSort] -> ShowS
$cshowList :: [IfSort] -> ShowS
show :: IfSort -> String
$cshow :: IfSort -> String
showsPrec :: Int -> IfSort -> ShowS
$cshowsPrec :: Int -> IfSort -> ShowS
Show, Eq IfSort
Eq IfSort
-> (IfSort -> IfSort -> Ordering)
-> (IfSort -> IfSort -> Bool)
-> (IfSort -> IfSort -> Bool)
-> (IfSort -> IfSort -> Bool)
-> (IfSort -> IfSort -> Bool)
-> (IfSort -> IfSort -> IfSort)
-> (IfSort -> IfSort -> IfSort)
-> Ord IfSort
IfSort -> IfSort -> Bool
IfSort -> IfSort -> Ordering
IfSort -> IfSort -> IfSort
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: IfSort -> IfSort -> IfSort
$cmin :: IfSort -> IfSort -> IfSort
max :: IfSort -> IfSort -> IfSort
$cmax :: IfSort -> IfSort -> IfSort
>= :: IfSort -> IfSort -> Bool
$c>= :: IfSort -> IfSort -> Bool
> :: IfSort -> IfSort -> Bool
$c> :: IfSort -> IfSort -> Bool
<= :: IfSort -> IfSort -> Bool
$c<= :: IfSort -> IfSort -> Bool
< :: IfSort -> IfSort -> Bool
$c< :: IfSort -> IfSort -> Bool
compare :: IfSort -> IfSort -> Ordering
$ccompare :: IfSort -> IfSort -> Ordering
$cp1Ord :: Eq IfSort
Ord)

-- | A type alias for namespace control.
type Exp = ExpT

-- | Anonymous function for use in a SOAC.
data LambdaT rep = Lambda
  { LambdaT rep -> [LParam rep]
lambdaParams :: [LParam rep],
    LambdaT rep -> BodyT rep
lambdaBody :: BodyT rep,
    LambdaT rep -> [Type]
lambdaReturnType :: [Type]
  }

deriving instance RepTypes rep => Eq (LambdaT rep)

deriving instance RepTypes rep => Show (LambdaT rep)

deriving instance RepTypes rep => Ord (LambdaT rep)

-- | Type alias for namespacing reasons.
type Lambda = LambdaT

-- | A function and loop parameter.
type FParam rep = Param (FParamInfo rep)

-- | A lambda parameter.
type LParam rep = Param (LParamInfo rep)

-- | Function Declarations
data FunDef rep = FunDef
  { -- | Contains a value if this function is
    -- an entry point.
    FunDef rep -> Maybe EntryPoint
funDefEntryPoint :: Maybe EntryPoint,
    FunDef rep -> Attrs
funDefAttrs :: Attrs,
    FunDef rep -> Name
funDefName :: Name,
    FunDef rep -> [RetType rep]
funDefRetType :: [RetType rep],
    FunDef rep -> [FParam rep]
funDefParams :: [FParam rep],
    FunDef rep -> BodyT rep
funDefBody :: BodyT rep
  }

deriving instance RepTypes rep => Eq (FunDef rep)

deriving instance RepTypes rep => Show (FunDef rep)

deriving instance RepTypes rep => Ord (FunDef rep)

-- | Every entry point argument and return value has an annotation
-- indicating how it maps to the original source program type.
data EntryPointType
  = -- | Is an unsigned integer or array of unsigned
    -- integers.
    TypeUnsigned Uniqueness
  | -- | A black box type comprising this many core
    -- values.  The string is a human-readable
    -- description with no other semantics.
    TypeOpaque Uniqueness String Int
  | -- | Maps directly.
    TypeDirect Uniqueness
  deriving (EntryPointType -> EntryPointType -> Bool
(EntryPointType -> EntryPointType -> Bool)
-> (EntryPointType -> EntryPointType -> Bool) -> Eq EntryPointType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EntryPointType -> EntryPointType -> Bool
$c/= :: EntryPointType -> EntryPointType -> Bool
== :: EntryPointType -> EntryPointType -> Bool
$c== :: EntryPointType -> EntryPointType -> Bool
Eq, Int -> EntryPointType -> ShowS
[EntryPointType] -> ShowS
EntryPointType -> String
(Int -> EntryPointType -> ShowS)
-> (EntryPointType -> String)
-> ([EntryPointType] -> ShowS)
-> Show EntryPointType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EntryPointType] -> ShowS
$cshowList :: [EntryPointType] -> ShowS
show :: EntryPointType -> String
$cshow :: EntryPointType -> String
showsPrec :: Int -> EntryPointType -> ShowS
$cshowsPrec :: Int -> EntryPointType -> ShowS
Show, Eq EntryPointType
Eq EntryPointType
-> (EntryPointType -> EntryPointType -> Ordering)
-> (EntryPointType -> EntryPointType -> Bool)
-> (EntryPointType -> EntryPointType -> Bool)
-> (EntryPointType -> EntryPointType -> Bool)
-> (EntryPointType -> EntryPointType -> Bool)
-> (EntryPointType -> EntryPointType -> EntryPointType)
-> (EntryPointType -> EntryPointType -> EntryPointType)
-> Ord EntryPointType
EntryPointType -> EntryPointType -> Bool
EntryPointType -> EntryPointType -> Ordering
EntryPointType -> EntryPointType -> EntryPointType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: EntryPointType -> EntryPointType -> EntryPointType
$cmin :: EntryPointType -> EntryPointType -> EntryPointType
max :: EntryPointType -> EntryPointType -> EntryPointType
$cmax :: EntryPointType -> EntryPointType -> EntryPointType
>= :: EntryPointType -> EntryPointType -> Bool
$c>= :: EntryPointType -> EntryPointType -> Bool
> :: EntryPointType -> EntryPointType -> Bool
$c> :: EntryPointType -> EntryPointType -> Bool
<= :: EntryPointType -> EntryPointType -> Bool
$c<= :: EntryPointType -> EntryPointType -> Bool
< :: EntryPointType -> EntryPointType -> Bool
$c< :: EntryPointType -> EntryPointType -> Bool
compare :: EntryPointType -> EntryPointType -> Ordering
$ccompare :: EntryPointType -> EntryPointType -> Ordering
$cp1Ord :: Eq EntryPointType
Ord)

-- | An entry point parameter, comprising its name and original type.
data EntryParam = EntryParam
  { EntryParam -> Name
entryParamName :: Name,
    EntryParam -> EntryPointType
entryParamType :: EntryPointType
  }
  deriving (EntryParam -> EntryParam -> Bool
(EntryParam -> EntryParam -> Bool)
-> (EntryParam -> EntryParam -> Bool) -> Eq EntryParam
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EntryParam -> EntryParam -> Bool
$c/= :: EntryParam -> EntryParam -> Bool
== :: EntryParam -> EntryParam -> Bool
$c== :: EntryParam -> EntryParam -> Bool
Eq, Int -> EntryParam -> ShowS
[EntryParam] -> ShowS
EntryParam -> String
(Int -> EntryParam -> ShowS)
-> (EntryParam -> String)
-> ([EntryParam] -> ShowS)
-> Show EntryParam
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EntryParam] -> ShowS
$cshowList :: [EntryParam] -> ShowS
show :: EntryParam -> String
$cshow :: EntryParam -> String
showsPrec :: Int -> EntryParam -> ShowS
$cshowsPrec :: Int -> EntryParam -> ShowS
Show, Eq EntryParam
Eq EntryParam
-> (EntryParam -> EntryParam -> Ordering)
-> (EntryParam -> EntryParam -> Bool)
-> (EntryParam -> EntryParam -> Bool)
-> (EntryParam -> EntryParam -> Bool)
-> (EntryParam -> EntryParam -> Bool)
-> (EntryParam -> EntryParam -> EntryParam)
-> (EntryParam -> EntryParam -> EntryParam)
-> Ord EntryParam
EntryParam -> EntryParam -> Bool
EntryParam -> EntryParam -> Ordering
EntryParam -> EntryParam -> EntryParam
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: EntryParam -> EntryParam -> EntryParam
$cmin :: EntryParam -> EntryParam -> EntryParam
max :: EntryParam -> EntryParam -> EntryParam
$cmax :: EntryParam -> EntryParam -> EntryParam
>= :: EntryParam -> EntryParam -> Bool
$c>= :: EntryParam -> EntryParam -> Bool
> :: EntryParam -> EntryParam -> Bool
$c> :: EntryParam -> EntryParam -> Bool
<= :: EntryParam -> EntryParam -> Bool
$c<= :: EntryParam -> EntryParam -> Bool
< :: EntryParam -> EntryParam -> Bool
$c< :: EntryParam -> EntryParam -> Bool
compare :: EntryParam -> EntryParam -> Ordering
$ccompare :: EntryParam -> EntryParam -> Ordering
$cp1Ord :: Eq EntryParam
Ord)

-- | Information about the inputs and outputs (return value) of an entry
-- point.
type EntryPoint = (Name, [EntryParam], [EntryPointType])

-- | An entire Futhark program.
data Prog rep = Prog
  { -- | Top-level constants that are computed at program startup, and
    -- which are in scope inside all functions.
    Prog rep -> Stms rep
progConsts :: Stms rep,
    -- | The functions comprising the program.  All funtions are also
    -- available in scope in the definitions of the constants, so be
    -- careful not to introduce circular dependencies (not currently
    -- checked).
    Prog rep -> [FunDef rep]
progFuns :: [FunDef rep]
  }
  deriving (Prog rep -> Prog rep -> Bool
(Prog rep -> Prog rep -> Bool)
-> (Prog rep -> Prog rep -> Bool) -> Eq (Prog rep)
forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Prog rep -> Prog rep -> Bool
$c/= :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
== :: Prog rep -> Prog rep -> Bool
$c== :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
Eq, Eq (Prog rep)
Eq (Prog rep)
-> (Prog rep -> Prog rep -> Ordering)
-> (Prog rep -> Prog rep -> Bool)
-> (Prog rep -> Prog rep -> Bool)
-> (Prog rep -> Prog rep -> Bool)
-> (Prog rep -> Prog rep -> Bool)
-> (Prog rep -> Prog rep -> Prog rep)
-> (Prog rep -> Prog rep -> Prog rep)
-> Ord (Prog rep)
Prog rep -> Prog rep -> Bool
Prog rep -> Prog rep -> Ordering
Prog rep -> Prog rep -> Prog rep
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall rep. RepTypes rep => Eq (Prog rep)
forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
forall rep. RepTypes rep => Prog rep -> Prog rep -> Ordering
forall rep. RepTypes rep => Prog rep -> Prog rep -> Prog rep
min :: Prog rep -> Prog rep -> Prog rep
$cmin :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Prog rep
max :: Prog rep -> Prog rep -> Prog rep
$cmax :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Prog rep
>= :: Prog rep -> Prog rep -> Bool
$c>= :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
> :: Prog rep -> Prog rep -> Bool
$c> :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
<= :: Prog rep -> Prog rep -> Bool
$c<= :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
< :: Prog rep -> Prog rep -> Bool
$c< :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Bool
compare :: Prog rep -> Prog rep -> Ordering
$ccompare :: forall rep. RepTypes rep => Prog rep -> Prog rep -> Ordering
$cp1Ord :: forall rep. RepTypes rep => Eq (Prog rep)
Ord, Int -> Prog rep -> ShowS
[Prog rep] -> ShowS
Prog rep -> String
(Int -> Prog rep -> ShowS)
-> (Prog rep -> String) -> ([Prog rep] -> ShowS) -> Show (Prog rep)
forall rep. RepTypes rep => Int -> Prog rep -> ShowS
forall rep. RepTypes rep => [Prog rep] -> ShowS
forall rep. RepTypes rep => Prog rep -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Prog rep] -> ShowS
$cshowList :: forall rep. RepTypes rep => [Prog rep] -> ShowS
show :: Prog rep -> String
$cshow :: forall rep. RepTypes rep => Prog rep -> String
showsPrec :: Int -> Prog rep -> ShowS
$cshowsPrec :: forall rep. RepTypes rep => Int -> Prog rep -> ShowS
Show)