quickcheck-state-machine-0.1.0: src/Test/StateMachine/Internal/ScopeCheck.hs
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
-----------------------------------------------------------------------------
-- |
-- Module : Test.StateMachine.Internal.ScopeCheck
-- Copyright : (C) 2017, ATS Advanced Telematic Systems GmbH
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : Stevan Andjelkovic <stevan@advancedtelematic.com>
-- Stability : provisional
-- Portability : non-portable (GHC extensions)
--
-- This module provides scope-checking for internal actions. This
-- functionality isn't used anywhere in the library, but can be useful
-- for writing
-- <https://github.com/advancedtelematic/quickcheck-state-machine/blob/master/example/src/MutableReference/Prop.hs metaproperties>.
--
-----------------------------------------------------------------------------
module Test.StateMachine.Internal.ScopeCheck
( scopeCheck
, scopeCheckParallel
) where
import Data.Monoid
((<>))
import Data.Set
(Set)
import qualified Data.Set as S
import Test.StateMachine.Internal.Sequential
(getUsedVars)
import Test.StateMachine.Internal.Types
import Test.StateMachine.Types
------------------------------------------------------------------------
-- | Scope-check a program, i.e. make sure that no action uses a
-- reference that doesn't exist.
scopeCheck :: forall act. HFoldable act => Program act -> Bool
scopeCheck = go S.empty . unProgram
where
go :: Set Var -> [Internal act] -> Bool
go _ [] = True
go known (Internal act (Symbolic var) : iacts) =
getUsedVars act `S.isSubsetOf` known && go (S.insert var known) iacts
-- | Same as above, but for parallel programs.
scopeCheckParallel :: HFoldable act => ParallelProgram act -> Bool
scopeCheckParallel (ParallelProgram (Fork l p r)) =
scopeCheck (p <> l) && scopeCheck (p <> r)