import CStrings ( identToC )
import Constants ( mIN_MP_INT_SIZE, mP_STRUCT_SIZE )
import HeapOffs ( addOff, intOff, totHdrSize, HeapOffset )
-import PprStyle ( codeStyle, ifaceStyle )
+import PprStyle --( codeStyle, ifaceStyle )
import PprType ( pprParendGenType, GenTyVar{-instance Outputable-} )
import Pretty
import SMRep ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
import TyCon ( TyCon{-instances-} )
-import Type ( getAppDataTyConExpandingDicts, maybeAppDataTyConExpandingDicts,
+import Type {- ( getAppDataTyConExpandingDicts, maybeAppDataTyConExpandingDicts,
mkForAllTys, mkFunTy, mkFunTys, applyTyCon, typePrimRep
- )
-import TyVar ( alphaTyVar, betaTyVar, gammaTyVar, GenTyVar{-instance Eq-} )
+ ) -}
+import TyVar --( alphaTyVar, betaTyVar, gammaTyVar, GenTyVar{-instance Eq-} )
import Unique ( Unique{-instance Eq-} )
import Util ( panic#, assoc, panic{-ToDo:rm-} )
+#if __GLASGOW_HASKELL__ >= 202
+import Outputable
+#endif
\end{code}
%************************************************************************
| TakeMVarOp | PutMVarOp
| ReadIVarOp | WriteIVarOp
- | MakeForeignObjOp -- foreign objects (malloc pointers or any old URL)
+ | MakeForeignObjOp -- foreign objects (malloc pointers or any old URL)
+ | WriteForeignObjOp -- modifying foreign objects [obscuro factor: 200]
| MakeStablePtrOp | DeRefStablePtrOp
\end{code}
tagOf_PrimOp ReadIVarOp = ILIT(153)
tagOf_PrimOp WriteIVarOp = ILIT(154)
tagOf_PrimOp MakeForeignObjOp = ILIT(155)
-tagOf_PrimOp MakeStablePtrOp = ILIT(156)
-tagOf_PrimOp DeRefStablePtrOp = ILIT(157)
-tagOf_PrimOp (CCallOp _ _ _ _ _) = ILIT(158)
-tagOf_PrimOp ErrorIOPrimOp = ILIT(159)
-tagOf_PrimOp ReallyUnsafePtrEqualityOp = ILIT(160)
-tagOf_PrimOp SeqOp = ILIT(161)
-tagOf_PrimOp ParOp = ILIT(162)
-tagOf_PrimOp ForkOp = ILIT(163)
-tagOf_PrimOp DelayOp = ILIT(164)
-tagOf_PrimOp WaitReadOp = ILIT(165)
-tagOf_PrimOp WaitWriteOp = ILIT(166)
-
-tagOf_PrimOp ParGlobalOp = ILIT(167)
-tagOf_PrimOp ParLocalOp = ILIT(168)
-tagOf_PrimOp ParAtOp = ILIT(169)
-tagOf_PrimOp ParAtAbsOp = ILIT(170)
-tagOf_PrimOp ParAtRelOp = ILIT(171)
-tagOf_PrimOp ParAtForNowOp = ILIT(172)
-tagOf_PrimOp CopyableOp = ILIT(173)
-tagOf_PrimOp NoFollowOp = ILIT(174)
+tagOf_PrimOp WriteForeignObjOp = ILIT(156)
+tagOf_PrimOp MakeStablePtrOp = ILIT(157)
+tagOf_PrimOp DeRefStablePtrOp = ILIT(158)
+tagOf_PrimOp (CCallOp _ _ _ _ _) = ILIT(159)
+tagOf_PrimOp ErrorIOPrimOp = ILIT(160)
+tagOf_PrimOp ReallyUnsafePtrEqualityOp = ILIT(161)
+tagOf_PrimOp SeqOp = ILIT(162)
+tagOf_PrimOp ParOp = ILIT(163)
+tagOf_PrimOp ForkOp = ILIT(164)
+tagOf_PrimOp DelayOp = ILIT(165)
+tagOf_PrimOp WaitReadOp = ILIT(166)
+tagOf_PrimOp WaitWriteOp = ILIT(167)
+
+tagOf_PrimOp ParGlobalOp = ILIT(168)
+tagOf_PrimOp ParLocalOp = ILIT(169)
+tagOf_PrimOp ParAtOp = ILIT(170)
+tagOf_PrimOp ParAtAbsOp = ILIT(171)
+tagOf_PrimOp ParAtRelOp = ILIT(172)
+tagOf_PrimOp ParAtForNowOp = ILIT(173)
+tagOf_PrimOp CopyableOp = ILIT(174)
+tagOf_PrimOp NoFollowOp = ILIT(175)
tagOf_PrimOp _ = panic# "tagOf_PrimOp: pattern-match"
ReadIVarOp,
WriteIVarOp,
MakeForeignObjOp,
+ WriteForeignObjOp,
MakeStablePtrOp,
DeRefStablePtrOp,
ReallyUnsafePtrEqualityOp,
primOpInfo IntRemOp = Dyadic SLIT("remInt#") intPrimTy
primOpInfo IntNegOp = Monadic SLIT("negateInt#") intPrimTy
+primOpInfo IntAbsOp = Monadic SLIT("absInt#") intPrimTy
\end{code}
%************************************************************************
%************************************************************************
%* *
-\subsubsection[PrimOps-makeForeignObj]{PrimOpInfo for Foreign Objects}
+\subsubsection[PrimOps-ForeignObj]{PrimOpInfo for Foreign Objects}
%* *
%************************************************************************
associated with the object is invoked (currently, each ForeignObj has a
direct reference to its finaliser). -- SOF
-The only function defined over @ForeignObj@s is:
+A @ForeignObj@ is created by the @makeForeignObj#@ primitive:
\begin{pseudocode}
makeForeignObj# :: Addr# -- foreign object
-> StateAndForeignObj# _RealWorld# ForeignObj#
\end{pseudocode}
+
\begin{code}
primOpInfo MakeForeignObjOp
= AlgResult SLIT("makeForeignObj#") []
stateAndForeignObjPrimTyCon [realWorldTy]
\end{code}
+[Experimental--SOF]
+In addition, another @ForeignObj@ primitive is provided for destructively modifying
+the external object wrapped up inside a @ForeignObj@. This primitive is used
+when a mixed programming interface of implicit and explicit de-allocation is used,
+e.g., if @ForeignObj@s are used to implement @Handle@s, then @Handle@s can be
+released either explicitly (through @hClose@) or implicitly (via a finaliser).
+When releasing/closing the @Handle@ explicitly, care must be taken to avoid having
+the finaliser for the embedded @ForeignObj@ attempt the same thing later.
+We deal with this situation, by allowing the programmer to destructively modify
+the data field of the @ForeignObj@ to hold a special value the finaliser recognises,
+and does not attempt to free (e.g., filling the data slot with \tr{NULL}).
+
+\begin{pseudocode}
+writeForeignObj# :: ForeignObj# -- foreign object
+ -> Addr# -- new data value
+ -> StateAndForeignObj# _RealWorld# ForeignObj#
+\end{pseudocode}
+
+\begin{code}
+primOpInfo WriteForeignObjOp
+ = let {
+ s = alphaTy; s_tv = alphaTyVar
+ } in
+ PrimResult SLIT("writeForeignObj#") [s_tv]
+ [foreignObjPrimTy, addrPrimTy, mkStatePrimTy s]
+ statePrimTyCon VoidRep [s]
+\end{code}
+
%************************************************************************
%* *
\subsubsection[PrimOp-stable-pointers]{PrimOpInfo for ``stable pointers''}
(addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
(intOff mIN_MP_INT_SIZE)))
--- ccall may allocate heap if it is explicitly allowed to (_ccall_gc_)
--- or if it returns a ForeignObj.
+{-
+ ccall may allocate heap if it is explicitly allowed to (_ccall_gc_)
+ or if it returns a ForeignObj.
+ Hmm..the allocation for makeForeignObj# is known (and fixed), so
+ why dod we need to be so indeterminate about it? --SOF
+-}
primOpHeapReq (CCallOp _ _ mayGC@True _ _) = VariableHeapRequired
primOpHeapReq (CCallOp _ _ mayGC@False _ _) = NoHeapRequired
primOpHeapReq MakeForeignObjOp = VariableHeapRequired
+primOpHeapReq WriteForeignObjOp = NoHeapRequired
-- this occasionally has to expand the Stable Pointer table
primOpHeapReq MakeStablePtrOp = VariableHeapRequired
fragilePrimOp ParOp = True
fragilePrimOp ForkOp = True
fragilePrimOp SeqOp = True
-fragilePrimOp MakeForeignObjOp = True -- SOF
+fragilePrimOp MakeForeignObjOp = True -- SOF
+fragilePrimOp WriteForeignObjOp = True -- SOF
fragilePrimOp MakeStablePtrOp = True
fragilePrimOp DeRefStablePtrOp = True -- ??? JSM & ADR
primOpNeedsWrapper DoubleDecodeOp = True
primOpNeedsWrapper MakeForeignObjOp = True
+primOpNeedsWrapper WriteForeignObjOp = True
primOpNeedsWrapper MakeStablePtrOp = True
primOpNeedsWrapper DeRefStablePtrOp = True
Output stuff:
\begin{code}
-pprPrimOp :: PprStyle -> PrimOp -> Pretty
+pprPrimOp :: PprStyle -> PrimOp -> Doc
showPrimOp :: PprStyle -> PrimOp -> String
-showPrimOp sty op
- = ppShow 1000{-random-} (pprPrimOp sty op)
+showPrimOp sty op = render (pprPrimOp sty op)
pprPrimOp sty (CCallOp fun is_casm may_gc arg_tys res_ty)
= let
if may_gc then "_ccall_GC_ " else "_ccall_ "
after
- = if is_casm then ppStr "''" else ppNil
+ = if is_casm then text "''" else empty
pp_tys
- = ppCat (map (pprParendGenType sty) (res_ty:arg_tys))
+ = hsep (map (pprParendGenType sty) (res_ty:arg_tys))
in
- ppBesides [ppStr before, ppPStr fun, after, ppSP, ppLbrack, pp_tys, ppRbrack]
+ hcat [text before, ptext fun, after, space, brackets pp_tys]
pprPrimOp sty other_op
| codeStyle sty -- For C just print the primop itself
= identToC str
| ifaceStyle sty -- For interfaces Print it qualified with GHC.
- = ppPStr SLIT("GHC.") `ppBeside` ppPStr str
+ = ptext SLIT("GHC.") <> ptext str
| otherwise -- Unqualified is good enough
- = ppPStr str
+ = ptext str
where
str = primOp_str other_op