[project @ 1999-02-01 18:06:31 by simonm]
[ghc-hetmet.git] / ghc / compiler / prelude / PrimOp.lhs
index 8dd4415..1e073e4 100644 (file)
@@ -31,10 +31,10 @@ import Demand               ( Demand, wwLazy, wwPrim, wwStrict )
 import Var             ( TyVar )
 import CallConv                ( CallConv, pprCallConv )
 import PprType         ( pprParendType )
-import OccName         ( OccName, pprOccName, varOcc )
-import TyCon           ( TyCon )
-import Type            ( mkForAllTys, mkForAllTy, mkFunTy, mkFunTys, 
-                         mkTyConApp, typePrimRep,
+import OccName         ( OccName, pprOccName, mkSrcVarOcc )
+import TyCon           ( TyCon, tyConArity )
+import Type            ( mkForAllTys, mkForAllTy, mkFunTy, mkFunTys, mkTyVarTys,
+                         mkTyConTy, mkTyConApp, typePrimRep,
                          splitAlgTyConApp, Type, isUnboxedTupleType, 
                          splitAlgTyConApp_maybe
                        )
@@ -172,6 +172,11 @@ data PrimOp
 
     | MkWeakOp
     | DeRefWeakOp
+    | FinaliseWeakOp
+
+    | MakeStableNameOp
+    | EqStableNameOp
+    | StableNameToIntOp
 
     | MakeStablePtrOp
     | DeRefStablePtrOp
@@ -496,32 +501,36 @@ tagOf_PrimOp MakeForeignObjOp                   = ILIT(201)
 tagOf_PrimOp WriteForeignObjOp               = ILIT(202)
 tagOf_PrimOp MkWeakOp                        = ILIT(203)
 tagOf_PrimOp DeRefWeakOp                     = ILIT(204)
-tagOf_PrimOp MakeStablePtrOp                 = ILIT(205)
-tagOf_PrimOp DeRefStablePtrOp                = ILIT(206)
-tagOf_PrimOp EqStablePtrOp                   = ILIT(207)
-tagOf_PrimOp (CCallOp _ _ _ _)               = ILIT(208)
-tagOf_PrimOp ReallyUnsafePtrEqualityOp       = ILIT(209)
-tagOf_PrimOp SeqOp                           = ILIT(210)
-tagOf_PrimOp ParOp                           = ILIT(211)
-tagOf_PrimOp ForkOp                          = ILIT(212)
-tagOf_PrimOp KillThreadOp                    = ILIT(213)
-tagOf_PrimOp DelayOp                         = ILIT(214)
-tagOf_PrimOp WaitReadOp                              = ILIT(215)
-tagOf_PrimOp WaitWriteOp                     = ILIT(216)
-tagOf_PrimOp ParGlobalOp                     = ILIT(217)
-tagOf_PrimOp ParLocalOp                              = ILIT(218)
-tagOf_PrimOp ParAtOp                         = ILIT(219)
-tagOf_PrimOp ParAtAbsOp                              = ILIT(220)
-tagOf_PrimOp ParAtRelOp                              = ILIT(221)
-tagOf_PrimOp ParAtForNowOp                   = ILIT(222)
-tagOf_PrimOp CopyableOp                              = ILIT(223)
-tagOf_PrimOp NoFollowOp                              = ILIT(224)
-tagOf_PrimOp NewMutVarOp                     = ILIT(225)
-tagOf_PrimOp ReadMutVarOp                    = ILIT(226)
-tagOf_PrimOp WriteMutVarOp                   = ILIT(227)
-tagOf_PrimOp SameMutVarOp                    = ILIT(228)
-tagOf_PrimOp CatchOp                         = ILIT(229)
-tagOf_PrimOp RaiseOp                         = ILIT(230)
+tagOf_PrimOp FinaliseWeakOp                  = ILIT(205)
+tagOf_PrimOp MakeStableNameOp                = ILIT(206)
+tagOf_PrimOp EqStableNameOp                  = ILIT(207)
+tagOf_PrimOp StableNameToIntOp               = ILIT(208)
+tagOf_PrimOp MakeStablePtrOp                 = ILIT(209)
+tagOf_PrimOp DeRefStablePtrOp                = ILIT(210)
+tagOf_PrimOp EqStablePtrOp                   = ILIT(211)
+tagOf_PrimOp (CCallOp _ _ _ _)               = ILIT(212)
+tagOf_PrimOp ReallyUnsafePtrEqualityOp       = ILIT(213)
+tagOf_PrimOp SeqOp                           = ILIT(214)
+tagOf_PrimOp ParOp                           = ILIT(215)
+tagOf_PrimOp ForkOp                          = ILIT(216)
+tagOf_PrimOp KillThreadOp                    = ILIT(217)
+tagOf_PrimOp DelayOp                         = ILIT(218)
+tagOf_PrimOp WaitReadOp                              = ILIT(219)
+tagOf_PrimOp WaitWriteOp                     = ILIT(220)
+tagOf_PrimOp ParGlobalOp                     = ILIT(221)
+tagOf_PrimOp ParLocalOp                              = ILIT(222)
+tagOf_PrimOp ParAtOp                         = ILIT(223)
+tagOf_PrimOp ParAtAbsOp                              = ILIT(224)
+tagOf_PrimOp ParAtRelOp                              = ILIT(225)
+tagOf_PrimOp ParAtForNowOp                   = ILIT(226)
+tagOf_PrimOp CopyableOp                              = ILIT(227)
+tagOf_PrimOp NoFollowOp                              = ILIT(228)
+tagOf_PrimOp NewMutVarOp                     = ILIT(229)
+tagOf_PrimOp ReadMutVarOp                    = ILIT(230)
+tagOf_PrimOp WriteMutVarOp                   = ILIT(231)
+tagOf_PrimOp SameMutVarOp                    = ILIT(232)
+tagOf_PrimOp CatchOp                         = ILIT(233)
+tagOf_PrimOp RaiseOp                         = ILIT(234)
 
 tagOf_PrimOp op = pprPanic# "tagOf_PrimOp: pattern-match" (ppr op)
 --panic# "tagOf_PrimOp: pattern-match"
@@ -758,6 +767,10 @@ allThePrimOps
        WriteForeignObjOp,
        MkWeakOp,
        DeRefWeakOp,
+       FinaliseWeakOp,
+       MakeStableNameOp,
+       EqStableNameOp,
+       StableNameToIntOp,
        MakeStablePtrOp,
        DeRefStablePtrOp,
        EqStablePtrOp,
@@ -809,10 +822,10 @@ data PrimOpInfo
                [Type] 
                Type 
 
-mkDyadic str  ty = Dyadic  (varOcc str) ty
-mkMonadic str ty = Monadic (varOcc str) ty
-mkCompare str ty = Compare (varOcc str) ty
-mkGenPrimOp str tvs tys ty = GenPrimOp (varOcc str) tvs tys ty
+mkDyadic str  ty = Dyadic  (mkSrcVarOcc str) ty
+mkMonadic str ty = Monadic (mkSrcVarOcc str) ty
+mkCompare str ty = Compare (mkSrcVarOcc str) ty
+mkGenPrimOp str tvs tys ty = GenPrimOp (mkSrcVarOcc str) tvs tys ty
 \end{code}
 
 Utility bits:
@@ -874,6 +887,7 @@ primOpStrictness CatchOp      = ([wwLazy, wwLazy], False)
 primOpStrictness RaiseOp         = ([wwLazy], True)    -- NB: True => result is bottom
 
 primOpStrictness MkWeakOp        = ([wwLazy, wwLazy, wwLazy, wwPrim], False)
+primOpStrictness MakeStableNameOp = ([wwLazy, wwPrim], False)
 primOpStrictness MakeStablePtrOp  = ([wwLazy, wwPrim], False)
 
        -- The rest all have primitive-typed arguments
@@ -1233,82 +1247,51 @@ primOpInfo (ReadByteArrayOp kind)
        s = alphaTy; s_tv = alphaTyVar
 
        op_str         = _PK_ ("read" ++ primRepString kind ++ "Array#")
-       relevant_type  = assoc "primOpInfo{ReadByteArrayOp}" tbl kind
+       (tvs, prim_ty) = mkPrimTyApp betaTyVars kind
        state          = mkStatePrimTy s
-
-        tvs
-         | kind == StablePtrRep = [s_tv, betaTyVar]
-         | otherwise            = [s_tv]
     in
-    mkGenPrimOp op_str tvs
+    mkGenPrimOp op_str (s_tv:tvs)
        [mkMutableByteArrayPrimTy s, intPrimTy, state]
-       (unboxedPair [state, relevant_type])
-  where
-    tbl = [ (CharRep,   charPrimTy),
-           (IntRep,     intPrimTy),
-           (WordRep,    wordPrimTy),
-           (AddrRep,    addrPrimTy),
-           (FloatRep,   floatPrimTy),
-           (StablePtrRep, mkStablePtrPrimTy betaTy),
-           (DoubleRep,  doublePrimTy) ]
-
-  -- How come there's no Word byte arrays? ADR
+       (unboxedPair [state, prim_ty])
 
 primOpInfo (WriteByteArrayOp kind)
   = let
        s = alphaTy; s_tv = alphaTyVar
        op_str = _PK_ ("write" ++ primRepString kind ++ "Array#")
-       prim_ty = mkTyConApp (primRepTyCon kind) []
-
-        (the_prim_ty, tvs)
-         | kind == StablePtrRep = (mkStablePtrPrimTy betaTy, [s_tv, betaTyVar])
-         | otherwise            = (prim_ty, [s_tv])
-
+       (tvs, prim_ty) = mkPrimTyApp betaTyVars kind
     in
-    mkGenPrimOp op_str tvs
-       [mkMutableByteArrayPrimTy s, intPrimTy, the_prim_ty, mkStatePrimTy s]
+    mkGenPrimOp op_str (s_tv:tvs)
+       [mkMutableByteArrayPrimTy s, intPrimTy, prim_ty, mkStatePrimTy s]
        (mkStatePrimTy s)
 
 primOpInfo (IndexByteArrayOp kind)
   = let
        op_str = _PK_ ("index" ++ primRepString kind ++ "Array#")
-
-        (prim_tycon_args, tvs)
-         | kind == StablePtrRep = ([alphaTy], [alphaTyVar])
-         | otherwise            = ([],[])
+        (tvs, prim_ty) = mkPrimTyApp alphaTyVars kind
     in
-    mkGenPrimOp op_str tvs [byteArrayPrimTy, intPrimTy] 
-       (mkTyConApp (primRepTyCon kind) prim_tycon_args)
+    mkGenPrimOp op_str tvs [byteArrayPrimTy, intPrimTy] prim_ty
 
 primOpInfo (IndexOffForeignObjOp kind)
   = let
        op_str = _PK_ ("index" ++ primRepString kind ++ "OffForeignObj#")
-
-        (prim_tycon_args, tvs)
-         | kind == StablePtrRep = ([alphaTy], [alphaTyVar])
-         | otherwise            = ([], [])
+        (tvs, prim_ty) = mkPrimTyApp alphaTyVars kind
     in
-    mkGenPrimOp op_str tvs [foreignObjPrimTy, intPrimTy] 
-       (mkTyConApp (primRepTyCon kind) prim_tycon_args)
+    mkGenPrimOp op_str tvs [foreignObjPrimTy, intPrimTy] prim_ty
 
 primOpInfo (IndexOffAddrOp kind)
   = let
        op_str = _PK_ ("index" ++ primRepString kind ++ "OffAddr#")
-
-        (prim_tycon_args, tvs)
-         | kind == StablePtrRep = ([alphaTy], [alphaTyVar])
-         | otherwise            = ([], [])
+        (tvs, prim_ty) = mkPrimTyApp alphaTyVars kind
     in
-    mkGenPrimOp op_str tvs [addrPrimTy, intPrimTy] 
-       (mkTyConApp (primRepTyCon kind) prim_tycon_args)
+    mkGenPrimOp op_str tvs [addrPrimTy, intPrimTy] prim_ty
 
 primOpInfo (WriteOffAddrOp kind)
   = let
        s = alphaTy; s_tv = alphaTyVar
        op_str = _PK_ ("write" ++ primRepString kind ++ "OffAddr#")
-       prim_ty = mkTyConApp (primRepTyCon kind) []
+        (tvs, prim_ty) = mkPrimTyApp betaTyVars kind
     in
-    mkGenPrimOp op_str [s_tv]
+    mkGenPrimOp op_str (s_tv:tvs)
        [addrPrimTy, intPrimTy, prim_ty, mkStatePrimTy s]
        (mkStatePrimTy s)
 
@@ -1402,14 +1385,14 @@ catch :: a  -> (b -> a) -> a
 \begin{code}
 primOpInfo CatchOp   
   = let
-       a = alphaTy; a_tv = alphaTyVar;
+       a = alphaTy; a_tv = alphaTyVar
        b = betaTy;  b_tv = betaTyVar;
     in
     mkGenPrimOp SLIT("catch#") [a_tv, b_tv] [a, mkFunTy b a] a
 
 primOpInfo RaiseOp
   = let
-       a = alphaTy; a_tv = alphaTyVar;
+       a = alphaTy; a_tv = alphaTyVar
        b = betaTy;  b_tv = betaTyVar;
     in
     mkGenPrimOp SLIT("raise#") [a_tv, b_tv] [a] b
@@ -1578,41 +1561,76 @@ primOpInfo DeRefWeakOp
        (unboxedTriple [realWorldStatePrimTy, intPrimTy, alphaTy])
 \end{code}
 
+Weak pointers can be finalised early by using the finalise# operation:
+       
+       finalise# :: Weak# v -> State# RealWorld -> State# RealWorld
+
+\begin{code}
+primOpInfo FinaliseWeakOp
+ = mkGenPrimOp SLIT("finaliseWeak#") [alphaTyVar]
+       [mkWeakPrimTy alphaTy, realWorldStatePrimTy]
+       realWorldStatePrimTy
+\end{code}
+
 %************************************************************************
 %*                                                                     *
-\subsubsection[PrimOp-stable-pointers]{PrimOpInfo for ``stable pointers''}
+\subsubsection[PrimOp-stable-pointers]{PrimOpInfo for stable pointers and stable names}
 %*                                                                     *
 %************************************************************************
 
-A {\em stable pointer} is an index into a table of pointers into the
-heap.  Since the garbage collector is told about stable pointers, it
-is safe to pass a stable pointer to external systems such as C
+A {\em stable name/pointer} is an index into a table of stable name
+entries.  Since the garbage collector is told about stable pointers,
+it is safe to pass a stable pointer to external systems such as C
 routines.
 
-Here's what the operations and types are supposed to be (from
-state-interface document).
-
 \begin{verbatim}
