{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ExistentialQuantification #-}
module Data.Array.Knead.Symbolic.Render.Argument (
   Arg.T(Arg.Cons),
   Arg.unit,
   Arg.primitive,
   Arg.pair,
   Arg.triple,
   array,
   ) where

import qualified Data.Array.Knead.Symbolic.Physical as Phys
import qualified Data.Array.Knead.Symbolic.Private as Core
import qualified Data.Array.Knead.Shape as Shape
import qualified Data.Array.Knead.Expression as Expr
import Data.Array.Knead.Code (getElementPtr)

import qualified Data.Array.Comfort.Storable.Unchecked as Array

import qualified LLVM.DSL.Render.Argument as Arg
import LLVM.DSL.Expression (unExp)

import qualified LLVM.Extra.Multi.Value.Storable as Storable
import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
import qualified LLVM.Extra.Multi.Value as MultiValue

import Foreign.ForeignPtr (withForeignPtr, touchForeignPtr)

import Prelude2010
import Prelude ()



array ::
   (Shape.C sh, Marshal.C sh, Storable.C a) =>
   Arg.T (Phys.Array sh a) (Core.Array sh a)
array =
   Arg.Cons
      (Expr.uncurry $ \esh eptr ->
         Core.Array esh
            (\ix -> do
               sh <- unExp esh
               MultiValue.Cons ptr <- unExp eptr
               Storable.load =<< getElementPtr sh ptr ix))
      (\(Array.Array sh fptr) ->
         withForeignPtr fptr $ \ptr ->
         return ((sh, ptr), touchForeignPtr fptr))