silo:std.temporal

Source src/silo:std.temporal

1##! Duration and Instant types — pure-Silo temporal values.
2##!
3##! Covers `IDuration` with constructors, accessors, simple arithmetic,
4##! and `Eq` / `Ord`, plus `Instant` as a record with a pure-Silo
5##! `.duration-since`.
6##!
7##! Unsigned-duration arithmetic, `IDuration + IDuration`, subtraction
8##! combinations, `.mul-f64` / `.div-f64` / `.checked-*` /
9##! `.saturating-*`, `.elapsed`, and a `Display` impl land once the
10##! supporting operator specialisation, `+Panic`, `+Temporal` effect,
11##! and `FmtSpec`-aware `.fmt` arrive.
12
13:use
14  :open core AnyInt Bool Ordering
15  :open traits Add Sub Mul Div Eq Ord
16:end
17
18# si[impl stdlib.duration.type+2]
19:record(pub) IDuration .nanos AnyInt :end
20
21# si[impl stdlib.uduration.type]
22# Runtime value is always non-negative; field typed AnyInt because the checker
23# cannot currently narrow AnyInt ops' outputs to AnyUInt. Re-tighten to AnyUInt
24# after Phase 1b operator specialisation + `TryFrom AnyInt AnyUInt` lands.
25:record(pub) UDuration .nanos AnyInt :end
26
27# si[impl stdlib.instant.type]
28:record(pub) Instant .nanos AnyInt :end
29
30# si[impl stdlib.duration.from-secs]
31# si[impl stdlib.duration.from-millis]
32# si[impl stdlib.duration.from-micros]
33# si[impl stdlib.duration.from-nanos]
34# si[impl stdlib.duration.secs]
35# si[impl stdlib.duration.millis]
36# si[impl stdlib.duration.micros]
37# si[impl stdlib.duration.is-zero]
38# si[impl stdlib.duration.subsec-nanos]
39# si[impl stdlib.duration.subsec-millis]
40# si[impl stdlib.duration.subsec-micros]
41:impl IDuration
42  .secs ( IDuration -> AnyInt )
43    .nanos 1000000000 / ;
44  .millis ( IDuration -> AnyInt )
45    .nanos 1000000 / ;
46  .micros ( IDuration -> AnyInt )
47    .nanos 1000 / ;
48  .is-zero ( IDuration -> Bool )
49    .nanos 0 = ;
50  # Wrap-to-non-negative via `((a mod n) + n) mod n` so negative IDuration
51  # values yield the natural Rust-style subsec component. Spec declares the
52  # result as AnyUInt, but the checker cannot currently prove the wrapped
53  # expression is non-negative, so we widen to AnyInt here; at runtime the
54  # value is always in [0, n).
55  .subsec-nanos ( IDuration -> AnyInt )
56    .nanos 1000000000 mod 1000000000 + 1000000000 mod ;
57  .subsec-micros ( IDuration -> AnyInt )
58    .nanos 1000 / 1000000 mod 1000000 + 1000000 mod ;
59  .subsec-millis ( IDuration -> AnyInt )
60    .nanos 1000000 / 1000 mod 1000 + 1000 mod ;
61:end
62
63# Free fn constructors — the spec writes these as `.from-secs` style,
64# but they're AnyInt → IDuration, not IDuration methods; they take no
65# receiver of IDuration type. Use non-dotted names and let callers write
66# `5 duration-from-secs` until the free-fn dotted-name surface lands.
67:fn(pub) duration-from-secs ( AnyInt -> IDuration )
68  1000000000 * IDuration
69:end
70
71:fn(pub) duration-from-millis ( AnyInt -> IDuration )
72  1000000 * IDuration
73:end
74
75:fn(pub) duration-from-micros ( AnyInt -> IDuration )
76  1000 * IDuration
77:end
78
79:fn(pub) duration-from-nanos ( AnyInt -> IDuration )
80  IDuration
81:end
82
83:fn(pub) uduration-from-secs ( AnyInt -> UDuration )
84  1000000000 * UDuration
85:end
86
87:fn(pub) uduration-from-millis ( AnyInt -> UDuration )
88  1000000 * UDuration
89:end
90
91:fn(pub) uduration-from-micros ( AnyInt -> UDuration )
92  1000 * UDuration
93:end
94
95:fn(pub) uduration-from-nanos ( AnyInt -> UDuration )
96  UDuration
97:end
98
99# si[impl stdlib.duration.subsec-nanos]
100# si[impl stdlib.duration.subsec-millis]
101# si[impl stdlib.duration.subsec-micros]
102:impl UDuration
103  .subsec-nanos ( UDuration -> AnyInt )
104    .nanos 1000000000 mod ;
105  .subsec-micros ( UDuration -> AnyInt )
106    .nanos 1000 / 1000000 mod ;
107  .subsec-millis ( UDuration -> AnyInt )
108    .nanos 1000000 / 1000 mod ;
109:end
110
111# si[impl stdlib.duration.traits+1] — Eq/Ord on IDuration.
112:impl Eq IDuration IDuration
113  .= ( IDuration IDuration -> Bool )
114    pop-> b pop-> a
115    a .nanos b .nanos = ;
116:end
117
118:impl Ord IDuration IDuration
119  .< ( IDuration IDuration -> Bool )
120    pop-> b pop-> a
121    a .nanos b .nanos < ;
122  .> ( IDuration IDuration -> Bool )
123    pop-> b pop-> a
124    a .nanos b .nanos > ;
125:end
126
127# si[impl stdlib.instant.traits] — Eq/Ord on Instant.
128:impl Eq Instant Instant
129  .= ( Instant Instant -> Bool )
130    pop-> b pop-> a
131    a .nanos b .nanos = ;
132:end
133
134:impl Ord Instant Instant
135  .< ( Instant Instant -> Bool )
136    pop-> b pop-> a
137    a .nanos b .nanos < ;
138  .> ( Instant Instant -> Bool )
139    pop-> b pop-> a
140    a .nanos b .nanos > ;
141:end
142
143# si[impl stdlib.instant.duration-since+1]
144:impl Instant
145  .duration-since ( Instant Instant -> IDuration )
146    pop-> earlier pop-> later
147    later .nanos earlier .nanos - IDuration ;
148:end