{-
   Copyright 2016, Dominic Orchard, Andrew Rice, Mistral Contrastin, Matthew Danish

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-}

{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}

module Camfort.Specification.Stencils.Syntax
  (
    -- * Datatypes and Aliases
    Linearity(..)
  , Region(..)
  , RegionDecl
  , RegionEnv
  , RegionProd(..)
  , RegionSum(..)
  , Spatial(..)
  , SpecDecl
  , SpecDecls
  , Specification(..)
  , IsStencil
  , Variable
    -- * Functions
  , absoluteRep
  , fromBool
  , groupKeyBy
  , hasDuplicates
  , isEmpty
  , isUnit
  , pprintSpecDecls
  , setLinearity
  ) where

import Camfort.Specification.Stencils.Model ( Multiplicity(..)
                                            , peel
                                            , Approximation(..)
                                            )

import Prelude hiding (sum)

import Data.Data
import Data.List hiding (sum)
import Control.Applicative

type Variable = String

{-  Contains the syntax representation for stencil specifications -}

{- *** 0. Representations -}

-- 'absoluteRep' is an integer to use to represent absolute indexing expressions
-- (which may be constants, non-affine indexing expressions, or expressions
--  involving non-induction variables). This is set to maxBoound :: Int usually,
-- but can be made smaller for debugging purposes,
-- e.g., 100, but it needs to be high enough to clash with reasonable
-- relative indices.
absoluteRep :: Int
absoluteRep :: Int
absoluteRep = Int
forall a. Bounded a => a
maxBound

{- *** 1 . Specification syntax -}

type RegionDecl = (Variable, RegionSum)
type SpecDecl   = ([Variable], Specification)

-- List of region sums associated to region variables
type RegionEnv = [(Variable, RegionSum)]

-- List of specifications associated to variables
-- This is not a map so there might be multiple entries for each variable
-- use `lookupAggregate` to access it
type SpecDecls = [SpecDecl]

pprintSpecDecls :: SpecDecls -> String
pprintSpecDecls :: SpecDecls -> String
pprintSpecDecls =
 (([String], Specification) -> String) -> SpecDecls -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\([String]
names, Specification
spec) ->
            Specification -> String
forall a. Show a => a -> String
show Specification
spec String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" :: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," [String]
names String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n")

-- Top-level of specifications: may be either spatial or temporal

-- | `isStencil` is used to mark whether a specification is associated
-- | with a stencil computation, or a general array computation
type IsStencil = Bool

data Specification =
  Specification (Multiplicity (Approximation Spatial)) IsStencil
    deriving (Specification -> Specification -> Bool
(Specification -> Specification -> Bool)
-> (Specification -> Specification -> Bool) -> Eq Specification
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Specification -> Specification -> Bool
$c/= :: Specification -> Specification -> Bool
== :: Specification -> Specification -> Bool
$c== :: Specification -> Specification -> Bool
Eq, Typeable Specification
DataType
Constr
Typeable Specification
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Specification -> c Specification)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Specification)
-> (Specification -> Constr)
-> (Specification -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Specification))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c Specification))
-> ((forall b. Data b => b -> b) -> Specification -> Specification)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Specification -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Specification -> r)
-> (forall u. (forall d. Data d => d -> u) -> Specification -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> Specification -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Specification -> m Specification)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Specification -> m Specification)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Specification -> m Specification)
-> Data Specification
Specification -> DataType
Specification -> Constr
(forall b. Data b => b -> b) -> Specification -> Specification
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Specification -> c Specification
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Specification
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Specification -> u
forall u. (forall d. Data d => d -> u) -> Specification -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Specification -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Specification -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Specification -> m Specification
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Specification -> m Specification
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Specification
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Specification -> c Specification
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Specification)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c Specification)
$cSpecification :: Constr
$tSpecification :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Specification -> m Specification
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Specification -> m Specification
gmapMp :: (forall d. Data d => d -> m d) -> Specification -> m Specification
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Specification -> m Specification
gmapM :: (forall d. Data d => d -> m d) -> Specification -> m Specification
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Specification -> m Specification
gmapQi :: Int -> (forall d. Data d => d -> u) -> Specification -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Specification -> u
gmapQ :: (forall d. Data d => d -> u) -> Specification -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Specification -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Specification -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Specification -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Specification -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Specification -> r
gmapT :: (forall b. Data b => b -> b) -> Specification -> Specification
$cgmapT :: (forall b. Data b => b -> b) -> Specification -> Specification
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c Specification)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c Specification)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Specification)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Specification)
dataTypeOf :: Specification -> DataType
$cdataTypeOf :: Specification -> DataType
toConstr :: Specification -> Constr
$ctoConstr :: Specification -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Specification
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Specification
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Specification -> c Specification
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Specification -> c Specification
$cp1Data :: Typeable Specification
Data, Typeable)

