{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
-- |
-- Module      : Data.Array.Accelerate.Debug.Trace
-- Copyright   : [2008..2020] The Accelerate Team
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- Functions for tracing and monitoring execution. These are useful for
-- investigating bugs.
--
-- @since 1.4.0.0
--

module Data.Array.Accelerate.Debug.Trace (

  -- * Tracing
  -- $tracing
  --
  atrace, atraceArray, atraceId, atraceExp,

) where

import Data.Array.Accelerate.Language
import Data.Array.Accelerate.Smart
import Data.Array.Accelerate.Sugar.Array                            as S
import Data.Array.Accelerate.Sugar.Elt
import qualified Data.Array.Accelerate.Representation.Array         as R
import qualified Data.Array.Accelerate.Representation.Shape         as R

import Data.Text


-- $tracing
--
-- The 'atrace', 'atraceArray', 'atraceId', and 'atraceExp' functions print
-- messages to an output stream. They are intended for \"printf
-- debugging\", that is: tracing the flow of execution and printing
-- interesting values.
--
-- Note that arrays are printed in their internal representation (using
-- 'Data.Array.Accelerate.Sugar.Array.ArraysR'), which causes that tuples
-- or custom data types are shown differently.
--
-- These functions have the same caveats as those defined in "Debug.Trace".
--

-- | Outputs the trace message to the console before the 'Acc' computation
-- proceeds with the result of the second argument.
--
atrace :: Arrays a => Text -> Acc a -> Acc a
atrace :: forall a. Arrays a => Text -> Acc a -> Acc a
atrace Text
message (Acc SmartAcc (ArraysR a)
result)
  = SmartAcc (ArraysR a) -> Acc a
forall a. SmartAcc (ArraysR a) -> Acc a
Acc
  (SmartAcc (ArraysR a) -> Acc a) -> SmartAcc (ArraysR a) -> Acc a
forall a b. (a -> b) -> a -> b
$ PreSmartAcc SmartAcc SmartExp (ArraysR a) -> SmartAcc (ArraysR a)
forall a. PreSmartAcc SmartAcc SmartExp a -> SmartAcc a
SmartAcc
  (PreSmartAcc SmartAcc SmartExp (ArraysR a) -> SmartAcc (ArraysR a))
-> PreSmartAcc SmartAcc SmartExp (ArraysR a)
-> SmartAcc (ArraysR a)
forall a b. (a -> b) -> a -> b
$ Message ()
-> SmartAcc ()
-> SmartAcc (ArraysR a)
-> PreSmartAcc SmartAcc SmartExp (ArraysR a)
forall arrs1 (acc :: * -> *) as (exp :: * -> *).
Message arrs1 -> acc arrs1 -> acc as -> PreSmartAcc acc exp as
Atrace ((() -> String)
-> Maybe (CodeQ (() -> String)) -> Text -> Message ()
forall a.
(a -> String) -> Maybe (CodeQ (a -> String)) -> Text -> Message a
Message (\()
_ -> String
"")
           (CodeQ (() -> String) -> Maybe (CodeQ (() -> String))
forall a. a -> Maybe a
Just [|| \p
_ -> a
"" ||]) Text
message) (PreSmartAcc SmartAcc SmartExp () -> SmartAcc ()
forall a. PreSmartAcc SmartAcc SmartExp a -> SmartAcc a
SmartAcc PreSmartAcc SmartAcc SmartExp ()
forall (acc :: * -> *) (exp :: * -> *). PreSmartAcc acc exp ()
Anil :: SmartAcc ()) SmartAcc (ArraysR a)
result

-- | Outputs the trace message and the array(s) from the second argument to
-- the console, before the 'Acc' computation proceeds with the result of
-- the third argument.
--
atraceArray :: forall a b. (Arrays a, Arrays b, Show a) => Text -> Acc a -> Acc b -> Acc b
atraceArray :: forall a b.
(Arrays a, Arrays b, Show a) =>
Text -> Acc a -> Acc b -> Acc b
atraceArray Text
message (Acc SmartAcc (ArraysR a)
inspect) (Acc SmartAcc (ArraysR b)
result)
  = SmartAcc (ArraysR b) -> Acc b
forall a. SmartAcc (ArraysR a) -> Acc a
Acc
  (SmartAcc (ArraysR b) -> Acc b) -> SmartAcc (ArraysR b) -> Acc b
forall a b. (a -> b) -> a -> b
$ PreSmartAcc SmartAcc SmartExp (ArraysR b) -> SmartAcc (ArraysR b)
forall a. PreSmartAcc SmartAcc SmartExp a -> SmartAcc a
SmartAcc
  (PreSmartAcc SmartAcc SmartExp (ArraysR b) -> SmartAcc (ArraysR b))
-> PreSmartAcc SmartAcc SmartExp (ArraysR b)
-> SmartAcc (ArraysR b)
forall a b. (a -> b) -> a -> b
$ Message (ArraysR a)
-> SmartAcc (ArraysR a)
-> SmartAcc (ArraysR b)
-> PreSmartAcc SmartAcc SmartExp (ArraysR b)
forall arrs1 (acc :: * -> *) as (exp :: * -> *).
Message arrs1 -> acc arrs1 -> acc as -> PreSmartAcc acc exp as
Atrace ((ArraysR a -> String)
-> Maybe (CodeQ (ArraysR a -> String))
-> Text
-> Message (ArraysR a)
forall a.
(a -> String) -> Maybe (CodeQ (a -> String)) -> Text -> Message a
Message (a -> String
forall a. Show a => a -> String
show (a -> String) -> (ArraysR a -> a) -> ArraysR a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Arrays a => ArraysR a -> a
toArr @a)
           (CodeQ (ArraysR a -> String) -> Maybe (CodeQ (ArraysR a -> String))
forall a. a -> Maybe a
Just [|| a -> String
forall a. Show a => a -> String
show (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Arrays a => ArraysR a -> a
toArr @a ||]) Text
message) SmartAcc (ArraysR a)
inspect SmartAcc (ArraysR b)
result

-- | Outputs the trace message and the array(s) to the console, before the
-- 'Acc' computation proceeds with the result of that array.
--
atraceId :: (Arrays a, Show a) => Text -> Acc a -> Acc a
atraceId :: forall a. (Arrays a, Show a) => Text -> Acc a -> Acc a
atraceId Text
message Acc a
value = Text -> Acc a -> Acc a -> Acc a
forall a b.
(Arrays a, Arrays b, Show a) =>
Text -> Acc a -> Acc b -> Acc b
atraceArray Text
message Acc a
value Acc a
value

-- | Outputs the trace message and a scalar value to the console, before
-- the 'Acc' computation proceeds with the result of the third argument.
--
atraceExp :: forall e a. (Elt e, Show e, Arrays a) => Text -> Exp e -> Acc a -> Acc a
atraceExp :: forall e a.
(Elt e, Show e, Arrays a) =>
Text -> Exp e -> Acc a -> Acc a
atraceExp Text
message Exp e
value (Acc SmartAcc (ArraysR a)
result) =
  let Acc SmartAcc (ArraysR (Scalar e))
inspect = Exp e -> Acc (Scalar e)
forall e. Elt e => Exp e -> Acc (Scalar e)
unit Exp e
value
   in SmartAcc (ArraysR a) -> Acc a
forall a. SmartAcc (ArraysR a) -> Acc a
Acc
    (SmartAcc (ArraysR a) -> Acc a) -> SmartAcc (ArraysR a) -> Acc a
forall a b. (a -> b) -> a -> b
$ PreSmartAcc SmartAcc SmartExp (ArraysR a) -> SmartAcc (ArraysR a)
forall a. PreSmartAcc SmartAcc SmartExp a -> SmartAcc a
SmartAcc
    (PreSmartAcc SmartAcc SmartExp (ArraysR a) -> SmartAcc (ArraysR a))
-> PreSmartAcc SmartAcc SmartExp (ArraysR a)
-> SmartAcc (ArraysR a)
forall a b. (a -> b) -> a -> b
$ Message (Array () (EltR e))
-> SmartAcc (Array () (EltR e))
-> SmartAcc (ArraysR a)
-> PreSmartAcc SmartAcc SmartExp (ArraysR a)
forall arrs1 (acc :: * -> *) as (exp :: * -> *).
Message arrs1 -> acc arrs1 -> acc as -> PreSmartAcc acc exp as
Atrace ((Array () (EltR e) -> String)
-> Maybe (CodeQ (Array () (EltR e) -> String))
-> Text
-> Message (Array () (EltR e))
forall a.
(a -> String) -> Maybe (CodeQ (a -> String)) -> Text -> Message a
Message (\Array () (EltR e)
a -> e -> String
forall a. Show a => a -> String
show (forall a. Elt a => EltR a -> a
toElt @e (ArrayR (Array () (EltR e)) -> Array () (EltR e) -> () -> EltR e
forall sh e. ArrayR (Array sh e) -> Array sh e -> sh -> e
R.indexArray (ShapeR () -> TypeR (EltR e) -> ArrayR (Array () (EltR e))
forall sh e. ShapeR sh -> TypeR e -> ArrayR (Array sh e)
R.ArrayR ShapeR ()
R.dim0 (forall a. Elt a => TypeR (EltR a)
eltR @e)) Array () (EltR e)
a ())))
             (CodeQ (Array () (EltR e) -> String)
-> Maybe (CodeQ (Array () (EltR e) -> String))
forall a. a -> Maybe a
Just [|| \p
a -> a -> String
forall a. Show a => a -> String
show (forall a. Elt a => EltR a -> a
toElt @e (ArrayR (Array sh e) -> Array sh e -> sh -> e
forall sh e. ArrayR (Array sh e) -> Array sh e -> sh -> e
R.indexArray (ShapeR sh -> TypeR e -> ArrayR (Array sh e)
forall sh e. ShapeR sh -> TypeR e -> ArrayR (Array sh e)
R.ArrayR ShapeR ()
R.dim0 (forall a. Elt a => TypeR (EltR a)
eltR @e)) p
a ())) ||]) Text
message) SmartAcc (Array () (EltR e))
inspect SmartAcc (ArraysR a)
result