    {-# LANGUAGE TypeFamilies #-}

    -- | Transform any SOACs to @for@-loops.
    --
    -- Example:
    --
    -- @
    -- let ys = map (\x -> x + 2) xs
    -- @
    --
    -- becomes something like:
    --
    -- @
    -- let out = scratch n i32
    -- let ys =
    --   loop (ys' = out) for i < n do
    --     let x = xs[i]
    --     let y = x + 2
    --     let ys'[i] = y
    --     in ys'
    -- @
    module Futhark.Pass.FirstOrderTransform (firstOrderTransform) where

    import Futhark.IR.SOACS (SOACS, scopeOf)
    import Futhark.Pass
    import Futhark.Transform.FirstOrderTransform (FirstOrderRep, transformConsts, transformFunDef)

    -- | The first-order transformation pass.
    firstOrderTransform :: (FirstOrderRep rep) => Pass SOACS rep
    firstOrderTransform :: forall rep. FirstOrderRep rep => Pass SOACS rep
    firstOrderTransform =
      String
    -> String -> (Prog SOACS -> PassM (Prog rep)) -> Pass SOACS rep
    forall fromrep torep.
    String
    -> String
    -> (Prog fromrep -> PassM (Prog torep))
    -> Pass fromrep torep
    Pass
        String
    "first order transform"
        String
    "Transform all SOACs to for-loops."
        ((Prog SOACS -> PassM (Prog rep)) -> Pass SOACS rep)
    -> (Prog SOACS -> PassM (Prog rep)) -> Pass SOACS rep
    forall a b. (a -> b) -> a -> b
    $ (Stms SOACS -> PassM (Stms rep))
    -> (Stms rep -> FunDef SOACS -> PassM (FunDef rep))
    -> Prog SOACS
    -> PassM (Prog rep)
    forall fromrep torep.
    (Stms fromrep -> PassM (Stms torep))
    -> (Stms torep -> FunDef fromrep -> PassM (FunDef torep))
    -> Prog fromrep
    -> PassM (Prog torep)
    intraproceduralTransformationWithConsts
          Stms SOACS -> PassM (Stms rep)
    forall (m :: * -> *) torep.
    (MonadFreshNames m, FirstOrderRep torep) =>
    Stms SOACS -> m (Stms torep)
    transformConsts
          (Scope rep -> FunDef SOACS -> PassM (FunDef rep)
    forall (m :: * -> *) torep.
    (MonadFreshNames m, FirstOrderRep torep) =>
    Scope torep -> FunDef SOACS -> m (FunDef torep)
    transformFunDef (Scope rep -> FunDef SOACS -> PassM (FunDef rep))
    -> (Stms rep -> Scope rep)
    -> Stms rep
    -> FunDef SOACS
    -> PassM (FunDef rep)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Stms rep -> Scope rep
    forall rep a. Scoped rep a => a -> Scope rep
    scopeOf)