module Lang.LamIf.Monads where import FP import MAAM import Lang.LamIf.Stamp import Lang.LamIf.Semantics import Lang.LamIf.Values import Lang.LamIf.Domains -- # Common Injection newtype InjectLamIf val a = InjectLamIf { runInjectLamIf ∷ (a,LamIfState val) } isoInjectLamIf ∷ InjectLamIf val a ⇄ (a,LamIfState val) isoInjectLamIf = Iso runInjectLamIf InjectLamIf -- # Path Sensitive -- Transition System newtype PathSensitiveΣᵇ val a = PathSensitiveΣᵇ { runPathSensitiveΣᵇ ∷ PolyStateΠ (LamIfState val) (NondetJoinΠ ID) a } isoPathSensitiveΣᵇ ∷ PathSensitiveΣᵇ val a ⇄ PolyStateΠ (LamIfState val) (NondetJoinΠ ID) a isoPathSensitiveΣᵇ = Iso runPathSensitiveΣᵇ PathSensitiveΣᵇ isoPathSensitiveΣᵇ2 ∷ PathSensitiveΣᵇ val ↝⇄ PolyStateΠ (LamIfState val) (NondetJoinΠ ID) isoPathSensitiveΣᵇ2 = iso2FromIso isoPathSensitiveΣᵇ instance Inject (InjectLamIf val) (PathSensitiveΣᵇ val) where inject = isoInject (iso2FromIso $ sym $ sym isoInjectLamIf ⌾ isoID ⌾ isoStateI) isoPathSensitiveΣᵇ2 newtype PathSensitiveΣ val a = PathSensitiveΣ { runPathSensitiveΣ ∷ 𝒫 (a,LamIfState val) } deriving (POrd,Bot,Join,JoinLattice,Difference,Pretty) isoPathSensitiveΣ ∷ (Ord val,Ord a) ⇒ PathSensitiveΣ val a ⇄ PathSensitiveΣᵇ val a isoPathSensitiveΣ = Iso (PathSensitiveΣᵇ ∘ PolyStateΠ ∘ NondetJoinΠ ∘ ID ∘ lazySet ∘ runPathSensitiveΣ) (PathSensitiveΣ ∘ set ∘ runID ∘ runNondetJoinΠ ∘ runPolyStateΠ ∘ runPathSensitiveΣᵇ) -- Monad newtype PathSensitiveM val a = PathSensitiveM { runPathSensitiveM ∷ PolyStateT (LamIfState val) (NondetJoinT ID) a } deriving (Functor,Monad,MonadBot,MonadJoin,MonadJoinLattice,MonadState (LamIfState val)) isoPathSensitiveM ∷ PathSensitiveM val a ⇄ PolyStateT (LamIfState val) (NondetJoinT ID) a isoPathSensitiveM = Iso runPathSensitiveM PathSensitiveM isoPathSensitiveM2 ∷ PathSensitiveM val ↝⇄ PolyStateT (LamIfState val) (NondetJoinT ID) isoPathSensitiveM2 = iso2FromIso isoPathSensitiveM instance GaloisTransformer (PathSensitiveΣᵇ val) (PathSensitiveM val) where αGT = isoαGT isoPathSensitiveΣᵇ2 isoPathSensitiveM2 γGT = isoγGT isoPathSensitiveΣᵇ2 isoPathSensitiveM2 -- Execution instance (POrd val,JoinLattice val,Val val) ⇒ MonadLamIf val (PathSensitiveM val) instance (Ord val,POrd val,JoinLattice val,Val val) ⇒ ExecutionLamIf val (InjectLamIf val) (PathSensitiveΣᵇ val) (PathSensitiveM val) -- # Path Insensitive data LamIfContext val = LamIfContext { ctxEnv ∷ Env , ctxΚAddr ∷ Maybe ExpAddr , ctxTime ∷ Time } deriving (Eq,Ord) makePrettyRecord ''LamIfContext data LamIfStores val = LamIfStores { storesStore ∷ Store val , storesΚStore ∷ KStore val } deriving (Eq,Ord) makePrettyRecord ''LamIfStores instance (POrd val) ⇒ POrd (LamIfStores val) where (⊑⊒) = poCompareFromLte $ \ (LamIfStores σ₁ κσ₁) (LamIfStores σ₂ κσ₂) → meets [σ₁ ⊑ σ₂,κσ₁ ⊑ κσ₂] instance Bot (LamIfStores val) where bot = LamIfStores bot bot instance (Join val) ⇒ Join (LamIfStores val) where LamIfStores σ₁ κσ₁ ⊔ LamIfStores σ₂ κσ₂ = LamIfStores (σ₁ ⊔ σ₂) (κσ₁ ⊔ κσ₂) instance (Join val) ⇒ JoinLattice (LamIfStores val) instance (Difference val) ⇒ Difference (LamIfStores val) where LamIfStores σ₁ κσ₁ ⊟ LamIfStores σ₂ κσ₂ = LamIfStores (σ₁ ⊟ σ₂) (κσ₁ ⊟ κσ₂) splitLamIfState ∷ LamIfState val → (LamIfContext val,LamIfStores val) splitLamIfState (LamIfState ρ κl τ σ κσ) = (LamIfContext ρ κl τ,LamIfStores σ κσ) combineLamIfState ∷ (LamIfContext val,LamIfStores val) → LamIfState val combineLamIfState (LamIfContext ρ κl τ,LamIfStores σ κσ) = LamIfState ρ κl τ σ κσ isoSplitLamIfState ∷ LamIfState val ⇄ (LamIfContext val,LamIfStores val) isoSplitLamIfState = Iso splitLamIfState combineLamIfState isoCombineLamIfState ∷ (a,LamIfState val) ⇄ ((a,LamIfContext val),LamIfStores val) isoCombineLamIfState = Iso (\ (x,splitLamIfState → (ctx,stores)) → ((x,ctx),stores)) (\ ((x,ctx),stores) → (x,combineLamIfState (ctx,stores))) -- ## Flow Sensitive -- Transition System newtype FlowSensitiveΣᵇ val a = FlowSensitiveΣᵇ { runFlowSensitiveΣᵇ ∷ PolyStateΠ (LamIfContext val) (FlowJoinΠ (LamIfStores val) ID) a } isoFlowSensitiveΣᵇ ∷ FlowSensitiveΣᵇ val a ⇄ PolyStateΠ (LamIfContext val) (FlowJoinΠ (LamIfStores val) ID) a isoFlowSensitiveΣᵇ = Iso runFlowSensitiveΣᵇ FlowSensitiveΣᵇ isoFlowSensitiveΣ2ᵇ ∷ FlowSensitiveΣᵇ val ↝⇄ PolyStateΠ (LamIfContext val) (FlowJoinΠ (LamIfStores val) ID) isoFlowSensitiveΣ2ᵇ = iso2FromIso isoFlowSensitiveΣᵇ instance Inject (InjectLamIf val) (FlowSensitiveΣᵇ val) where inject = isoInject (iso2FromIso $ sym (sym isoCombineLamIfState ⌾ isoID ⌾ isoStateI ⌾ isoStateI) ⌾ isoInjectLamIf) isoFlowSensitiveΣ2ᵇ newtype FlowSensitiveΣ val a = FlowSensitiveΣ { runFlowSensitiveΣ ∷ (a,LamIfContext val) ⇰ LamIfStores val } deriving (POrd,Bot,Join,JoinLattice,Difference,Pretty) isoFlowSensitiveΣ ∷ (Ord a,Join val) ⇒ FlowSensitiveΣ val a ⇄ FlowSensitiveΣᵇ val a isoFlowSensitiveΣ = Iso (FlowSensitiveΣᵇ ∘ PolyStateΠ ∘ FlowJoinΠ ∘ ID ∘ lazyDictJoin ∘ runFlowSensitiveΣ) (FlowSensitiveΣ ∘ dictJoin ∘ runID ∘ runFlowJoinΠ ∘ runPolyStateΠ ∘ runFlowSensitiveΣᵇ) -- Monad newtype FlowSensitiveM val a = FlowSensitiveM { runFlowSensitiveM ∷ PolyStateT (LamIfContext val) (FlowJoinT (LamIfStores val) ID) a } deriving (Functor,Monad,MonadBot,MonadJoin,MonadJoinLattice) isoFlowSensitiveM ∷ FlowSensitiveM val a ⇄ PolyStateT (LamIfContext val) (FlowJoinT (LamIfStores val) ID) a isoFlowSensitiveM = Iso runFlowSensitiveM FlowSensitiveM isoFlowSensitiveM2 ∷ FlowSensitiveM val ↝⇄ PolyStateT (LamIfContext val) (FlowJoinT (LamIfStores val) ID) isoFlowSensitiveM2 = iso2FromIso isoFlowSensitiveM instance (Join val) ⇒ MonadState (LamIfState val) (FlowSensitiveM val) where stateE ∷ StateT (LamIfState val) (FlowSensitiveM val) ↝ FlowSensitiveM val stateE = FlowSensitiveM ∘ PolyStateT ∘ fmap stateE ∘ stateE ∘ fmap stateCommute ∘ splitState ∘ mapState isoSplitLamIfState ∘ fmap (runPolyStateT ∘ runFlowSensitiveM) stateI ∷ FlowSensitiveM val ↝ StateT (LamIfState val) (FlowSensitiveM val) stateI = fmap (FlowSensitiveM ∘ PolyStateT) ∘ mapState (sym isoSplitLamIfState) ∘ mergeState ∘ fmap stateCommute ∘ stateI ∘ fmap stateI ∘ runPolyStateT ∘ runFlowSensitiveM instance (Join val) ⇒ GaloisTransformer (FlowSensitiveΣᵇ val) (FlowSensitiveM val) where αGT = isoαGT isoFlowSensitiveΣ2ᵇ isoFlowSensitiveM2 γGT = isoγGT isoFlowSensitiveΣ2ᵇ isoFlowSensitiveM2 instance (POrd val,JoinLattice val,Val val) ⇒ MonadLamIf val (FlowSensitiveM val) instance (Ord val,POrd val,JoinLattice val,Difference val,Val val,Pretty val) ⇒ ExecutionLamIf val (InjectLamIf val) (FlowSensitiveΣᵇ val) (FlowSensitiveM val) -- ## Flow Insensitive -- Transition System newtype FlowInsensitiveΣᵇ val a = FlowInsensitiveΣᵇ { runFlowInsensitiveΣᵇ ∷ PolyStateΠ (LamIfContext val) (NondetJoinΠ (StateΠ (LamIfStores val) ID)) a } isoFlowInsensitiveΣᵇ ∷ FlowInsensitiveΣᵇ val a ⇄ PolyStateΠ (LamIfContext val) (NondetJoinΠ (StateΠ (LamIfStores val) ID)) a isoFlowInsensitiveΣᵇ = Iso runFlowInsensitiveΣᵇ FlowInsensitiveΣᵇ isoFlowInsensitiveΣᵇ2 ∷ FlowInsensitiveΣᵇ val ↝⇄ PolyStateΠ (LamIfContext val) (NondetJoinΠ (StateΠ (LamIfStores val) ID)) isoFlowInsensitiveΣᵇ2 = iso2FromIso isoFlowInsensitiveΣᵇ instance Inject (InjectLamIf val) (FlowInsensitiveΣᵇ val) where inject = isoInject (iso2FromIso $ sym (sym isoCombineLamIfState ⌾ isoID ⌾ isoStateI ⌾ isoStateI) ⌾ isoInjectLamIf) isoFlowInsensitiveΣᵇ2 newtype FlowInsensitiveΣ val a = FlowInsensitiveΣ { runFlowInsensitiveΣ ∷ (𝒫(a,LamIfContext val),LamIfStores val) } deriving (POrd,Bot,Join,JoinLattice,Difference,Pretty) isoFlowInsensitiveΣ ∷ (Ord a) ⇒ FlowInsensitiveΣ val a ⇄ FlowInsensitiveΣᵇ val a isoFlowInsensitiveΣ = Iso (FlowInsensitiveΣᵇ ∘ PolyStateΠ ∘ NondetJoinΠ ∘ StateΠ ∘ ID ∘ mapFst lazySet ∘ runFlowInsensitiveΣ) (FlowInsensitiveΣ ∘ mapFst set ∘ runID ∘ runStateΠ ∘ runNondetJoinΠ ∘ runPolyStateΠ ∘ runFlowInsensitiveΣᵇ) -- Monad newtype FlowInsensitiveM val a = FlowInsensitiveM { runFlowInsensitiveM ∷ PolyStateT (LamIfContext val) (NondetJoinT (StateT (LamIfStores val) ID)) a } deriving (Functor,Monad,MonadBot,MonadJoin,MonadJoinLattice) isoFlowInsensitiveM ∷ FlowInsensitiveM val a ⇄ PolyStateT (LamIfContext val) (NondetJoinT (StateT (LamIfStores val) ID)) a isoFlowInsensitiveM = Iso runFlowInsensitiveM FlowInsensitiveM isoFlowInsensitiveM2 ∷ FlowInsensitiveM val ↝⇄ PolyStateT (LamIfContext val) (NondetJoinT (StateT (LamIfStores val) ID)) isoFlowInsensitiveM2 = iso2FromIso isoFlowInsensitiveM instance (Join val) ⇒ MonadState (LamIfState val) (FlowInsensitiveM val) where stateE ∷ StateT (LamIfState val) (FlowInsensitiveM val) ↝ FlowInsensitiveM val stateE = FlowInsensitiveM ∘ PolyStateT ∘ fmap stateE ∘ stateE ∘ fmap stateCommute ∘ splitState ∘ mapState isoSplitLamIfState ∘ fmap (runPolyStateT ∘ runFlowInsensitiveM) stateI ∷ FlowInsensitiveM val ↝ StateT (LamIfState val) (FlowInsensitiveM val) stateI = fmap (FlowInsensitiveM ∘ PolyStateT) ∘ mapState (sym isoSplitLamIfState) ∘ mergeState ∘ fmap stateCommute ∘ stateI ∘ fmap stateI ∘ runPolyStateT ∘ runFlowInsensitiveM instance (Join val) ⇒ GaloisTransformer (FlowInsensitiveΣᵇ val) (FlowInsensitiveM val) where αGT = isoαGT isoFlowInsensitiveΣᵇ2 isoFlowInsensitiveM2 γGT = isoγGT isoFlowInsensitiveΣᵇ2 isoFlowInsensitiveM2 instance (POrd val,JoinLattice val,Val val) ⇒ MonadLamIf val (FlowInsensitiveM val) instance (Ord val,POrd val,JoinLattice val,Difference val,Val val,Pretty val) ⇒ ExecutionLamIf val (InjectLamIf val) (FlowInsensitiveΣᵇ val) (FlowInsensitiveM val) -- # Monad Parameters data MonadParam where MonadParam ∷ ∀ val ς' ς m. P m → ς Exp ⇄ ς' Exp → (ς Exp → Doc) → W (ExecutionLamIf val (InjectLamIf val) ς' m,LFPLamIf ς) → MonadParam pathSensitive ∷ DomainParam → MonadParam pathSensitive (DomainParam (P ∷ P val) W) = MonadParam (P ∷ P (PathSensitiveM val)) isoPathSensitiveΣ (pretty ∘ mapKeyJoin varAddrName ∘ joins ∘ mapSet (store ∘ snd) ∘ runPathSensitiveΣ) W flowSensitive ∷ DomainParam → MonadParam flowSensitive (DomainParam (P ∷ P val) W) = MonadParam (P ∷ P (FlowSensitiveM val)) isoFlowSensitiveΣ (pretty ∘ mapKeyJoin varAddrName ∘ storesStore ∘ joins ∘ values ∘ runFlowSensitiveΣ) W flowInsensitive ∷ DomainParam → MonadParam flowInsensitive (DomainParam (P ∷ P val) W) = MonadParam (P ∷ P (FlowInsensitiveM val)) isoFlowInsensitiveΣ (pretty ∘ mapKeyJoin varAddrName ∘ storesStore ∘ snd ∘ runFlowInsensitiveΣ) W