{-# OPTIONS --cubical-compatible --guardedness #-}
module System.Clock where
open import Level using (Level; 0ℓ; Lift; lower)
open import Data.Bool.Base using (if_then_else_)
open import Data.Fin.Base using (Fin; toℕ)
open import Data.Nat.Base as ℕ using (ℕ; zero; suc; _+_; _∸_; _^_; _<ᵇ_)
import Data.Nat.Show as ℕ using (show)
open import Data.Nat.DivMod using (_/_)
import Data.Nat.Properties as ℕₚ
open import Data.String.Base using (String; _++_; padLeft)
open import IO.Base
open import Function.Base using (_$_; _∘′_)
open import Foreign.Haskell using (_,_)
open import Relation.Nullary.Decidable using (False; fromWitnessFalse; toWitnessFalse)
private
variable
a : Level
A : Set a
open import System.Clock.Primitive as Prim
public
using ( Clock
; monotonic
; realTime
; processCPUTime
; threadCPUTime
; monotonicRaw
; bootTime
; monotonicCoarse
; realTimeCoarse
)
record Time : Set where
constructor mkTime
field seconds : ℕ
nanoseconds : ℕ
open Time public
getTime : Clock → IO Time
getTime c = do
(a , b) ← lift (Prim.getTime c)
pure $ mkTime a b
diff : Time → Time → Time
diff (mkTime ss sns) (mkTime es ens) =
if ens <ᵇ sns
then mkTime (es ∸ suc ss) ((1000000000 + ens) ∸ sns)
else mkTime (es ∸ ss) (ens ∸ sns)
record Timed (A : Set a) : Set a where
constructor mkTimed
field value : A
time : Time
time : IO A → IO (Timed A)
time io = do
start ← lift! $ getTime realTime
a ← io
end ← lift! $ getTime realTime
pure $ mkTimed a $ diff (lower start) (lower end)
time′ : IO {0ℓ} A → IO Time
time′ io = Timed.time <$> time io
show : Time →
Fin 10 →
String
show (mkTime s ns) prec = secs ++ "s" ++ padLeft '0' decimals nsecs where
decimals = toℕ prec
secs = ℕ.show s
prf = ℕₚ.m^n≢0 10 (9 ∸ decimals)
nsecs = ℕ.show ((ns / (10 ^ (9 ∸ decimals))) {{prf}})