1
+ {-# LANGUAGE ExplicitNamespaces #-}
1
2
{-# LANGUAGE RankNTypes #-}
2
3
{-# LANGUAGE ScopedTypeVariables #-}
3
4
@@ -19,8 +20,11 @@ module Control.Monad.IOSim (
19
20
setCurrentTime ,
20
21
unshareClock ,
21
22
-- * Simulation trace
22
- Trace (.. ),
23
- TraceEvent (.. ),
23
+ type SimTrace ,
24
+ Trace (Cons , Nil , Trace , SimTrace , TraceMainReturn , TraceMainException , TraceDeadlock ),
25
+ SimResult (.. ),
26
+ SimEvent (.. ),
27
+ SimEventType (.. ),
24
28
ThreadLabel ,
25
29
Labelled (.. ),
26
30
traceEvents ,
@@ -31,6 +35,9 @@ module Control.Monad.IOSim (
31
35
selectTraceEventsDynamic' ,
32
36
selectTraceEventsSay ,
33
37
selectTraceEventsSay' ,
38
+ traceSelectTraceEvents ,
39
+ traceSelectTraceEventsDynamic ,
40
+ traceSelectTraceEventsSay ,
34
41
printTraceEventsSay ,
35
42
-- * Eventlog
36
43
EventlogEvent (.. ),
@@ -39,15 +46,19 @@ module Control.Monad.IOSim (
39
46
execReadTVar ,
40
47
-- * Deprecated interfaces
41
48
SimM ,
42
- SimSTM
49
+ SimSTM ,
50
+ TraceEvent
43
51
) where
44
52
45
53
import Prelude
46
54
47
55
import Data.Dynamic (fromDynamic )
48
56
import Data.List (intercalate )
57
+ import Data.Bifoldable
49
58
import Data.Typeable (Typeable )
50
59
60
+ import Data.List.Trace
61
+
51
62
import Control.Exception (throw )
52
63
53
64
import Control.Monad.ST.Lazy
@@ -59,81 +70,115 @@ import Control.Monad.IOSim.Internal
59
70
60
71
61
72
selectTraceEvents
62
- :: (TraceEvent -> Maybe b )
63
- -> Trace a
73
+ :: (SimEventType -> Maybe b )
74
+ -> SimTrace a
64
75
-> [b ]
65
- selectTraceEvents fn = go
66
- where
67
- go (Trace _ _ _ ev trace) = case fn ev of
68
- Just x -> x : go trace
69
- Nothing -> go trace
70
- go (TraceMainException _ e _) = throw (FailureException e)
71
- go (TraceDeadlock _ threads) = throw (FailureDeadlock threads)
72
- go (TraceMainReturn _ _ _) = []
76
+ selectTraceEvents fn =
77
+ bifoldr ( \ v _
78
+ -> case v of
79
+ MainException _ e _ -> throw (FailureException e)
80
+ Deadlock _ threads -> throw (FailureDeadlock threads)
81
+ MainReturn _ _ _ -> []
82
+ )
83
+ ( \ b acc -> b : acc )
84
+ []
85
+ . traceSelectTraceEvents fn
73
86
74
87
selectTraceEvents'
75
- :: (TraceEvent -> Maybe b )
76
- -> Trace a
88
+ :: (SimEventType -> Maybe b )
89
+ -> SimTrace a
77
90
-> [b ]
78
- selectTraceEvents' fn = go
79
- where
80
- go (Trace _ _ _ ev trace) = case fn ev of
81
- Just x -> x : go trace
82
- Nothing -> go trace
83
- go (TraceMainException _ _ _) = []
84
- go (TraceDeadlock _ _) = []
85
- go (TraceMainReturn _ _ _) = []
91
+ selectTraceEvents' fn =
92
+ bifoldr ( \ _ _ -> [] )
93
+ ( \ b acc -> b : acc )
94
+ []
95
+ . traceSelectTraceEvents fn
86
96
87
97
-- | Select all the traced values matching the expected type. This relies on
88
98
-- the sim's dynamic trace facility.
89
99
--
90
100
-- For convenience, this throws exceptions for abnormal sim termination.
91
101
--
92
- selectTraceEventsDynamic :: forall a b . Typeable b => Trace a -> [b ]
102
+ selectTraceEventsDynamic :: forall a b . Typeable b => SimTrace a -> [b ]
93
103
selectTraceEventsDynamic = selectTraceEvents fn
94
104
where
95
- fn :: TraceEvent -> Maybe b
105
+ fn :: SimEventType -> Maybe b
96
106
fn (EventLog dyn) = fromDynamic dyn
97
107
fn _ = Nothing
98
108
99
109
-- | Like 'selectTraceEventsDynamic' but returns partial trace if an excpetion
100
110
-- is found in it.
101
111
--
102
- selectTraceEventsDynamic' :: forall a b . Typeable b => Trace a -> [b ]
112
+ selectTraceEventsDynamic' :: forall a b . Typeable b => SimTrace a -> [b ]
103
113
selectTraceEventsDynamic' = selectTraceEvents' fn
104
114
where
105
- fn :: TraceEvent -> Maybe b
115
+ fn :: SimEventType -> Maybe b
106
116
fn (EventLog dyn) = fromDynamic dyn
107
117
fn _ = Nothing
108
118
109
119
-- | Get a trace of 'EventSay'.
110
120
--
111
121
-- For convenience, this throws exceptions for abnormal sim termination.
112
122
--
113
- selectTraceEventsSay :: Trace a -> [String ]
123
+ selectTraceEventsSay :: SimTrace a -> [String ]
114
124
selectTraceEventsSay = selectTraceEvents fn
115
125
where
116
- fn :: TraceEvent -> Maybe String
126
+ fn :: SimEventType -> Maybe String
117
127
fn (EventSay s) = Just s
118
128
fn _ = Nothing
119
129
120
130
-- | Like 'selectTraceEventsSay' but return partial trace if an exception is
121
131
-- found in it.
122
132
--
123
- selectTraceEventsSay' :: Trace a -> [String ]
133
+ selectTraceEventsSay' :: SimTrace a -> [String ]
124
134
selectTraceEventsSay' = selectTraceEvents' fn
125
135
where
126
- fn :: TraceEvent -> Maybe String
136
+ fn :: SimEventType -> Maybe String
127
137
fn (EventSay s) = Just s
128
138
fn _ = Nothing
129
139
130
140
-- | Print all 'EventSay' to the console.
131
141
--
132
142
-- For convenience, this throws exceptions for abnormal sim termination.
133
143
--
134
- printTraceEventsSay :: Trace a -> IO ()
144
+ printTraceEventsSay :: SimTrace a -> IO ()
135
145
printTraceEventsSay = mapM_ print . selectTraceEventsSay
136
146
147
+
148
+ -- | The most general select function. It is a _total_ function.
149
+ --
150
+ traceSelectTraceEvents
151
+ :: (SimEventType -> Maybe b )
152
+ -> SimTrace a
153
+ -> Trace (SimResult a ) b
154
+ traceSelectTraceEvents fn = bifoldr ( \ v _acc -> Nil v )
155
+ ( \ eventCtx acc
156
+ -> case fn (seType eventCtx) of
157
+ Nothing -> acc
158
+ Just b -> Cons b acc
159
+ )
160
+ undefined -- it is ignored
161
+
162
+ -- | Select dynamic events. It is a _total_ function.
163
+ --
164
+ traceSelectTraceEventsDynamic :: forall a b . Typeable b
165
+ => SimTrace a -> Trace (SimResult a ) b
166
+ traceSelectTraceEventsDynamic = traceSelectTraceEvents fn
167
+ where
168
+ fn :: SimEventType -> Maybe b
169
+ fn (EventLog dyn) = fromDynamic dyn
170
+ fn _ = Nothing
171
+
172
+
173
+ -- | Select say events. It is a _total_ function.
174
+ --
175
+ traceSelectTraceEventsSay :: forall a . SimTrace a -> Trace (SimResult a ) String
176
+ traceSelectTraceEventsSay = traceSelectTraceEvents fn
177
+ where
178
+ fn :: SimEventType -> Maybe String
179
+ fn (EventSay s) = Just s
180
+ fn _ = Nothing
181
+
137
182
-- | Simulation termination with failure
138
183
--
139
184
data Failure =
@@ -183,24 +228,24 @@ runSimOrThrow mainAction =
183
228
runSimStrictShutdown :: forall a . (forall s . IOSim s a ) -> Either Failure a
184
229
runSimStrictShutdown mainAction = traceResult True (runSimTrace mainAction)
185
230
186
- traceResult :: Bool -> Trace a -> Either Failure a
231
+ traceResult :: Bool -> SimTrace a -> Either Failure a
187
232
traceResult strict = go
188
233
where
189
- go (Trace _ _ _ _ t) = go t
234
+ go (SimTrace _ _ _ _ t) = go t
190
235
go (TraceMainReturn _ _ tids@ (_: _))
191
236
| strict = Left (FailureSloppyShutdown tids)
192
237
go (TraceMainReturn _ x _) = Right x
193
238
go (TraceMainException _ e _) = Left (FailureException e)
194
239
go (TraceDeadlock _ threads) = Left (FailureDeadlock threads)
195
240
196
- traceEvents :: Trace a -> [(Time , ThreadId , Maybe ThreadLabel , TraceEvent )]
197
- traceEvents (Trace time tid tlbl event t) = (time, tid, tlbl, event)
198
- : traceEvents t
199
- traceEvents _ = []
241
+ traceEvents :: SimTrace a -> [(Time , ThreadId , Maybe ThreadLabel , SimEventType )]
242
+ traceEvents (SimTrace time tid tlbl event t) = (time, tid, tlbl, event)
243
+ : traceEvents t
244
+ traceEvents _ = []
200
245
201
246
202
247
203
248
-- | See 'runSimTraceST' below.
204
249
--
205
- runSimTrace :: forall a . (forall s . IOSim s a ) -> Trace a
250
+ runSimTrace :: forall a . (forall s . IOSim s a ) -> SimTrace a
206
251
runSimTrace mainAction = runST (runSimTraceST mainAction)
0 commit comments