isEmpty :: Specification -> Bool
isEmpty :: Specification -> Bool
isEmpty (Specification Multiplicity (Approximation Spatial)
mult Bool
_) = Approximation Spatial -> Bool
forall t. RegionRig t => t -> Bool
isUnit (Approximation Spatial -> Bool)
-> (Multiplicity (Approximation Spatial) -> Approximation Spatial)
-> Multiplicity (Approximation Spatial)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Multiplicity (Approximation Spatial) -> Approximation Spatial
forall a. Peelable a => a -> CoreTyp a
peel (Multiplicity (Approximation Spatial) -> Bool)
-> Multiplicity (Approximation Spatial) -> Bool
forall a b. (a -> b) -> a -> b
$ Multiplicity (Approximation Spatial)
mult

-- **********************
-- Spatial specifications:
-- is a regionSum
--
-- Regions are in disjunctive normal form (with respect to
--  products on dimensions and sums):
--    i.e., (A * B) U (C * D)...
data Spatial = Spatial RegionSum
  deriving (Spatial -> Spatial -> Bool
(Spatial -> Spatial -> Bool)
-> (Spatial -> Spatial -> Bool) -> Eq Spatial
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Spatial -> Spatial -> Bool
$c/= :: Spatial -> Spatial -> Bool
== :: Spatial -> Spatial -> Bool
$c== :: Spatial -> Spatial -> Bool
Eq, Typeable Spatial
DataType
Constr
Typeable Spatial
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Spatial -> c Spatial)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Spatial)
-> (Spatial -> Constr)
-> (Spatial -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Spatial))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Spatial))
-> ((forall b. Data b => b -> b) -> Spatial -> Spatial)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Spatial -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Spatial -> r)
-> (forall u. (forall d. Data d => d -> u) -> Spatial -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Spatial -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Spatial -> m Spatial)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Spatial -> m Spatial)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Spatial -> m Spatial)
-> Data Spatial
Spatial -> DataType
Spatial -> Constr
(forall b. Data b => b -> b) -> Spatial -> Spatial
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Spatial -> c Spatial
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Spatial
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Spatial -> u
forall u. (forall d. Data d => d -> u) -> Spatial -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Spatial -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Spatial -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Spatial -> m Spatial
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Spatial -> m Spatial
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Spatial
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Spatial -> c Spatial
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Spatial)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Spatial)
$cSpatial :: Constr
$tSpatial :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Spatial -> m Spatial
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Spatial -> m Spatial
gmapMp :: (forall d. Data d => d -> m d) -> Spatial -> m Spatial
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Spatial -> m Spatial
gmapM :: (forall d. Data d => d -> m d) -> Spatial -> m Spatial
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Spatial -> m Spatial
gmapQi :: Int -> (forall d. Data d => d -> u) -> Spatial -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Spatial -> u
gmapQ :: (forall d. Data d => d -> u) -> Spatial -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Spatial -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Spatial -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Spatial -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Spatial -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Spatial -> r
gmapT :: (forall b. Data b => b -> b) -> Spatial -> Spatial
$cgmapT :: (forall b. Data b => b -> b) -> Spatial -> Spatial
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Spatial)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Spatial)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Spatial)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Spatial)
dataTypeOf :: Spatial -> DataType
$cdataTypeOf :: Spatial -> DataType
toConstr :: Spatial -> Constr
$ctoConstr :: Spatial -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Spatial
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Spatial
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Spatial -> c Spatial
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Spatial -> c Spatial
$cp1Data :: Typeable Spatial
Data, Typeable)

-- Helpers for dealing with linearity information

-- A boolean is used to represent multiplicity in the backend
-- with False = multiplicity=1 and True = multiplicity > 1
fromBool :: Bool -> Linearity
fromBool :: Bool -> Linearity
fromBool Bool
True = Linearity
NonLinear
fromBool Bool
False = Linearity
Linear

