28 | Show ClockType where
30 | show Monotonic = "monotonic"
31 | show Duration = "duration"
32 | show Process = "process"
33 | show Thread = "thread"
34 | show GCCPU = "gcCPU"
35 | show GCReal = "gcReal"
40 | data Clock : (type : ClockType) -> Type where
42 | : {type : ClockType}
43 | -> (seconds : Integer)
44 | -> (nanoseconds : Integer)
48 | Eq (Clock type) where
49 | (MkClock seconds1 nanoseconds1) == (MkClock seconds2 nanoseconds2) =
50 | seconds1 == seconds2 && nanoseconds1 == nanoseconds2
53 | Ord (Clock type) where
54 | compare (MkClock seconds1 nanoseconds1) (MkClock seconds2 nanoseconds2) =
55 | case compare seconds1 seconds2 of
58 | EQ => compare nanoseconds1 nanoseconds2
61 | Show (Clock type) where
62 | show (MkClock {type} seconds nanoseconds) =
63 | show type ++ ": " ++ show seconds ++ "s " ++ show nanoseconds ++ "ns"
72 | showTime : (s, ns : Nat) -> (clk : Clock type) -> String
73 | showTime s ns (MkClock seconds nanoseconds) =
74 | let seconds' = show seconds
75 | nanoseconds' = show nanoseconds
76 | in concat [ padLeft s '0' seconds'
77 | , if ns == 0 then "" else "."
78 | , padRight ns '0' $
substr 0 ns $
(padLeft 9 '0' nanoseconds')
84 | seconds : Clock type -> Integer
85 | seconds (MkClock s _) = s
89 | nanoseconds : Clock type -> Integer
90 | nanoseconds (MkClock _ ns) = ns
97 | makeDuration : (s : Integer) -> (ns : Integer) -> Clock Duration
98 | makeDuration = MkClock
101 | data OSClock : Type where [external]
106 | data ClockTypeMandatory
113 | isClockMandatory : ClockType -> ClockTypeMandatory
114 | isClockMandatory GCCPU = Optional
115 | isClockMandatory GCReal = Optional
116 | isClockMandatory _ = Mandatory
118 | %foreign "scheme:blodwen-clock-time-monotonic"
119 | "RefC:clockTimeMonotonic"
120 | "javascript:lambda:()=>performance.now()"
121 | prim__clockTimeMonotonic : PrimIO OSClock
124 | clockTimeMonotonic : IO OSClock
125 | clockTimeMonotonic = fromPrim prim__clockTimeMonotonic
127 | %foreign "scheme:blodwen-clock-time-utc"
128 | "RefC:clockTimeUtc"
129 | "javascript:lambda:()=>Date.now()"
130 | prim__clockTimeUtc : PrimIO OSClock
133 | clockTimeUtc : IO OSClock
134 | clockTimeUtc = fromPrim prim__clockTimeUtc
136 | %foreign "scheme:blodwen-clock-time-process"
137 | "RefC:clockTimeProcess"
138 | "javascript:support:clockTimeProcess,support_system_clock"
139 | prim__clockTimeProcess : PrimIO OSClock
142 | clockTimeProcess : IO OSClock
143 | clockTimeProcess = fromPrim prim__clockTimeProcess
145 | %foreign "scheme:blodwen-clock-time-thread"
146 | "RefC:clockTimeThread"
147 | "javascript:support:clockTimeThread,support_system_clock"
148 | prim__clockTimeThread : PrimIO OSClock
151 | clockTimeThread : IO OSClock
152 | clockTimeThread = fromPrim prim__clockTimeThread
154 | %foreign "scheme:blodwen-clock-time-gccpu"
155 | "RefC:clockTimeGcCpu"
156 | "javascript:lambda:()=>null"
157 | prim__clockTimeGcCpu : PrimIO OSClock
161 | clockTimeGcCpu : IO OSClock
162 | clockTimeGcCpu = fromPrim prim__clockTimeGcCpu
164 | %foreign "scheme:blodwen-clock-time-gcreal"
165 | "RefC:clockTimeGcReal"
166 | "javascript:lambda:()=>null"
167 | prim__clockTimeGcReal : PrimIO OSClock
171 | clockTimeGcReal : IO OSClock
172 | clockTimeGcReal = fromPrim prim__clockTimeGcReal
174 | fetchOSClock : ClockType -> IO OSClock
175 | fetchOSClock UTC = clockTimeUtc
176 | fetchOSClock Monotonic = clockTimeMonotonic
177 | fetchOSClock Process = clockTimeProcess
178 | fetchOSClock Thread = clockTimeThread
179 | fetchOSClock GCCPU = clockTimeGcCpu
180 | fetchOSClock GCReal = clockTimeGcReal
181 | fetchOSClock Duration = clockTimeMonotonic
183 | %foreign "scheme:blodwen-is-time?"
185 | "javascript:lambda:(x)=>x===null?0:1"
186 | prim__osClockValid : OSClock -> PrimIO Int
189 | osClockValid : OSClock -> IO Int
190 | osClockValid clk = fromPrim (prim__osClockValid clk)
192 | %foreign "scheme:blodwen-clock-second"
194 | "javascript:lambda:(x)=>BigInt(Math.floor(x/1000))"
195 | prim__osClockSecond : OSClock -> PrimIO Bits64
198 | osClockSecond : OSClock -> IO Bits64
199 | osClockSecond clk = fromPrim (prim__osClockSecond clk)
201 | %foreign "scheme:blodwen-clock-nanosecond"
202 | "RefC:clockNanosecond"
203 | "javascript:lambda:(x)=>BigInt(Math.floor((x%1000)*1000*1000))"
204 | prim__osClockNanosecond : OSClock -> PrimIO Bits64
207 | osClockNanosecond : OSClock -> IO Bits64
208 | osClockNanosecond clk = fromPrim (prim__osClockNanosecond clk)
211 | fromOSClock : {type : ClockType} -> OSClock -> IO (Clock type)
216 | (cast !(osClockSecond clk))
217 | (cast !(osClockNanosecond clk))
224 | clockTimeReturnType : (typ : ClockType) -> Type
225 | clockTimeReturnType typ with (isClockMandatory typ)
226 | clockTimeReturnType typ | Optional = Maybe (Clock typ)
227 | clockTimeReturnType typ | Mandatory = Clock typ
232 | clockTime : (typ : ClockType) -> IO (clockTimeReturnType typ)
233 | clockTime clockType with (isClockMandatory clockType)
234 | clockTime clockType | Mandatory = fetchOSClock clockType >>= fromOSClock
235 | clockTime clockType | Optional = do
236 | clk <- fetchOSClock clockType
237 | valid <- map (== 1) $
osClockValid clk
239 | then map Just $
fromOSClock clk
244 | toNano : Clock type -> Integer
245 | toNano (MkClock seconds nanoseconds) =
246 | let scale = 1000000000
247 | in scale * seconds + nanoseconds
253 | fromNano : {type : ClockType} -> (n : Integer) -> Clock type
255 | let scale = 1000000000
256 | seconds = n `div` scale
257 | nanoseconds = n `mod` scale
258 | in MkClock seconds nanoseconds
264 | timeDifference : Clock type -> Clock type -> Clock Duration
265 | timeDifference end start = fromNano $
toNano end - toNano start
269 | addDuration : {type : ClockType} -> Clock type -> Clock Duration -> Clock type
270 | addDuration clock duration = fromNano $
toNano clock + toNano duration
274 | subtractDuration : {type : ClockType} -> Clock type -> Clock Duration -> Clock type
275 | subtractDuration clock duration = fromNano $
toNano clock - toNano duration