Files
ww/lib/time/time.ww
Hojun-Cho aadc6618f0 lib: banner purge + WHY-only comment sweep (rule 8)
Every // ---- section banner dies (132 -> 0): names carry the WHAT.
Narration deleted (filename restatements, run-with lines, what-the-
next-line-does); every ref/hare cite, task cite, divergence, ABI/
layout contract, and ownership qualifier kept (borrowed-view lines
restored where the sweep over-cut). Comment-only proven: all 442
walk-workdir .s and 32 import-probe .s byte-identical before/after;
libbyteid 56-roster all-ID.
2026-08-08 21:10:18 +09:00

118 lines
3.9 KiB
Plaintext

// time — clocks, instants, durations. Mirrors Hare's lib/time
// (ref/hare/time/duration.ha, instant.ha, arithm.ha,
// +linux/functions.ha). Calendar / date / strftime / timezone live in
// separate Hare modules
// and graduate when callers / supporting stdlib arrive.
//
// `duration` is a NAMED alias of i64 (lib/math/random precedent
// at lib/math/random/random.ww:8); ww treats NAMED as a newtype,
// so cross-i64 arithmetic inside this module needs explicit casts.
// Hare's structural alias semantics let those casts vanish, but
// our type checker is strict.
package time;
@symbol("rt_syscall") fn syscall2(num: i64, a: i64, b: i64) i64;
@symbol("rt_syscall") fn syscall4(num: i64, a: i64, b: i64, c: i64, d: i64) i64;
def SYS_CLOCK_GETTIME: i64 = 228;
def SYS_CLOCK_NANOSLEEP: i64 = 230;
// ref/hare/time/duration.ha:6. 290y representable range.
export type duration = i64;
// ref/hare/time/duration.ha:9-18. Plan-9 naming (lowercase)
// diverges from Hare's uppercase per project rule 4.
export def nanosecond: duration = 1i64;
export def microsecond: duration = 1000i64;
export def millisecond: duration = 1000000i64;
export def second: duration = 1000000000i64;
// ref/hare/time/instant.ha:9. (sec, nsec) pair — NOT POSIX struct
// timespec (which uses u32 nsec). Layout matches Linux's struct
// timespec on 64-bit (i64+i64) so we can pass &instant directly
// to clock_gettime.
export type instant = struct {
sec: i64,
nsec: i64,
};
// ref/hare/time/+linux/functions.ha:84. First cut exposes only
// realtime and monotonic; Hare's process_cpu / thread_cpu / boot /
// realtime_alarm / boot_alarm / tai graduate when a caller needs
// them (CLAUDE.md rule 9 — Hare-fidelity, no premature surface).
export type clock = enum i32 {
realtime = 0,
monotonic = 1,
};
// ref/hare/time/+linux/functions.ha:138. Hare's now() also aborts
// on impossible errnos. (instant | oserror) is deliberately not
// the return shape — EINVAL / EFAULT are programmer errors (bad
// clock id, bad ptr), and a 1-word-payload sum return walks into
// task #9's cgen-divergence trap.
export fn now(c: clock) instant = {
let i: instant;
let rc = syscall2(SYS_CLOCK_GETTIME, (c as i32): i64, (&i): i64);
if (rc != 0i64) { abort("time.now: clock_gettime failed"); };
return i;
};
// ref/hare/time/+linux/functions.ha:40-58 and
// ref/hare/sys/+linux/syscalls.ha:524-536. WW has no default parameters,
// so the Hare clock argument is explicit. The raw syscall reports -EINTR;
// restarting with the kernel-written remainder keeps the requested delay.
export fn sleep(d: duration, c: clock) void = {
let ns: i64 = d: i64;
let sec: i64 = second: i64;
let req: instant;
req.sec = ns / sec;
req.nsec = ns % sec;
for (true) {
let rem: instant;
let rc: i64 = syscall4(SYS_CLOCK_NANOSLEEP,
(c as i32): i64, 0i64, (&req): i64, (&rem): i64);
if (rc == 0i64) { return; };
if (rc != -4i64) { abort("time.sleep: clock_nanosleep failed"); };
req = rem;
};
};
// ref/hare/time/arithm.ha:9. The negative-duration branch normalises
// nsec into [0, second).
export fn add(i: instant, x: duration) instant = {
let r: instant;
let xi: i64 = x: i64;
let sec: i64 = second: i64;
let nsec: i64 = nanosecond: i64;
if (xi == 0i64) {
r.sec = i.sec;
r.nsec = i.nsec;
return r;
};
if (xi > 0i64) {
r.sec = i.sec + (i.nsec + xi) / sec;
r.nsec = (i.nsec + xi) % sec;
return r;
};
r.sec = i.sec + (i.nsec + xi - sec + nsec) / sec;
r.nsec = (i.nsec + (xi % sec) + sec) % sec;
return r;
};
// ref/hare/time/arithm.ha:26. Sign convention: b - a.
export fn diff(a: instant, b: instant) duration = {
let sec: i64 = second: i64;
let v: i64 = ((b.sec - a.sec) * sec) + (b.nsec - a.nsec);
return v: duration;
};
// ref/hare/time/arithm.ha:32. -1 if a < b, 0 if equal, +1 if a > b.
export fn compare(a: instant, b: instant) i8 = {
if (a.sec < b.sec) { return -1i8; };
if (a.sec > b.sec) { return 1i8; };
if (a.nsec < b.nsec) { return -1i8; };
if (a.nsec > b.nsec) { return 1i8; };
return 0i8;
};