packages feed

cpsa-4.4.1: src/CPSA/Roletran/Displayer.hs

-- Displays protocols and terms as S-expressions

-- Copyright (c) 2020 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.Roletran.Displayer (
  displayProt, displayTerm, displaySort) where

import qualified Data.List as L
import qualified Data.Map.Strict as M
import CPSA.Lib.SExpr
import CPSA.Roletran.Algebra
import CPSA.Roletran.Protocol

-- Display of protocols

displayProt :: Prot -> SExpr ()
displayProt p =
  L () (S () "defprotocol" : S () (pname p) : S () "basic" : rs)
  where
    rs = map displayRole (roles p)

-- Display of roles

displayRole :: Role -> SExpr ()
displayRole r =
  L () (S () "defrole" :
        S () (rname r) :
        L () (S () "vars" : displayVars (rvars r)) :
        L () (S () "trace" : displayTrace (rtrace r)) :
        displayOptional "uniq-orig" (map displayTerm uniques)
         (displayOptional "inputs" (map displayTerm (rinputs r))
           (displayOptional "outputs" (map displayTerm (routputs r)) [])))
  where
    uniques = L.sort (map fst (runiques r))

displayOptional :: String -> [SExpr ()] -> [SExpr ()] -> [SExpr ()]
displayOptional _ [] rest = rest
displayOptional key value rest =
  L () (S () key : value) : rest

displayVars :: VarEnv -> [SExpr ()]
displayVars env =
  case map displayVar (M.toList env) of
    [] -> []
    (v,t):pairs -> loop t [v] pairs
  where
    loop t vs [] = [L () (reverse (t:vs))]
    loop t vs ((v',t'):xs)
      | t == t' = loop t (v':vs) xs
      | otherwise = L () (reverse (t:vs)):loop t' [v'] xs
    displayVar (v, s) = (S () v, S () $ displaySort s)

displaySort :: Sort -> String
displaySort Text = "text"
displaySort Data = "data"
displaySort Name = "name"
displaySort Skey = "skey"
displaySort Akey = "akey"
displaySort Ikey = "ikey"
displaySort Mesg = "mesg"
displaySort Chan = "chan"

displayTrace :: Trace -> [SExpr ()]
displayTrace trace =
    map displayDt trace
    where
      displayDt (In _ ch t) =
        L () [S () "recv", displayTerm ch, displayTerm t]
      displayDt (Out _  ch t) =
        L () [S () "send", displayTerm ch, displayTerm t]

displayTerm :: Term -> SExpr ()
displayTerm (Txt v) = S () v
displayTerm (Dta v) = S () v
displayTerm (Nam v) = S () v
displayTerm (Sky k) = displaySkey k
displayTerm (Aky k) = displayAkey k
displayTerm (Iky k) = displayIkey k
displayTerm (Msg v) = S () v
displayTerm (Tag v) = Q () v
displayTerm (Pr x y) =
  L () (S () "cat" : displayTerm x : displayList y)
displayTerm (En x y) =
  L () (S () "enc" : displayEnc x y)
displayTerm (Hsh x) =
  L () (S () "cat" : displayList x)
displayTerm (Chn v) = S () v

displaySkey :: Skey -> SExpr ()
displaySkey (SVar v) = S () v
displaySkey (Ltk x y) =
  L () [S () "ltk", S () x, S () y]

displayAkey :: Akey -> SExpr ()
displayAkey (AVar v) = S () v
displayAkey (Pubk v) =
  L () [S () "pubk", S () v]
displayAkey (Pubk2 c v) =
  L () [S () "pubk", Q () c, S () v]

displayIkey :: Akey -> SExpr ()
displayIkey (AVar v) =
  L () [S () "invk", S () v]
displayIkey (Pubk v) =
  L () [S () "privk", S () v]
displayIkey (Pubk2 c v) =
  L () [S () "privk", Q () c, S () v]

displayList :: Term -> [SExpr ()]
displayList (Pr x y) = displayTerm x : displayList y
displayList t = [displayTerm t]

displayEnc :: Term -> Term -> [SExpr ()]
displayEnc (Pr x y) t = displayTerm x : displayEnc y t
displayEnc x y = [displayTerm x, displayTerm y]