module Camfort.Specification.Stencils.CheckBackend
(
SynToAst(..)
, SynToAstError
, regionNotInScope
) where
import Data.Function (on)
import Camfort.Specification.Stencils.Syntax
import Camfort.Specification.Stencils.Model
import qualified Camfort.Specification.Stencils.Parser.Types as SYN
data SynToAstError = RegionNotInScope String
deriving (Eq)
regionNotInScope :: String -> SynToAstError
regionNotInScope = RegionNotInScope
instance Show SynToAstError where
show (RegionNotInScope r) = "Error: region " ++ r ++ " is not in scope."
class SynToAst s t | s -> t where
synToAst :: (?renv :: RegionEnv) => s -> Either SynToAstError t
instance SynToAst SYN.Specification (Either RegionDecl SpecDecl) where
synToAst (SYN.SpecDec spec vars) = do
spec' <- synToAst spec
return $ Right (vars, spec')
synToAst (SYN.RegionDec rvar region) = do
spec' <- synToAst region
return $ Left (rvar, spec')
instance SynToAst SYN.SpecInner Specification where
synToAst (SYN.SpecInner spec isStencil) = do
spec' <- synToAst spec
return $ Specification spec' isStencil
instance SynToAst (Multiplicity (Approximation SYN.Region)) (Multiplicity (Approximation Spatial)) where
synToAst (Once a) = fmap Once . synToAst $ a
synToAst (Mult a) = fmap Mult . synToAst $ a
instance SynToAst (Approximation SYN.Region) (Approximation Spatial) where
synToAst (Exact s) = fmap (Exact . Spatial) . synToAst $ s
synToAst (Bound s1 s2) = (Bound `on` (fmap Spatial)) <$> synToAst s1 <*> synToAst s2
instance SynToAst (Maybe SYN.Region) (Maybe RegionSum) where
synToAst Nothing = pure Nothing
synToAst (Just r) = fmap Just . synToAst $ r
instance SynToAst SYN.Region RegionSum where
synToAst = dnf
dnf :: (?renv :: RegionEnv) => SYN.Region -> Either SynToAstError RegionSum
dnf (SYN.RegionConst rconst) = pure . Sum $ [Product [rconst]]
dnf (SYN.And r1 r2) = do
r1' <- dnf r1
r2' <- dnf r2
return $ Sum $ unSum r1' >>= (\(Product ps1) ->
unSum r2' >>= (\(Product ps2) ->
return $ Product $ ps1 ++ ps2))
dnf (SYN.Or r1 r2) = do
r1' <- dnf r1
r2' <- dnf r2
return $ Sum $ unSum r1' ++ unSum r2'
dnf (SYN.Var v) =
case lookup v ?renv of
Nothing -> Left (RegionNotInScope v)
Just rs -> return rs