% % (c) The Foo Project, University of Glasgow 1998-99 % % @(#) $Docid: Dec. 27th 2001 00:14 Sigbjorn Finne $ % @(#) $Contactid: sof@galois.com $ % Prior to converting (core) IDL declarations to Haskell, we run a renaming pass over the IDL, performing the following tasks: - fields labels, method names and types are renamed so as to be unique within the scope of a Haskell module. - For imported types, adjust the module name to point to the Haskell interface/module we're importing from. To be more precise, IDL has three namespaces: * struct/union/enum tags * component names (fields, parameter names) * other (typedef names, method names and enumeration constants) which are mapped onto the following Haskell namespaces: * tags => type constructors (unique per module.) * field labels => varids (unique per module.) * parameter names => varids (unique per function.) * typedef nms. => type ids (unique per module.) * method names => varids (unique per module.) * module names => modids (unique per translation unit.) * interface names => varids / modids (unique per translation unit.) An added wrinkle when mapping from IDL into Haskell namespaces is that we have to make sure we don't map IDL names onto Haskell keywords/reserved ids. \begin{code} module Rename ( renameDecls, IsoEnv, IfaceNukeEnv ) where import RnMonad import CoreIDL import BasicTypes import CoreUtils ( mkHaskellTyConName, isMethod, mkIfaceTypeName, getTypeAttributes, localiseTypes ) import Attribute ( isConstantAttribute, hasAttributeWithName, hasAttributeWithNames, sourceAttribute, filterAttributes, filterOutAttributes, findAttribute, findStringAttributes ) import Utils ( dropSuffix, mapMbM, splitLast ) import DsMonad ( TypeEnv, SourceEnv, TagEnv, IfaceEnv ) import Opts ( optOneModulePerInterface, optCoalesceIsomorphicMethods, optPrefixIfaceName, optAppendIfaceName, optInlineTypes, optCharPtrIsString, optUseStdDispatch ) import Maybe ( isJust, fromMaybe ) import List ( isPrefixOf ) import Monad ( when, mplus ) import Char ( isUpper, toUpper ) import Literal \end{code} This module's shopfront is @renameDecls@, renaming a list of declarations. Along with the renamed decls, @renameDecls@ returns an environment of method names. The environment contains signatures of methods for which there exist isomorphic definitions, .e.g., @ interface IA { void foo(); }; interface IB { void foo(); }; @ The @foo@ method in @IB@ is isomorphic to the one in @IA@, a fact that may be exploited when generating code, creating just an overloaded version of @foo@ (or one that is just not as strongly typed.) \begin{code} renameDecls :: TypeEnv -> TagEnv -> SourceEnv -> IfaceEnv -> [Decl] -> ([Decl], IsoEnv, IfaceNukeEnv) renameDecls tenv tgenv senv ienv ds = runRnM tenv tgenv senv ienv $ mapM renameDecl (localiseTypes ds) \end{code} Renaming individual definitions: \begin{code} renameDecl :: Decl -> RnM Decl renameDecl (Typedef i t orig_ty) = do i' <- renameTypeId (normaliseIdName i) t' <- renameType t getModuleName $ \ x -> do n_ty <- normaliseTy x [] t' return (Typedef i' n_ty orig_ty) renameDecl (Constant i t o_t e) = do i' <- renameVarId (normaliseIdName i) t' <- renameType t o_t' <- relabelType False o_t return (Constant i' t' o_t' e) renameDecl (Interface i is_ref inh ds) = do i' <- renameConId (normaliseIdName i) i'' <- renameTypeId i' is_source <- isSourceIface (idName i) let i''' | is_source = i''{idAttributes=sourceAttribute:idAttributes i''} | otherwise = i'' nm = mkHaskellTyConName (idName i''') startOffset | nm == "IUnknown" = Just 0 | otherwise = Just (sum (map snd inh)) rnDecl d | isMethod d = do d' <- renameDecl d incMethOffset return d' | otherwise = renameDecl d deps = map remove $ filterAttributes (idAttributes i) ["depender"] where remove (Attribute _ [ParamLit (LitLit s)]) = mkHaskellTyConName (snd (splitLast "." s)) remove _ = "" ds' <- setMethOffset startOffset $ setIfaceName nm ( if optOneModulePerInterface then withDependers deps (setModuleName nm (withNewVarIdEnv (mapM rnDecl ds))) else mapM rnDecl ds) sane_inh <- if optOneModulePerInterface then normaliseInh nm deps inh else getModuleName $ \ mod_nm -> do normaliseInh mod_nm [] inh i_final <- if optOneModulePerInterface then return (i'''{idModule=Nothing}) else normaliseModName i''' let d = Interface i_final is_ref sane_inh ds' when (not is_ref) (addIface (idName i_final) d) return d renameDecl (Module i ms) = do i' <- renameModId (normaliseIdName i) ms' <- setModuleName (idName i') (inNewModule (mapM renameDecl ms)) return (Module i' ms') renameDecl (Library i ls) = do i' <- renameModId (normaliseIdName i) ls' <- setModuleName (idName i') (inNewModule (mapM renameDecl ls)) return (Library i' ls') renameDecl (DispInterface i ii ps ms) = do i' <- renameTypeId (normaliseIdName i) >>= \ x -> renameConId x >>= normaliseModName is_source <- isSourceIface (idName i) let i'' | is_source = i'{idAttributes=sourceAttribute:idAttributes i'} | otherwise = i' nm = mkHaskellTyConName (idName i'') is_wrapper = isJust ii && not optUseStdDispatch reDecl | is_wrapper = relabelDecl | otherwise = renameDecl (ps',ms') <- setIfaceName nm ( withNew nm ( do ps' <- mapM reDecl ps ms' <- mapM reDecl ms return (ps', ms'))) ii' <- case ii of Nothing -> return Nothing Just d -> do d' <- relabelDecl d return (Just d') let d = DispInterface i'' ii' ps' ms' addIface (idName i'') d return d where withNew nm | optOneModulePerInterface = (setModuleName nm).withNewVarIdEnv | otherwise = id renameDecl (CoClass i ls) = do i' <- if optOneModulePerInterface then renameConId (normaliseIdName i) >>= renameClassId else renameClassId (normaliseIdName i) ls' <- mapM renameCoCDecl ls case ls' of [x] -> do when optOneModulePerInterface (addNukeIface (idName (coClassId x)) i') return (CoClass i' ls') _ -> return (CoClass i' ls') renameDecl (Method i cc res ps offs) = getIfaceName $ \ if_name -> do let -- We pin on the prefixes of propgetters and putters -- here, and rename that. attrs = idAttributes i i' = normaliseIdName i real_i | attrs `hasAttributeWithName` "propget" = i'{idName=if_mangle ("get"++mkHaskellTyConName (idName i))} | attrs `hasAttributeWithNames` ["propput", "propputref"] = i'{idName=if_mangle ("set"++mkHaskellTyConName (idName i))} | optPrefixIfaceName = i'{idName=if_mangle (idName i)} | otherwise = i' h_if_name = mkIfaceTypeName if_name if_mangle | optPrefixIfaceName = \ x -> h_if_name ++ "_" ++ x | optAppendIfaceName = \ x -> x ++ shorten_if h_if_name | otherwise = id mangled_i | optAppendIfaceName && not optOneModulePerInterface = real_i{idName=if_mangle (idName i')} | otherwise = real_i -- IFooBar => FB -- FooBar => FB -- IntFoo => IF shorten_if ls = case ls of 'I':x:xs | isUpper x -> shorten (x:xs) xs -> shorten xs shorten [] = [] shorten (x:xs) = toUpper x : filter (isUpper) xs the_i <- renameVarId2 mangled_i real_i -- fish out the attributes from the result type, so -- that all of them are attached to the method Id. -- (this is done chiefly to cope with the [ignore] -- attribute, which causes type names to be shorted -- during type renaming and relabelling.) -- -- see relabelDecl.Method comment as to why [ignore]s -- are filtered out here. let ty_attrs = filterOutAttributes (getTypeAttributes (resultOrigType res)) ["ignore"] res' <- renameResult res ps' <- withNewVarIdEnv $ do ps' <- mapM renameParam ps mapM renameParamAttr ps' off <- getMethOffset when optCoalesceIsomorphicMethods (checkIsomorphicMeth real_i off res' ps') return (Method the_i{idAttributes=idAttributes the_i ++ ty_attrs} cc res' ps' offs) renameDecl (Property i ty mb_off set_i get_i) = do set_i' <- renameId (normaliseIdName set_i) get_i' <- renameId (normaliseIdName get_i) ty' <- renameType ty return (Property i ty' mb_off set_i' get_i') renameDecl d@(HsLiteral _) = return d renameDecl d@(CInclude _) = return d renameDecl d@(CLiteral _) = return d \end{code} \begin{code} renameCoCDecl :: CoClassDecl -> RnM CoClassDecl renameCoCDecl d = do i' <- relabelTyConId i >>= normaliseModName mb_d <- lookupIface (idName i') return (d{coClassId=i',coClassDecl=mb_d `mplus` coClassDecl d}) where i = normaliseIdName (coClassId d) \end{code} \begin{code} relabelDecl :: Decl -> RnM Decl relabelDecl (Interface i is_ref inh ds) = do i' <- relabelTyConId (normaliseIdName i) ds' <- mapM relabelDecl ds i'' <- normaliseModName i' getModuleName $ \ mod_nm -> do inh' <- normaliseInh mod_nm [] inh return (Interface i'' is_ref inh' ds') relabelDecl (DispInterface i ii ps ms) = do i' <- relabelTyConId i i'' <- normaliseModName i' ms' <- mapM relabelDecl ms return (DispInterface i'' ii ps ms') relabelDecl (Method i cc res ps offs) = do i' <- relabelVarId i ps' <- mapM relabelParam ps -- [ignore] attributes attached to the result type are *not* -- propagated to the method Id. let ty_attrs = filterOutAttributes (getTypeAttributes (resultOrigType res)) ["ignore"] res' <- relabelResult res return (Method i'{idAttributes=idAttributes i' ++ ty_attrs} cc res' ps' offs) relabelDecl (Property i ty mb_off set_i get_i) = do set_i' <- relabelVarId (normaliseIdName set_i) get_i' <- relabelVarId (normaliseIdName get_i) ty' <- relabelType False ty return (Property i ty' mb_off set_i' get_i') relabelDecl d = return d \end{code} \begin{code} renameVarId :: Id -> RnM Id renameVarId i = lookupVarIdAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) renameModId :: Id -> RnM Id renameModId i = lookupModIdAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) normaliseModName :: Id -> RnM Id normaliseModName i = getModuleName $ \ mod_nm -> case (idModule i) of Just x | x == mod_nm -> return (i{idModule=Nothing}) | otherwise -> return (i{idModule=Just (mkHaskellTyConName (dropSuffix x))}) _ -> return (i{idModule=Nothing}) normaliseIdName :: Id -> Id normaliseIdName i = case findAttribute "hs_name" (idAttributes i) of Just (Attribute _ [ParamLit (StringLit s)]) -> i{idName=s} _ -> adjustHsNameId i renameId :: Id -> RnM Id renameId i = lookupVarIdAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) renameVarId2 :: Id -> Id -> RnM Id renameVarId2 i2 i = do flg <- varIdInScope (idName i) -- if it's already there, try using i2 instead. if flg then renameVarId i2 else renameVarId i renameConId :: Id -> RnM Id renameConId i = lookupTyConAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) renameClassId :: Id -> RnM Id renameClassId i = lookupClassIdAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) renameTyConId :: Id -> RnM Id renameTyConId i = lookupTyConAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) renameTypeId :: Id -> RnM Id renameTypeId i = lookupTypeIdAndAddEnv (idName i) $ \ nm -> return (i{idName=nm}) \end{code} Check to see if a method's result and parameters are isomorphic (upto parameter names) of any others: \begin{code} checkIsomorphicMeth :: Id -> Maybe Int -> Result -> [Param] -> RnM () checkIsomorphicMeth i mem_off res params = do r <- lookupMethod (idOrigName i) -- use original names here. case r of Nothing -> -- none yet, add an entry for the method and return. addMethod (idOrigName i) (mem_off,res,params) Just alts | any checkOne alts -> -- name & params matched, store it. addIsoMethod (idOrigName i) (res, params) | otherwise -> addMethod (idOrigName i) (mem_off, res,params) where checkOne (off,r,ps) = off == mem_off && resultType r == resultType res && all (\ (p1,p2) -> paramMode p1 == paramMode p2 && paramType p1 == paramType p2) -- ToDo: check attributes too. (zip ps params) \end{code} \begin{code} renameType :: Type -> RnM Type renameType ty = case ty of Struct i [] mbsz -> do r <- lookupTag (idName i) case r of Just (mod,nm) -> do mb_r <- lookupTypeId nm let r' = fmap (snd) mb_r return (Name nm nm mod Nothing r' Nothing) Nothing -> do --i' <- renameTagId i return (Struct i [] mbsz) Struct i fields mbsz -> do i' <- renameTyConId i {- Need to rename all the fields ids first, since field types may have attributes that refer to another field (and these might be forward refs). Sigh. -} fields' <- mapM renameFieldId fields fields'' <- mapM renameField fields' fields''' <- mapM relabelFieldAttr fields'' return (Struct i' fields''' mbsz) Enum i flg vals -> do i_r <- renameTyConId i i' <- normaliseModName i_r i'' <- {- Make sure we've got the right module. -} case idModule i' of Nothing -> do r <- lookupTag (idName i) case r of Just (Just mod, _) -> setModuleName mod (normaliseModName i') -- drop the module qualifier if it's the same as the name of the -- containing module [this prunage is only done in the one-mod-per-iface -- setting at the moment.] _ -> return i' Just _ -> return i' vals' <- mapM renameEnumTag vals return (Enum i'' flg vals') Union i t struct_tg un_tg switches -> do i' <- renameTyConId i struct_tg' <- renameTyConId struct_tg un_tg' <- renameTyConId un_tg switches' <- mapM renameSwitch switches return (Union i' t struct_tg' un_tg' switches') UnionNon i switches -> do i' <- renameTyConId i switches' <- mapM renameSwitch switches return (UnionNon i' switches') CUnion i fields mbsz -> do i' <- renameTyConId i fields' <- mapM renameFieldId fields fields'' <- mapM renameField fields' return (CUnion i' fields'' mbsz) FunTy cc res ps -> do res' <- renameResult res ps' <- mapM renameParam ps return (FunTy cc res' ps') Pointer _ _ x@(Char _) | optCharPtrIsString -> return (String x False Nothing) Pointer pt isExp t -> do t' <- renameType t return (Pointer pt isExp t') Array t es -> do t' <- renameType t return (Array t' es) SafeArray t -> do t' <- renameType t return (SafeArray t') Sequence t mb_sz mb_term -> do t' <- renameType t return (Sequence t' mb_sz mb_term) {- We adjust the module part of a name (if any) from the name of the IDL source file to the Haskell module that contains it. -} Name nm orig_nm mod mb_attrs mb_ty mb_ti -> getModuleName $ \ mod_nm -> getDependers $ \ deps -> lookupTypeIdEnv (adjustHsName (fromMaybe [] mb_attrs) nm) $ \ nm' -> do mb_attrs' <- mapMbM renameAttrs mb_attrs ren_ty <- case mb_ty of Nothing -> do r <- lookupTypeId (adjustHsName (fromMaybe [] mb_attrs) nm) case r of Nothing -> return (Name nm' orig_nm mod mb_attrs' (fmap snd r) mb_ti) -- avoid 'obvious' loops. Just (_, t) -> do t' <- relabelType True t return (Name nm' orig_nm mod mb_attrs' (Just t') mb_ti) Just ty1 -> do ty' <- relabelType True ty1 -- optionally shortening out imported synonyms -- can sometimes reduce external dependencies. if (optInlineTypes && isJust mod && nm /= "HRESULT") || ((getTypeAttributes ty1 ++ fromMaybe [] mb_attrs) `hasAttributeWithName` "ignore") then return ty' else return (Name nm' orig_nm mod mb_attrs' (Just ty') mb_ti) normaliseTy mod_nm deps ren_ty Iface{} -> getModuleName $ \ if_name -> getDependers $ \ deps -> do normaliseTy if_name deps ty _ -> return ty -- drop the module qualifier if it's the same as the name of the -- containing module. normaliseTy :: String -> [String] -> Type -> RnM Type normaliseTy mod_nm ls t = case t of Iface nm (Just mod) onm attrs is_idis inh | mkHaskellTyConName mod == mod_nm -> do inh1 <- getBestInheritInfo nm inh inh' <- normaliseInh mod_nm ls inh1 return (Iface (mkHaskellTyConName nm) Nothing onm attrs is_idis inh') Iface nm mod onm attrs is_idis inh -> do inh1 <- getBestInheritInfo nm inh inh' <- normaliseInh mod_nm ls inh1 return (Iface (mkHaskellTyConName nm) mod' onm attrs is_idis inh') where mod' = case mod of Nothing -> mod Just x -> let h_mod = mkHaskellTyConName x in if (optOneModulePerInterface && h_mod `elem` ls) then Just (h_mod ++ "Ty") else Just h_mod Name nm orig_nm mb_mod mb_attrs mb_ty mb_ti -> do mb_ty' <- mapMbM (normaliseTy mod_nm ls) mb_ty let mb_mod' = case mb_mod of Just x | mkHaskellTyConName x == mod_nm -> Nothing | otherwise -> Just (mkHaskellTyConName (dropSuffix x)) _ -> Nothing return (Name (mkHaskellTyConName nm) orig_nm mb_mod' mb_attrs mb_ty' mb_ti) Pointer x isExp ty -> do ty' <- normaliseTy mod_nm ls ty return (Pointer x isExp ty') SafeArray ty -> do ty' <- normaliseTy mod_nm ls ty return (SafeArray ty') Sequence ty mb_sz mb_term -> do ty' <- normaliseTy mod_nm ls ty return (Sequence ty' mb_sz mb_term) Array ty e -> do ty' <- normaliseTy mod_nm ls ty return (Array ty e) _ -> return t normaliseInh :: String -> [String] -> InterfaceInherit -> RnM InterfaceInherit normaliseInh mod_nm ls inh = do inh' <- updateMethodCount inh mapM tweakMod inh' where tweakMod (q,n) = do m <- adjustName optOneModulePerInterface q (qModule q) mbNm <- adjustName False q (Just (qName q)) let nm = fromMaybe (qName q) mbNm case m of Just x | x == mod_nm -> return (q{qModule=Nothing,qName=nm}, n) _ -> return (q{qModule=m,qName=nm}, n) adjustName isModule q nm = case nm of Nothing | isModule && (qName q) `elem` ls -> return (Just ((qName q) ++ "Ty")) | otherwise -> return nm Just h_mod -> lookupTyConEnv h_mod $ \ _ -> -- 11/00: -- suspicious lack of use of the result, but i'm leaving it -- as is, for fear of perturbing anything right now. if (isModule && h_mod `elem` ls) then return (Just (h_mod ++ "Ty")) else return (Just (mkHaskellTyConName h_mod)) {- In the following setting: interface IB; interface IA : IB { ... }; interface IB { ... }; we need to know how many methods there are in IB when generating the stubs for the IA methods. 'updateMethodCount' updates this info for IA's inherited interfaces, using the type environment that was gathered during desugaring. [ -fsort-defns will in most cases sort this one out for us, but this fwd. ref. situation may still occur in a strongly connected group of ifaces. ] -} updateMethodCount :: InterfaceInherit -> RnM InterfaceInherit updateMethodCount is = mapM updateMethod is where updateMethod (i,n) | n /= 0 = return (i,n) -- non-zero method count means -- that it is up-to-date. | otherwise = do res <- lookupIface (qName i) case res of Just DispInterface{} -> return (i, 7) Just iface@Interface{declInherit=inhs,declDecls=ds} -> do -- make sure the parent info is up-to-date. is' <- updateMethodCount inhs let inh_meths = sum (map snd is') no_meths = length (filter isMethod ds) -- update info in env for the benefit of others. addIface (qName i) (iface{declInherit=is'}) -- ToDo: attribute Interface decls with vtbl sizes. return (i, no_meths + inh_meths) _ -> return (i,n) {- In case we were processing something like: interface A; interface B { ... f(...A* x...); } interface A : X { ... }; The inheritance info 'X' for A isn't known when processing interface B. Rectify that here. -} getBestInheritInfo :: Name -> InterfaceInherit -> RnM InterfaceInherit getBestInheritInfo nm inh = do res <- lookupTypeId nm case res of Just (_, Iface _ _ _ _ _ inh2) | not (null inh2) -> return inh2 _ -> return inh \end{code} \begin{code} relabelType :: Bool -> Type -> RnM Type relabelType derefTy ty = case ty of Struct i [] mbsz -> do r <- lookupTag (idName i) case r of Just (mod,nm) -> do r1 <- lookupTypeId nm case r1 of Just (_,t) -> return (Name nm nm mod Nothing (Just t) Nothing) Nothing -> do return (Name nm nm mod Nothing Nothing Nothing) Nothing -> do --i' <- relabelTyConId i return (Struct i [] mbsz) Struct i fields mbsz -> do i' <- relabelTyConId i fields' <- mapM relabelField fields fields'' <- mapM relabelFieldAttr fields' return (Struct i' fields' mbsz) Enum i flg vals -> do i' <- relabelTyConId i >>= normaliseModName vals' <- mapM relabelEnumTag vals return (Enum i' flg vals') Union i t struct_tg un_tg switches -> do i' <- relabelTyConId i struct_tg' <- relabelTyConId struct_tg un_tg' <- relabelTyConId un_tg switches' <- mapM relabelSwitch switches return (Union i' t struct_tg' un_tg' switches') UnionNon i switches -> do i' <- relabelTyConId i switches' <- mapM relabelSwitch switches return (UnionNon i' switches') CUnion i fields mbsz -> do i' <- relabelTyConId i fields' <- mapM relabelField fields return (CUnion i' fields' mbsz) Pointer _ _ x@(Char _) | optCharPtrIsString -> return (String x False Nothing) Pointer pt isExp t -> do t' <- relabelType derefTy t return (Pointer pt isExp t') Array t es -> do t' <- relabelType derefTy t return (Array t' es) SafeArray t -> do t' <- relabelType derefTy t return (SafeArray t') Sequence t mb_sz mb_term -> do t' <- relabelType derefTy t return (Sequence t' mb_sz mb_term) FunTy cc res ps -> do res' <- relabelResult res ps' <- mapM relabelParam ps return (FunTy cc res' ps') {- We adjust the module part of a name (if any) from the name of the IDL source file to the Haskell module that contains it. -} Name nm orig_nm mod mb_attrs mb_ty mb_ti -> getModuleName $ \ mod_nm -> getDependers $ \ deps -> do lookupTypeIdEnv (adjustHsName (fromMaybe [] mb_attrs) nm) $ \ nm' -> do mb_attrs' <- mapMbM renameAttrs mb_attrs ren_ty <- case mb_ty of Nothing -> do r <- lookupTypeId (adjustHsName (fromMaybe [] mb_attrs) nm) case r of -- avoid chains of type names.. -- iff there's no TypeInfo attached to the outermost, since -- it takes precedence later on as it completely describes the ty. Just (_, t) | derefTy -> do t' <- relabelType False t return (Name nm' orig_nm mod mb_attrs' (Just t') mb_ti) Just (_,(Name _ _ _ a o_t mb_ti2)) | isJust mb_ti -> return (Name nm' orig_nm mod a o_t mb_ti2) _ -> return (Name nm' orig_nm mod mb_attrs' (fmap snd r) mb_ti) Just ty1 | optInlineTypes && isJust mod && nm /= "HRESULT" -> return ty1 | (fromMaybe [] mb_attrs ++ getTypeAttributes ty1) `hasAttributeWithName` "ignore" -> return ty1 | otherwise -> do ty' <- if False && derefTy then relabelType False ty1 else return ty1 return (Name nm' orig_nm mod mb_attrs' (Just ty') mb_ti) normaliseTy mod_nm deps ren_ty Iface{} -> getModuleName $ \ if_name -> getDependers $ \ deps -> do normaliseTy if_name deps ty _ -> return ty \end{code} \begin{code} renameParam :: Param -> RnM Param renameParam (Param i m ty orig_ty has_dep) = do i' <- renameVarId i ty' <- renameType ty orig_ty' <- relabelType True orig_ty return (Param i' m ty' orig_ty' has_dep) relabelParam :: Param -> RnM Param relabelParam (Param i m ty orig_ty has_dep) = do i' <- relabelVarId i ty' <- relabelType False ty orig_ty' <- relabelType False orig_ty return (Param i' m ty' orig_ty' has_dep) relabelField :: Field -> RnM Field relabelField (Field i ty orig_ty mb_sz mb_off) = do i' <- relabelVarId i ty' <- relabelType False ty orig_ty' <- relabelType False orig_ty return (Field i' ty' orig_ty' mb_sz mb_off) relabelResult :: Result -> RnM Result relabelResult (Result ty orig_ty) = do ty' <- relabelType False ty orig_ty' <- relabelType False orig_ty return (Result ty' orig_ty') relabelSwitch :: Switch -> RnM Switch relabelSwitch (Switch i labs ty orig_ty) = do i' <- relabelVarId i ty' <- relabelType False ty orig_ty' <- relabelType False orig_ty return (Switch i' labs ty' orig_ty') relabelSwitch s = return s renameFieldId :: Field -> RnM Field renameFieldId f = do i' <- renameVarId (fieldId f) return (f{fieldId=i'}) renameField :: Field -> RnM Field renameField f@Field{fieldType=ty,fieldOrigType=o_ty} = do ty' <- renameType ty o_ty' <- relabelType True o_ty return f{fieldType=ty',fieldOrigType=o_ty'} {- UNUSED renameFieldAttr :: Field -> RnM Field renameFieldAttr f@Field{fieldId=i} = do attrs <- mapM renameAttribute (idAttributes i) return (f{fieldId=i{idAttributes=attrs}}) -} relabelFieldAttr :: Field -> RnM Field relabelFieldAttr f@Field{fieldId=i} = do attrs <- mapM relabelAttribute (idAttributes i) return (f{fieldId=i{idAttributes=attrs}}) renameResult :: Result -> RnM Result renameResult (Result ty orig_ty) = do ty' <- renameType ty orig_ty' <- relabelType True orig_ty return (Result ty' orig_ty') renameParamAttr :: Param -> RnM Param renameParamAttr p = do attrs <- mapM renameAttribute (idAttributes (paramId p)) return (p{paramId=(paramId p){idAttributes=attrs}}) renameAttrs :: [Attribute] -> RnM [Attribute] renameAttrs = mapM renameAttribute renameAttribute :: Attribute -> RnM Attribute renameAttribute at | isConstantAttribute at = return at -- NB: not just an optimisation, -- atParams will fail when given a (moded) constant attributes! | otherwise = do params <- mapM renameAttrParam (atParams at) return (at{atParams=params}) renameAttrParam :: AttributeParam -> RnM AttributeParam renameAttrParam p = case p of ParamVar nm -> lookupVarIdEnv nm $ \ v -> return (ParamVar v) ParamType t -> do t' <- renameType t return (ParamType t') ParamLit _ -> return p ParamVoid -> return p ParamPtr ptr -> do p' <- renameAttrParam ptr return (ParamPtr p') ParamExpr e -> do e' <- renameExpr e return (ParamExpr e') relabelAttribute :: Attribute -> RnM Attribute relabelAttribute at | isConstantAttribute at = return at -- NB: not just an optimisation, -- atParams will fail when given a (moded) constant attributes! | otherwise = do params <- mapM relabelAttrParam (atParams at) return (at{atParams=params}) relabelAttrParam :: AttributeParam -> RnM AttributeParam relabelAttrParam p = case p of ParamVar nm -> lookupVarIdEnv nm $ \ v -> return (ParamVar v) ParamType t -> do t' <- relabelType True t return (ParamType t') ParamLit _ -> return p ParamVoid -> return p ParamPtr ptr -> do p' <- relabelAttrParam ptr return (ParamPtr p') ParamExpr e -> do e' <- renameExpr e return (ParamExpr e') renameSwitch :: Switch -> RnM Switch renameSwitch (Switch i labs ty orig_ty) = do i' <- renameVarId i ty' <- renameType ty orig_ty' <- relabelType True orig_ty return (Switch i' labs ty' orig_ty') renameSwitch s = return s renameEnumTag :: EnumValue -> RnM EnumValue renameEnumTag (EnumValue nm (Left v)) = do nm' <- renameTyConId (adjustHsNameId nm) return (EnumValue nm' (Left v)) renameEnumTag (EnumValue nm (Right e)) = do nm' <- renameTyConId (adjustHsNameId nm) e' <- renameExpr e return (EnumValue nm' (Right e')) relabelEnumTag :: EnumValue -> RnM EnumValue relabelEnumTag ev = let i = enumName ev in lookupTyConEnv (idName i) $ \ nm -> return (ev{enumName=i{idName=nm}}) relabelVarId :: Id -> RnM Id relabelVarId i = lookupVarIdEnv (idName i) $ \ v -> return (i{idName=v}) relabelTyConId :: Id -> RnM Id relabelTyConId i = lookupTyConEnv (idName i) $ \ v -> return (i{idName=v}) \end{code} \begin{code} renameExpr :: Expr -> RnM Expr renameExpr e = case e of Binary bop e1 e2 -> do e1' <- renameExpr e1 e2' <- renameExpr e2 return (Binary bop e1' e2') Cond e1 e2 e3 -> do e1' <- renameExpr e1 e2' <- renameExpr e2 e3' <- renameExpr e3 return (Cond e1' e2' e3') Unary op e1 -> do e1' <- renameExpr e1 return (Unary op e1') Var nm -> lookupVarIdEnv nm $ \ v -> return (Var v) Lit _ -> return e Cast t e1 -> do e' <- renameExpr e1 return (Cast t e') Sizeof t -> do t' <- relabelType True t return (Sizeof t') \end{code} \begin{code} adjustHsNameId :: Id -> Id adjustHsNameId i = i{idName=adjustHsName (idAttributes i) (idName i)} adjustHsName :: [Attribute] -> Name -> Name adjustHsName attr nm = rmPrefix prefixes where prefixes = findStringAttributes "hs_prefix" attr rmPrefix [] = nm rmPrefix (x:xs) | x `isPrefixOf` nm = drop (length x) nm | otherwise = rmPrefix xs \end{code}