% % (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 -- remove the included bits 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 <+> {-pp_callconv <+> -} ppId i {- ((ppId i <> lparen) $$ ppParams params) <> rparen -} <+> ppRaises mb_raises <+> ppContext mb_ctxt <> semi -- where -- pp_callconv = mapFromMb empty (ppCallConv True) mb_callconv 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) -- [(Bool, Id, [Attribute])] = 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" -- or was that bool? ppType TyOctet = text "octet" -- aka byte 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}