hasDuplicates :: Eq a => [a] -> ([a], Bool)
hasDuplicates :: [a] -> ([a], Bool)
hasDuplicates [a]
xs = ([a] -> [a]
forall a. Eq a => [a] -> [a]
nub [a]
xs, [a] -> [a]
forall a. Eq a => [a] -> [a]
nub [a]
xs [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
/= [a]
xs)

setLinearity :: Linearity -> Specification -> Specification
setLinearity :: Linearity -> Specification -> Specification
setLinearity Linearity
l (Specification Multiplicity (Approximation Spatial)
mult Bool
isStencil)
  | Linearity
l Linearity -> Linearity -> Bool
forall a. Eq a => a -> a -> Bool
== Linearity
Linear    = Multiplicity (Approximation Spatial) -> Bool -> Specification
Specification (Approximation Spatial -> Multiplicity (Approximation Spatial)
forall a. a -> Multiplicity a
Once (Approximation Spatial -> Multiplicity (Approximation Spatial))
-> Approximation Spatial -> Multiplicity (Approximation Spatial)
forall a b. (a -> b) -> a -> b
$ Multiplicity (Approximation Spatial)
-> CoreTyp (Multiplicity (Approximation Spatial))
forall a. Peelable a => a -> CoreTyp a
peel Multiplicity (Approximation Spatial)
mult) Bool
isStencil
  | Linearity
l Linearity -> Linearity -> Bool
forall a. Eq a => a -> a -> Bool
== Linearity
NonLinear = Multiplicity (Approximation Spatial) -> Bool -> Specification
Specification (Approximation Spatial -> Multiplicity (Approximation Spatial)
forall a. a -> Multiplicity a
Mult (Approximation Spatial -> Multiplicity (Approximation Spatial))
-> Approximation Spatial -> Multiplicity (Approximation Spatial)
forall a b. (a -> b) -> a -> b
$ Multiplicity (Approximation Spatial)
-> CoreTyp (Multiplicity (Approximation Spatial))
forall a. Peelable a => a -> CoreTyp a
peel Multiplicity (Approximation Spatial)
mult) Bool
isStencil
  | Bool
otherwise      = String -> Specification
forall a. HasCallStack => String -> a
error String
"setLinearity: impossible"

data Linearity = Linear | NonLinear deriving (Linearity -> Linearity -> Bool
(Linearity -> Linearity -> Bool)
-> (Linearity -> Linearity -> Bool) -> Eq Linearity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Linearity -> Linearity -> Bool
$c/= :: Linearity -> Linearity -> Bool
== :: Linearity -> Linearity -> Bool
$c== :: Linearity -> Linearity -> Bool
Eq, Typeable Linearity
DataType
Constr
Typeable Linearity
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Linearity -> c Linearity)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Linearity)
-> (Linearity -> Constr)
-> (Linearity -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Linearity))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Linearity))
-> ((forall b. Data b => b -> b) -> Linearity -> Linearity)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Linearity -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Linearity -> r)
-> (forall u. (forall d. Data d => d -> u) -> Linearity -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> Linearity -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Linearity -> m Linearity)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Linearity -> m Linearity)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Linearity -> m Linearity)
-> Data Linearity
Linearity -> DataType
Linearity -> Constr
(forall b. Data b => b -> b) -> Linearity -> Linearity
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Linearity -> c Linearity
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Linearity
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Linearity -> u
forall u. (forall d. Data d => d -> u) -> Linearity -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Linearity -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Linearity -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Linearity -> m Linearity
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Linearity -> m Linearity
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Linearity
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Linearity -> c Linearity
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Linearity)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Linearity)
$cNonLinear :: Constr
$cLinear :: Constr
$tLinearity :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Linearity -> m Linearity
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Linearity -> m Linearity
gmapMp :: (forall d. Data d => d -> m d) -> Linearity -> m Linearity
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Linearity -> m Linearity
gmapM :: (forall d. Data d => d -> m d) -> Linearity -> m Linearity
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Linearity -> m Linearity
gmapQi :: Int -> (forall d. Data d => d -> u) -> Linearity -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Linearity -> u
gmapQ :: (forall d. Data d => d -> u) -> Linearity -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Linearity -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Linearity -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Linearity -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Linearity -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Linearity -> r
gmapT :: (forall b. Data b => b -> b) -> Linearity -> Linearity
$cgmapT :: (forall b. Data b => b -> b) -> Linearity -> Linearity
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Linearity)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Linearity)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Linearity)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Linearity)
dataTypeOf :: Linearity -> DataType
$cdataTypeOf :: Linearity -> DataType
toConstr :: Linearity -> Constr
$ctoConstr :: Linearity -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Linearity
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Linearity
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Linearity -> c Linearity
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Linearity -> c Linearity
$cp1Data :: Typeable Linearity
Data, Typeable)

type Dimension  = Int -- spatial dimensions are 1 indexed
type Depth      = Int
type IsRefl     = Bool

-- Individual regions
data Region where
    Forward  :: Depth -> Dimension -> IsRefl -> Region
    Backward :: Depth -> Dimension -> IsRefl -> Region
    Centered :: Depth -> Dimension -> IsRefl -> Region
  deriving (Region -> Region -> Bool
(Region -> Region -> Bool)
-> (Region -> Region -> Bool) -> Eq Region
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Region -> Region -> Bool
$c/= :: Region -> Region -> Bool
== :: Region -> Region -> Bool
$c== :: Region -> Region -> Bool
Eq, Typeable Region
DataType
Constr
Typeable Region
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Region -> c Region)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Region)
-> (Region -> Constr)
-> (Region -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Region))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Region))
-> ((forall b. Data b => b -> b) -> Region -> Region)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Region -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Region -> r)
-> (forall u. (forall d. Data d => d -> u) -> Region -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Region -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Region -> m Region)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Region -> m Region)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Region -> m Region)
-> Data Region
Region -> DataType
Region -> Constr
(forall b. Data b => b -> b) -> Region -> Region
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Region -> c Region
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Region
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Region -> u
forall u. (forall d. Data d => d -> u) -> Region -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Region -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Region -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Region -> m Region
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Region -> m Region
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Region
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Region -> c Region
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Region)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Region)
$cCentered :: Constr
$cBackward :: Constr
$cForward :: Constr
$tRegion :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Region -> m Region
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Region -> m Region
gmapMp :: (forall d. Data d => d -> m d) -> Region -> m Region
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Region -> m Region
gmapM :: (forall d. Data d => d -> m d) -> Region -> m Region
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Region -> m Region
gmapQi :: Int -> (forall d. Data d => d -> u) -> Region -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Region -> u
gmapQ :: (forall d. Data d => d -> u) -> Region -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Region -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Region -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Region -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Region -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Region -> r
gmapT :: (forall b. Data b => b -> b) -> Region -> Region
$cgmapT :: (forall b. Data b => b -> b) -> Region -> Region
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Region)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Region)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Region)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Region)
dataTypeOf :: Region -> DataType
$cdataTypeOf :: Region -> DataType
toConstr :: Region -> Constr
$ctoConstr :: Region -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Region
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Region
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Region -> c Region
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Region -> c Region
$cp1Data :: Typeable Region
Data, Typeable)

