futhark-0.9.1: src/Futhark/Representation/AST/Syntax.hs
{-# LANGUAGE TypeFamilies, FlexibleContexts, FlexibleInstances, StandaloneDeriving #-}
-- | Futhark core language skeleton. Concrete representations further
-- extend this skeleton by defining a "lore", which specifies concrete
-- annotations ("Futhark.Representation.AST.Annotations") and
-- semantics.
module Futhark.Representation.AST.Syntax
(
module Language.Futhark.Core
, module Futhark.Representation.AST.Annotations
, module Futhark.Representation.AST.Syntax.Core
-- * Types
, Uniqueness(..)
, NoUniqueness(..)
, Rank(..)
, ArrayShape(..)
, Space (..)
, TypeBase(..)
, Diet(..)
-- * Abstract syntax tree
, Ident (..)
, SubExp(..)
, PatElem
, PatElemT (..)
, PatternT (..)
, Pattern
, StmAux(..)
, Stm(..)
, Stms
, Result
, BodyT(..)
, Body
, BasicOp (..)
, UnOp (..)
, BinOp (..)
, CmpOp (..)
, ConvOp (..)
, DimChange (..)
, ShapeChange
, ExpT(..)
, Exp
, LoopForm (..)
, IfAttr (..)
, IfSort (..)
, Safety (..)
, LambdaT(..)
, Lambda
-- * Definitions
, ParamT (..)
, FParam
, LParam
, FunDefT (..)
, FunDef
, EntryPoint
, EntryPointType(..)
, ProgT(..)
, Prog
-- * Utils
, oneStm
, stmsFromList
, stmsToList
, stmsHead
)
where
import Data.Foldable
import Data.Loc
import qualified Data.Sequence as Seq
import Language.Futhark.Core
import Futhark.Representation.AST.Annotations
import Futhark.Representation.AST.Syntax.Core
-- | A type alias for namespace control.
type PatElem lore = PatElemT (LetAttr lore)
-- | A pattern is conceptually just a list of names and their types.
data PatternT attr =
Pattern { patternContextElements :: [PatElemT attr]
-- ^ existential context (sizes and memory blocks)
, patternValueElements :: [PatElemT attr]
-- ^ "real" values
}
deriving (Ord, Show, Eq)
instance Functor PatternT where
fmap f (Pattern ctx val) = Pattern (map (fmap f) ctx) (map (fmap f) val)
instance Semigroup (PatternT attr) where
Pattern cs1 vs1 <> Pattern cs2 vs2 = Pattern (cs1++cs2) (vs1++vs2)
instance Monoid (PatternT attr) where
mempty = Pattern [] []
-- | A type alias for namespace control.
type Pattern lore = PatternT (LetAttr lore)
-- | Auxilliary Information associated with a statement.
data StmAux attr = StmAux { stmAuxCerts :: !Certificates
, stmAuxAttr :: attr
}
deriving (Ord, Show, Eq)
-- | A local variable binding.
data Stm lore = Let { stmPattern :: Pattern lore
, stmAux :: StmAux (ExpAttr lore)
, stmExp :: Exp lore
}
deriving instance Annotations lore => Ord (Stm lore)
deriving instance Annotations lore => Show (Stm lore)
deriving instance Annotations lore => Eq (Stm lore)
-- | A sequence of statements.
type Stms lore = Seq.Seq (Stm lore)
oneStm :: Stm lore -> Stms lore
oneStm = Seq.singleton
stmsFromList :: [Stm lore] -> Stms lore
stmsFromList = Seq.fromList
stmsToList :: Stms lore -> [Stm lore]
stmsToList = toList
stmsHead :: Stms lore -> Maybe (Stm lore, Stms lore)
stmsHead stms = case Seq.viewl stms of stm Seq.:< stms' -> Just (stm, stms')
Seq.EmptyL -> Nothing
-- | The result of a body is a sequence of subexpressions.
type Result = [SubExp]
-- | A body consists of a number of bindings, terminating in a result
-- (essentially a tuple literal).
data BodyT lore = Body { bodyAttr :: BodyAttr lore
, bodyStms :: Stms lore
, bodyResult :: Result
}
deriving instance Annotations lore => Ord (BodyT lore)
deriving instance Annotations lore => Show (BodyT lore)
deriving instance Annotations lore => Eq (BodyT lore)
-- | 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 = DimCoercion d
-- ^ The new dimension is guaranteed to be numerically
-- equal to the old one.
| DimNew d
-- ^ The new dimension is not necessarily numerically
-- equal to the old one.
deriving (Ord, Show)
instance Eq d => Eq (DimChange d) where
DimCoercion x == DimNew y = x == y
DimCoercion x == DimCoercion y = x == y
DimNew x == DimCoercion y = x == y
DimNew x == DimNew y = x == y
instance Functor DimChange where
fmap f (DimCoercion d) = DimCoercion $ f d
fmap f (DimNew d) = DimNew $ f d
instance Foldable DimChange where
foldMap f (DimCoercion d) = f d
foldMap f (DimNew d) = f d
instance Traversable DimChange where
traverse f (DimCoercion d) = DimCoercion <$> f d
traverse f (DimNew d) = DimNew <$> f d
-- | A list of 'DimChange's, indicating the new dimensions of an array.
type ShapeChange d = [DimChange d]
-- | A primitive operation that returns something of known size and
-- does not itself contain any bindings.
data BasicOp lore
= SubExp SubExp
-- ^ A variable or constant.
| Opaque SubExp
-- ^ Semantically and operationally just identity, but is
-- invisible/impenetrable to optimisations (hopefully). This is
-- just a hack to avoid optimisation (so, to work around compiler
-- limitations).
| ArrayLit [SubExp] Type
-- ^ Array literals, e.g., @[ [1+x, 3], [2, 1+4] ]@.
-- Second arg is the element type of the rows of the array.
-- Scalar operations
| UnOp UnOp SubExp
-- ^ Unary operation.
| BinOp BinOp SubExp SubExp
-- ^ Binary operation.
| CmpOp CmpOp SubExp SubExp
-- ^ Comparison - result type is always boolean.
| ConvOp ConvOp SubExp
-- ^ Conversion "casting".
| Assert SubExp (ErrorMsg SubExp) (SrcLoc, [SrcLoc])
-- ^ Turn a boolean into a certificate, halting the program with the
-- given error message if the boolean is false.
-- Primitive array operations
| Index VName (Slice SubExp)
-- ^ The certificates for bounds-checking are part of the 'Stm'.
| Update VName (Slice SubExp) SubExp
-- ^ An in-place update of the given array at the given position.
-- Consumes the array.
| Concat Int VName [VName] SubExp
-- ^ @concat@0([1],[2, 3, 4]) = [1, 2, 3, 4]@.
| Copy VName
-- ^ Copy the given array. The result will not alias anything.
| Manifest [Int] VName
-- ^ Manifest an array with dimensions represented in the given
-- order. The result will not alias anything.
-- Array construction.
| Iota SubExp SubExp SubExp IntType
-- ^ @iota(n, x, s) = [x,x+s,..,x+(n-1)*s]@.
--
-- The 'IntType' indicates the type of the array returned and the
-- offset/stride arguments, but not the length argument.
| Replicate Shape SubExp
-- ^ @replicate([3][2],1) = [[1,1], [1,1], [1,1]]@
| Repeat [Shape] Shape VName
-- ^ Repeat each dimension of the input array some number of times,
-- given by the corresponding shape. For an array of rank @k@, the
-- list must contain @k@ shapes. A shape may be empty (in which
-- case the dimension is not repeated, but it is still present).
-- The last shape indicates the amount of extra innermost
-- dimensions. All other extra dimensions are added *before* the original dimension.
| Scratch PrimType [SubExp]
-- ^ Create array of given type and shape, with undefined elements.
-- Array index space transformation.
| Reshape (ShapeChange SubExp) VName
-- ^ 1st arg is the new shape, 2nd arg is the input array *)
| Rearrange [Int] 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.
| Rotate [SubExp] 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.
deriving (Eq, Ord, Show)
-- | The root Futhark expression type. The 'Op' constructor contains
-- a lore-specific operation. Do-loops, branches and function calls
-- are special. Everything else is a simple 'BasicOp'.
data ExpT lore
= BasicOp (BasicOp lore)
-- ^ A simple (non-recursive) operation.
| Apply Name [(SubExp, Diet)] [RetType lore] (Safety, SrcLoc, [SrcLoc])
| If SubExp (BodyT lore) (BodyT lore) (IfAttr (BranchType lore))
| DoLoop [(FParam lore, SubExp)] [(FParam lore, SubExp)] (LoopForm lore) (BodyT lore)
-- ^ @loop {a} = {v} (for i < n|while b) do b@. The merge
-- parameters are divided into context and value part.
| Op (Op lore)
deriving instance Annotations lore => Eq (ExpT lore)
deriving instance Annotations lore => Show (ExpT lore)
deriving instance Annotations lore => Ord (ExpT lore)
-- | Whether something is safe or unsafe (mostly function calls, and
-- in the context of whether operations are dynamically checked).
-- When we inline an 'Unsafe' function, we remove all safety checks in
-- its body. The 'Ord' instance picks 'Unsafe' as being less than
-- 'Safe'.
data Safety = Unsafe | Safe deriving (Eq, Ord, Show)
-- | For-loop or while-loop?
data LoopForm lore = ForLoop VName IntType SubExp [(LParam lore,VName)]
| WhileLoop VName
deriving instance Annotations lore => Eq (LoopForm lore)
deriving instance Annotations lore => Show (LoopForm lore)
deriving instance Annotations lore => Ord (LoopForm lore)
-- | Data associated with a branch.
data IfAttr rt = IfAttr { ifReturns :: [rt]
, ifSort :: IfSort
}
deriving (Eq, Show, Ord)
data IfSort = IfNormal -- ^ An ordinary branch.
| IfFallback -- ^ 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.
deriving (Eq, Show, Ord)
-- | A type alias for namespace control.
type Exp = ExpT
-- | Anonymous function for use in a SOAC.
data LambdaT lore = Lambda { lambdaParams :: [LParam lore]
, lambdaBody :: BodyT lore
, lambdaReturnType :: [Type]
}
deriving instance Annotations lore => Eq (LambdaT lore)
deriving instance Annotations lore => Show (LambdaT lore)
deriving instance Annotations lore => Ord (LambdaT lore)
-- | Type alias for namespacing reasons.
type Lambda = LambdaT
type FParam lore = ParamT (FParamAttr lore)
type LParam lore = ParamT (LParamAttr lore)
-- | Function Declarations
data FunDefT lore = FunDef { funDefEntryPoint :: Maybe EntryPoint
-- ^ Contains a value if this function is
-- an entry point.
, funDefName :: Name
, funDefRetType :: [RetType lore]
, funDefParams :: [FParam lore]
, funDefBody :: BodyT lore
}
deriving instance Annotations lore => Eq (FunDefT lore)
deriving instance Annotations lore => Show (FunDefT lore)
deriving instance Annotations lore => Ord (FunDefT lore)
-- | Information about the parameters and return value of an entry
-- point. The first element is for parameters, the second for return
-- value.
type EntryPoint = ([EntryPointType], [EntryPointType])
-- | Every entry point argument and return value has an annotation
-- indicating how it maps to the original source program type.
data EntryPointType = TypeUnsigned
-- ^ Is an unsigned integer or array of unsigned
-- integers.
| TypeOpaque String Int
-- ^ A black box type comprising this many core
-- values. The string is a human-readable
-- description with no other semantics.
| TypeDirect
-- ^ Maps directly.
deriving (Eq, Show, Ord)
-- | Type alias for namespace reasons.
type FunDef = FunDefT
-- | An entire Futhark program.
newtype ProgT lore = Prog { progFunctions :: [FunDef lore] }
deriving (Eq, Ord, Show)
-- | Type alias for namespace reasons.
type Prog = ProgT