-makeStablePtr#  :: a -> State# _RealWorld -> (# State# _RealWorld, a #)
-freeStablePtr#  :: StablePtr# a -> State# _RealWorld -> State# _RealWorld
-deRefStablePtr# :: StablePtr# a -> State# _RealWorld -> (# State# _RealWorld, a #)
+makeStablePtr#  :: a -> State# RealWorld -> (# State# RealWorld, a #)
+freeStablePtr   :: StablePtr# a -> State# RealWorld -> State# RealWorld
+deRefStablePtr# :: StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #)
 eqStablePtr#    :: StablePtr# a -> StablePtr# a -> Int#
 \end{verbatim}
 
-It may seem a bit surprising that @makeStablePtr#@ is a @PrimIO@
+It may seem a bit surprising that @makeStablePtr#@ is a @IO@
 operation since it doesn't (directly) involve IO operations.  The
 reason is that if some optimisation pass decided to duplicate calls to
 @makeStablePtr#@ and we only pass one of the stable pointers over, a
-massive space leak can result.  Putting it into the PrimIO monad
+massive space leak can result.  Putting it into the IO monad
 prevents this.  (Another reason for putting them in a monad is to
-ensure correct sequencing wrt the side-effecting @freeStablePtr#@
+ensure correct sequencing wrt the side-effecting @freeStablePtr@
 operation.)
 
