%
% (c) The Foo Project, University of Glasgow, 1999
%
% @(#) $Docid: Nov. 24th 2003 09:56 Sigbjorn Finne $
% @(#) $Contactid: sof@galois.com $
%
Marshalling procedures/function values
\begin{code}
module MarshallFun ( marshallFun ) where
import BasicTypes
import Attribute
import Literal
import LibUtils
import CgMonad
import qualified AbstractH as Haskell ( HDecl )
import AbsHUtils
import CoreIDL
import CoreUtils
import MarshallType
import MarshallServ ( cgServMethod )
import MarshallMethod ( cgMethod )
import MarshallCore
import Maybe
\end{code}
@marshallFun@ performs two major tasks:
+ generates the marshalling code reqd. to deal
with function values / callbacks.
+ generates the wrapper code needed for exposing
Haskell functions (i.e., non COM) to the outside
world.
As elsewhere, the Haskell code generating code is pig ugly.
\begin{code}
marshallFun :: Maybe Name -> Id -> Type -> CgM Haskell.HDecl
marshallFun mb_mod_nm i (FunTy cc res ps)
| exportFun = do
h <- setInterfaceFlag StdFFI (cgServMethod i real_result ps False False)
return (andDecls [m_decl, e_decl, h])
| otherwise = do
h <- setInterfaceFlag StdFFI (cgServMethod i real_result ps False False)
d <- setInterfaceFlag StdFFI (cgMethod (i{idName=uw_name}) cc real_result ps
Nothing (Just i_name))
let decl_list = imp_decls ++ exp_decls
ds <- mapM exportDecl decl_list
return (andDecls (ds ++ [d,h]))
where
exportFun = isJust mb_mod_nm
imp_decls =
[ (u_name, u_decl)
, (i_name, i_decl)
, (re_name, re_decl)
, (s_name, s_decl)
]
exp_decls =
[ (m_name, m_decl)
, (e_name, e_decl)
, (wr_name, wr_decl)
]
real_result = res{resultType=res_ty, resultOrigType=res_orig_ty}
res_ty = removePtr (resultType res)
res_orig_ty = removePtr (resultOrigType res)
name = mkVarName (idName i)
v_name = mkHaskellVarName (idName i)
m_name
| not exportFun = qName (prefix marshallPrefix name)
| otherwise = qName (appendStr "_proxy" name)
e_name
| not exportFun = qName (prefix "export_" name)
| otherwise = m_name
i_name = qName (prefix "import_" name)
w_name = mkWrapperName (qName name)
wr_name = qName (prefix marshallRefPrefix name)
re_name = qName (prefix unmarshallRefPrefix name)
uw_name = qName (prefix "unwrap_" name)
u_name = qName (prefix unmarshallPrefix name)
isPure = not exportFun && (idAttributes i) `hasAttributeWithName` "pure"
(ty, mb_c) = toHaskellMethodTy isPure False False Nothing ps real_result
base_ty = toHaskellBaseMethodTy True ps real_result
i_base_ty = toHaskellBaseMethodTy False ps real_result
m_decl = m_tysig `andDecl` m_def
m_tysig = genTypeSig m_name mb_c m_type
m_def
| not exportFun = funDef m_name [patVar v_name] m_rhs
| otherwise = funDef m_name [] m_rhs
m_rhs
| not exportFun = funApply (var e_name) [funApply (var w_name) [var v_name]]
| otherwise = funApply (var w_name) [varName f_name]
m_type
| exportFun = ty
| otherwise = funTy ty (io (tyPtr ty))
wr_decl = wr_tysig `andDecl` wr_def
wr_tysig = genTypeSig wr_name mb_c wr_type
wr_type = funTy (tyPtr (tyPtr ty)) $
funTy ty $
io_unit
wr_def = funDef wr_name [patVar "fptr", patVar v_name] wr_rhs
wr_rhs =
bind (funApply (var m_name) [var v_name]) (var "ptr") $
funApp w_ptr [var "fptr", var "ptr"]
e_decl = fexport cc e_loc e_name e_ty
e_prim_ty = funTy base_ty (io (tyPtr ty))
f_name =
case (findAttribute "entry" (idAttributes i)) of
Just (Attribute _ (ParamLit (StringLit x) : _)) -> mkQVarName mb_mod_nm x
_ -> mkQVarName mb_mod_nm (idName i)
(e_loc, e_ty)
| exportFun = (Just (idName i), base_ty)
| otherwise = (Nothing, e_prim_ty)
i_decl = primcst cc i_name (funTy (tyPtr ty) i_base_ty)
has_structs c_ty_args c_res_ty
u_decl = u_tysig `andDecl` u_def
u_tysig = genTypeSig u_name mb_c (funTy (tyPtr ty) (io ty))
u_def = funDef u_name [patVar "fptr"] u_rhs
u_rhs = ret (funApply (var uw_name) [funApply (var i_name) [var "fptr"]])
re_decl = re_tysig `andDecl` re_def
re_tysig = genTypeSig re_name mb_c (funTy (tyPtr ty) (io ty))
re_def = funDef re_name [] re_rhs
re_rhs = var u_name
s_name = qName (prefix sizeofPrefix name)
s_decl = s_tysig `andDecl` s_def
s_tysig = typeSig s_name tyWord32
s_def = funDef s_name [] s_rhs
s_rhs = szType addrTy
has_structs = any (fst) ls
ls@(c_res_ty:c_ty_args) = map (isStruct.toCType) (res_ty:p_tys)
where
isStruct (Left x) = (False, x)
isStruct (Right x) = (True, x)
p_tys = map paramType ps
w_ptr = prefix marshallRefPrefix (mkQVarName hdirectLib ptrName)
marshallFun _ _ _ = error "marshallFun"
\end{code}