packages feed

cpsa-2.3.1: src/CPSA/Parameters/Flow.hs

-- Performs a data flow analysis of traces in protocol roles

-- Copyright (c) 2009 The MITRE Corporation
--
-- This program is free software: you can redistribute it and/or
-- modify it under the terms of the BSD License as published by the
-- University of California.

module CPSA.Parameters.Flow (dataFlow) where

import CPSA.Lib.CPSA

dataFlow :: (Algebra t p g s e c, Monad m) => String -> g ->
            SExpr Pos -> m (SExpr ())
dataFlow nom origin (L pos (S _ "defprotocol" :
                            S _ name :
                            S _ alg :
                            xs))
    | nom == alg =
        do
          xs <- mapM (mapRole origin) xs
          return (L () (S () "defprotocol" :
                        S () name :
                        S () alg :
                        xs))
    | otherwise = fail (shows pos $ "Expecting terms in algebra " ++ nom)
dataFlow _ _ x = return (strip x)

-- Strip positions from an S-expression

strip :: SExpr a -> SExpr ()
strip (S _ s) = S () s
strip (Q _ s) = Q () s
strip (N _ n) = N () n
strip (L _ l) = L () (map strip l)

mapRole :: (Algebra t p g s e c, Monad m) => g ->
           SExpr Pos -> m (SExpr ())
mapRole gen (L _ (S _ "defrole" :
                  S _ name :
	          L _ (S _ "vars" : vars) :
                  L _ (S _ "trace" : trace) :
                  rest)) =
    do
      (_, vs) <- loadVars gen vars
      c <- loadTrace vs trace
      let rest' = addParams (displayParams vs (flow c)) (map strip rest)
      trace <- mapM stripEvt trace
      return (L () (S () "defrole" :
                    S () name :
	            L () (S () "vars" : map strip vars) :
                    L () (S () "trace" : trace) :
                    rest'))
mapRole _ x = return (strip x)

loadTrace :: (Algebra t p g s e c, Monad m) => [t] ->
             [SExpr Pos] -> m [Event t]
loadTrace vars xs = mapM (loadEvt vars) xs

loadEvt :: (Algebra t p g s e c, Monad m) => [t] ->
          SExpr Pos -> m (Event t)
loadEvt vars (L _ [S _ "recv", t]) =
    do
      t <- loadTerm vars t
      return (In t)
loadEvt vars (L _ [S _ "send", t]) =
    do
      t <- loadTerm vars t
      return (Out t)
loadEvt _ (L pos [S _ dir, _]) =
    fail (shows pos $ "Unrecognized direction " ++ dir)
loadEvt _ x = fail (shows (annotation x) "Malformed direction")

displayParams :: Algebra t p g s e c => [t] -> [[t]] -> [SExpr ()]
displayParams vs inits =
    map (L () . map (displayTerm ctx)) inits
    where
      ctx = addToContext emptyContext vs

addParams :: [SExpr ()] -> [SExpr ()] -> [SExpr ()]
addParams inits rest =
    filter notParams rest ++ [L () (S () "parameters" : inits)]
    where
      notParams (L () (S () "parameters" : _)) = False
      notParams _ = True

stripEvt ::Monad m => SExpr Pos -> m (SExpr ())
stripEvt (L _ [S _ "send", t]) = return (L () [S () "send", strip t])
stripEvt (L _ [S _ "recv", t]) = return (L () [S () "recv", strip t])
stripEvt x = fail (shows (annotation x) "Malformed direction")