+An important property of stable pointers is that if you call
+makeStablePtr# twice on the same object you get the same stable
+pointer back.
+
 Note that we can implement @freeStablePtr#@ using @_ccall_@ (and,
 besides, it's not likely to be used from Haskell) so it's not a
 primop.
 
-Question: Why @_RealWorld@ - won't any instance of @_ST@ do the job? [ADR]
+Question: Why @RealWorld@ - won't any instance of @_ST@ do the job? [ADR]
+
+Stable Names
+~~~~~~~~~~~~
+
+A stable name is like a stable pointer, but with three important differences:
+
+       (a) You can't deRef one to get back to the original object.
+       (b) You can convert one to an Int.
+       (c) You don't need to 'freeStableName'
+
+The existence of a stable name doesn't guarantee to keep the object it
+points to alive (unlike a stable pointer), hence (a).
+
+Invariants:
+       
+       (a) makeStableName always returns the same value for a given
+           object (same as stable pointers).
+
+       (b) if two stable names are equal, it implies that the objects
+           from which they were created were the same.
+
+       (c) stableNameToInt always returns the same Int for a given
+           stable name.
 
 \begin{code}
 primOpInfo MakeStablePtrOp
@@ -1630,6 +1648,22 @@ primOpInfo EqStablePtrOp
   = mkGenPrimOp SLIT("eqStablePtr#") [alphaTyVar, betaTyVar]
        [mkStablePtrPrimTy alphaTy, mkStablePtrPrimTy betaTy]
        intPrimTy
