<commit_before>{-|

Some template haskell helper functions. For speed considerations we
often need to unroll computations. Typing such unrolled definitions
are repeatitive and error prone. This module provides Template Haskell
based functions to eliminate some of these. For function definitions,
also consider using the INLINE pragma.

-}

module Raaz.Util.TH
       ( constants
       , matrix
       , variable, variable', variableGen
       , signature
       , permute
       -- * Subscripting variables.
       -- $subscripting
       , sub, subE, subP
       ) where

import Control.Monad
import Data.List(intercalate)
import Language.Haskell.TH
import Language.Haskell.TH.Syntax(Lift(..))

-- | Declare a list of constants. For example the expression
-- @constants "k" ''Int [1, 1 ,2, 3]@ will lead to the following
-- declarations.
--
-- > k_0 :: Int
-- > k_0 = 1
-- > k_1 :: Int
-- > k_1 = 1
-- > k_2 :: Int
-- > k_2 = 2
-- > k_3 :: Int
-- > k_3 = 3
--
-- This combinator gives an easy way of declaring round constants in a
-- cryptographic algorithm.
constants :: Lift val
          => String  -- ^ variable name.
          -> Name    -- ^ the type of the variable
          -> [val]   -- ^ the values
          -> DecsQ
constants = constantP []


-- | A matrix variant of `constants`: @matrix "k" ''Int [[0,1],[2,3]]@ gives
-- the declaration
--
-- > k_0_0 :: Int
-- > k_0_0 = 0
-- > ...
-- > ...
-- > k_1_1 :: Int
-- > k_1_1 = 3
matrix :: Lift val
       => String    -- ^ the base name of the variable
       -> Name      -- ^ the type of the variable
       -> [[val]]   -- ^ the value matrix
       -> DecsQ
matrix k ty = fmap concat . zipWithM outer [0..]
  where outer i = constantP [i] k ty


-- | Worker function to define constants.
constantP :: Lift v
          => [Int]
          -> String
          -> Name
          -> [v]
          -> DecsQ
constantP is k ty = fmap concat . zipWithM inner [0..]
   where inner i v = sequence [ signature k ty index
                              , variable  k (const $ lift v) index
                              ]
               where index = is ++ [i]

-- | The expression @signature "x" ''Int [1,2]@ declares the following
-- type signature.
--
-- > x_1_2 :: Int
--
signature :: String -> Name -> [Int] -> DecQ
signature k ty is = sigD (k `sub` is) $ conT ty


-- | Generate a variable definition. The expression @variable "x" exp [1,2]@
-- will result in a declaration that looks like
--
-- > x_1_2 = [| $(exp [1,2]) |]
--
--
variable :: String          -- ^ Variable name
         -> ([Int] -> ExpQ) -- ^ the rhs of the variable
         -> [Int]           -- ^ subscript
         -> DecQ
variable k rhs is = valD (k `subP` is)
                         (normalB $ rhs is)
                         []

-- | Genrates a variable definition and type signature.
variable' :: String          -- ^ Variable name
          -> Name            -- ^ Type
          -> ([Int] -> ExpQ) -- ^ The rhs of the variable definition
          -> [Int]           -- ^ The subscript
          -> DecsQ
variable' k ty rhs is = variableGen k (conT ty) rhs is


-- | The most general type of variable declaration.
variableGen :: String          -- ^ Variable name
            -> TypeQ           -- ^ Type signature
            -> ([Int] -> ExpQ) -- ^ The rhs of the variable definition
            -> [Int]           -- ^ The subscript
            -> DecsQ
variableGen k ty rhs is = sequence [ sigD (k `sub` is) ty
                                   , variable k rhs is
                                   ]

-- | The TH expression @permute [("x", "y"), ("u","v")] 5@ declares
-- the following variables
--
-- > x_5 = y_4<commit_msg>added a generic signature definition functions<commit_after>{-|

Some template haskell helper functions. For speed considerations we
often need to unroll computations. Typing such unrolled definitions
are repeatitive and error prone. This module provides Template Haskell
based functions to eliminate some of these. For function definitions,
also consider using the INLINE pragma.

-}

