| 1 | {- | |
|---|
| 2 | Module : $Id$ |
|---|
| 3 | Description : Pretty printing for CspCASL |
|---|
| 4 | Copyright : (c) Andy Gimblett and Uni Bremen 2006 |
|---|
| 5 | License : similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt |
|---|
| 6 | |
|---|
| 7 | Maintainer : a.m.gimblett@swansea.ac.uk |
|---|
| 8 | Stability : provisional |
|---|
| 9 | Portability : portable |
|---|
| 10 | |
|---|
| 11 | Printing abstract syntax of CSP-CASL |
|---|
| 12 | |
|---|
| 13 | -} |
|---|
| 14 | module CspCASL.Print_CspCASL where |
|---|
| 15 | |
|---|
| 16 | import CASL.ToDoc () |
|---|
| 17 | |
|---|
| 18 | import Common.Doc |
|---|
| 19 | import Common.DocUtils |
|---|
| 20 | import Common.Keywords (elseS, ifS, thenS) |
|---|
| 21 | |
|---|
| 22 | import CspCASL.AS_CspCASL |
|---|
| 23 | import CspCASL.AS_CspCASL_Process |
|---|
| 24 | import CspCASL.CspCASL_Keywords |
|---|
| 25 | |
|---|
| 26 | instance Pretty CspCASLSentence where |
|---|
| 27 | pretty _ = empty |
|---|
| 28 | |
|---|
| 29 | instance Pretty CspBasicSpec where |
|---|
| 30 | pretty = printCspBasicSpec |
|---|
| 31 | |
|---|
| 32 | printCspBasicSpec :: CspBasicSpec -> Doc |
|---|
| 33 | printCspBasicSpec ccs = |
|---|
| 34 | chan_part $+$ proc_part |
|---|
| 35 | where chan_part = case (length chans) of |
|---|
| 36 | 0 -> empty |
|---|
| 37 | 1 -> (keyword channelS) <+> printChanDecs chans |
|---|
| 38 | _ -> (keyword channelsS) <+> printChanDecs chans |
|---|
| 39 | proc_part = (keyword processS) <+> |
|---|
| 40 | (printProcItems (proc_items ccs)) |
|---|
| 41 | chans = channels ccs |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | printChanDecs :: [CHANNEL_DECL] -> Doc |
|---|
| 45 | printChanDecs cds = (vcat . punctuate semi . map pretty) cds |
|---|
| 46 | |
|---|
| 47 | instance Pretty CHANNEL_DECL where |
|---|
| 48 | pretty = printChanDecl |
|---|
| 49 | |
|---|
| 50 | printChanDecl :: CHANNEL_DECL -> Doc |
|---|
| 51 | printChanDecl (ChannelDecl ns s) = |
|---|
| 52 | (ppWithCommas ns) <+> colon <+> (pretty s) |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | printProcItems :: [PROC_ITEM] -> Doc |
|---|
| 56 | printProcItems ps = foldl ($+$) empty (map pretty ps) |
|---|
| 57 | |
|---|
| 58 | instance Pretty PROC_ITEM where |
|---|
| 59 | pretty = printProcItem |
|---|
| 60 | |
|---|
| 61 | printProcItem :: PROC_ITEM -> Doc |
|---|
| 62 | printProcItem (Proc_Decl pn args alpha) = |
|---|
| 63 | (pretty pn) <> (printArgs args) <+> colon <+> (pretty alpha) <+> semi |
|---|
| 64 | where printArgs [] = empty |
|---|
| 65 | printArgs a = parens $ ppWithCommas a |
|---|
| 66 | printProcItem (Proc_Eq pn p) = |
|---|
| 67 | (pretty pn) <+> equals <+> (pretty p) |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | instance Pretty PARM_PROCNAME where |
|---|
| 71 | pretty = printParmProcname |
|---|
| 72 | |
|---|
| 73 | printParmProcname :: PARM_PROCNAME -> Doc |
|---|
| 74 | printParmProcname (ParmProcname pn args) = |
|---|
| 75 | pretty pn <> (printArgs args) |
|---|
| 76 | where printArgs [] = empty |
|---|
| 77 | printArgs a = parens $ ppWithCommas a |
|---|
| 78 | |
|---|
| 79 | instance Pretty PROC_ALPHABET where |
|---|
| 80 | pretty = printProcAlphabet |
|---|
| 81 | |
|---|
| 82 | printProcAlphabet :: PROC_ALPHABET -> Doc |
|---|
| 83 | printProcAlphabet (ProcAlphabet commTypes _) = ppWithCommas commTypes |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | instance Pretty PROCESS where |
|---|
| 87 | pretty = printProcess |
|---|
| 88 | |
|---|
| 89 | printProcess :: PROCESS -> Doc |
|---|
| 90 | printProcess pr = case pr of |
|---|
| 91 | -- precedence 0 |
|---|
| 92 | Skip _ -> text skipS |
|---|
| 93 | Stop _ -> text stopS |
|---|
| 94 | Div _ -> text divS |
|---|
| 95 | Run es _ -> (text runS) <+> lparen <+> (pretty es) <+> rparen |
|---|
| 96 | Chaos es _ -> (text chaosS) <+> lparen <+> (pretty es) <+> rparen |
|---|
| 97 | NamedProcess pn ts _ -> |
|---|
| 98 | (pretty pn) <+> |
|---|
| 99 | if (null ts) |
|---|
| 100 | then ppWithCommas ts |
|---|
| 101 | else lparen <+> (ppWithCommas ts) <+> rparen |
|---|
| 102 | -- precedence 1 |
|---|
| 103 | ConditionalProcess f p q _ -> |
|---|
| 104 | ((keyword ifS) <+> (pretty f) <+> |
|---|
| 105 | (keyword thenS) <+> (glue pr p) <+> |
|---|
| 106 | (keyword elseS) <+> (glue pr q) |
|---|
| 107 | ) |
|---|
| 108 | -- precedence 2 |
|---|
| 109 | Hiding p es _ -> |
|---|
| 110 | (pretty p) <+> hiding_proc <+> (pretty es) |
|---|
| 111 | RenamingProcess p r _ -> |
|---|
| 112 | ((pretty p) <+> |
|---|
| 113 | ren_proc_open <+> (ppWithCommas r) <+> ren_proc_close) |
|---|
| 114 | -- precedence 3 |
|---|
| 115 | Sequential p q _ -> |
|---|
| 116 | (pretty p) <+> sequential <+> (glue pr q) |
|---|
| 117 | PrefixProcess ev p _ -> |
|---|
| 118 | (pretty ev) <+> prefix_proc <+> (glue pr p) |
|---|
| 119 | InternalPrefixProcess v s p _ -> |
|---|
| 120 | (internal_choice <+> (pretty v) <+> |
|---|
| 121 | (text svar_sortS) <+> (pretty s) <+> |
|---|
| 122 | prefix_proc <+> (glue pr p) |
|---|
| 123 | ) |
|---|
| 124 | ExternalPrefixProcess v s p _ -> |
|---|
| 125 | (external_choice <+> (pretty v) <+> |
|---|
| 126 | (text svar_sortS) <+> (pretty s) <+> |
|---|
| 127 | prefix_proc <+> (glue pr p) |
|---|
| 128 | ) |
|---|
| 129 | -- precedence 4 |
|---|
| 130 | InternalChoice p q _ -> |
|---|
| 131 | (pretty p) <+> internal_choice <+> (glue pr q) |
|---|
| 132 | ExternalChoice p q _ -> |
|---|
| 133 | (pretty p) <+> external_choice <+> (glue pr q) |
|---|
| 134 | -- precedence 5 |
|---|
| 135 | Interleaving p q _ -> |
|---|
| 136 | (pretty p) <+> interleave <+> (glue pr q) |
|---|
| 137 | SynchronousParallel p q _ -> |
|---|
| 138 | (pretty p) <+> synchronous <+> (glue pr q) |
|---|
| 139 | GeneralisedParallel p es q _ -> |
|---|
| 140 | ((pretty p) <+> genpar_open <+> (pretty es) <+> |
|---|
| 141 | genpar_close <+> (glue pr q)) |
|---|
| 142 | AlphabetisedParallel p les res q _ -> |
|---|
| 143 | ((pretty p) <+> alpar_open <+> |
|---|
| 144 | (pretty les) <+> alpar_sep <+> (pretty res) <+> |
|---|
| 145 | alpar_close <+> (glue pr q) |
|---|
| 146 | ) |
|---|
| 147 | |
|---|
| 148 | -- glue and prec_comp decide whether the child in the parse tree needs |
|---|
| 149 | -- to be parenthesised or not. Parentheses are necessary if the |
|---|
| 150 | -- right-child is at the same level of precedence as the parent but is |
|---|
| 151 | -- a different operator; otherwise, they're not. |
|---|
| 152 | |
|---|
| 153 | glue :: PROCESS -> PROCESS -> Doc |
|---|
| 154 | glue x y = if (prec_comp x y) |
|---|
| 155 | then lparen <+> pretty y <+> rparen |
|---|
| 156 | else pretty y |
|---|
| 157 | |
|---|
| 158 | -- This is really nasty, but sledgehammer effective and allows fine |
|---|
| 159 | -- control. Unmaintainable, however. :-( I imagine there's a way to |
|---|
| 160 | -- compare the types in a less boilerplate manner, but OTOH there are |
|---|
| 161 | -- some special cases where it's nice to be explicit. Also, hiding |
|---|
| 162 | -- and renaming are distinctly non-standard. *shrug* |
|---|
| 163 | |
|---|
| 164 | prec_comp :: PROCESS -> PROCESS -> Bool |
|---|
| 165 | prec_comp x y = |
|---|
| 166 | case x of |
|---|
| 167 | Hiding _ _ _ -> |
|---|
| 168 | case y of RenamingProcess _ _ _ -> True |
|---|
| 169 | _ -> False |
|---|
| 170 | RenamingProcess _ _ _ -> |
|---|
| 171 | case y of Hiding _ _ _ -> True |
|---|
| 172 | _ -> False |
|---|
| 173 | Sequential _ _ _ -> |
|---|
| 174 | case y of InternalPrefixProcess _ _ _ _ -> True |
|---|
| 175 | ExternalPrefixProcess _ _ _ _ -> True |
|---|
| 176 | _ -> False |
|---|
| 177 | PrefixProcess _ _ _ -> |
|---|
| 178 | case y of Sequential _ _ _ -> True |
|---|
| 179 | _ -> False |
|---|
| 180 | InternalPrefixProcess _ _ _ _ -> |
|---|
| 181 | case y of Sequential _ _ _ -> True |
|---|
| 182 | _ -> False |
|---|
| 183 | ExternalPrefixProcess _ _ _ _ -> |
|---|
| 184 | case y of Sequential _ _ _ -> True |
|---|
| 185 | _ -> False |
|---|
| 186 | ExternalChoice _ _ _ -> |
|---|
| 187 | case y of InternalChoice _ _ _ -> True |
|---|
| 188 | _ -> False |
|---|
| 189 | InternalChoice _ _ _ -> |
|---|
| 190 | case y of ExternalChoice _ _ _ -> True |
|---|
| 191 | _ -> False |
|---|
| 192 | Interleaving _ _ _ -> |
|---|
| 193 | case y of SynchronousParallel _ _ _ -> True |
|---|
| 194 | GeneralisedParallel _ _ _ _ -> True |
|---|
| 195 | AlphabetisedParallel _ _ _ _ _ -> True |
|---|
| 196 | _ -> False |
|---|
| 197 | SynchronousParallel _ _ _ -> |
|---|
| 198 | case y of Interleaving _ _ _ -> True |
|---|
| 199 | GeneralisedParallel _ _ _ _ -> True |
|---|
| 200 | AlphabetisedParallel _ _ _ _ _ -> True |
|---|
| 201 | _ -> False |
|---|
| 202 | GeneralisedParallel _ _ _ _ -> |
|---|
| 203 | case y of Interleaving _ _ _ -> True |
|---|
| 204 | SynchronousParallel _ _ _ -> True |
|---|
| 205 | AlphabetisedParallel _ _ _ _ _ -> True |
|---|
| 206 | _ -> False |
|---|
| 207 | AlphabetisedParallel _ _ _ _ _ -> |
|---|
| 208 | case y of Interleaving _ _ _ -> True |
|---|
| 209 | SynchronousParallel _ _ _ -> True |
|---|
| 210 | GeneralisedParallel _ _ _ _ -> True |
|---|
| 211 | _ -> False |
|---|
| 212 | _ -> False |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | instance Pretty EVENT where |
|---|
| 216 | pretty = printEvent |
|---|
| 217 | |
|---|
| 218 | printEvent :: EVENT -> Doc |
|---|
| 219 | printEvent (TermEvent t _) = pretty t |
|---|
| 220 | printEvent (ChanSend cn t _) = (pretty cn) <+> |
|---|
| 221 | (text chan_sendS) <+> |
|---|
| 222 | (pretty t) |
|---|
| 223 | printEvent (ChanNonDetSend cn v s _) = |
|---|
| 224 | (pretty cn) <+> (text chan_sendS) <+> |
|---|
| 225 | (pretty v) <+> (text svar_sortS) <+> (pretty s) |
|---|
| 226 | printEvent (ChanRecv cn v s _) = |
|---|
| 227 | (pretty cn) <+> (text chan_receiveS) <+> |
|---|
| 228 | (pretty v) <+> (text svar_sortS) <+> (pretty s) |
|---|
| 229 | |
|---|
| 230 | instance Pretty EVENT_SET where |
|---|
| 231 | pretty = printEventSet |
|---|
| 232 | |
|---|
| 233 | printEventSet :: EVENT_SET -> Doc |
|---|
| 234 | printEventSet (EventSet es _) = ppWithCommas es |
|---|