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