module Raaz.Util.TH
       ( constants
       , matrix
       , variable, variable', variableGen
       , signature, signatureGen
       , permute
       -- * Subscripting variables.
       -- $subscripting
       , sub, subE, subP
       ) where

import Control.Monad
import Data.List(intercalate)
import Language.Haskell.TH
import Language.Haskell.TH.Syntax(Lift(..))

-- | Declare a list of constants. For example the expression
-- @constants "k" ''Int [1, 1 ,2, 3]@ will lead to the following
-- declarations.
--
-- > k_0 :: Int
-- > k_0 = 1
-- > k_1 :: Int
-- > k_1 = 1
-- > k_2 :: Int
-- > k_2 = 2
-- > k_3 :: Int
-- > k_3 = 3
--
-- This combinator gives an easy way of declaring round constants in a
-- cryptographic algorithm.
constants :: Lift val
          => String  -- ^ variable name.
          -> Name    -- ^ the type of the variable
          -> [val]   -- ^ the values
          -> DecsQ
constants = constantP []


-- | A matrix variant of `constants`: @matrix "k" ''Int [[0,1],[2,3]]@ gives
-- the declaration
--
-- > k_0_0 :: Int
-- > k_0_0 = 0
-- > ...
-- > ...
-- > k_1_1 :: Int
-- > k_1_1 = 3
matrix :: Lift val
       => String    -- ^ the base name of the variable
       -> Name      -- ^ the type of the variable
       -> [[val]]   -- ^ the value matrix
       -> DecsQ
matrix k ty = fmap concat . zipWithM outer [0..]
  where outer i = constantP [i] k ty


-- | Worker function to define constants.
constantP :: Lift v
          => [Int]
          -> String
          -> Name
          -> [v]
          -> DecsQ
constantP is k ty = fmap concat . zipWithM inner [0..]
   where inner i v = sequence [ signature k ty index
                              , variable  k (const $ lift v) index
                              ]
               where index = is ++ [i]

-- | The expression @signature "x" ''Int [1,2]@ declares the following
-- type signature.
--
-- > x_1_2 :: Int
--
signature :: String   -- ^ Variable name
          -> Name     -- ^ The type name
          -> [Int]    -- ^ The subscript
          -> DecQ
signature k ty is = signatureGen k (conT ty) is

-- | A more general version of `signature`.
signatureGen :: String   -- ^ The variable
             -> TypeQ    -- ^ The type
             -> [Int]    -- ^ The subscript
             -> DecQ
signatureGen k ty is = sigD (k `sub` is) $ ty


-- | Generate a variable definition. The expression @variable "x" exp [1,2]@
-- will result in a declaration that looks like
--
-- > x_1_2 = [| $(exp [1,2]) |]
--
--
variable :: String          -- ^ Variable name
         -> ([Int] -> ExpQ) -- ^ the rhs of the variable
         -> [Int]           -- ^ subscript
         -> DecQ
variable k rhs is = valD (k `subP` is)
                         (normalB $ rhs is)
                         []

-- | Genrates a variable definition and type signature.
variable' :: String          -- ^ Variable name
          -> Name            -- ^ Type
          -> ([Int] -> ExpQ) -- ^ The rhs of the variable definition
          -> [Int]           -- ^ The subscript
          -> DecsQ
variable' k ty rhs is = variableGen k (conT ty) rhs is


-- | The most general type of variable declaration.
variableGen :: String          -- ^ Variable name
            -> TypeQ           -- ^ Type signature
            -> ([Int] -> ExpQ) -- ^ The rhs of the variable definition
            -> [Int]           -- ^ The subscript
            -> DecsQ
variableGen k ty rhs is = sequence [ signatureGen k ty is
                                   , variable k rhs is
                                   ]

-- | The TH expression @permute [("x", "y"), ("u","v")] 5@ declares
-- the following variables
--
-- > x_5 = y_4
{'fraction_non_alphanumeric': 0.12974232811083775, 'fraction_numerical': 0.011653502524925547, 'mean_word_length': 1.628999319264806, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6864594', 'n_tokens_mistral': 2295, 'n_tokens_neox': 2223, 'n_words': 838}