diff --git a/common/ShowCode.hs b/common/ShowCode.hs
index 2873e46..983849d 100644
--- a/common/ShowCode.hs
+++ b/common/ShowCode.hs
@@ -19,20 +19,125 @@ with this program. If not, see .
-- | A module with type-classes and functions for displaying code, dependent on the context.
-- Primarily, this means showing code as occam in error messages for the occam frontend, and Rain code for the Rain frontend.
+
+
+-- TODO: This module is a mess. It should probably use the writer monad instead of this +>> operator, and I've put
+-- in some settings but some of them (such as realCode) are not wired up, and there's no easy way to set them
+-- from outside this module. Also, some things aren't quite right (such as replicated IFs), and due to the way
+-- the occam parser works, a few SEQs get introduced if you parse a file then write it out again straight away.
+
+-- So I'm committing this for the time being, but it really does need some work (and some tests, of course*) later on.
+
+-- * My plan for testing was to take each of the cgtests, and parse it in to AST_A. Then print AST_A using this
+-- module, and feed it back in to the parser to get AST_B. Then check if AST_A and AST_B are equal.
+
module ShowCode (showCode, showOccam, showRain, formatCode, extCode) where
import Control.Monad.State
import Data.Generics
import Data.List
-import Text.PrettyPrint.HughesPJ
+import qualified Data.Map as Map
+import Text.PrettyPrint.HughesPJ hiding (space, colon)
import Text.Regex
import qualified AST as A
import CompState
+data ShowOccamState = ShowOccamState {
+ indentLevel :: Int, -- The indent level in spaces (add two for each indent)
+ outerItem :: [String], -- What we are currently inside for Structureds, e.g. "IF" or "SEQ". Use the head of the list
+ useOriginalName :: Bool, -- Whether to use the original proc names
+ realCode :: Bool, -- Whether to leave out all helpful hints (e.g. {protocol} on Protocols)
+ originalNames :: Map.Map String String,
+ suppressNextIndent :: Bool,
+ -- Used to pass down variables for input modes, or for subscripts:
+ tempItem :: OccamWriter String
+}
+
+--TODO use the Writer monad instead, with StateT
+type OccamWriter a = State ShowOccamState a
+
+initialShowOccamState :: Map.Map String String -> ShowOccamState
+initialShowOccamState origNames = ShowOccamState {indentLevel = 0, outerItem = [], useOriginalName = True, realCode = True,
+ originalNames = origNames,suppressNextIndent = False, tempItem = return ""}
+
+showInputModeOccamM :: A.Variable -> A.InputMode -> OccamWriter String
+showInputModeOccamM v im = do modify (\s -> s {tempItem = showOccamM v})
+ showOccamM im
+
+showSubscriptOccamM :: ShowOccam a => a -> A.Subscript -> OccamWriter String
+showSubscriptOccamM arr s = do modify (\s -> s {tempItem = showOccamM arr})
+ showOccamM s
+
+suppressIndent :: OccamWriter String
+suppressIndent = do st <- get
+ put (st {suppressNextIndent = True})
+ return ""
+
+showOccamLine :: OccamWriter String -> OccamWriter String
+showOccamLine s = do st <- get
+ (if (suppressNextIndent st)
+ then do put (st {suppressNextIndent = False})
+ return ""
+ else return (replicate (indentLevel st) ' ')
+ ) +>> s +>> return "\n"
+
+
+occamIndent :: OccamWriter String
+occamIndent = do st <- get
+ put (st { indentLevel = (indentLevel st) + 2} )
+ return ""
+occamOutdent :: OccamWriter String
+occamOutdent = do st <- get
+ put (st { indentLevel = (indentLevel st) - 2} )
+ return ""
+
+occamBlock :: OccamWriter String -> OccamWriter String
+occamBlock s = occamIndent +>> s +>> occamOutdent
+
+showName :: A.Name -> OccamWriter String
+showName n = do st <- get
+ return $ if useOriginalName st then Map.findWithDefault k k (originalNames st) else k
+ where k = A.nameName n
+
+helper :: String -> OccamWriter String
+helper s = do st <- get
+ return $ if (realCode st) then "" else s
+
+currentContext :: OccamWriter String
+currentContext = get >>= (return . head . outerItem)
+
+pushContext :: String -> OccamWriter String
+pushContext x = do st <- get
+ put (st {outerItem = (x:(outerItem st))})
+ return ""
+
+beginStr :: String -> OccamWriter String
+beginStr n = pushContext n >> occamIndent
+
+endStr :: OccamWriter String
+endStr = popContext >> occamOutdent
+
+popContext :: OccamWriter String
+popContext = do st <- get
+ put (st {outerItem = tail (outerItem st)})
+ return ""
+
+doStr :: String -> OccamWriter String -> OccamWriter String
+doStr n s = showOccamLine (return n) +>> (beginStr n) +>> s +>> endStr
+
+--TODO remove this function? Or at least rename it
+showOccam :: ShowOccam a => a -> String
+showOccam x = evalState (showOccamM x) (initialShowOccamState Map.empty)
+
+bracket :: OccamWriter String -> OccamWriter String
+bracket x = return "(" +>> x +>> return ")"
+
-- | A type-class that indicates that the data (AST item) is displayable as occam code.
class ShowOccam a where
- showOccam :: a -> String
+-- showOccam :: a -> String
+-- showOccam = const ""
+ showOccamM :: a -> OccamWriter String
-- | A type-class that indicates that the data (AST item) is displayable as Rain code.
class ShowRain a where
@@ -42,9 +147,13 @@ class ShowRain a where
showCode :: (CSM m, ShowOccam a, ShowRain a) => a -> m String
showCode o
= do st <- get
- return $ case csFrontend st of
- FrontendOccam -> showOccam o
- FrontendRain -> showRain o
+ case csFrontend st of
+ FrontendOccam -> do st <- get
+ return $ evalState (showOccamM o) (initialShowOccamState $ transformNames $ csNames st)
+ FrontendRain -> return $ showRain o
+ where
+ transformNames :: Map.Map String A.NameDef -> Map.Map String String
+ transformNames = Map.map A.ndOrigName
-- | Some type hackery to allow formatCode to take a variable number of functions.
class CSM m => ShowCodeFormat a m | a -> m where
@@ -74,32 +183,33 @@ formatCode fmt = chain (splitRegex (mkRegex "%") fmt) []
--Type-class instances follow for ShowOccam and ShowRain:
instance ShowOccam A.Type where
- showOccam A.Bool = "BOOL"
- showOccam A.Byte = "BYTE"
- showOccam A.UInt16 = "UINT16"
- showOccam A.UInt32 = "UINT32"
- showOccam A.UInt64 = "UINT64"
- showOccam A.Int = "INT"
- showOccam A.Int8 = "INT8"
- showOccam A.Int16 = "INT16"
- showOccam A.Int32 = "INT32"
- showOccam A.Int64 = "INT64"
- showOccam A.Real32 = "REAL32"
- showOccam A.Real64 = "REAL64"
- showOccam (A.Array ds t)
- = concat [case d of
+ showOccamM A.Bool = return "BOOL"
+ showOccamM A.Byte = return "BYTE"
+ showOccamM A.UInt16 = return "UINT16"
+ showOccamM A.UInt32 = return "UINT32"
+ showOccamM A.UInt64 = return "UINT64"
+ showOccamM A.Int = return "INT"
+ showOccamM A.Int8 = return "INT8"
+ showOccamM A.Int16 = return "INT16"
+ showOccamM A.Int32 = return "INT32"
+ showOccamM A.Int64 = return "INT64"
+ showOccamM A.Real32 = return "REAL32"
+ showOccamM A.Real64 = return "REAL64"
+ showOccamM A.Any = return "ANY"
+ showOccamM A.Timer = return "TIMER"
+ showOccamM A.Time = return "TIME"
+
+ showOccamM (A.Array ds t)
+ = (return $ concat [case d of
A.Dimension n -> "[" ++ show n ++ "]"
A.UnknownDimension -> "[]"
- | d <- ds] ++ showOccam t
- showOccam (A.UserDataType n) = A.nameName n ++ "{data type}"
- showOccam (A.Record n) = A.nameName n ++ "{record}"
- showOccam (A.UserProtocol n) = A.nameName n ++ "{protocol}"
- showOccam (A.Chan _ _ t) = "CHAN OF " ++ showOccam t
- showOccam (A.Counted ct et) = showOccam ct ++ "::" ++ showOccam et
- showOccam A.Any = "ANY"
- showOccam A.Timer = "TIMER"
- showOccam A.Time = "TIME"
- showOccam (A.Port t) = "PORT OF " ++ showOccam t
+ | d <- ds]) +>> showOccamM t
+ showOccamM (A.Chan _ _ t) = return "CHAN OF " +>> showOccamM t
+ showOccamM (A.Counted ct et) = showOccamM ct +>> return "::" +>> showOccamM et
+ showOccamM (A.Port t) = return "PORT OF " +>> showOccamM t
+ showOccamM (A.UserDataType n) = showName n +>> helper "{data type}"
+ showOccamM (A.Record n) = showName n +>> helper "{record}"
+ showOccamM (A.UserProtocol n) = showName n +>> helper "{protocol}"
instance ShowRain A.Type where
@@ -125,28 +235,28 @@ instance ShowRain A.Type where
showRain x = ""
instance ShowOccam A.DyadicOp where
- showOccam A.Add = "+"
- showOccam A.Subtr = "-"
- showOccam A.Mul = "*"
- showOccam A.Div = "/"
- showOccam A.Rem = "REM"
- showOccam A.Plus = "PLUS"
- showOccam A.Minus = "MINUS"
- showOccam A.Times = "TIMES"
- showOccam A.BitAnd = "/\\"
- showOccam A.BitOr = "\\/"
- showOccam A.BitXor = "><"
- showOccam A.LeftShift = "<<"
- showOccam A.RightShift = ">>"
- showOccam A.And = "AND"
- showOccam A.Or = "OR"
- showOccam A.Eq = "="
- showOccam A.NotEq = "<>"
- showOccam A.Less = "<"
- showOccam A.More = ">"
- showOccam A.LessEq = "<="
- showOccam A.MoreEq = ">="
- showOccam A.After = "AFTER"
+ showOccamM A.Add = return "+"
+ showOccamM A.Subtr = return "-"
+ showOccamM A.Mul = return "*"
+ showOccamM A.Div = return "/"
+ showOccamM A.Rem = return "REM"
+ showOccamM A.Plus = return "PLUS"
+ showOccamM A.Minus = return "MINUS"
+ showOccamM A.Times = return "TIMES"
+ showOccamM A.BitAnd = return "/\\"
+ showOccamM A.BitOr = return "\\/"
+ showOccamM A.BitXor = return "><"
+ showOccamM A.LeftShift = return "<<"
+ showOccamM A.RightShift = return ">>"
+ showOccamM A.And = return "AND"
+ showOccamM A.Or = return "OR"
+ showOccamM A.Eq = return "="
+ showOccamM A.NotEq = return "<>"
+ showOccamM A.Less = return "<"
+ showOccamM A.More = return ">"
+ showOccamM A.LessEq = return "<="
+ showOccamM A.MoreEq = return ">="
+ showOccamM A.After = return "AFTER"
instance ShowRain A.DyadicOp where
@@ -165,12 +275,18 @@ instance ShowRain A.DyadicOp where
showRain A.MoreEq = ">="
showRain x = ""
+instance ShowOccam A.MonadicOp where
+ showOccamM A.MonadicSubtr = return "-"
+ showOccamM A.MonadicMinus = return "MINUS"
+ showOccamM A.MonadicBitNot = return "~"
+ showOccamM A.MonadicNot = return "NOT"
+
instance ShowOccam A.Variable where
- showOccam (A.Variable _ n) = show n
- showOccam (A.SubscriptedVariable _ s v) = showOccam v ++ "[" ++ show s ++ "]"
- showOccam (A.DirectedVariable _ A.DirUnknown v) = showOccam v
- showOccam (A.DirectedVariable _ A.DirInput v) = showOccam v ++ "?"
- showOccam (A.DirectedVariable _ A.DirOutput v) = showOccam v ++ "!"
+ showOccamM (A.Variable _ n) = showName n
+ showOccamM (A.SubscriptedVariable _ s v) = showSubscriptOccamM v s
+ showOccamM (A.DirectedVariable _ A.DirUnknown v) = showOccamM v
+ showOccamM (A.DirectedVariable _ A.DirInput v) = showOccamM v +>> return "?"
+ showOccamM (A.DirectedVariable _ A.DirOutput v) = showOccamM v +>> return "!"
instance ShowRain A.Variable where
showRain (A.Variable _ n) = show n
@@ -178,6 +294,222 @@ instance ShowRain A.Variable where
showRain (A.DirectedVariable _ A.DirOutput v) = "!" ++ showRain v
showRain x = ""
+instance ShowOccam A.ArrayElem where
+ showOccamM (A.ArrayElemArray elems) = return "[" +>> showWithCommas elems +>> return "]"
+ showOccamM (A.ArrayElemExpr e) = showOccamM e
+
+instance ShowOccam A.LiteralRepr where
+ showOccamM (A.RealLiteral _ s) = return s
+ showOccamM (A.IntLiteral _ s) = return s
+ showOccamM (A.HexLiteral _ s) = return ("#" ++ s)
+ showOccamM (A.ByteLiteral _ s) = return ("'" ++ s ++ "'")
+ showOccamM (A.ArrayLiteral _ elems) = return "[" +>> showWithCommas elems +>> return "]"
+ --TODO record literals
+
+instance ShowOccam A.Subscript where
+ showOccamM (A.Subscript _ e) = getTempItem +>> return "[" +>> showOccamM e +>> return "]"
+ showOccamM (A.SubscriptField _ n) = getTempItem +>> return "[" +>> showName n +>> return "]"
+ showOccamM (A.SubscriptFromFor _ start count)
+ = return "[" +>> getTempItem +>> return " FROM " +>> showOccamM start +>> return " FOR " +>> showOccamM count +>> return "]"
+ showOccamM (A.SubscriptFor _ count)
+ = return "[" +>> getTempItem +>> return " FOR " +>> showOccamM count +>> return "]"
+ showOccamM (A.SubscriptFrom _ start)
+ = return "[" +>> getTempItem +>> return " FROM " +>> showOccamM start +>> return "]"
+
+
+convOrSpace :: A.ConversionMode -> OccamWriter String
+convOrSpace A.DefaultConversion = space
+convOrSpace A.Round = return " ROUND "
+convOrSpace A.Trunc = return " TRUNC "
+
+instance ShowOccam A.Expression where
+ showOccamM (A.Monadic _ op e) = bracket $ showOccamM op +>> space +>> showOccamM e
+ showOccamM (A.Dyadic _ op lhs rhs) = bracket $ showOccamM lhs +>> space +>> showOccamM op +>> space +>> showOccamM rhs
+ showOccamM (A.MostPos _ t) = bracket $ return "MOSTPOS " +>> showOccamM t
+ showOccamM (A.MostNeg _ t) = bracket $ return "MOSTNEG " +>> showOccamM t
+ showOccamM (A.SizeType _ t) = bracket $ return "SIZE " +>> showOccamM t
+ showOccamM (A.SizeExpr _ e) = bracket $ return "SIZE " +>> showOccamM e
+ showOccamM (A.SizeVariable _ v) = bracket $ return "SIZE " +>> showOccamM v
+ showOccamM (A.Conversion _ cm t e) = bracket $ showOccamM t +>> convOrSpace cm +>> showOccamM e
+ showOccamM (A.ExprVariable _ v) = showOccamM v
+ showOccamM (A.Literal _ _ lit) = showOccamM lit
+ showOccamM (A.True _) = return "TRUE"
+ showOccamM (A.False _) = return "FALSE"
+ showOccamM (A.FunctionCall _ n es) = showName n +>> return "(" +>> showWithCommas es +>> return ")"
+ showOccamM (A.SubscriptedExpr _ s e) = showSubscriptOccamM e s
+ showOccamM (A.BytesInExpr _ e) = bracket $ return "BYTESIN " +>> showOccamM e
+ showOccamM (A.BytesInType _ t) = bracket $ return "BYTESIN " +>> showOccamM t
+ showOccamM (A.OffsetOf _ t n) = return "OFFSETOF(" +>> showOccamM t +>> return " , " +>> showName n +>> return ")"
+ --TODO exprconstr
+
+instance ShowOccam A.Formal where
+ showOccamM (A.Formal am t n) = (maybeVal am)
+ +>> (showOccamM t)
+ +>> space
+ +>> (showName n)
+
+space :: OccamWriter String
+space = return " "
+
+colon :: OccamWriter String
+colon = return ":"
+
+maybeVal :: A.AbbrevMode -> OccamWriter String
+maybeVal am = return $ if (am == A.ValAbbrev) then "VAL " else ""
+
+instance ShowOccam A.Specification where
+ -- TODO add specmode to the output
+ showOccamM (A.Specification _ n (A.Proc _ sm params body))
+ = do n' <- showName n
+ params' <- showAll (intersperse (return ",") $ map showOccamM params)
+ --TODO use the occamdoc setting
+ showOccamLine (return $ "PROC " ++ n' ++ "(" ++ params' ++ ")") +>> occamIndent +>> showOccamM body +>> occamOutdent +>> showOccamLine (return ":")
+ showOccamM (A.Specification _ n (A.Declaration _ t))
+ = showOccamLine $ showOccamM t +>> space +>> showName n +>> colon
+ showOccamM (A.Specification _ n (A.Is _ am t v))
+ = showOccamLine $ (maybeVal am) +>> showOccamM t +>> space +>> showName n +>> return " IS " +>> showOccamM v +>> colon
+ showOccamM (A.Specification _ n (A.IsExpr _ am t e))
+ = showOccamLine $ (maybeVal am) +>> showOccamM t +>> space +>> showName n +>> return " IS " +>> showOccamM e +>> colon
+ showOccamM (A.Specification _ n (A.IsChannelArray _ t vs))
+ = showOccamLine $ showOccamM t +>> space +>> showName n +>> return " IS [" +>> showWithCommas vs +>> return "]:"
+ showOccamM (A.Specification _ n (A.DataType _ t))
+ = showOccamLine $ return "DATA TYPE " +>> showName n +>> return " IS " +>> showOccamM t +>> colon
+ showOccamM (A.Specification _ n (A.RecordType _ packed fields))
+ = (showOccamLine $ return "DATA TYPE " +>> showName n)
+ +>> occamIndent
+ +>> (showOccamLine $ return (if packed then "PACKED RECORD" else "RECORD"))
+ +>> occamIndent
+ +>> (showAll (map (\(n,t) -> showOccamLine $ showOccamM t +>> space +>> showName n +>> colon) fields))
+ +>> occamOutdent
+ +>> occamOutdent
+ +>> (showOccamLine colon)
+ --TODO use the specmode
+ showOccamM (A.Specification _ n (A.Function _ sm retTypes params el@(A.OnlyEL {})))
+ = showOccamLine $
+ showWithCommas retTypes +>> (return " FUNCTION ") +>> showName n +>> return "(" +>> showWithCommas params +>> return ")"
+ +>> return " IS " +>> showOccamM el +>> colon
+ showOccamM (A.Specification _ n (A.Function _ sm retTypes params body))
+ = (showOccamLine $ showWithCommas retTypes +>> (return " FUNCTION ") +>> showName n +>> return "(" +>> showWithCommas params +>> return ")")
+ +>> occamIndent
+ +>> showOccamM body
+ +>> occamOutdent
+ +>> showOccamLine colon
+ showOccamM (A.Specification _ n (A.Protocol _ ts))
+ = showOccamLine $ return "PROTOCOL " +>> showName n +>> return " IS " +>> showWithSemis ts +>> colon
+ showOccamM (A.Specification _ n (A.ProtocolCase _ nts))
+ = (showOccamLine $ return "PROTOCOL " +>> showName n) +>> occamBlock
+ (showOccamLine (return "CASE") +>> occamBlock
+ (showAll $ map (showOccamLine . showProtocolItem) nts)
+ ) +>> colon
+ showOccamM (A.Specification _ n (A.Retypes _ am t v))
+ = showOccamLine $ maybeVal am +>> showOccamM t +>> space +>> showName n +>> return " RETYPES " +>> showOccamM v +>> colon
+ showOccamM (A.Specification _ n (A.RetypesExpr _ am t e))
+ = showOccamLine $ maybeVal am +>> showOccamM t +>> space +>> showName n +>> return " RETYPES " +>> showOccamM e +>> colon
+
+showProtocolItem :: (A.Name, [A.Type]) -> OccamWriter String
+showProtocolItem (n,ts) = showAll $ intersperse (return " ; ") $ [showName n] ++ (map showOccamM ts)
+
+instance ShowOccam A.Variant where
+ showOccamM (A.Variant _ n iis p)
+ = (showOccamLine (showAll $ intersperse (return " ; ") $ [showName n] ++ (map showOccamM iis)))
+ +>> occamIndent +>> showOccamM p +>> occamOutdent
+
+instance ShowOccam A.Actual where
+ showOccamM (A.ActualVariable _ _ v) = showOccamM v
+ showOccamM (A.ActualExpression _ e) = showOccamM e
+
+instance ShowOccam A.OutputItem where
+ showOccamM (A.OutExpression _ e) = showOccamM e
+ showOccamM (A.OutCounted _ ce ae) = showOccamM ce +>> return " :: " +>> showOccamM ae
+
+getTempItem :: OccamWriter String
+getTempItem = get >>= tempItem
+
+instance ShowOccam A.InputItem where
+ showOccamM (A.InVariable _ v) = showOccamM v
+ showOccamM (A.InCounted _ cv av) = showOccamM cv +>> return " :: " +>> showOccamM av
+
+instance ShowOccam A.InputMode where
+ showOccamM (A.InputSimple _ iis)
+ = showOccamLine $ getTempItem +>> return " ? " +>> (showWithSemis iis)
+ showOccamM (A.InputCase _ str)
+ = (showOccamLine $ getTempItem +>> return " ? CASE") +>> occamIndent +>> showOccamM str +>> occamOutdent
+ showOccamM (A.InputTimerRead _ ii)
+ = showOccamLine $ getTempItem +>> return " ? " +>> showOccamM ii
+ showOccamM (A.InputTimerAfter _ e)
+ = showOccamLine $ getTempItem +>> return " ? AFTER " +>> showOccamM e
+
+
+instance ShowOccam A.Alternative where
+ showOccamM (A.Alternative _ v im p) = showInputModeOccamM v im +>> occamIndent +>> showOccamM p +>> occamOutdent
+ showOccamM (A.AlternativeCond _ e v im p) = showOccamM e +>> return " & " +>> suppressIndent +>> showOccamM (A.Alternative undefined v im p)
+
+instance ShowOccam A.Replicator where
+ showOccamM (A.For _ n start count) = return " " +>> showName n +>> return " = " +>> showOccamM start +>> return " FOR " +>> showOccamM count
+ showOccamM (A.ForEach _ n e) = return " " +>> showName n +>> return " IN " +>> showOccamM e
+
+instance ShowOccam A.Choice where
+ showOccamM (A.Choice _ e p) = showOccamLine (showOccamM e) +>> occamBlock (showOccamM p)
+
+instance ShowOccam A.Option where
+ showOccamM (A.Option _ es p) = showOccamLine (showAll $ intersperse (return " , ") $ map showOccamM es) +>> occamBlock (showOccamM p)
+ showOccamM (A.Else _ p) = showOccamLine (return "ELSE") +>> occamBlock (showOccamM p)
+
+instance ShowOccam A.Structured where
+ showOccamM (A.Spec _ spec str) = showOccamM spec +>> showOccamM str
+ showOccamM (A.Rep _ rep str)
+ = do item <- currentContext
+ (showOccamLine (return (item ++ " ") +>> showOccamM rep)) +>> occamIndent +>> showOccamM str +>> occamOutdent
+ showOccamM (A.OnlyP _ p) = showOccamM p
+ showOccamM (A.OnlyEL _ el) = showOccamM el
+ showOccamM (A.OnlyA _ a) = showOccamM a
+ showOccamM (A.OnlyV _ v) = showOccamM v
+ showOccamM (A.OnlyC _ c) = showOccamM c
+ showOccamM (A.OnlyO _ o) = showOccamM o
+ showOccamM (A.Several _ ss) = showAll $ map showOccamM ss
+ showOccamM (A.ProcThen _ p str) = showOccamLine (return "VALOF") +>> occamBlock (showOccamM p +>> showOccamLine (return "RESULT " +>> showOccamM str))
+
+showWithCommas :: ShowOccam a => [a] -> OccamWriter String
+showWithCommas ss = showAll $ intersperse (return " , ") $ map showOccamM ss
+
+showWithSemis :: ShowOccam a => [a] -> OccamWriter String
+showWithSemis ss = showAll $ intersperse (return " ; ") $ map showOccamM ss
+
+instance ShowOccam A.ExpressionList where
+ showOccamM (A.ExpressionList _ es) = showWithCommas es
+ --TODO functioncalllist
+
+outer :: String -> A.Structured -> OccamWriter String
+outer keyword (A.Rep _ rep str) = showOccamLine (return keyword +>> showOccamM rep) +>> beginStr keyword +>> showOccamM str +>> endStr
+outer keyword str = doStr keyword (showOccamM str)
+
+instance ShowOccam A.Process where
+ showOccamM (A.Assign _ vs el) = showOccamLine (showWithCommas vs +>> return ":=" +>> showOccamM el)
+ showOccamM (A.Skip _) = showOccamLine $ return "SKIP"
+ showOccamM (A.Stop _) = showOccamLine $ return "STOP"
+ showOccamM (A.Input _ v im) = showInputModeOccamM v im
+ showOccamM (A.Output _ v ois) = showOccamLine $ showOccamM v +>> return " ! " +>> (showWithSemis ois)
+ showOccamM (A.OutputCase _ v n ois) = showOccamLine $ showOccamM v +>> return " ! " +>>
+ (showAll $ intersperse (return " ; ") $ [showName n] ++ (map showOccamM ois))
+ --TODO gettime and wait ?
+
+ --TODO proccall
+ showOccamM (A.ProcCall _ n params) = showOccamLine $ showName n +>> return " ( " +>> showWithCommas params +>> return " ) "
+ showOccamM (A.While _ e p) = (showOccamLine $ return "WHILE " +>> showOccamM e) +>> occamIndent +>> showOccamM p +>> occamOutdent
+ showOccamM (A.Case _ e s) = (showOccamLine $ return "CASE " +>> showOccamM e) +>> occamBlock (showOccamM s)
+ showOccamM (A.If _ str) = outer "IF" str
+ showOccamM (A.Alt _ False str) = outer "ALT" str
+ showOccamM (A.Alt _ True str) = outer "PRI ALT" str
+ showOccamM (A.Seq _ str) = outer "SEQ" str
+ showOccamM (A.Par _ A.PlainPar str) = outer "PAR" str
+ showOccamM (A.Par _ A.PriPar str) = outer "PRI PAR" str
+ showOccamM (A.Par _ A.PlacedPar str) = outer "PLACED PAR" str
+-- showOccamM _x = return $ "#error unimplemented" ++ show _x
+
+--TEMP:
+instance ShowRain a where
+ showRain = const ""
+
-- | Extends an existing (probably generic) function with cases for everything that has a specific ShowOccam and ShowRain instance
-- This is a bit of manual wiring. Because we can't generically deduce whether or not
-- a given Data item has a showRain\/showOccam implementation (that I know of), I have
@@ -186,6 +518,23 @@ instance ShowRain A.Variable where
-- classes you have to provide a specific instance above anyway, I don't think that adding
-- one more line while you're at it is too bad.
extCode :: Typeable b => (b -> Doc) -> (forall a. (ShowOccam a, ShowRain a) => a -> String) -> (b -> Doc)
-extCode q f = q `extQ` (text . (f :: A.Type -> String))
+extCode q f = q
`extQ` (text . (f :: A.DyadicOp -> String))
+ `extQ` (text . (f :: A.Expression -> String))
+ `extQ` (text . (f :: A.ExpressionList -> String))
+ `extQ` (text . (f :: A.Formal -> String))
+ `extQ` (text . (f :: A.MonadicOp -> String))
+ `extQ` (text . (f :: A.Process -> String))
+ `extQ` (text . (f :: A.Replicator -> String))
+ `extQ` (text . (f :: A.Specification -> String))
+ `extQ` (text . (f :: A.Structured -> String))
+ `extQ` (text . (f :: A.Type -> String))
`extQ` (text . (f :: A.Variable -> String))
+
+(+>>) :: State s [a] -> State s [a] -> State s [a]
+(+>>) x y = do x' <- x
+ y' <- y
+ return (x' ++ y')
+
+showAll :: [State s [a]] -> State s [a]
+showAll = foldl (+>>) (return [])