%
% (c) The Foo Project, University of Glasgow, 1998
%
% @(#) $Docid: Feb. 9th 2003 15:07 Sigbjorn Finne $
% @(#) $Contactid: sof@galois.com $
%
\begin{code}
module PpIDLSyn where
import IDLSyn
import PP
import Literal
import BasicTypes
import Utils
import Maybe
import Opts ( optDebug, optIncludeAsImport, optExcludeSysIncludes )
type IDLDoc = PPDoc ()
showIDL :: IDLDoc -> String
showIDL i = showPPDoc i ()
ppIDL :: String -> [Defn] -> IDLDoc
ppIDL src ds
| optIncludeAsImport || optExcludeSysIncludes = vsep (map ppDefn (trundle [Nothing] ds)) $$ text ""
| otherwise = vsep (map ppDefn ds) $$ text ""
where
trundle _ [] = []
trundle ks@(keepIt:ls) (x:xs) =
case x of
IncludeStart ix | isJust keepIt || is_src -> trundle (Just forKeeps : ks) xs
where
is_src = src == ix
forKeeps = fromMaybe True keepIt && is_src
IncludeEnd -> trundle ls xs
_ | fromMaybe True keepIt -> x : trundle ks xs
| otherwise -> trundle ks xs
trundle [] ls = ls
\end{code}
\begin{code}
ppId :: Id -> IDLDoc
ppId iden =
case iden of
Id i -> text i
AttrId as i -> ppAttrs False as <> ppId i
ArrayId i dims -> ppId i <> ppList (map ppExpr dims)
FunId i mb_cc ps -> (pp_callconv mb_cc) <+> ppId i <> parens (ppParams ps)
BitFieldId x i -> ppId i <+> char ':' <> text (show x)
CConvId cc i -> (pp_callconv (Just cc)) <+> ppId i
Pointed quals i -> text (replicate len '*') <> ppId i
where
len = length quals
where
pp_callconv mb_cc = mapFromMb empty (ppCallConv True) mb_cc
\end{code}
%*
%
\subsection{Pretty printing a definition}
%
%*
\begin{code}
ppDefn :: Defn -> IDLDoc
ppDefn (Typedef t attrs ids)
= text "typedef" <+>
ppAttrs False attrs <+>
ppType t <+>
hsep (punctuate comma (map ppId ids)) <> semi
ppDefn (TypeDecl t) = ppType t <> semi
ppDefn (ExternDecl t is) = text "extern" <+> ppType t <+> hsep (punctuate comma (map ppId is)) <> semi
ppDefn (Constant i attrs t expr)
= ppAttrs False attrs <> text "const" <+> ppType t <+> ppId i <+> equals <+> ppExpr expr <> semi
ppDefn (Attributed attrs d)
= ppAttrs False attrs $+$ ppDefn d
ppDefn (Attribute ids read_only t)
| read_only = text "readonly" <+> ppType t <+> hsep (punctuate comma (map ppId ids)) <> semi
| otherwise = ppType t <+> hsep (punctuate comma (map ppId ids)) <> semi
ppDefn (Operation i res_ty mb_raises mb_ctxt)
= ppType res_ty <+> ppId i
<+> ppRaises mb_raises <+> ppContext mb_ctxt <> semi
ppDefn (Exception i mems)
= text "exception" <+> ppId i <+> ppMembers mems <> semi
ppDefn (Interface i inherit ds)
= hang (text "interface" <+> ppId i <+>
hsep (punctuate (text ":")
(text "" : map text inherit)) <+> char '{')
4 (ppDefns ds) $$
char '}' <> semi
ppDefn (Forward i)
= text "interface" <+> ppId i <> semi
ppDefn (Module i ds)
= text "module" <+> ppId i <+> char '{' $$
ppDefns ds $$
char '}' <> semi
ppDefn (DispInterface i props meths)
= text "dispinterface" <+> ppId i <+> char '{' $$
hang (text "properties:")
8 (ppProps props) $$
hang (text "methods:")
8 (ppDefns meths) $$
char '}' <> semi
ppDefn (DispInterfaceDecl i iid)
= text "dispinterface" <+> ppId i <+> char '{' $$
text "interface" <+> ppId iid <> semi $$
char '}' <> semi
ppDefn (CoClass i c_mems)
= text "coclass" <+> ppId i <+>
char '{' $$
ppCoCMembers c_mems $$
char '}' <> semi
ppDefn (Library i ds)
= text "library" <+> ppId i <+> char '{' $$
ppDefns ds $$
char '}' <> semi
ppDefn (CppQuote str)
= text "cpp_quote" <+> parens (doubleQuotes (text str))
ppDefn (HsQuote str)
= text "hs_quote" <+> parens (doubleQuotes (text str))
ppDefn (CInclude str)
= text "include" <+> text str
ppDefn (Import imps)
| optDebug =
text "import" <+>
hsep (punctuate comma (map (\ (v,defs) -> doubleQuotes (text v) $$ vcat (map ppDefn defs)) imps)) <> semi
| otherwise =
text "import" <+>
hsep (punctuate comma (map (\ (v,_) -> doubleQuotes (text v)) imps)) <> semi
ppDefn (ImportLib imp)
= text "importlib" <+> parens (doubleQuotes (text imp)) <> semi
ppDefn (Pragma str)
= text "#pragma" <+> text str
ppDefn (IncludeStart _) = empty
ppDefn IncludeEnd = empty
\end{code}
%*
%
\subsection{Pretty printing types}
%
%*
\begin{code}
ppType :: Type -> IDLDoc
ppType (TyApply f a) = ppType f <+> ppType a
ppType (TyInteger sz) = ppSize sz
ppType (TyFloat sz) =
text $
case sz of
Short -> "float"
Long -> "double"
LongLong -> "long double"
Natural -> "float"
ppType (TySigned isSigned)
| isSigned = text "signed"
| otherwise = text "unsigned"
ppType TyChar = text "char"
ppType TyWChar = text "wchar"
ppType TyBool = text "boolean"
ppType TyOctet = text "octet"
ppType TyAny = text "any"
ppType TyObject = text "Object"
ppType TyStable = text "StablePtr"
ppType TyVoid = text "void"
ppType TyBString = text "BSTR"
ppType (TyPointer t) = ppType t <> char '*'
ppType (TyArray t es) = ppType t <> ppList (map ppExpr es)
ppType (TySafeArray t) = text "SAFEARRAY" <> parens (ppType t)
ppType (TyFun mb_cc t ps) =
ppType t <+> parens (pp_callconv <+> char '*') <>
parens (ppParams ps)
where
pp_callconv = mapFromMb empty (ppCallConv True) mb_cc
ppType (TyStruct mb_tag [] _) =
text "struct" <+> tag
where
tag = mapFromMb empty ppId mb_tag
ppType (TyStruct mb_tag mems mb_pack) =
hang (text "struct" <+> tag <+> char '{')
4 (ppMembers mems) $$
char '}' $$
fromMaybe empty (fmap (\ x -> text "/*" <> text (show x) <> text "*/") mb_pack)
where
tag = mapFromMb empty ppId mb_tag
ppType (TyString mblen) =
text "string" <>
(mapFromMb empty
(\ l -> char '<' <> ppExpr l <> char '>') mblen)
ppType (TyWString mblen) =
text "wstring" <>
(mapFromMb empty
(\ l -> char '<' <> ppExpr l <> char '>') mblen)
ppType (TySequence t mblen) =
text "sequence" <>
char '<' <> ppType t <>
(mapFromMb empty (\ l -> comma <> ppExpr l) mblen) <>
char '>'
ppType (TyFixed Nothing) = text "fixed"
ppType (TyFixed (Just (e,i))) =
text "fixed" <> char '<' <>
ppExpr e <> comma <+> ppILit i <>
char '>'
ppType (TyName nm _) = text nm
ppType (TyIface nm) = text nm
ppType (TyUnion struct_name ty switch_name union_name switches) =
text "union" <+>
(mapFromMb empty ppId struct_name) <+>
text "switch" <>
parens (ppType ty <+> ppId switch_name) <+>
(mapFromMb empty ppId union_name) <+> char '{' $+$
ppSwitches switches $+$
char '}'
ppType (TyCUnion mbid members _) =
hang (text "union" <+>
(mapFromMb empty ppId mbid) <+> char '{')
3 (ppMembers members) $+$
char '}'
ppType (TyUnionNon mbid switches) =
hang (text "union" <+>
(mapFromMb empty ppId mbid) <+> char '{')
3 (ppSwitches switches) $+$
char '}'
ppType (TyEnum mbid enums) =
hang (text "enum" <+> pp_id <+> char '{')
3 (pp_vals) $$
char '}'
where
pp_id = mapFromMb empty ppId mbid
pp_vals =
vsep (punctuate comma (map ppVal enums))
ppVal (i, attrs, Nothing) = ppAttrs False attrs <> ppId i
ppVal (i, attrs, Just e) = ppAttrs False attrs <> ppId i <+> equals <+> ppExpr e
ppType (TyQualifier q) = ppQualifier q
\end{code}
%*
%
\subsection{Misc pretty printing functions}
%
%*
\begin{code}
ppMembers :: [Member] -> IDLDoc
ppMembers mems = ppDecls (map ppMember mems)
ppMember :: Member -> IDLDoc
ppMember (t, attrs, ids) =
ppAttrs False attrs <+> ppType t <+> hcat (punctuate comma (map ppId ids))
ppDefns :: [Defn] -> IDLDoc
ppDefns ls = ppDecls (map ppDefn ls)
ppAttrs :: Bool -> [Attribute] -> IDLDoc
ppAttrs isParam []
| isParam = text "[in]"
| otherwise = empty
ppAttrs _ as = ppList (map ppAttr as)
ppAttr :: Attribute -> IDLDoc
ppAttr (Mode dir) = ppDirection dir
ppAttr (Attrib f []) = ppId f
ppAttr (Attrib f args) =
ppId f <> parens (hsep (punctuate comma (map ppAttrParam args)))
where
ppAttrParam EmptyAttr = empty
ppAttrParam (AttrExpr e) = ppExpr e
ppAttrParam (AttrLit l) = ppLit l
ppAttrParam (AttrPtr a) = char '*' <> ppAttrParam a
ppCoCMembers :: [CoClassMember] -> IDLDoc
ppCoCMembers mems = ppDecls (map ppCoCMember mems)
ppCoCMember :: CoClassMember -> IDLDoc
ppCoCMember (isInterface, i, attrs) =
ppAttrs False attrs <+>
(if isInterface then
text "interface"
else
text "dispinterface") <+>
ppId i
ppParams :: [Param] -> IDLDoc
ppParams ps = vsep (punctuate comma (map ppParam ps))
ppParam :: Param -> IDLDoc
ppParam (Param nm ty attrs) = ppAttrs True attrs <+> ppType ty <+> ppId nm
ppRaises :: Maybe Raises -> IDLDoc
ppRaises Nothing = empty
ppRaises (Just ids) =
text "raises" <+>
ppTuple (map text ids)
ppContext :: Maybe Context -> IDLDoc
ppContext Nothing = empty
ppContext (Just ids) =
text "context" <+>
ppTuple (map (doubleQuotes.text) ids)
ppProps :: [([Attribute], Type, Id)] -> IDLDoc
ppProps ls = ppDecls (map ppProp ls)
ppProp :: ([Attribute], Type, Id) -> IDLDoc
ppProp (as, ty, nm) = ppAttrs False as <+> ppType ty <+> ppId nm
ppSwitches :: [Switch] -> IDLDoc
ppSwitches ls = ppDecls (map ppSwitch ls)
ppSwitch :: Switch -> IDLDoc
ppSwitch (Switch labels Nothing) =
ppCaseLabels labels
ppSwitch (Switch labels (Just param)) =
ppCaseLabels labels <+> ppParam param
\end{code}
%*
%
\subsection{Pretty printing expressions}
%
%*
\begin{code}
ppExpr :: Expr -> IDLDoc
ppExpr (Binary op e1 e2) =
parens (ppExpr e1) <+>
ppBinaryOp op <+>
parens (ppExpr e2)
ppExpr (Unary op e) =
ppUnaryOp op <+> parens (ppExpr e)
ppExpr (Var i) = text i
ppExpr (Lit l) = ppLit l
ppExpr (Cast t e) = parens (ppType t) <> parens (ppExpr e)
ppExpr (Sizeof ty) = text "sizeof" <> parens (ppType ty)
ppExpr (Cond a b c) = parens (ppExpr a) <+> char '?' <+> ppExpr b <+> char ':' <+> ppExpr c
ppCaseLabels :: [CaseLabel] -> IDLDoc
ppCaseLabels ls = hsep (punctuate (text ": ") (map ppCaseLabel ls))
ppCaseLabel :: CaseLabel -> IDLDoc
ppCaseLabel Default = text "default"
ppCaseLabel (Case es) = text "case" <+> ppTuple (map ppExpr es)
\end{code}