cpsa-3.4.0: src/CPSA/Lib/Displayer.hs
-- Displays protocols and preskeletons as S-expressions.
-- 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.Lib.Displayer (displayProt, displayPreskel, displayNode) where
import qualified Data.List as L
import qualified Data.Set as S
import CPSA.Lib.SExpr
import CPSA.Lib.Algebra
import CPSA.Lib.Declaration
import CPSA.Lib.State
import CPSA.Lib.Protocol
import CPSA.Lib.Strand
import CPSA.Lib.Utilities
{-- Debugging support
import CPSA.Lib.Debug
--}
-- Display of protocols
displayProt :: Algebra t p g s e c => Prot t g -> SExpr ()
displayProt p =
L () (S () "defprotocol" : S () (pname p) : S () (alg p) : rs)
where
rs = foldl f (pcomment p) (reverse (roles p))
f rs r = displayRole r : rs
displayRole :: Algebra t p g s e c => Role t -> SExpr ()
displayRole r =
L () (S () "defrole" :
S () (rname r) :
L () (S () "vars" : displayVars ctx vars) :
L () (S () "trace" : displayTrace ctx (rtrace r)) :
displayRoleDeclarations ctx (rdecls r)
(rcomment r))
where
ctx = varsContext vars
vars = rvars r
varsContext :: Algebra t p g s e c => [t] -> c
varsContext vars =
addToContext emptyContext vars
displayTerms :: Algebra t p g s e c => c -> [t] -> [SExpr ()]
displayTerms ctx ts = map (displayTerm ctx) (L.sort ts)
displayTermsUnsorted ::Algebra t p g s e c => c -> [t] -> [SExpr ()]
displayTermsUnsorted ctx ts = map (displayTerm ctx) ts
displayTermPlusMaybeOneInts :: Algebra t p g s e c => c ->
RoleDeclInstList t -> [SExpr ()]
displayTermPlusMaybeOneInts ctx ts = map (displayTermPlusMaybeOneInt ctx) ts
displayTermPlusMaybeOneInt :: Algebra t p g s e c => c ->
RoleDeclInst t -> SExpr ()
displayTermPlusMaybeOneInt ctx dinst
| (length (dlocs dinst) > 1) || (length (dterms dinst) /= 1) =
assertError("Displayer.displayTermPlusMaybeOneInt: patterns unexpectedly exhausted in displayer")
| (length (dlocs dinst) == 1) = L () [displayTerm ctx
(head (dterms dinst)),
N () ((dlocs dinst)!!0)]
| otherwise = displayTerm ctx (head (dterms dinst))
displayTermPlusMaybeOneNodes :: Algebra t p g s e c => c ->
SkelDeclInstList t -> [SExpr ()]
displayTermPlusMaybeOneNodes ctx ts = map (displayTermPlusMaybeOneNode ctx) ts
displayTermPlusMaybeOneNode :: Algebra t p g s e c => c ->
SkelDeclInst t -> SExpr ()
displayTermPlusMaybeOneNode ctx dinst
| (length (dlocs dinst) > 1) || (length (dterms dinst) /= 1) =
assertError("Displayer.displayTermPlusMaybeOneNode patterns unexpectedly exhausted in displayer")
| (length (dlocs dinst) == 1) = L () [displayTerm ctx
(head (dterms dinst)),
L () [N () $ fst $ (dlocs dinst)!!0,
N () $ snd $ (dlocs dinst)!!0]]
| otherwise = displayTerm ctx (head (dterms dinst))
displayOptional :: String -> [SExpr ()] -> [SExpr ()] -> [SExpr ()]
displayOptional _ [] rest = rest
displayOptional key value rest =
L () (S () key : value) : rest
displayTrace :: Algebra t p g s e c => c ->
Trace t -> [SExpr ()]
displayTrace ctx trace =
map displayDt trace
where
displayDt (In t) = L () [S () "recv", displayTerm ctx t]
displayDt (Out t) = L () [S () "send", displayTerm ctx t]
displayDt (Sync t) = L () (displayTran ctx t)
displayTran :: Algebra t p g s e c => c -> Tran t -> [SExpr ()]
displayTran ctx (Tran(Just now, Just next, Nothing)) =
[S () "tran", displayTerm ctx now, displayTerm ctx next]
displayTran ctx (Tran(Just now, Just next, Just label)) =
[S () "tran", displayTerm ctx now, displayTerm ctx next,
displayTerm ctx label]
displayTran ctx (Tran(Just now, Nothing, Nothing)) =
[S () "obsv", displayTerm ctx now]
displayTran ctx (Tran(Just now, Nothing, Just label)) =
[S () "obsv", displayTerm ctx now, displayTerm ctx label]
displayTran ctx (Tran(Nothing, Just next, Nothing)) =
[S () "init", displayTerm ctx next]
displayTran ctx (Tran(Nothing, Just next, Just label)) =
[S () "init", displayTerm ctx next, displayTerm ctx label]
displayTran _ (Tran(Nothing, Nothing, _)) =
assertError("Displayer.displayTran: encountered sync node with current or next state")
-- Display of preskeletons
displayPreskel :: Algebra t p g s e c => Preskel t g s e ->
[SExpr ()] -> SExpr ()
displayPreskel k rest =
L () (S () "defskeleton" :
S () (pname (protocol k)) :
L () (S () "vars" : displayVars ctx vars) :
foldr f (displayRest k ctx rest) (insts k))
where
ctx = varsContext vars
vars = kvars k
f i rest = displayInst ctx i : rest
-- Display the remainder of a preskeleton
displayRest :: Algebra t p g s e c => Preskel t g s e ->
c -> [SExpr ()] -> [SExpr ()]
displayRest k ctx rest =
displayOptional "precedes" (displayOrdering (orderings k))
(displayOptional "leadsto" (displayOrdering (leadsto k))
(displayOptional "priority" (displayPriorities (kpriorities k))
(displaySkelDeclarations ctx (decls k)
(kcomment k ++
(displayOperation k ctx
(displayOptional "traces" traces rest))))))
where
traces = map (L () . displayTrace ctx . trace) (insts k)
-- Display declarations
displaySkelDeclarations :: Algebra t p g s e c =>
c -> SkelDeclarations t ->
[SExpr ()] -> [SExpr ()]
displaySkelDeclarations ctx decls rest =
displaySkelDeclarationList ctx (declarationTags decls) decls rest
displayRoleDeclarations :: Algebra t p g s e c =>
c -> RoleDeclarations t ->
[SExpr ()] -> [SExpr ()]
displayRoleDeclarations ctx decls rest =
displayRoleDeclarationList ctx (declarationRoleTags decls) decls rest
-- Display an individually tagged declaration
displaySkelDeclarationList :: Algebra t p g s e c => c ->
[(String, (DeclOutFormat, Bool))] ->
SkelDeclarations t -> [SExpr ()] -> [SExpr ()]
displaySkelDeclarationList _ [] _ rest = rest
displaySkelDeclarationList ctx (a:b) decls rest =
displaySkelDeclaration ctx a decls
(displaySkelDeclarationList ctx b decls rest)
displayRoleDeclarationList :: Algebra t p g s e c => c ->
[(String, (DeclOutFormat, Bool))] ->
RoleDeclarations t -> [SExpr ()] -> [SExpr ()]
displayRoleDeclarationList _ [] _ rest = rest
displayRoleDeclarationList ctx (a:b) decls rest =
displayRoleDeclaration ctx a decls
(displayRoleDeclarationList ctx b decls rest)
displaySkelDeclaration :: Algebra t p g s e c => c ->
(String, (DeclOutFormat, Bool)) ->
SkelDeclarations t -> [SExpr ()] -> [SExpr ()]
displaySkelDeclaration ctx (tag, (BasicOutFmt, True)) decls rest =
displaySkelAuxDeclaration ctx tag (tagDecls tag decls) rest
displaySkelDeclaration ctx (tag, (MultiTermOutFmt, True)) decls rest =
displaySkelAuxDeclaration2 ctx tag (tagDecls tag decls) rest
displaySkelDeclaration ctx (tag, (BasicOutFmt, False)) decls rest =
displayOptional tag (displayTerms ctx (tagDeclsTermsOnly tag decls)) rest
displaySkelDeclaration ctx (tag, (GeneralOutFmt, False)) decls rest =
displayOptional tag (displaySkelDeclGen ctx (tagDecls tag decls)) rest
displaySkelDeclaration _ (tag, (LocOutFmt, False)) decls rest =
displayOptional tag (displaySkelDeclLoc (tagDecls tag decls)) rest
displaySkelDeclaration ctx (tag, (BasicRoleOutFmt, False)) decls rest =
displayOptional tag (displayTermPlusMaybeOneNodes ctx (tagDecls tag decls)) rest
displaySkelDeclaration ctx (tag, (MultiTermOutFmt, False)) decls rest =
displayOptional tag (map (\ item -> (L () (displayTermsUnsorted ctx (dterms item))))
(tagDecls tag decls)) rest
displaySkelDeclaration _ (tag,_) _ _ =
assertError("Displayer.displaySkelDeclaration: skel output format not supported yet: " ++ tag)
displaySkelAuxDeclaration :: Algebra t p g s e c => c -> String ->
SkelDeclInstList t -> [SExpr ()] -> [SExpr ()]
displaySkelAuxDeclaration ctx tag dis rest =
(L () (S () tag:(dAuxDecl (L.sort (L.nub $ map daux dis)) )):rest)
where
dAuxDecl [] = []
dAuxDecl (stag:r) = ((L () (S () stag:
(displayTerms ctx
(concatMap dterms
(filter (\di -> daux di == stag) dis)))))
:dAuxDecl r)
displaySkelAuxDeclaration2 :: Algebra t p g s e c => c -> String ->
SkelDeclInstList t -> [SExpr ()] -> [SExpr ()]
displaySkelAuxDeclaration2 ctx tag dis rest =
(L () (S () tag:(dAuxDecl (L.sort (L.nub $ map daux dis)))):rest)
where
dAuxDecl [] = []
dAuxDecl (stag:r) = ((L () (S () stag:
(dAuxDecl2 (filter (\di -> daux di == stag) dis)))):
(dAuxDecl r))
dAuxDecl2 [] = []
dAuxDecl2 (di:r) = ((L () (displayTermsUnsorted ctx (dterms di))):
(dAuxDecl2 r))
displayRoleAuxDeclaration :: Algebra t p g s e c => c -> String ->
RoleDeclInstList t -> [SExpr ()] -> [SExpr ()]
displayRoleAuxDeclaration ctx tag dis rest =
(L () (S () tag:(dAuxDecl (L.sort (L.nub $ map daux dis)) )):rest)
where
dAuxDecl [] = []
dAuxDecl (stag:r) = ((L () (S () stag:
(displayTerms ctx
(concatMap dterms
(filter (\di -> daux di == stag) dis)))))
:dAuxDecl r)
displayRoleAuxDeclaration2 :: Algebra t p g s e c => c -> String ->
RoleDeclInstList t -> [SExpr ()] -> [SExpr ()]
displayRoleAuxDeclaration2 ctx tag dis rest =
(L () (S () tag:(dAuxDecl (L.sort (L.nub $ map daux dis)))):rest)
where
dAuxDecl [] = []
dAuxDecl (stag:r) = ((L () (S () stag:
(dAuxDecl2 (filter (\di -> daux di == stag) dis)))):
(dAuxDecl r))
dAuxDecl2 [] = []
dAuxDecl2 (di:r) = ((L () (displayTermsUnsorted ctx (dterms di))):
(dAuxDecl2 r))
displayRoleDeclaration :: Algebra t p g s e c => c ->
(String, (DeclOutFormat, Bool)) ->
RoleDeclarations t -> [SExpr ()] -> [SExpr ()]
displayRoleDeclaration ctx (tag, (BasicOutFmt, True)) decls rest =
displayRoleAuxDeclaration ctx tag (tagDecls tag decls) rest
displayRoleDeclaration ctx (tag, (BasicOutFmt, False)) decls rest =
displayOptional tag (displayTerms ctx (tagDeclsTermsOnly tag decls)) rest
displayRoleDeclaration ctx (tag, (MultiTermOutFmt, True)) decls rest =
displayRoleAuxDeclaration2 ctx tag (tagDecls tag decls) rest
displayRoleDeclaration ctx (tag, (MultiTermOutFmt, False)) decls rest =
displayOptional tag (map (\ item -> (L () (displayTermsUnsorted ctx (dterms item))))
(tagDecls tag decls)) rest
displayRoleDeclaration ctx (tag, (BasicRoleOutFmt, False)) decls rest =
displayOptional tag (displayTermPlusMaybeOneInts ctx (tagDecls tag decls)) rest
displayRoleDeclaration ctx (tag, (GeneralOutFmt, False)) decls rest =
displayOptional tag (displayRoleDeclGen ctx (tagDecls tag decls)) rest
displayRoleDeclaration _ (tag,_) _ _ =
assertError("Displayer.displayRoleDeclaration: role output format not supported yet: " ++ tag)
displaySkelDeclGen :: (Algebra t p g s e c) => c -> SkelDeclInstList t ->
[SExpr ()]
displaySkelDeclGen _ [] = []
displaySkelDeclGen ctx (d:ds) =
displaySkelDeclGenItem ctx d (displaySkelDeclGen ctx ds)
displayRoleDeclGen :: (Algebra t p g s e c) => c -> RoleDeclInstList t ->
[SExpr ()]
displayRoleDeclGen _ [] = []
displayRoleDeclGen ctx (d:ds) =
displayRoleDeclGenItem ctx d (displayRoleDeclGen ctx ds)
displaySkelDeclGenItem :: (Algebra t p g s e c) => c -> SkelDeclInst t ->
[SExpr ()] -> [SExpr ()]
displaySkelDeclGenItem ctx dinst rest =
(L () ((L () (displayTermsUnsorted ctx ts)):(displayNodes ns)): rest)
where
ts = dterms dinst
ns = dlocs dinst
displayRoleDeclGenItem :: (Algebra t p g s e c) => c -> RoleDeclInst t ->
[SExpr ()] -> [SExpr ()]
displayRoleDeclGenItem ctx dinst rest =
(L () ((L () (displayTermsUnsorted ctx ts)):(displayInts ns)): rest)
where
ts = dterms dinst
ns = dlocs dinst
displaySkelDeclLoc :: (Algebra t p g s e c) => SkelDeclInstList t ->
[SExpr ()]
displaySkelDeclLoc [] = []
displaySkelDeclLoc (d:ds) =
displaySkelDeclLocItem d (displaySkelDeclLoc ds)
displaySkelDeclLocItem :: (Algebra t p g s e c) => SkelDeclInst t ->
[SExpr ()] -> [SExpr ()]
displaySkelDeclLocItem dinst rest =
displayNodes ns ++ rest
where
ns = dlocs dinst
displayInst :: Algebra t p g s e c => c ->
Instance t e -> SExpr ()
displayInst ctx s =
case listenerTerm s of
Just t -> L () [S () "deflistener", displayTerm ctx t]
Nothing ->
L () (S () "defstrand" :
S () (rname r) :
N () (height s) :
map (displayMaplet rctx ctx) maplets)
where
r = role s
domain = rvars r
maplets = L.sort (reify domain (env s))
rctx = varsContext domain
displayMaplet :: Algebra t p g s e c => c -> c -> (t, t) -> SExpr ()
displayMaplet domain range (x, t)=
L () [displayTerm domain x, displayTerm range t]
displayPriorities :: [(Node,Int)] -> [SExpr ()]
displayPriorities priorities =
map displayPriority priorities
displayPriority :: (Node,Int) -> SExpr ()
displayPriority ((s,i),p) =
L () [L () [N () s, N () i], N () p]
displayOrdering :: [Pair] -> [SExpr ()]
displayOrdering orderings =
map displayPair (L.sort orderings)
displayPair :: Pair -> SExpr ()
displayPair (n0, n1) =
L () [displayNode n0, displayNode n1]
displayInts :: [Int] -> [SExpr ()]
displayInts [] = []
displayInts (i:is) = (N () i):(displayInts is)
displayNodes :: [Node] -> [SExpr ()]
displayNodes [] = []
displayNodes (n:ns) = [displayNode n] ++ displayNodes ns
displayNode :: Node -> SExpr ()
displayNode (s, p) = L () [N () s, N () p]
-- Display the reason the preskeleton was created
displayOperation :: Algebra t p g s e c => Preskel t g s e ->
c -> [SExpr ()] -> [SExpr ()]
displayOperation k ctx rest =
case operation k of
New -> rest
Contracted subst cause ->
let substitution = displaySubst ctx subst in
displayCause (L () (S () "contracted" : substitution)) cause
Displaced s s' role height cause ->
displayCause
(L () [S () "displaced", N () s, N () s', S () role, N () height])
cause
AddedStrand role height cause ->
displayCause
(L () [S () "added-strand", S () role, N () height]) cause
AddedListener t cause ->
displayCause (L () [S () "added-listener", displayOpTerm ctx t]) cause
AddedAbsence t1 t2 cause ->
displayCause (L () [S () "added-absence", displayOpTerm ctx t1,
displayOpTerm ctx t2]) cause
AlgebraSolved subst cause ->
let substitution = displaySubst ctx subst in
displayCause (L () (S () "algebra-contracted" : substitution)) cause
Generalized method ->
let desc = displayMethod ctx method in
L () (S () "operation" : S () "generalization" : desc) : rest
Collapsed s s' ->
let desc = [N () s, N () s'] in
L () (S () "operation" : S () "collapsed" : desc) : rest
where
displayCause op (Cause dir node critical escape) =
L () (S () "operation" :
displayDirection dir :
op :
displayOpTerm ctx critical :
displayNode node :
displayOpTerms ctx (S.toList escape)) : rest
displayDirection Encryption = S () "encryption-test"
displayDirection Nonce = S () "nonce-test"
displayDirection StatePassing = S () "state-passing-test"
displayMethod _ (Deleted node) =
[S () "deleted", displayNode node]
displayMethod _ (Weakened (n0, n1)) =
[S () "weakened", L () [displayNode n0, displayNode n1] ]
displayMethod ctx (Separated t) =
[S () "separated", displayOpTerm ctx t]
displayMethod ctx (Forgot t) =
[S () "forgot", displayOpTerm ctx t]
-- Terms in the operation field may contain variables not in the skeleton
displayOpTerm :: Algebra t p g s e c => c -> t -> SExpr ()
displayOpTerm ctx t = displayTerm (addToContext ctx [t]) t
displayOpTerms :: Algebra t p g s e c => c -> [t] -> [SExpr ()]
displayOpTerms ctx ts = map (displayTerm (addToContext ctx ts)) (L.sort ts)