+
+primOpInfo MakeStableNameOp
+  = mkGenPrimOp SLIT("makeStableName#") [alphaTyVar]
+       [alphaTy, realWorldStatePrimTy]
+       (unboxedPair [realWorldStatePrimTy, 
+                       mkTyConApp stableNamePrimTyCon [alphaTy]])
+
+primOpInfo EqStableNameOp
+  = mkGenPrimOp SLIT("eqStableName#") [alphaTyVar, betaTyVar]
+       [mkStableNamePrimTy alphaTy, mkStableNamePrimTy betaTy]
+       intPrimTy
+
+primOpInfo StableNameToIntOp
+  = mkGenPrimOp SLIT("stableNameToInt#") [alphaTyVar]
+       [mkStableNamePrimTy alphaTy]
+       intPrimTy
 \end{code}
 
 %************************************************************************
@@ -1771,9 +1805,9 @@ primOpOutOfLine op
        FloatDecodeOp           -> True
        DoubleDecodeOp          -> True
        MkWeakOp                -> True
-       DeRefWeakOp             -> True
+       FinaliseWeakOp          -> True
+       MakeStableNameOp        -> True
        MakeForeignObjOp        -> True
-       MakeStablePtrOp         -> True
        NewMutVarOp             -> True
        NewMVarOp               -> True
        ForkOp                  -> True