-- An (arbitrary) ordering on regions for the sake of normalisation
instance Ord Region where
  (Forward Int
dep Int
dim Bool
_) <= :: Region -> Region -> Bool
<= (Forward Int
dep' Int
dim' Bool
_)
    | Int
dep Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
dep' = Int
dim Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dim'
    | Bool
otherwise   = Int
dep Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dep'

  (Backward Int
dep Int
dim Bool
_) <= (Backward Int
dep' Int
dim' Bool
_)
    | Int
dep Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
dep' = Int
dim Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dim'
    | Bool
otherwise   = Int
dep Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dep'

  (Centered Int
dep Int
dim Bool
_) <= (Centered Int
dep' Int
dim' Bool
_)
    | Int
dep Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
dep' = Int
dim Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dim'
    | Bool
otherwise   = Int
dep Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dep'

  -- Order in the way defined above: Forward <: Backward <: Centered
  Forward{}  <= Region
_          = Bool
True
  Backward{} <= Centered{} = Bool
True
  Region
_          <= Region
_          = Bool
False

-- Product of specifications
newtype RegionProd = Product {RegionProd -> [Region]
unProd :: [Region]}
  deriving (RegionProd -> RegionProd -> Bool
(RegionProd -> RegionProd -> Bool)
-> (RegionProd -> RegionProd -> Bool) -> Eq RegionProd
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RegionProd -> RegionProd -> Bool
$c/= :: RegionProd -> RegionProd -> Bool
== :: RegionProd -> RegionProd -> Bool
$c== :: RegionProd -> RegionProd -> Bool
Eq, Typeable RegionProd
DataType
Constr
Typeable RegionProd
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> RegionProd -> c RegionProd)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c RegionProd)
-> (RegionProd -> Constr)
-> (RegionProd -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c RegionProd))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c RegionProd))
-> ((forall b. Data b => b -> b) -> RegionProd -> RegionProd)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> RegionProd -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> RegionProd -> r)
-> (forall u. (forall d. Data d => d -> u) -> RegionProd -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> RegionProd -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> RegionProd -> m RegionProd)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> RegionProd -> m RegionProd)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> RegionProd -> m RegionProd)
-> Data RegionProd
RegionProd -> DataType
RegionProd -> Constr
(forall b. Data b => b -> b) -> RegionProd -> RegionProd
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionProd -> c RegionProd
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionProd
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> RegionProd -> u
forall u. (forall d. Data d => d -> u) -> RegionProd -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RegionProd -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RegionProd -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionProd
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionProd -> c RegionProd
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RegionProd)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionProd)
$cProduct :: Constr
$tRegionProd :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
gmapMp :: (forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
gmapM :: (forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RegionProd -> m RegionProd
gmapQi :: Int -> (forall d. Data d => d -> u) -> RegionProd -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> RegionProd -> u
gmapQ :: (forall d. Data d => d -> u) -> RegionProd -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> RegionProd -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RegionProd -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RegionProd -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RegionProd -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RegionProd -> r
gmapT :: (forall b. Data b => b -> b) -> RegionProd -> RegionProd
$cgmapT :: (forall b. Data b => b -> b) -> RegionProd -> RegionProd
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionProd)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionProd)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c RegionProd)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RegionProd)
dataTypeOf :: RegionProd -> DataType
$cdataTypeOf :: RegionProd -> DataType
toConstr :: RegionProd -> Constr
$ctoConstr :: RegionProd -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionProd
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionProd
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionProd -> c RegionProd
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionProd -> c RegionProd
$cp1Data :: Typeable RegionProd
Data, Typeable)

