-- | A `Procedure` is an abstract imperative loop nest. -- The loops are represented as a separated loop anatomy, to make it -- easy to incrementally build them from a data flow graph expressed -- as a `Process`. -- module DDC.Core.Flow.Procedure ( Procedure (..) , Nest (..) , Context (..) , StmtStart (..) , StmtBody (..) , StmtEnd (..)) where import DDC.Core.Flow.Exp import DDC.Core.Flow.Prim import DDC.Core.Flow.Context import Data.Monoid -- | An imperative procedure made up of some loops. data Procedure = Procedure { procedureName :: Name , procedureParamTypes :: [BindF] , procedureParamValues :: [BindF] , procedureNest :: Nest } -- | A loop nest. data Nest = NestEmpty | NestList { nestList :: [Nest]} -- Used to define the outer loop of a process. | NestLoop { nestRate :: Type Name , nestStart :: [StmtStart] , nestBody :: [StmtBody] , nestInner :: Nest , nestEnd :: [StmtEnd] , nestResult :: Exp () Name } -- Guarded context, -- used when lowering pack-like operations. | NestGuard { nestOuterRate :: Type Name , nestInnerRate :: Type Name , nestFlags :: Bound Name , nestBody :: [StmtBody] , nestInner :: Nest } -- Segmented context, -- used when lowering segmented operations. | NestSegment { nestOuterRate :: Type Name , nestInnerRate :: Type Name , nestLength :: Bound Name , nestBody :: [StmtBody] , nestInner :: Nest } deriving Show instance Monoid Nest where mempty = NestEmpty mappend n1 n2 = case (n1, n2) of (NestEmpty, _) -> n2 (_, NestEmpty) -> n1 (NestList ns1, NestList ns2) -> NestList (ns1 ++ ns2) (NestList ns1, _) -> NestList (ns1 ++ [n2]) (_, NestList ns2) -> NestList (n1 : ns2) (_, _) -> NestList [n1, n2] -- | Statements that can appear at the start of a loop. -- These initialise accumulators. data StmtStart -- | Evaluate a pure expression = StartStmt { startResultBind :: Bind Name , startExpression :: Exp () Name } -- | Allocate a new vector. | StartVecNew { startVecNewName :: Name , startVecNewElemType :: Type Name , startVecNewRate :: Type Name } -- | Inititlise a new accumulator. | StartAcc { startAccName :: Name , startAccType :: Type Name , startAccExp :: Exp () Name } deriving Show -- | Statements that appear in the body of a loop. data StmtBody -- | Evaluate a pure expression. = BodyStmt { -- | Bind for the result bodyResultBind :: Bind Name -- | Expression to evaluate , bodyExpression :: Exp () Name } -- | Write to a vector. | BodyVecWrite { -- | Name of the vector. bodyVecName :: Name -- | Type of the element. , bodyVecWriteElemType :: Type Name -- | Expression for the index to write to. , bodyVecWriteIx :: Exp () Name -- | Expression for the value to write. , bodyVecWriteVal :: Exp () Name } -- | Read from an accumulator. | BodyAccRead { -- | Name of the accumulator. bodyAccName :: Name -- | Type of the accumulator. , bodyAccType :: Type Name -- | Binder for the read value. , bodyAccNameBind :: Bind Name } -- | Body of an accumulation operation. -- Writes to the accumulator. | BodyAccWrite { -- | Name of the accumulator. bodyAccName :: Name -- | Type of the accumulator. , bodyAccType :: Type Name -- | Expression to update the accumulator. , bodyAccExp :: Exp () Name } deriving Show -- | Statements that appear after a loop to cleanup. data StmtEnd -- | Generic ending statements. = EndStmt { endBind :: Bind Name , endExp :: Exp () Name } -- | Read the result of an accumulator. | EndAcc { endName :: Name , endType :: Type Name , endAccName :: Name } -- | Destructively truncate a vector to its final size. | EndVecTrunc { endVecName :: Name , endVecType :: Type Name , endVecRate :: Type Name } deriving Show