@@ -1853,7 +1887,9 @@ primOpHasSideEffects MakeForeignObjOp  = True
 primOpHasSideEffects WriteForeignObjOp = True
 primOpHasSideEffects MkWeakOp                 = True
 primOpHasSideEffects DeRefWeakOp       = True
+primOpHasSideEffects FinaliseWeakOp    = True
 primOpHasSideEffects MakeStablePtrOp   = True
+primOpHasSideEffects MakeStableNameOp  = True
 primOpHasSideEffects EqStablePtrOp     = True  -- SOF
 primOpHasSideEffects DeRefStablePtrOp  = True  -- ??? JSM & ADR
 
@@ -1914,7 +1950,7 @@ primOpNeedsWrapper DoubleTanhOp           = True
 primOpNeedsWrapper DoublePowerOp       = True
 primOpNeedsWrapper DoubleEncodeOp      = True
 
-primOpNeedsWrapper MakeStablePtrOp     = True
+primOpNeedsWrapper MakeStableNameOp    = True
 primOpNeedsWrapper DeRefStablePtrOp    = True
 
 primOpNeedsWrapper DelayOp             = True
@@ -2011,6 +2047,15 @@ commutableOp _             = False
 
 Utils:
 \begin{code}
+mkPrimTyApp :: [TyVar] -> PrimRep -> ([TyVar], Type)
+       -- CharRep       -->  ([],  Char#)
+       -- StablePtrRep  -->  ([a], StablePtr# a)
+mkPrimTyApp tvs kind
+  = (forall_tvs, mkTyConApp tycon (mkTyVarTys forall_tvs))
+  where
+    tycon      = primRepTyCon kind
+    forall_tvs = take (tyConArity tycon) tvs
+
 dyadic_fun_ty  ty = mkFunTys [ty, ty] ty
 monadic_fun_ty ty = mkFunTy  ty ty
 compare_fun_ty ty = mkFunTys [ty, ty] boolTy