-- Sum of product specifications
newtype RegionSum = Sum {RegionSum -> [RegionProd]
unSum :: [RegionProd]}
  deriving (RegionSum -> RegionSum -> Bool
(RegionSum -> RegionSum -> Bool)
-> (RegionSum -> RegionSum -> Bool) -> Eq RegionSum
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RegionSum -> RegionSum -> Bool
$c/= :: RegionSum -> RegionSum -> Bool
== :: RegionSum -> RegionSum -> Bool
$c== :: RegionSum -> RegionSum -> Bool
Eq, Typeable RegionSum
DataType
Constr
Typeable RegionSum
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> RegionSum -> c RegionSum)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c RegionSum)
-> (RegionSum -> Constr)
-> (RegionSum -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c RegionSum))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionSum))
-> ((forall b. Data b => b -> b) -> RegionSum -> RegionSum)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> RegionSum -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> RegionSum -> r)
-> (forall u. (forall d. Data d => d -> u) -> RegionSum -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> RegionSum -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> RegionSum -> m RegionSum)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> RegionSum -> m RegionSum)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> RegionSum -> m RegionSum)
-> Data RegionSum
RegionSum -> DataType
RegionSum -> Constr
(forall b. Data b => b -> b) -> RegionSum -> RegionSum
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionSum -> c RegionSum
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionSum
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> RegionSum -> u
forall u. (forall d. Data d => d -> u) -> RegionSum -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RegionSum -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RegionSum -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionSum
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionSum -> c RegionSum
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RegionSum)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionSum)
$cSum :: Constr
$tRegionSum :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
gmapMp :: (forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
gmapM :: (forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> RegionSum -> m RegionSum
gmapQi :: Int -> (forall d. Data d => d -> u) -> RegionSum -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> RegionSum -> u
gmapQ :: (forall d. Data d => d -> u) -> RegionSum -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> RegionSum -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RegionSum -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> RegionSum -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RegionSum -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> RegionSum -> r
gmapT :: (forall b. Data b => b -> b) -> RegionSum -> RegionSum
$cgmapT :: (forall b. Data b => b -> b) -> RegionSum -> RegionSum
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionSum)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c RegionSum)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c RegionSum)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c RegionSum)
dataTypeOf :: RegionSum -> DataType
$cdataTypeOf :: RegionSum -> DataType
toConstr :: RegionSum -> Constr
$ctoConstr :: RegionSum -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionSum
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c RegionSum
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionSum -> c RegionSum
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> RegionSum -> c RegionSum
$cp1Data :: Typeable RegionSum
Data, Typeable)

