lib: retire os.assert/abort shims — assert/abort are builtins (#58 respell)
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.
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
package time;
|
||||
|
||||
@symbol("rt_syscall") fn syscall2(num: i64, a: i64, b: i64) i64;
|
||||
@symbol("rt_abort") fn abort(msg: str) void;
|
||||
|
||||
def SYS_CLOCK_GETTIME: i64 = 228;
|
||||
|
||||
@@ -111,13 +110,6 @@ import time;
|
||||
@symbol("rt_syscall") fn syscall4(num: nr, a: i64, b: i64, c: i64, d: i64) i64;
|
||||
|
||||
@symbol("rt_free") export fn free(p: *void, n: u64) void;
|
||||
@symbol("rt_abort") fn abort(msg: str) void;
|
||||
|
||||
// Hare-style runtime check. Caller passes a message that's printed
|
||||
// to stderr before exit(1).
|
||||
export fn assert(cond: bool, msg: str) void = {
|
||||
if (!cond) { abort(msg); };
|
||||
};
|
||||
|
||||
// Linux amd64 syscall numbers. Internal to this module — passed as
|
||||
// the first arg of syscall0..4 via libwwrt's rt_syscall trampoline.
|
||||
@@ -1003,7 +995,7 @@ export fn contains(s: []u8, needles: (u8 | []u8)...) bool = {
|
||||
// ltrim — borrowed view of `in` with leading bytes in `trim` stripped.
|
||||
// `trim` must be non-empty. ref/hare/bytes/trim.ha:7.
|
||||
export fn ltrim(in: []u8, trim: u8...) []u8 = {
|
||||
os.assert(trim.len > 0, "bytes.ltrim called with empty trim set");
|
||||
assert(trim.len > 0, "bytes.ltrim called with empty trim set");
|
||||
let i: i32 = 0;
|
||||
for (i < in.len && contains(trim, in[i])) { i += 1; };
|
||||
let r: []u8;
|
||||
@@ -1018,7 +1010,7 @@ export fn ltrim(in: []u8, trim: u8...) []u8 = {
|
||||
// `size` underflow at i==0 to terminate; ww indices are signed i32, so
|
||||
// the equivalent termination is spelled `i >= 0` explicitly.
|
||||
export fn rtrim(in: []u8, trim: u8...) []u8 = {
|
||||
os.assert(trim.len > 0, "bytes.rtrim called with empty trim set");
|
||||
assert(trim.len > 0, "bytes.rtrim called with empty trim set");
|
||||
let i: i32 = in.len - 1;
|
||||
for (i >= 0 && contains(trim, in[i])) { i -= 1; };
|
||||
let r: []u8;
|
||||
@@ -1086,8 +1078,8 @@ export fn zero(s: []u8) void = {
|
||||
// `delim` is borrowed; caller keeps it valid for the tokenizer's
|
||||
// lifetime. ref/hare/bytes/tokenize.ha:22.
|
||||
export fn tokenize(in: []u8, delim: u8...) tokenizer = {
|
||||
os.assert(delim.len > 0, "bytes.tokenize called with empty slice");
|
||||
os.assert((in.len: i64) < types.I64_MAX,
|
||||
assert(delim.len > 0, "bytes.tokenize called with empty slice");
|
||||
assert((in.len: i64) < types.I64_MAX,
|
||||
"bytes.tokenize: input length exceeds I64_MAX");
|
||||
let t: tokenizer;
|
||||
t.in = in;
|
||||
@@ -1103,8 +1095,8 @@ export fn tokenize(in: []u8, delim: u8...) tokenizer = {
|
||||
// rtokenize — reverse-direction tokenize. First next_token yields the
|
||||
// last token, last next_token yields the first. ref/hare/bytes/tokenize.ha:40.
|
||||
export fn rtokenize(in: []u8, delim: u8...) tokenizer = {
|
||||
os.assert(delim.len > 0, "bytes.rtokenize called with empty slice");
|
||||
os.assert((in.len: i64) < types.I64_MAX,
|
||||
assert(delim.len > 0, "bytes.rtokenize called with empty slice");
|
||||
assert((in.len: i64) < types.I64_MAX,
|
||||
"bytes.rtokenize: input length exceeds I64_MAX");
|
||||
let t: tokenizer;
|
||||
t.in = in;
|
||||
@@ -1258,7 +1250,7 @@ export fn remaining_tokens(s: *tokenizer) []u8 = {
|
||||
//
|
||||
// ref/hare/bytes/tokenize.ha:156.
|
||||
export fn splitn(in: []u8, delim: []u8, n: i32) [][]u8 = {
|
||||
os.assert(delim.len > 0,
|
||||
assert(delim.len > 0,
|
||||
"bytes.splitn must not be called with an empty delimiter");
|
||||
let toks: [][]u8;
|
||||
toks.ptr = nil: *[]u8;
|
||||
@@ -1296,7 +1288,7 @@ export fn splitn(in: []u8, delim: []u8, n: i32) [][]u8 = {
|
||||
//
|
||||
// ref/hare/bytes/tokenize.ha:186.
|
||||
export fn rsplitn(in: []u8, delim: []u8, n: i32) [][]u8 = {
|
||||
os.assert(delim.len > 0,
|
||||
assert(delim.len > 0,
|
||||
"bytes.rsplitn called with empty delimiter");
|
||||
let toks: [][]u8;
|
||||
toks.ptr = nil: *[]u8;
|
||||
@@ -1365,7 +1357,7 @@ export fn cut(in: []u8, delim: (u8 | []u8)) ([]u8, []u8) = {
|
||||
let ln: i32 = match (delim) {
|
||||
case let c: u8 => yield 1i32;
|
||||
case let sub: []u8 => {
|
||||
os.assert(sub.len > 0,
|
||||
assert(sub.len > 0,
|
||||
"bytes.cut called with empty delimiter");
|
||||
yield sub.len;
|
||||
};
|
||||
@@ -1389,7 +1381,7 @@ export fn rcut(in: []u8, delim: (u8 | []u8)) ([]u8, []u8) = {
|
||||
let ln: i32 = match (delim) {
|
||||
case let c: u8 => yield 1i32;
|
||||
case let sub: []u8 => {
|
||||
os.assert(sub.len > 0,
|
||||
assert(sub.len > 0,
|
||||
"bytes.rcut called with empty delimiter");
|
||||
yield sub.len;
|
||||
};
|
||||
@@ -2068,7 +2060,7 @@ fn utf8bytelenbounded(it: *iterator, end: i32) i32 = {
|
||||
// defaulting end=END is omitted: ww has no default-parameter syntax
|
||||
// (filed as #37). Byte-indexed counterpart: [[bytesub]].
|
||||
export fn sub(s: str, start: i32, end: i32) str = {
|
||||
os.assert(start <= end, "strings.sub: start is higher than end");
|
||||
assert(start <= end, "strings.sub: start is higher than end");
|
||||
let it: iterator = iter(s);
|
||||
let starti: i32 = utf8bytelenbounded(&it, start);
|
||||
let endi: i32 = utf8bytelenbounded(&it, end - start);
|
||||
@@ -2084,8 +2076,8 @@ export fn sub(s: str, start: i32, end: i32) str = {
|
||||
// codepoint); the equivalent Hare predicate is `s[i] & 0xc0 == 0x80`
|
||||
// at ref/hare/strings/sub.ha:72-73.
|
||||
export fn bytesub(s: str, start: i32, end: i32) (str | utf8.invalid) = {
|
||||
os.assert(start <= end, "strings.bytesub: start is higher than end");
|
||||
os.assert(end <= s.len, "strings.bytesub: end exceeds string length");
|
||||
assert(start <= end, "strings.bytesub: start is higher than end");
|
||||
assert(end <= s.len, "strings.bytesub: end exceeds string length");
|
||||
if (start < s.len && (s[start] & 0xC0u8) == 0x80u8) {
|
||||
let e: utf8.invalid; return e;
|
||||
};
|
||||
@@ -2513,7 +2505,7 @@ export fn tokenize(s: str, delim: str) tokenizer = {
|
||||
let d: []u8 = toutf8(delim);
|
||||
let i: i32 = 0;
|
||||
for (i < d.len) {
|
||||
os.assert((d[i] & 0x80u8) == 0u8,
|
||||
assert((d[i] & 0x80u8) == 0u8,
|
||||
"strings.tokenize cannot tokenize on non-ASCII delimiters");
|
||||
i += 1;
|
||||
};
|
||||
@@ -2527,7 +2519,7 @@ export fn rtokenize(s: str, delim: str) tokenizer = {
|
||||
let d: []u8 = toutf8(delim);
|
||||
let i: i32 = 0;
|
||||
for (i < d.len) {
|
||||
os.assert((d[i] & 0x80u8) == 0u8,
|
||||
assert((d[i] & 0x80u8) == 0u8,
|
||||
"strings.rtokenize cannot tokenize on non-ASCII delimiters");
|
||||
i += 1;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user