The flat checker scope makes ANY decl named assert/abort anywhere in the combined unit disable the builtin unit-wide (the #45 shadow shape: scope_lookup_prefer's cross-module fallback finds it). lib carried three colliding @symbol("rt_abort") shims (os, time, strconv/stof) plus the os.assert wrapper, so a bare assert(cond) in ANY program importing os mis-bound os.assert and failed arity — a hard blocker for regex fold-5 (regex.ha:660/670 bring builtin-assert mass). Ruled respell-now per the recurrence test (#45 -> #58). Delete the shims and the os.assert wrapper; every bare abort(msg) caller (regex, strings, utf8, hash, getopt, encoding/*, time, stof) now lands on the builtin, and the ~40 os.assert(c, m) sites respell to the builtin assert(c, m) — restoring the exact Hare spelling the lib ports diverged from (e.g. ref/hare/bytes/tokenize.ha:23). os.assert had no Hare counterpart (Hare's assert is a language builtin); rule-9 wrapper removed. temp/dirs/bufio already use the non-colliding rtabort spelling and keep it. Now-dead 'import os;' lines kept (pre-existing precedent: lib/strconv/strconv.ww carries one); a tree-wide dead-import sweep is a separate concern. regex.ww's if+abort workarounds citing #58 stay for the fold-5 owner to fold back into assert. combined.ww regenerated for all five selfhost tools + the smoke fixture via make.
97 lines
3.2 KiB
Plaintext
97 lines
3.2 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 /
|
|
// sleep 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;
|
|
|
|
def SYS_CLOCK_GETTIME: i64 = 228;
|
|
|
|
// 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/arithm.ha:9. Adds duration to instant. 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. Returns duration from a to b.
|
|
// 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;
|
|
};
|