alignArrays :: ProgC a -> ProgC a
alignArrays = go . view
  where
    go :: ProgramView TargetCMD (Param2 Prim PrimType') a -> ProgC a
    go (Return x) = unview (Return x)
    go (x :>>= y) = unview (align (traverse x) :>>= \r -> go (view (y r)))

    traverse :: forall a. TargetCMD TargetPrams a -> TargetCMD TargetPrams a
    traverse x = case (prj x :: Maybe (Imp.ControlCMD TargetPrams a)) of
        Just (Imp.If cond t f)     -> inj $ Imp.If cond (alignArrays t) (alignArrays f)
        Just (Imp.For range body)  -> inj $ Imp.For range (\i -> alignArrays (body i))
        Just (Imp.While cond body) -> inj $ Imp.While (alignArrays cond) (alignArrays body)
        _ -> x

    align :: forall a. TargetCMD TargetPrams a -> TargetCMD TargetPrams a
    align x = case (prj x :: Maybe (Imp.ArrCMD TargetPrams a)) of
        Just (Imp.NewArr   base len) -> inj $ Imp.NewCArr   base al len
        Just (Imp.ConstArr base as)  -> inj $ Imp.ConstCArr base al as
        _ -> x
      where
        al :: forall i. Integral i => Maybe i
        al = Just $ fromIntegral dmaAlign


--------------------------------------------------------------------------------
-- Core program main wrapper and declaration generator
--------------------------------------------------------------------------------
alignArrays :: ProgC a -> ProgC a
alignArrays = go . view
  where
    go :: ProgramView TargetCMD (Param2 Prim PrimType') a -> ProgC a
    go (Return x) = unview (Return x)
    go (x :>>= y) = unview (align (traverse x) :>>= \r -> go (view (y r)))

    traverse :: forall a. TargetCMD TargetPrams a -> TargetCMD TargetPrams a
    traverse x = case (prj x :: Maybe (Imp.ControlCMD TargetPrams a)) of
        Just (Imp.If cond t f)     -> inj $ Imp.If cond (alignArrays t) (alignArrays f)
        Just (Imp.For range body)  -> inj $ Imp.For range (\i -> alignArrays (body i))
        Just (Imp.While cond body) -> inj $ Imp.While (alignArrays cond) (alignArrays body)
        _ -> x

    align :: forall a. TargetCMD TargetPrams a -> TargetCMD TargetPrams a
    align x = case (prj x :: Maybe (Imp.ArrCMD TargetPrams a)) of
        Just (Imp.NewArr   base len) -> inj $ Imp.NewCArr   base al len
        Just (Imp.ConstArr base as)  -> inj $ Imp.ConstCArr base al as
        _ -> x
      where
        al :: forall i. Integral i => Maybe i
        al = Just $ fromIntegral dmaAlign


--------------------------------------------------------------------------------
-- Core program main wrapper and declaration generator
--------------------------------------------------------------------------------
alignArrays = go . view
  where
    go :: ProgramView TargetCMD (Param2 Prim PrimType') a -> ProgC a
    go (Return x) = unview (Return x)
    go (x :>>= y) = unview (align (traverse x) :>>= \r -> go (view (y r)))

    traverse :: forall a. TargetCMD TargetPrams a -> TargetCMD TargetPrams a
    traverse x = case (prj x :: Maybe (Imp.ControlCMD TargetPrams a)) of
        Just (Imp.If cond t f)     -> inj $ Imp.If cond (alignArrays t) (alignArrays f)
        Just (Imp.For range body)  -> inj $ Imp.For range (\i -> alignArrays (body i))
        Just (Imp.While cond body) -> inj $ Imp.While (alignArrays cond) (alignArrays body)
        _ -> x

    align :: forall a. TargetCMD TargetPrams a -> TargetCMD TargetPrams a
    align x = case (prj x :: Maybe (Imp.ArrCMD TargetPrams a)) of
        Just (Imp.NewArr   base len) -> inj $ Imp.NewCArr   base al len
        Just (Imp.ConstArr base as)  -> inj $ Imp.ConstCArr base al as
        _ -> x
      where
        al :: forall i. Integral i => Maybe i
        al = Just $ fromIntegral dmaAlign


--------------------------------------------------------------------------------
-- Core program main wrapper and declaration generator
--------------------------------------------------------------------------------