[project @ 1997-08-25 22:25:50 by sof]
[ghc-hetmet.git] / ghc / compiler / utils / SST.lhs
1 \section{SST: the strict state transformer monad}
2 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4 \begin{code}
5 #include "HsVersions.h"
6
7 module SST(
8         SYN_IE(SST), SST_R, SYN_IE(FSST), FSST_R,
9
10         runSST, sstToST, stToSST,
11         thenSST, thenSST_, returnSST, fixSST,
12         thenFSST, thenFSST_, returnFSST, failFSST,
13         recoverFSST, recoverSST, fixFSST,
14         unsafeInterleaveSST, 
15
16         newMutVarSST, readMutVarSST, writeMutVarSST
17 #if __GLASGOW_HASKELL__ >= 200
18         , MutableVar
19 #else
20         , MutableVar(..), _MutableArray
21 #endif
22   ) where
23
24 #if __GLASGOW_HASKELL__ == 201
25 import GHCbase
26 #elif __GLASGOW_HASKELL__ >= 202
27 import GlaExts
28 import STBase
29 import ArrBase
30 import ST
31 #else
32 import PreludeGlaST ( MutableVar(..), _MutableArray(..), ST(..) )
33 #endif
34
35 CHK_Ubiq() -- debugging consistency check
36 \end{code}
37
38 \begin{code}
39 data SST_R s r = SST_R r (State# s)
40 type SST s r = State# s -> SST_R s r
41
42 \end{code}
43
44 \begin{code}
45 -- converting to/from ST
46
47 sstToST :: SST s r -> ST s r
48 stToSST :: ST s r -> SST s r
49
50 #if __GLASGOW_HASKELL__ >= 200
51
52 sstToST sst = ST $ \ (S# s) ->
53    case sst s of SST_R r s' -> (r, S# s')
54
55 stToSST (ST st) = \ s ->
56    case st (S# s) of (r, S# s') -> SST_R r s'
57
58 #else
59 sstToST sst (S# s)
60   = case sst s of SST_R r s' -> (r, S# s')
61 stToSST st s
62   = case st (S# s) of (r, S# s') -> SST_R r s'
63 #endif
64
65 -- Type of runSST should be builtin ...
66 -- runSST :: forall r. (forall s. SST s r) -> r
67
68 #if __GLASGOW_HASKELL__ >= 200
69 # define REAL_WORLD RealWorld
70 # define MUT_ARRAY  MutableArray
71 #else
72 # define REAL_WORLD _RealWorld
73 # define MUT_ARRAY  _MutableArray
74 #endif
75
76 runSST :: SST REAL_WORLD r  -> r
77 runSST m = case m realWorld# of SST_R r s -> r
78
79 unsafeInterleaveSST :: SST s r -> SST s r
80 unsafeInterleaveSST m s = SST_R r s             -- Duplicates the state!
81                         where
82                           SST_R r _ = m s
83
84 returnSST :: r -> SST s r
85 thenSST   :: SST s r -> (r -> State# s -> b) -> State# s -> b
86 thenSST_  :: SST s r -> (State# s -> b) -> State# s -> b
87 fixSST    :: (r -> SST s r) -> SST s r
88 {-# INLINE returnSST #-}
89 {-# INLINE thenSST #-}
90 {-# INLINE thenSST_ #-}
91
92 -- Hence:
93 --      thenSST :: SST s r -> (r -> SST  s r')     -> SST  s r'
94 -- and  thenSST :: SST s r -> (r -> FSST s r' err) -> FSST s r' err
95
96 -- Hence:
97 --      thenSST_ :: SST s r -> SST  s r'     -> SST  s r'
98 -- and  thenSST_ :: SST s r -> FSST s r' err -> FSST s r' err
99
100 thenSST  m k s = case m s of { SST_R r s' -> k r s' }
101
102 thenSST_ m k s = case m s of { SST_R r s' -> k s' }
103
104 returnSST r s = SST_R r s
105
106 fixSST m s = result
107            where
108              result       = m loop s
109              SST_R loop _ = result
110 \end{code}
111
112
113 \section{FSST: the failable strict state transformer monad}
114 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115
116 \begin{code}
117 data FSST_R s r err
118   = FSST_R_OK   r   (State# s)
119   | FSST_R_Fail err (State# s)
120
121 type FSST s r err = State# s -> FSST_R s r err
122 \end{code}
123
124 \begin{code}
125 failFSST    :: err -> FSST s r err
126 fixFSST     :: (r -> FSST s r err) -> FSST s r err
127 recoverFSST :: (err -> FSST s r err) -> FSST s r err -> FSST s r err
128 recoverSST  :: (err -> SST s r) -> FSST s r err -> SST s r
129 returnFSST  :: r -> FSST s r err
130 thenFSST    :: FSST s r err -> (r -> FSST s r' err) -> FSST s r' err
131 thenFSST_   :: FSST s r err -> FSST s r' err -> FSST s r' err
132 {-# INLINE failFSST #-}
133 {-# INLINE returnFSST #-}
134 {-# INLINE thenFSST #-}
135 {-# INLINE thenFSST_ #-}
136
137 thenFSST m k s = case m s of
138                    FSST_R_OK r s'     -> k r s'
139                    FSST_R_Fail err s' -> FSST_R_Fail err s'
140
141 thenFSST_ m k s = case m s of
142                     FSST_R_OK r s'     -> k s'
143                     FSST_R_Fail err s' -> FSST_R_Fail err s'
144
145 returnFSST r s = FSST_R_OK r s
146
147 failFSST err s = FSST_R_Fail err s
148
149 recoverFSST recovery_fn m s
150   = case m s of 
151         FSST_R_OK r s'     -> FSST_R_OK r s'
152         FSST_R_Fail err s' -> recovery_fn err s'
153
154 recoverSST recovery_fn m s
155   = case m s of 
156         FSST_R_OK r s'     -> SST_R r s'
157         FSST_R_Fail err s' -> recovery_fn err s'
158
159 fixFSST m s = result
160             where
161               result           = m loop s
162               FSST_R_OK loop _ = result
163 \end{code}
164
165 Mutables
166 ~~~~~~~~
167 Here we implement mutable variables.  ToDo: get rid of the array impl.
168
169 \begin{code}
170 newMutVarSST   :: a -> SST s (MutableVar s a)
171 readMutVarSST  :: MutableVar s a -> SST s a
172 writeMutVarSST :: MutableVar s a -> a -> SST s ()
173
174 newMutVarSST init s#
175   = case (newArray# 1# init s#)     of { StateAndMutableArray# s2# arr# ->
176     SST_R (MUT_ARRAY vAR_IXS arr#) s2# }
177   where
178     vAR_IXS = error "Shouldn't access `bounds' of a MutableVar\n"
179
180 readMutVarSST (MUT_ARRAY _ var#) s#
181   = case readArray# var# 0# s#  of { StateAndPtr# s2# r ->
182     SST_R r s2# }
183
184 writeMutVarSST (MUT_ARRAY _ var#) val s#
185   = case writeArray# var# 0# val s# of { s2# ->
186     SST_R () s2# }
187 \end{code}
188