module Camfort.Specification.Stencils.Consistency ( consistent
, ConsistencyResult(..) ) where
import qualified Camfort.Helpers.Vec as V
import Camfort.Specification.Stencils.DenotationalSemantics
import Camfort.Specification.Stencils.Model
import Camfort.Specification.Stencils.Syntax
data ConsistencyResult =
Consistent
| Inconsistent String
deriving (Eq, Show)
consistent :: forall n .
Specification
-> Multiplicity (UnionNF n Offsets)
-> ConsistencyResult
consistent (Specification mult) observedIxs =
case (specModel, observedIxs) of
(Mult a, Mult b) -> a `consistent'` b
(Once a, Once b) -> a `consistent'` b
(Once _, Mult _) ->Inconsistent
"Specification is readOnce, but there are repeated indices."
(Mult _, Once _) -> Inconsistent
"Specification lacks readOnce, but the indices are inuque."
where
specModel :: Multiplicity (Approximation (UnionNF n (Interval Standard)))
specModel =
case sequence $ (sequence . fmap (regionsToIntervals nOfDims)) <$> mult of
Right model -> model
Left msg -> error msg
nOfDims :: V.Natural n
nOfDims = vecLength . peel $ observedIxs
consistent' :: Approximation (UnionNF n (Interval Standard))
-> UnionNF n Offsets
-> ConsistencyResult
consistent' (Exact unf) ixs =
case unfCompare unf ixs of
EQ -> Consistent
LT ->
Inconsistent "The specification covers a smaller area than the indices."
GT ->
Inconsistent "The specification covers a larger area than the indices."
consistent' (Bound (Just unf) Nothing) ixs =
case unfCompare unf ixs of
EQ -> Consistent
LT -> Consistent
GT -> Inconsistent $
"There are indices covered by the lower bound specification, but " ++
"could not observed in the indices."
consistent' (Bound Nothing (Just unf)) ixs =
case unfCompare unf ixs of
EQ -> Consistent
GT -> Consistent
LT -> Inconsistent
"There are indices outside the upper bound specification."
consistent' (Bound lb ub) ixs =
case (cLower, cUpper) of
(Consistent, Consistent) -> Consistent
(Consistent, inconsistent) -> inconsistent
(inconsistent, Consistent) -> inconsistent
(Inconsistent{}, Inconsistent{}) -> Inconsistent
"Neither the lower nor ther upper bound conform with the indices."
where
cLower = Bound lb Nothing `consistent'` ixs
cUpper = Bound Nothing ub `consistent'` ixs