instance Ord RegionProd where
   (Product [Region]
xs) <= :: RegionProd -> RegionProd -> Bool
<= (Product [Region]
xs') = [Region]
xs [Region] -> [Region] -> Bool
forall a. Ord a => a -> a -> Bool
<= [Region]
xs'


-- Operations on specifications

-- Operations on region specifications form a semiring
--  where `sum` is the additive, and `prod` is the multiplicative
--  [without the annihilation property for `zero` with multiplication]
class RegionRig t where
  sum  :: t -> t -> t
  prod :: t -> t -> t
  one  :: t
  zero :: t
  isUnit :: t -> Bool

-- Lifting to the `Maybe` constructor
instance RegionRig a => RegionRig (Maybe a) where
  sum :: Maybe a -> Maybe a -> Maybe a
sum (Just a
x) (Just a
y) = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ a -> a -> a
forall t. RegionRig t => t -> t -> t
sum a
x a
y
  sum Maybe a
x Maybe a
Nothing = Maybe a
x
  sum Maybe a
Nothing Maybe a
x = Maybe a
x

  prod :: Maybe a -> Maybe a -> Maybe a
prod (Just a
x) (Just a
y) = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ a -> a -> a
forall t. RegionRig t => t -> t -> t
prod a
x a
y
  prod Maybe a
x Maybe a
Nothing = Maybe a
x
  prod Maybe a
Nothing Maybe a
x = Maybe a
x

  one :: Maybe a
one  = a -> Maybe a
forall a. a -> Maybe a
Just a
forall t. RegionRig t => t
one
  zero :: Maybe a
zero = a -> Maybe a
forall a. a -> Maybe a
Just a
forall t. RegionRig t => t
zero

  isUnit :: Maybe a -> Bool
isUnit Maybe a
Nothing = Bool
True
  isUnit (Just a
x) = a -> Bool
forall t. RegionRig t => t -> Bool
isUnit a
x

instance RegionRig Spatial where
  sum :: Spatial -> Spatial -> Spatial
sum (Spatial RegionSum
s) (Spatial RegionSum
s') = RegionSum -> Spatial
Spatial (RegionSum -> RegionSum -> RegionSum
forall t. RegionRig t => t -> t -> t
sum RegionSum
s RegionSum
s')

  prod :: Spatial -> Spatial -> Spatial
prod (Spatial RegionSum
s) (Spatial RegionSum
s') = RegionSum -> Spatial
Spatial (RegionSum -> RegionSum -> RegionSum
forall t. RegionRig t => t -> t -> t
prod RegionSum
s RegionSum
s')

  one :: Spatial
one = RegionSum -> Spatial
Spatial RegionSum
forall t. RegionRig t => t
one
  zero :: Spatial
zero = RegionSum -> Spatial
Spatial RegionSum
forall t. RegionRig t => t
zero

  isUnit :: Spatial -> Bool
isUnit (Spatial RegionSum
ss) = RegionSum -> Bool
forall t. RegionRig t => t -> Bool
isUnit RegionSum
ss

instance RegionRig (Approximation Spatial) where
  sum :: Approximation Spatial
-> Approximation Spatial -> Approximation Spatial
sum (Exact Spatial
s) (Exact Spatial
s')      = Spatial -> Approximation Spatial
forall a. a -> Approximation a
Exact (Spatial -> Spatial -> Spatial
forall t. RegionRig t => t -> t -> t
sum Spatial
s Spatial
s')
  sum (Exact Spatial
s) (Bound Maybe Spatial
l Maybe Spatial
u)     = Maybe Spatial -> Maybe Spatial -> Approximation Spatial
forall a. Maybe a -> Maybe a -> Approximation a
Bound (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
sum (Spatial -> Maybe Spatial
forall a. a -> Maybe a
Just Spatial
s) Maybe Spatial
l) (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
sum (Spatial -> Maybe Spatial
forall a. a -> Maybe a
Just Spatial
s) Maybe Spatial
u)
  sum (Bound Maybe Spatial
l Maybe Spatial
u) (Bound Maybe Spatial
l' Maybe Spatial
u') = Maybe Spatial -> Maybe Spatial -> Approximation Spatial
forall a. Maybe a -> Maybe a -> Approximation a
Bound (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
sum Maybe Spatial
l Maybe Spatial
l') (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
sum Maybe Spatial
u Maybe Spatial
u')
  sum Approximation Spatial
s Approximation Spatial
s'                      = Approximation Spatial
-> Approximation Spatial -> Approximation Spatial
forall t. RegionRig t => t -> t -> t
sum Approximation Spatial
s' Approximation Spatial
s

  prod :: Approximation Spatial
-> Approximation Spatial -> Approximation Spatial
prod (Exact Spatial
s) (Exact Spatial
s')      = Spatial -> Approximation Spatial
forall a. a -> Approximation a
Exact (Spatial -> Spatial -> Spatial
forall t. RegionRig t => t -> t -> t
prod Spatial
s Spatial
s')
  prod (Exact Spatial
s) (Bound Maybe Spatial
l Maybe Spatial
u)     = Maybe Spatial -> Maybe Spatial -> Approximation Spatial
forall a. Maybe a -> Maybe a -> Approximation a
Bound (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
prod (Spatial -> Maybe Spatial
forall a. a -> Maybe a
Just Spatial
s) Maybe Spatial
l) (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
prod (Spatial -> Maybe Spatial
forall a. a -> Maybe a
Just Spatial
s) Maybe Spatial
u)
  prod (Bound Maybe Spatial
l Maybe Spatial
u) (Bound Maybe Spatial
l' Maybe Spatial
u') = Maybe Spatial -> Maybe Spatial -> Approximation Spatial
forall a. Maybe a -> Maybe a -> Approximation a
Bound (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
prod Maybe Spatial
l Maybe Spatial
l') (Maybe Spatial -> Maybe Spatial -> Maybe Spatial
forall t. RegionRig t => t -> t -> t
prod Maybe Spatial
u Maybe Spatial
u') -- (prod l u') (prod l' u))
  prod Approximation Spatial
s Approximation Spatial
s'                      = Approximation Spatial
-> Approximation Spatial -> Approximation Spatial
forall t. RegionRig t => t -> t -> t
prod Approximation Spatial
s' Approximation Spatial
s

  one :: Approximation Spatial
one  = Spatial -> Approximation Spatial
forall a. a -> Approximation a
Exact Spatial
forall t. RegionRig t => t
one
  zero :: Approximation Spatial
zero = Spatial -> Approximation Spatial
forall a. a -> Approximation a
Exact Spatial
forall t. RegionRig t => t
zero

  isUnit :: Approximation Spatial -> Bool
isUnit (Exact Spatial
s) = Spatial -> Bool
forall t. RegionRig t => t -> Bool
isUnit Spatial
s
  isUnit (Bound Maybe Spatial
x Maybe Spatial
y) = Maybe Spatial -> Bool
forall t. RegionRig t => t -> Bool
isUnit Maybe Spatial
x Bool -> Bool -> Bool
&& Maybe Spatial -> Bool
forall t. RegionRig t => t -> Bool
isUnit Maybe Spatial
y

instance RegionRig RegionSum where
  prod :: RegionSum -> RegionSum -> RegionSum
prod (Sum [RegionProd]
ss) (Sum [RegionProd]
ss') =
   [RegionProd] -> RegionSum
Sum ([RegionProd] -> RegionSum) -> [RegionProd] -> RegionSum
forall a b. (a -> b) -> a -> b
$ [RegionProd] -> [RegionProd]
forall a. Eq a => [a] -> [a]
nub ([RegionProd] -> [RegionProd]) -> [RegionProd] -> [RegionProd]
forall a b. (a -> b) -> a -> b
$ -- Take the cross product of list of summed specifications
     do (Product [Region]
spec) <- [RegionProd]
ss
        (Product [Region]
spec') <- [RegionProd]
ss'
        RegionProd -> [RegionProd]
forall (m :: * -> *) a. Monad m => a -> m a
return (RegionProd -> [RegionProd]) -> RegionProd -> [RegionProd]
forall a b. (a -> b) -> a -> b
$ [Region] -> RegionProd
Product ([Region] -> RegionProd) -> [Region] -> RegionProd
forall a b. (a -> b) -> a -> b
$ [Region] -> [Region]
forall a. Eq a => [a] -> [a]
nub ([Region] -> [Region]) -> [Region] -> [Region]
forall a b. (a -> b) -> a -> b
$ [Region] -> [Region]
forall a. Ord a => [a] -> [a]
sort ([Region] -> [Region]) -> [Region] -> [Region]
forall a b. (a -> b) -> a -> b
$ [Region]
spec [Region] -> [Region] -> [Region]
forall a. [a] -> [a] -> [a]
++ [Region]
spec'
  sum :: RegionSum -> RegionSum -> RegionSum
sum (Sum [RegionProd]
ss) (Sum [RegionProd]
ss') = [RegionProd] -> RegionSum
Sum ([RegionProd] -> RegionSum) -> [RegionProd] -> RegionSum
forall a b. (a -> b) -> a -> b
$ [RegionProd]
ss [RegionProd] -> [RegionProd] -> [RegionProd]
forall a. [a] -> [a] -> [a]
++ [RegionProd]
ss'
  zero :: RegionSum
zero = [RegionProd] -> RegionSum
Sum []
  one :: RegionSum
one = [RegionProd] -> RegionSum
Sum [[Region] -> RegionProd
Product []]
  isUnit :: RegionSum -> Bool
isUnit s :: RegionSum
s@(Sum [RegionProd]
ss) = RegionSum
s RegionSum -> RegionSum -> Bool
forall a. Eq a => a -> a -> Bool
== RegionSum
forall t. RegionRig t => t
zero Bool -> Bool -> Bool
|| RegionSum
s RegionSum -> RegionSum -> Bool
forall a. Eq a => a -> a -> Bool
== RegionSum
forall t. RegionRig t => t
one Bool -> Bool -> Bool
|| (RegionProd -> Bool) -> [RegionProd] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (RegionProd -> RegionProd -> Bool
forall a. Eq a => a -> a -> Bool
== [Region] -> RegionProd
Product []) [RegionProd]
ss

-- Pretty print top-level specifications
instance Show Specification where
  show :: Specification -> String
show (Specification Multiplicity (Approximation Spatial)
sp Bool
True)  = String
"stencil " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Multiplicity (Approximation Spatial) -> String
forall a. Show a => a -> String
show Multiplicity (Approximation Spatial)
sp
  show (Specification Multiplicity (Approximation Spatial)
sp Bool
False) = String
"access " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Multiplicity (Approximation Spatial) -> String
forall a. Show a => a -> String
show Multiplicity (Approximation Spatial)
sp

instance {-# OVERLAPS #-} Show (Multiplicity (Approximation Spatial)) where
  show :: Multiplicity (Approximation Spatial) -> String
show Multiplicity (Approximation Spatial)
mult
    | Mult Approximation Spatial
appr <- Multiplicity (Approximation Spatial)
mult = String -> String -> Approximation Spatial -> String
forall a. Show a => String -> String -> Approximation a -> String
apprStr String
forall (f :: * -> *) a. Alternative f => f a
empty String
forall (f :: * -> *) a. Alternative f => f a
empty Approximation Spatial
appr
    | Once Approximation Spatial
appr <- Multiplicity (Approximation Spatial)
mult = String -> String -> Approximation Spatial -> String
forall a. Show a => String -> String -> Approximation a -> String
apprStr String
"readOnce" String
", " Approximation Spatial
appr
    where
      apprStr :: String -> String -> Approximation a -> String
apprStr String
linearity String
sep Approximation a
appr =
        case Approximation a
appr of
          Exact a
s -> String
linearity String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String -> String
optionalSeparator String
sep (a -> String
forall a. Show a => a -> String
show a
s)
          Bound Maybe a
Nothing Maybe a
Nothing -> String
"empty"
          Bound Maybe a
Nothing (Just a
s) -> String
linearity String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String -> String
optionalSeparator String
sep String
"atMost, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
s
          Bound (Just a
s) Maybe a
Nothing -> String
linearity String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String -> String
optionalSeparator String
sep String
"atLeast, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
s
          Bound (Just a
sL) (Just a
sU) ->
            [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
linearity, String -> String -> String
optionalSeparator String
sep (a -> String
forall a. Show a => a -> String
show a
sL), String
";"
                   , if String
linearity String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
forall (f :: * -> *) a. Alternative f => f a
empty then String
"" else String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
linearity String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", "
                   , String
"atMost, ", a -> String
forall a. Show a => a -> String
show a
sU ]
      optionalSeparator :: String -> String -> String
optionalSeparator String
_   String
"" = String
""
      optionalSeparator String
sep String
s  = String
sep String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s

instance {-# OVERLAPS #-} Show (Approximation Spatial) where
  show :: Approximation Spatial -> String
show (Exact Spatial
s) = Spatial -> String
forall a. Show a => a -> String
show Spatial
s
  show (Bound Maybe Spatial
Nothing Maybe Spatial
Nothing) = String
"empty"
  show (Bound Maybe Spatial
Nothing (Just Spatial
s)) = String
"atMost, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Spatial -> String
forall a. Show a => a -> String
show Spatial
s
  show (Bound (Just Spatial
s) Maybe Spatial
Nothing) = String
"atLeast, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Spatial -> String
forall a. Show a => a -> String
show Spatial
s
  show (Bound (Just Spatial
sL) (Just Spatial
sU)) =
      String
"atLeast, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Spatial -> String
forall a. Show a => a -> String
show Spatial
sL String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"; atMost, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Spatial -> String
forall a. Show a => a -> String
show Spatial
sU

-- Pretty print spatial specs
instance Show Spatial where
  show :: Spatial -> String
show (Spatial RegionSum
region) =
    -- Map "empty" spec to Nothing here
    case RegionSum -> String
forall a. Show a => a -> String
show RegionSum
region of
      String
"empty" -> String
""
      String
xs      -> String
xs

-- Pretty print region sums
instance Show RegionSum where
    showsPrec :: Int -> RegionSum -> String -> String
showsPrec Int
_ (Sum []) = String -> String -> String
showString String
"empty"

    showsPrec Int
p (Sum [RegionProd]
specs) =
        Bool -> (String -> String) -> String -> String
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
6) ((String -> String) -> String -> String)
-> (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ [RegionProd] -> String -> String
forall a. Show a => [a] -> String -> String
inter [RegionProd]
specs
      where
        inter :: [a] -> String -> String
inter [ ] = String -> String
forall a. a -> a
id
        inter [ a
x ] = Int -> a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
6 a
x
        inter (a
x:[a]
xs) = Int -> a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
6 a
x (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
" + " String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> String -> String
inter [a]
xs

instance Show RegionProd where
    showsPrec :: Int -> RegionProd -> String -> String
showsPrec Int
_ (Product []) = String -> String -> String
showString String
"empty"
    showsPrec Int
p (Product [Region]
ss)  =
        Bool -> (String -> String) -> String -> String
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
7) ((String -> String) -> String -> String)
-> (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ [Region] -> String -> String
forall a. Show a => [a] -> String -> String
inter [Region]
ss
      where
        inter :: [a] -> String -> String
inter [ ] = String -> String
forall a. a -> a
id
        inter [ a
x ] = Int -> a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
7 a
x
        inter (a
x:[a]
xs) = Int -> a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
7 a
x (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char
'*' Char -> String -> String
forall a. a -> [a] -> [a]
:) (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> String -> String
inter [a]
xs

instance Show Region where
   show :: Region -> String
show (Forward Int
dep Int
dim Bool
reflx)   = String -> Int -> Int -> Bool -> String
forall dep dim.
(Show dep, Show dim) =>
String -> dep -> dim -> Bool -> String
showRegion String
"forward" Int
dep Int
dim Bool
reflx
   show (Backward Int
dep Int
dim Bool
reflx)  = String -> Int -> Int -> Bool -> String
forall dep dim.
(Show dep, Show dim) =>
String -> dep -> dim -> Bool -> String
showRegion String
"backward" Int
dep Int
dim Bool
reflx
   show (Centered Int
dep Int
dim Bool
reflx)
     | Int
dep Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = String
"pointed(dim=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
dim String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
     | Bool
otherwise = String -> Int -> Int -> Bool -> String
forall dep dim.
(Show dep, Show dim) =>
String -> dep -> dim -> Bool -> String
showRegion String
"centered" Int
dep Int
dim Bool
reflx

-- Helper for showing regions
showRegion :: (Show dep, Show dim) => String -> dep -> dim -> Bool -> [Char]
showRegion :: String -> dep -> dim -> Bool -> String
showRegion String
typ dep
depS dim
dimS Bool
reflx = String
typ String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(depth=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ dep -> String
forall a. Show a => a -> String
show dep
depS
                               String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", dim=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ dim -> String
forall a. Show a => a -> String
show dim
dimS
                               String -> String -> String
forall a. [a] -> [a] -> [a]
++ (if Bool
reflx then String
"" else String
", nonpointed")
                               String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

-- Helper for reassociating an association list, grouping the keys together that
-- have matching values
groupKeyBy :: Eq b => [(a, b)] -> [([a], b)]
groupKeyBy :: [(a, b)] -> [([a], b)]
groupKeyBy = [([a], b)] -> [([a], b)]
forall b a. Eq b => [([a], b)] -> [([a], b)]
groupKeyBy' ([([a], b)] -> [([a], b)])
-> ([(a, b)] -> [([a], b)]) -> [(a, b)] -> [([a], b)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, b) -> ([a], b)) -> [(a, b)] -> [([a], b)]
forall a b. (a -> b) -> [a] -> [b]
map (\ (a
k, b
v) -> ([a
k], b
v))
  where
    groupKeyBy' :: [([a], b)] -> [([a], b)]
groupKeyBy' []        = []
    groupKeyBy' [([a]
ks, b
v)] = [([a]
ks, b
v)]
    groupKeyBy' (([a]
ks1, b
v1):(([a]
ks2, b
v2):[([a], b)]
xs))
      | b
v1 b -> b -> Bool
forall a. Eq a => a -> a -> Bool
== b
v2          = [([a], b)] -> [([a], b)]
groupKeyBy' (([a]
ks1 [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
ks2, b
v1) ([a], b) -> [([a], b)] -> [([a], b)]
forall a. a -> [a] -> [a]
: [([a], b)]
xs)
      | Bool
otherwise         = ([a]
ks1, b
v1) ([a], b) -> [([a], b)] -> [([a], b)]
forall a. a -> [a] -> [a]
: [([a], b)] -> [([a], b)]
groupKeyBy' (([a]
ks2, b
v2) ([a], b) -> [([a], b)] -> [([a], b)]
forall a. a -> [a] -> [a]
: [([a], b)]
xs)