diff --git a/examples/lisp/lispcore.ww b/examples/lisp/lispcore.ww index 67523ed1..0d23e74a 100644 --- a/examples/lisp/lispcore.ww +++ b/examples/lisp/lispcore.ww @@ -378,8 +378,8 @@ export fn intern(s: str) i32 = { if (streqid(s, sym_off[i], sym_len[i])) { return i; }; i += 1; }; - os.assert(sym_count < SYM_CAP, "sym table full"); - os.assert(sym_blobuse + s.len <= SYM_BLOBSZ, "sym blob full"); + assert(sym_count < SYM_CAP, "sym table full"); + assert(sym_blobuse + s.len <= SYM_BLOBSZ, "sym blob full"); let off: i32 = sym_blobuse; let j: i32 = 0; for (j < s.len) { diff --git a/lib/bytes/bytes.ww b/lib/bytes/bytes.ww index fc37838d..e72fc793 100644 --- a/lib/bytes/bytes.ww +++ b/lib/bytes/bytes.ww @@ -145,7 +145,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; @@ -160,7 +160,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; @@ -228,8 +228,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; @@ -245,8 +245,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; @@ -400,7 +400,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; @@ -438,7 +438,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; @@ -507,7 +507,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; }; @@ -531,7 +531,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; }; diff --git a/lib/crypto/sha256/sha256.ww b/lib/crypto/sha256/sha256.ww index e025da29..74c533b6 100644 --- a/lib/crypto/sha256/sha256.ww +++ b/lib/crypto/sha256/sha256.ww @@ -205,7 +205,7 @@ fn sumfn(h: *hash.hash, buf: []u8) void = { case let e: io.error => abort("sha256.sum: length write errored"); }; - os.assert(st.nx == 0: size, "sha256.sum: residual partial block"); + assert(st.nx == 0: size, "sha256.sum: residual partial block"); let stride: i32 = size(u32): i32; let i: i32 = 0; diff --git a/lib/hash/hash.ww b/lib/hash/hash.ww index 49fee331..f1c8c174 100644 --- a/lib/hash/hash.ww +++ b/lib/hash/hash.ww @@ -63,7 +63,7 @@ export fn close(h: *hash) void = { // [[sz]] bytes. ref/hare/hash/hash.ha:35-38. ww spells Hare's `h.sum(...)` // as the explicit fn-ptr call `(*h.sum)(...)` (#193). export fn sum(h: *hash, buf: []u8) void = { - os.assert((buf.len: size) >= h.sz, + assert((buf.len: size) >= h.sz, "hash.sum buffer does not meet minimum required size for this hash function"); (*h.sum)(h, buf); }; diff --git a/lib/os/os.ww b/lib/os/os.ww index e6360fab..b0c8facb 100644 --- a/lib/os/os.ww +++ b/lib/os/os.ww @@ -13,13 +13,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. diff --git a/lib/strconv/decimal.ww b/lib/strconv/decimal.ww index c89fccf0..106f1ba0 100644 --- a/lib/strconv/decimal.ww +++ b/lib/strconv/decimal.ww @@ -22,7 +22,7 @@ // (when no continue exists in the loop). // - Hare `fn foo() T = if (cond) {...} else expr;` expression body // → ww requires a `{}` block body throughout. -// - Hare bare `assert(cond)` builtin → `os.assert(cond, msg)`; +// - Hare bare `assert(cond)` builtin → `assert(cond, msg)`; // wwstage cgen has no `assert` intercept (deferred fold). // - In-file instances of the above hoist pattern: `i_sz` (line 93) // hoists a per-iteration size cast out of a for-loop comparison @@ -110,7 +110,7 @@ fn leftshift(d: *decimal, k: u32) void = { let SZ_BOUND: size = (len(d.digits): size); let kU64: u64 = (k: u64); let MAXSHIFT_U32: u32 = (maxshift: u32); - os.assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); + assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); if (d.nd == (0u64: size)) { return; }; let nn: u32 = leftshift_newdigits(d, k); let r: int = (d.nd: int) - 1; diff --git a/lib/strconv/ftos.ww b/lib/strconv/ftos.ww index 64390d31..e3c36bec 100644 --- a/lib/strconv/ftos.ww +++ b/lib/strconv/ftos.ww @@ -42,7 +42,7 @@ // (stof.ww hex_to_bits precedent). // - `&&=` → `x = x && y`. `ibool=if(b)1 else 0` expr-body → block. // comma `let a=…, b=…` → split. `if/else` expr-yield → pre-bound -// local + block. `assert()` → `os.assert(cond,msg)`. +// local + block. `assert()` → `assert(cond,msg)`. // - 2D row-bind `mul=TBL[base]` → direct double-index `TBL[base][0/1]` // (#155 / #156, stof.ww eisel_lemire precedent). // - ibool's u8 result + the u8 BITCOUNT defs cast explicitly to u32/u64 @@ -62,7 +62,7 @@ import os; // (u128mul + the r128 struct live in stof.ww, fold-4's first consumer; // reused in-package here.) fn u128rshift(lo: u64, hi: u64, s: u32) u64 = { - os.assert(s <= 64u32, "strconv.u128rshift: s > 64"); + assert(s <= 64u32, "strconv.u128rshift: s > 64"); return (hi << (64u64 - (s: u64))) | (lo >> (s: u64)); }; @@ -73,7 +73,7 @@ fn pow5fac(v: u64) u32 = { let n_div_5: u64 = 3689348814741910323u64; let count: u32 = 0u32; for (true) { - os.assert(value != 0u64, "strconv.pow5fac: value == 0"); + assert(value != 0u64, "strconv.pow5fac: value == 0"); value *= m_inv_5; if (value > n_div_5) { break; }; count += 1u32; @@ -92,8 +92,8 @@ fn pow5multiple(v: u64, p: u32) bool = { return pow5fac(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:69. fn pow2multiple(v: u64, p: u32) bool = { - os.assert(v > 0u64, "strconv.pow2multiple: v == 0"); - os.assert(p < 64u32, "strconv.pow2multiple: p >= 64"); + assert(v > 0u64, "strconv.pow2multiple: v == 0"); + assert(p < 64u32, "strconv.pow2multiple: p >= 64"); return (v & ((1u64 << (p: u64)) - 1u64)) == 0u64; }; @@ -136,7 +136,7 @@ fn mulshiftall64(m: u64, mul0: u64, mul1: u64, j: i32, mm_shift: u32) ryuv = { // ref/hare/strconv/ftos_ryu.ha:140. fn log2pow5(e: u32) u32 = { - os.assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); + assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); return (e * 1217359u32) >> 19u32; }; @@ -146,13 +146,13 @@ fn pow5bits(e: u32) u32 = { return ceil_log2pow5(e); }; // ref/hare/strconv/ftos_ryu.ha:149. fn log10pow2(e: u32) u32 = { - os.assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); + assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); return (e * 78913u32) >> 18u32; }; // ref/hare/strconv/ftos_ryu.ha:154. fn log10pow5(e: u32) u32 = { - os.assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); + assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); return (e * 732923u32) >> 20u32; }; @@ -343,15 +343,15 @@ fn f64todecf64(mantissa: u64, exponent: u32) decf64 = { // u64 siblings at 32-bit width; they reuse the SHARED f64computeinvpow5/ // f64computepow5 (and thus the f64 SPLIT2 tables) per ftos_ryu.ha — there // is no separate f32 table. Same scalar-PARAM-mutation → copy-to-local, -// comma-split, assert → os.assert, expr-yield → block divergences as the -// f64 path above. ==== +// comma-split, expr-yield → block divergences as the f64 path +// above. ==== // ref/hare/strconv/ftos_ryu.ha:52. Largest p with 5^p | value (32-bit). fn pow5fac32(v: u32) u32 = { let value: u32 = v; let count: u32 = 0u32; for (true) { - os.assert(value != 0u32, "strconv.pow5fac32: value == 0"); + assert(value != 0u32, "strconv.pow5fac32: value == 0"); let q: u32 = value / 5u32; let r: u32 = value % 5u32; if (r != 0u32) { break; }; @@ -366,8 +366,8 @@ fn pow5multiple32(v: u32, p: u32) bool = { return pow5fac32(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:75. fn pow2multiple32(v: u32, p: u32) bool = { - os.assert(v > 0u32, "strconv.pow2multiple32: v == 0"); - os.assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); + assert(v > 0u32, "strconv.pow2multiple32: v == 0"); + assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); return (v & ((1u32 << p) - 1u32)) == 0u32; }; @@ -377,14 +377,14 @@ fn pow2multiple32(v: u32, p: u32) bool = { // (lib/types/types.ww — no `export`), so Hare's `types::U32_MAX` can't be // referenced cross-package. fn mulshift32(m: u32, a: u64, s: u32) u32 = { - os.assert(s > 32u32, "strconv.mulshift32: s <= 32"); + assert(s > 32u32, "strconv.mulshift32: s <= 32"); let a_lo: u64 = (a: u32): u64; let a_hi: u64 = a >> 32u64; let b0: u64 = (m: u64) * a_lo; let b1: u64 = (m: u64) * a_hi; let sum: u64 = (b0 >> 32u64) + b1; let ss: u64 = sum >> ((s: u64) - 32u64); - os.assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); + assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); return ss: u32; }; @@ -533,7 +533,7 @@ fn f32todecf32(mantissa: u32, exponent: u32) decf32 = { // ref/hare/strconv/ftos.ha:49. Decimal digit-count of n (n <= 1e17). fn declen(n: u64) uint = { - os.assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); + assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); if (n >= 100000000000000000u64) { return (18u32: uint); }; if (n >= 10000000000000000u64) { return (17u32: uint); }; if (n >= 1000000000000000u64) { return (16u32: uint); }; @@ -621,7 +621,7 @@ fn encode_f_dec(d: *decimal, buf: []u8, out: i32) i32 = { // logic only): no precision zeros, lowercase 'e', no '+'/two-digit pad. fn encode_e_dec(d: *decimal, buf: []u8, out: i32) i32 = { let o: i32 = out; - os.assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); + assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); buf[o] = (d.digits[0] + 48u8): u8; o += 1i32; if ((d.nd: i32) > 1i32) { diff --git a/lib/strconv/stof.ww b/lib/strconv/stof.ww index 71a8f973..bfce9c63 100644 --- a/lib/strconv/stof.ww +++ b/lib/strconv/stof.ww @@ -97,8 +97,6 @@ fn todig(c: u8) u8 = { return 0u8; // unreachable; rt_abort is void-typed (path-cov) }; -@symbol("rt_abort") fn abort(msg: str) void; - // ref/hare/strconv/stof.ha:25. type fast_parsed_float = struct { mantissa: u64, @@ -280,7 +278,7 @@ fn decimal_parse(d: *decimal, s: str) (void | invalid) = { // ref/hare/strconv/stof.ha:173. Count of leading zero bits in n>0. fn leading_zeroes(n: u64) uint = { - os.assert(n > 0u64, "strconv.leading_zeroes: n == 0"); + assert(n > 0u64, "strconv.leading_zeroes: n == 0"); let b: u64 = 0u64; if ((n & 0xFFFFFFFF00000000u64) > 0u64) { n >>= 32u64; @@ -599,7 +597,7 @@ export fn stof64(s: str, b: base) (f64 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof64: base must be DEC or HEX"); if (s.len == 0) { @@ -652,7 +650,7 @@ export fn stof32(s: str, b: base) (f32 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof32: base must be DEC or HEX"); if (s.len == 0) { diff --git a/lib/strings/strings.ww b/lib/strings/strings.ww index e0fb9c70..91c4daa7 100644 --- a/lib/strings/strings.ww +++ b/lib/strings/strings.ww @@ -223,7 +223,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); @@ -239,8 +239,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; }; @@ -668,7 +668,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; }; @@ -682,7 +682,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; }; diff --git a/lib/time/time.ww b/lib/time/time.ww index b496176a..2eefaa08 100644 --- a/lib/time/time.ww +++ b/lib/time/time.ww @@ -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; diff --git a/selfhost/cmd/w6a/main.combined.ww b/selfhost/cmd/w6a/main.combined.ww index 86ae658a..b0968325 100644 --- a/selfhost/cmd/w6a/main.combined.ww +++ b/selfhost/cmd/w6a/main.combined.ww @@ -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; }; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index f024c7e1..52c6af03 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -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; }; @@ -2816,7 +2808,7 @@ export fn rpad(s: str, p: rune, maxlen: i32) str = { // (when no continue exists in the loop). // - Hare `fn foo() T = if (cond) {...} else expr;` expression body // → ww requires a `{}` block body throughout. -// - Hare bare `assert(cond)` builtin → `os.assert(cond, msg)`; +// - Hare bare `assert(cond)` builtin → `assert(cond, msg)`; // wwstage cgen has no `assert` intercept (deferred fold). // - In-file instances of the above hoist pattern: `i_sz` (line 93) // hoists a per-iteration size cast out of a for-loop comparison @@ -2904,7 +2896,7 @@ fn leftshift(d: *decimal, k: u32) void = { let SZ_BOUND: size = (len(d.digits): size); let kU64: u64 = (k: u64); let MAXSHIFT_U32: u32 = (maxshift: u32); - os.assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); + assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); if (d.nd == (0u64: size)) { return; }; let nn: u32 = leftshift_newdigits(d, k); let r: int = (d.nd: int) - 1; @@ -3448,7 +3440,7 @@ export fn absi64(n: i64) u64 = { // (stof.ww hex_to_bits precedent). // - `&&=` → `x = x && y`. `ibool=if(b)1 else 0` expr-body → block. // comma `let a=…, b=…` → split. `if/else` expr-yield → pre-bound -// local + block. `assert()` → `os.assert(cond,msg)`. +// local + block. `assert()` → `assert(cond,msg)`. // - 2D row-bind `mul=TBL[base]` → direct double-index `TBL[base][0/1]` // (#155 / #156, stof.ww eisel_lemire precedent). // - ibool's u8 result + the u8 BITCOUNT defs cast explicitly to u32/u64 @@ -3468,7 +3460,7 @@ import os; // (u128mul + the r128 struct live in stof.ww, fold-4's first consumer; // reused in-package here.) fn u128rshift(lo: u64, hi: u64, s: u32) u64 = { - os.assert(s <= 64u32, "strconv.u128rshift: s > 64"); + assert(s <= 64u32, "strconv.u128rshift: s > 64"); return (hi << (64u64 - (s: u64))) | (lo >> (s: u64)); }; @@ -3479,7 +3471,7 @@ fn pow5fac(v: u64) u32 = { let n_div_5: u64 = 3689348814741910323u64; let count: u32 = 0u32; for (true) { - os.assert(value != 0u64, "strconv.pow5fac: value == 0"); + assert(value != 0u64, "strconv.pow5fac: value == 0"); value *= m_inv_5; if (value > n_div_5) { break; }; count += 1u32; @@ -3498,8 +3490,8 @@ fn pow5multiple(v: u64, p: u32) bool = { return pow5fac(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:69. fn pow2multiple(v: u64, p: u32) bool = { - os.assert(v > 0u64, "strconv.pow2multiple: v == 0"); - os.assert(p < 64u32, "strconv.pow2multiple: p >= 64"); + assert(v > 0u64, "strconv.pow2multiple: v == 0"); + assert(p < 64u32, "strconv.pow2multiple: p >= 64"); return (v & ((1u64 << (p: u64)) - 1u64)) == 0u64; }; @@ -3542,7 +3534,7 @@ fn mulshiftall64(m: u64, mul0: u64, mul1: u64, j: i32, mm_shift: u32) ryuv = { // ref/hare/strconv/ftos_ryu.ha:140. fn log2pow5(e: u32) u32 = { - os.assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); + assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); return (e * 1217359u32) >> 19u32; }; @@ -3552,13 +3544,13 @@ fn pow5bits(e: u32) u32 = { return ceil_log2pow5(e); }; // ref/hare/strconv/ftos_ryu.ha:149. fn log10pow2(e: u32) u32 = { - os.assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); + assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); return (e * 78913u32) >> 18u32; }; // ref/hare/strconv/ftos_ryu.ha:154. fn log10pow5(e: u32) u32 = { - os.assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); + assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); return (e * 732923u32) >> 20u32; }; @@ -3749,15 +3741,15 @@ fn f64todecf64(mantissa: u64, exponent: u32) decf64 = { // u64 siblings at 32-bit width; they reuse the SHARED f64computeinvpow5/ // f64computepow5 (and thus the f64 SPLIT2 tables) per ftos_ryu.ha — there // is no separate f32 table. Same scalar-PARAM-mutation → copy-to-local, -// comma-split, assert → os.assert, expr-yield → block divergences as the -// f64 path above. ==== +// comma-split, expr-yield → block divergences as the f64 path +// above. ==== // ref/hare/strconv/ftos_ryu.ha:52. Largest p with 5^p | value (32-bit). fn pow5fac32(v: u32) u32 = { let value: u32 = v; let count: u32 = 0u32; for (true) { - os.assert(value != 0u32, "strconv.pow5fac32: value == 0"); + assert(value != 0u32, "strconv.pow5fac32: value == 0"); let q: u32 = value / 5u32; let r: u32 = value % 5u32; if (r != 0u32) { break; }; @@ -3772,8 +3764,8 @@ fn pow5multiple32(v: u32, p: u32) bool = { return pow5fac32(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:75. fn pow2multiple32(v: u32, p: u32) bool = { - os.assert(v > 0u32, "strconv.pow2multiple32: v == 0"); - os.assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); + assert(v > 0u32, "strconv.pow2multiple32: v == 0"); + assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); return (v & ((1u32 << p) - 1u32)) == 0u32; }; @@ -3783,14 +3775,14 @@ fn pow2multiple32(v: u32, p: u32) bool = { // (lib/types/types.ww — no `export`), so Hare's `types::U32_MAX` can't be // referenced cross-package. fn mulshift32(m: u32, a: u64, s: u32) u32 = { - os.assert(s > 32u32, "strconv.mulshift32: s <= 32"); + assert(s > 32u32, "strconv.mulshift32: s <= 32"); let a_lo: u64 = (a: u32): u64; let a_hi: u64 = a >> 32u64; let b0: u64 = (m: u64) * a_lo; let b1: u64 = (m: u64) * a_hi; let sum: u64 = (b0 >> 32u64) + b1; let ss: u64 = sum >> ((s: u64) - 32u64); - os.assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); + assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); return ss: u32; }; @@ -3939,7 +3931,7 @@ fn f32todecf32(mantissa: u32, exponent: u32) decf32 = { // ref/hare/strconv/ftos.ha:49. Decimal digit-count of n (n <= 1e17). fn declen(n: u64) uint = { - os.assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); + assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); if (n >= 100000000000000000u64) { return (18u32: uint); }; if (n >= 10000000000000000u64) { return (17u32: uint); }; if (n >= 1000000000000000u64) { return (16u32: uint); }; @@ -4027,7 +4019,7 @@ fn encode_f_dec(d: *decimal, buf: []u8, out: i32) i32 = { // logic only): no precision zeros, lowercase 'e', no '+'/two-digit pad. fn encode_e_dec(d: *decimal, buf: []u8, out: i32) i32 = { let o: i32 = out; - os.assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); + assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); buf[o] = (d.digits[0] + 48u8): u8; o += 1i32; if ((d.nd: i32) > 1i32) { @@ -4612,8 +4604,6 @@ fn todig(c: u8) u8 = { return 0u8; // unreachable; rt_abort is void-typed (path-cov) }; -@symbol("rt_abort") fn abort(msg: str) void; - // ref/hare/strconv/stof.ha:25. type fast_parsed_float = struct { mantissa: u64, @@ -4795,7 +4785,7 @@ fn decimal_parse(d: *decimal, s: str) (void | invalid) = { // ref/hare/strconv/stof.ha:173. Count of leading zero bits in n>0. fn leading_zeroes(n: u64) uint = { - os.assert(n > 0u64, "strconv.leading_zeroes: n == 0"); + assert(n > 0u64, "strconv.leading_zeroes: n == 0"); let b: u64 = 0u64; if ((n & 0xFFFFFFFF00000000u64) > 0u64) { n >>= 32u64; @@ -5114,7 +5104,7 @@ export fn stof64(s: str, b: base) (f64 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof64: base must be DEC or HEX"); if (s.len == 0) { @@ -5167,7 +5157,7 @@ export fn stof32(s: str, b: base) (f32 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof32: base must be DEC or HEX"); if (s.len == 0) { diff --git a/selfhost/cmd/w6l/main.combined.ww b/selfhost/cmd/w6l/main.combined.ww index 596a5bf3..b6942475 100644 --- a/selfhost/cmd/w6l/main.combined.ww +++ b/selfhost/cmd/w6l/main.combined.ww @@ -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; }; diff --git a/selfhost/cmd/ww/main.combined.ww b/selfhost/cmd/ww/main.combined.ww index b82d66a2..4d0b0b4d 100644 --- a/selfhost/cmd/ww/main.combined.ww +++ b/selfhost/cmd/ww/main.combined.ww @@ -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; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index cbf36e17..cdadf451 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -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. @@ -813,7 +805,7 @@ export fn exists(path: str) bool = { // (when no continue exists in the loop). // - Hare `fn foo() T = if (cond) {...} else expr;` expression body // → ww requires a `{}` block body throughout. -// - Hare bare `assert(cond)` builtin → `os.assert(cond, msg)`; +// - Hare bare `assert(cond)` builtin → `assert(cond, msg)`; // wwstage cgen has no `assert` intercept (deferred fold). // - In-file instances of the above hoist pattern: `i_sz` (line 93) // hoists a per-iteration size cast out of a for-loop comparison @@ -901,7 +893,7 @@ fn leftshift(d: *decimal, k: u32) void = { let SZ_BOUND: size = (len(d.digits): size); let kU64: u64 = (k: u64); let MAXSHIFT_U32: u32 = (maxshift: u32); - os.assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); + assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); if (d.nd == (0u64: size)) { return; }; let nn: u32 = leftshift_newdigits(d, k); let r: int = (d.nd: int) - 1; @@ -1445,7 +1437,7 @@ export fn absi64(n: i64) u64 = { // (stof.ww hex_to_bits precedent). // - `&&=` → `x = x && y`. `ibool=if(b)1 else 0` expr-body → block. // comma `let a=…, b=…` → split. `if/else` expr-yield → pre-bound -// local + block. `assert()` → `os.assert(cond,msg)`. +// local + block. `assert()` → `assert(cond,msg)`. // - 2D row-bind `mul=TBL[base]` → direct double-index `TBL[base][0/1]` // (#155 / #156, stof.ww eisel_lemire precedent). // - ibool's u8 result + the u8 BITCOUNT defs cast explicitly to u32/u64 @@ -1465,7 +1457,7 @@ import os; // (u128mul + the r128 struct live in stof.ww, fold-4's first consumer; // reused in-package here.) fn u128rshift(lo: u64, hi: u64, s: u32) u64 = { - os.assert(s <= 64u32, "strconv.u128rshift: s > 64"); + assert(s <= 64u32, "strconv.u128rshift: s > 64"); return (hi << (64u64 - (s: u64))) | (lo >> (s: u64)); }; @@ -1476,7 +1468,7 @@ fn pow5fac(v: u64) u32 = { let n_div_5: u64 = 3689348814741910323u64; let count: u32 = 0u32; for (true) { - os.assert(value != 0u64, "strconv.pow5fac: value == 0"); + assert(value != 0u64, "strconv.pow5fac: value == 0"); value *= m_inv_5; if (value > n_div_5) { break; }; count += 1u32; @@ -1495,8 +1487,8 @@ fn pow5multiple(v: u64, p: u32) bool = { return pow5fac(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:69. fn pow2multiple(v: u64, p: u32) bool = { - os.assert(v > 0u64, "strconv.pow2multiple: v == 0"); - os.assert(p < 64u32, "strconv.pow2multiple: p >= 64"); + assert(v > 0u64, "strconv.pow2multiple: v == 0"); + assert(p < 64u32, "strconv.pow2multiple: p >= 64"); return (v & ((1u64 << (p: u64)) - 1u64)) == 0u64; }; @@ -1539,7 +1531,7 @@ fn mulshiftall64(m: u64, mul0: u64, mul1: u64, j: i32, mm_shift: u32) ryuv = { // ref/hare/strconv/ftos_ryu.ha:140. fn log2pow5(e: u32) u32 = { - os.assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); + assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); return (e * 1217359u32) >> 19u32; }; @@ -1549,13 +1541,13 @@ fn pow5bits(e: u32) u32 = { return ceil_log2pow5(e); }; // ref/hare/strconv/ftos_ryu.ha:149. fn log10pow2(e: u32) u32 = { - os.assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); + assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); return (e * 78913u32) >> 18u32; }; // ref/hare/strconv/ftos_ryu.ha:154. fn log10pow5(e: u32) u32 = { - os.assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); + assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); return (e * 732923u32) >> 20u32; }; @@ -1746,15 +1738,15 @@ fn f64todecf64(mantissa: u64, exponent: u32) decf64 = { // u64 siblings at 32-bit width; they reuse the SHARED f64computeinvpow5/ // f64computepow5 (and thus the f64 SPLIT2 tables) per ftos_ryu.ha — there // is no separate f32 table. Same scalar-PARAM-mutation → copy-to-local, -// comma-split, assert → os.assert, expr-yield → block divergences as the -// f64 path above. ==== +// comma-split, expr-yield → block divergences as the f64 path +// above. ==== // ref/hare/strconv/ftos_ryu.ha:52. Largest p with 5^p | value (32-bit). fn pow5fac32(v: u32) u32 = { let value: u32 = v; let count: u32 = 0u32; for (true) { - os.assert(value != 0u32, "strconv.pow5fac32: value == 0"); + assert(value != 0u32, "strconv.pow5fac32: value == 0"); let q: u32 = value / 5u32; let r: u32 = value % 5u32; if (r != 0u32) { break; }; @@ -1769,8 +1761,8 @@ fn pow5multiple32(v: u32, p: u32) bool = { return pow5fac32(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:75. fn pow2multiple32(v: u32, p: u32) bool = { - os.assert(v > 0u32, "strconv.pow2multiple32: v == 0"); - os.assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); + assert(v > 0u32, "strconv.pow2multiple32: v == 0"); + assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); return (v & ((1u32 << p) - 1u32)) == 0u32; }; @@ -1780,14 +1772,14 @@ fn pow2multiple32(v: u32, p: u32) bool = { // (lib/types/types.ww — no `export`), so Hare's `types::U32_MAX` can't be // referenced cross-package. fn mulshift32(m: u32, a: u64, s: u32) u32 = { - os.assert(s > 32u32, "strconv.mulshift32: s <= 32"); + assert(s > 32u32, "strconv.mulshift32: s <= 32"); let a_lo: u64 = (a: u32): u64; let a_hi: u64 = a >> 32u64; let b0: u64 = (m: u64) * a_lo; let b1: u64 = (m: u64) * a_hi; let sum: u64 = (b0 >> 32u64) + b1; let ss: u64 = sum >> ((s: u64) - 32u64); - os.assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); + assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); return ss: u32; }; @@ -1936,7 +1928,7 @@ fn f32todecf32(mantissa: u32, exponent: u32) decf32 = { // ref/hare/strconv/ftos.ha:49. Decimal digit-count of n (n <= 1e17). fn declen(n: u64) uint = { - os.assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); + assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); if (n >= 100000000000000000u64) { return (18u32: uint); }; if (n >= 10000000000000000u64) { return (17u32: uint); }; if (n >= 1000000000000000u64) { return (16u32: uint); }; @@ -2024,7 +2016,7 @@ fn encode_f_dec(d: *decimal, buf: []u8, out: i32) i32 = { // logic only): no precision zeros, lowercase 'e', no '+'/two-digit pad. fn encode_e_dec(d: *decimal, buf: []u8, out: i32) i32 = { let o: i32 = out; - os.assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); + assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); buf[o] = (d.digits[0] + 48u8): u8; o += 1i32; if ((d.nd: i32) > 1i32) { @@ -2497,7 +2489,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; @@ -2512,7 +2504,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; @@ -2580,8 +2572,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; @@ -2597,8 +2589,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; @@ -2752,7 +2744,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; @@ -2790,7 +2782,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; @@ -2859,7 +2851,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; }; @@ -2883,7 +2875,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; }; @@ -3585,7 +3577,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); @@ -3601,8 +3593,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; }; @@ -4030,7 +4022,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; }; @@ -4044,7 +4036,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; }; @@ -4612,8 +4604,6 @@ fn todig(c: u8) u8 = { return 0u8; // unreachable; rt_abort is void-typed (path-cov) }; -@symbol("rt_abort") fn abort(msg: str) void; - // ref/hare/strconv/stof.ha:25. type fast_parsed_float = struct { mantissa: u64, @@ -4795,7 +4785,7 @@ fn decimal_parse(d: *decimal, s: str) (void | invalid) = { // ref/hare/strconv/stof.ha:173. Count of leading zero bits in n>0. fn leading_zeroes(n: u64) uint = { - os.assert(n > 0u64, "strconv.leading_zeroes: n == 0"); + assert(n > 0u64, "strconv.leading_zeroes: n == 0"); let b: u64 = 0u64; if ((n & 0xFFFFFFFF00000000u64) > 0u64) { n >>= 32u64; @@ -5114,7 +5104,7 @@ export fn stof64(s: str, b: base) (f64 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof64: base must be DEC or HEX"); if (s.len == 0) { @@ -5167,7 +5157,7 @@ export fn stof32(s: str, b: base) (f32 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof32: base must be DEC or HEX"); if (s.len == 0) { diff --git a/selfhost/test/smoke.combined.ww b/selfhost/test/smoke.combined.ww index 02b7e464..65cca48f 100644 --- a/selfhost/test/smoke.combined.ww +++ b/selfhost/test/smoke.combined.ww @@ -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. @@ -813,7 +805,7 @@ export fn exists(path: str) bool = { // (when no continue exists in the loop). // - Hare `fn foo() T = if (cond) {...} else expr;` expression body // → ww requires a `{}` block body throughout. -// - Hare bare `assert(cond)` builtin → `os.assert(cond, msg)`; +// - Hare bare `assert(cond)` builtin → `assert(cond, msg)`; // wwstage cgen has no `assert` intercept (deferred fold). // - In-file instances of the above hoist pattern: `i_sz` (line 93) // hoists a per-iteration size cast out of a for-loop comparison @@ -901,7 +893,7 @@ fn leftshift(d: *decimal, k: u32) void = { let SZ_BOUND: size = (len(d.digits): size); let kU64: u64 = (k: u64); let MAXSHIFT_U32: u32 = (maxshift: u32); - os.assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); + assert(k <= MAXSHIFT_U32, "strconv.leftshift: k > maxshift"); if (d.nd == (0u64: size)) { return; }; let nn: u32 = leftshift_newdigits(d, k); let r: int = (d.nd: int) - 1; @@ -1445,7 +1437,7 @@ export fn absi64(n: i64) u64 = { // (stof.ww hex_to_bits precedent). // - `&&=` → `x = x && y`. `ibool=if(b)1 else 0` expr-body → block. // comma `let a=…, b=…` → split. `if/else` expr-yield → pre-bound -// local + block. `assert()` → `os.assert(cond,msg)`. +// local + block. `assert()` → `assert(cond,msg)`. // - 2D row-bind `mul=TBL[base]` → direct double-index `TBL[base][0/1]` // (#155 / #156, stof.ww eisel_lemire precedent). // - ibool's u8 result + the u8 BITCOUNT defs cast explicitly to u32/u64 @@ -1465,7 +1457,7 @@ import os; // (u128mul + the r128 struct live in stof.ww, fold-4's first consumer; // reused in-package here.) fn u128rshift(lo: u64, hi: u64, s: u32) u64 = { - os.assert(s <= 64u32, "strconv.u128rshift: s > 64"); + assert(s <= 64u32, "strconv.u128rshift: s > 64"); return (hi << (64u64 - (s: u64))) | (lo >> (s: u64)); }; @@ -1476,7 +1468,7 @@ fn pow5fac(v: u64) u32 = { let n_div_5: u64 = 3689348814741910323u64; let count: u32 = 0u32; for (true) { - os.assert(value != 0u64, "strconv.pow5fac: value == 0"); + assert(value != 0u64, "strconv.pow5fac: value == 0"); value *= m_inv_5; if (value > n_div_5) { break; }; count += 1u32; @@ -1495,8 +1487,8 @@ fn pow5multiple(v: u64, p: u32) bool = { return pow5fac(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:69. fn pow2multiple(v: u64, p: u32) bool = { - os.assert(v > 0u64, "strconv.pow2multiple: v == 0"); - os.assert(p < 64u32, "strconv.pow2multiple: p >= 64"); + assert(v > 0u64, "strconv.pow2multiple: v == 0"); + assert(p < 64u32, "strconv.pow2multiple: p >= 64"); return (v & ((1u64 << (p: u64)) - 1u64)) == 0u64; }; @@ -1539,7 +1531,7 @@ fn mulshiftall64(m: u64, mul0: u64, mul1: u64, j: i32, mm_shift: u32) ryuv = { // ref/hare/strconv/ftos_ryu.ha:140. fn log2pow5(e: u32) u32 = { - os.assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); + assert(e <= 3528u32, "strconv.log2pow5: e > 3528"); return (e * 1217359u32) >> 19u32; }; @@ -1549,13 +1541,13 @@ fn pow5bits(e: u32) u32 = { return ceil_log2pow5(e); }; // ref/hare/strconv/ftos_ryu.ha:149. fn log10pow2(e: u32) u32 = { - os.assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); + assert(e <= 1650u32, "strconv.log10pow2: e > 1650"); return (e * 78913u32) >> 18u32; }; // ref/hare/strconv/ftos_ryu.ha:154. fn log10pow5(e: u32) u32 = { - os.assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); + assert(e <= 2620u32, "strconv.log10pow5: e > 2620"); return (e * 732923u32) >> 20u32; }; @@ -1746,15 +1738,15 @@ fn f64todecf64(mantissa: u64, exponent: u32) decf64 = { // u64 siblings at 32-bit width; they reuse the SHARED f64computeinvpow5/ // f64computepow5 (and thus the f64 SPLIT2 tables) per ftos_ryu.ha — there // is no separate f32 table. Same scalar-PARAM-mutation → copy-to-local, -// comma-split, assert → os.assert, expr-yield → block divergences as the -// f64 path above. ==== +// comma-split, expr-yield → block divergences as the f64 path +// above. ==== // ref/hare/strconv/ftos_ryu.ha:52. Largest p with 5^p | value (32-bit). fn pow5fac32(v: u32) u32 = { let value: u32 = v; let count: u32 = 0u32; for (true) { - os.assert(value != 0u32, "strconv.pow5fac32: value == 0"); + assert(value != 0u32, "strconv.pow5fac32: value == 0"); let q: u32 = value / 5u32; let r: u32 = value % 5u32; if (r != 0u32) { break; }; @@ -1769,8 +1761,8 @@ fn pow5multiple32(v: u32, p: u32) bool = { return pow5fac32(v) >= p; }; // ref/hare/strconv/ftos_ryu.ha:75. fn pow2multiple32(v: u32, p: u32) bool = { - os.assert(v > 0u32, "strconv.pow2multiple32: v == 0"); - os.assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); + assert(v > 0u32, "strconv.pow2multiple32: v == 0"); + assert(p < 32u32, "strconv.pow2multiple32: p >= 32"); return (v & ((1u32 << p) - 1u32)) == 0u32; }; @@ -1780,14 +1772,14 @@ fn pow2multiple32(v: u32, p: u32) bool = { // (lib/types/types.ww — no `export`), so Hare's `types::U32_MAX` can't be // referenced cross-package. fn mulshift32(m: u32, a: u64, s: u32) u32 = { - os.assert(s > 32u32, "strconv.mulshift32: s <= 32"); + assert(s > 32u32, "strconv.mulshift32: s <= 32"); let a_lo: u64 = (a: u32): u64; let a_hi: u64 = a >> 32u64; let b0: u64 = (m: u64) * a_lo; let b1: u64 = (m: u64) * a_hi; let sum: u64 = (b0 >> 32u64) + b1; let ss: u64 = sum >> ((s: u64) - 32u64); - os.assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); + assert(ss <= 4294967295u64, "strconv.mulshift32: ss > U32_MAX"); return ss: u32; }; @@ -1936,7 +1928,7 @@ fn f32todecf32(mantissa: u32, exponent: u32) decf32 = { // ref/hare/strconv/ftos.ha:49. Decimal digit-count of n (n <= 1e17). fn declen(n: u64) uint = { - os.assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); + assert(n <= 100000000000000000u64, "strconv.declen: n > 1e17"); if (n >= 100000000000000000u64) { return (18u32: uint); }; if (n >= 10000000000000000u64) { return (17u32: uint); }; if (n >= 1000000000000000u64) { return (16u32: uint); }; @@ -2024,7 +2016,7 @@ fn encode_f_dec(d: *decimal, buf: []u8, out: i32) i32 = { // logic only): no precision zeros, lowercase 'e', no '+'/two-digit pad. fn encode_e_dec(d: *decimal, buf: []u8, out: i32) i32 = { let o: i32 = out; - os.assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); + assert(d.nd > (0u64: size), "strconv.encode_e_dec: nd == 0"); buf[o] = (d.digits[0] + 48u8): u8; o += 1i32; if ((d.nd: i32) > 1i32) { @@ -2497,7 +2489,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; @@ -2512,7 +2504,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; @@ -2580,8 +2572,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; @@ -2597,8 +2589,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; @@ -2752,7 +2744,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; @@ -2790,7 +2782,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; @@ -2859,7 +2851,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; }; @@ -2883,7 +2875,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; }; @@ -3585,7 +3577,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); @@ -3601,8 +3593,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; }; @@ -4030,7 +4022,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; }; @@ -4044,7 +4036,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; }; @@ -4612,8 +4604,6 @@ fn todig(c: u8) u8 = { return 0u8; // unreachable; rt_abort is void-typed (path-cov) }; -@symbol("rt_abort") fn abort(msg: str) void; - // ref/hare/strconv/stof.ha:25. type fast_parsed_float = struct { mantissa: u64, @@ -4795,7 +4785,7 @@ fn decimal_parse(d: *decimal, s: str) (void | invalid) = { // ref/hare/strconv/stof.ha:173. Count of leading zero bits in n>0. fn leading_zeroes(n: u64) uint = { - os.assert(n > 0u64, "strconv.leading_zeroes: n == 0"); + assert(n > 0u64, "strconv.leading_zeroes: n == 0"); let b: u64 = 0u64; if ((n & 0xFFFFFFFF00000000u64) > 0u64) { n >>= 32u64; @@ -5114,7 +5104,7 @@ export fn stof64(s: str, b: base) (f64 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof64: base must be DEC or HEX"); if (s.len == 0) { @@ -5167,7 +5157,7 @@ export fn stof32(s: str, b: base) (f32 | invalid | overflow) = { } else if (bb == base.HEX_LOWER) { bb = base.HEX; }; - os.assert(bb == base.DEC || bb == base.HEX, + assert(bb == base.DEC || bb == base.HEX, "strconv.stof32: base must be DEC or HEX"); if (s.len == 0) { diff --git a/test/wcc/700_e2e.c b/test/wcc/700_e2e.c index 7e8e9e17..d5235343 100644 --- a/test/wcc/700_e2e.c +++ b/test/wcc/700_e2e.c @@ -400,7 +400,7 @@ static const struct row rows[] = { " let p: *point = alloc(point { x = 7, y = 35 })!;\n" " let r: i64 = p.x + p.y;\n" " free(p);\n" - " os.assert(r == 42, \"sum mismatch\\n\");\n" + " assert(r == 42, \"sum mismatch\\n\");\n" " return r: i32;\n" "};", 42 }, /* Hare-style struct embedding: bare-name embed + anonymous diff --git a/test/wcc/900_stdlib.c b/test/wcc/900_stdlib.c index 2617328c..97c2e8eb 100644 --- a/test/wcc/900_stdlib.c +++ b/test/wcc/900_stdlib.c @@ -36,7 +36,7 @@ static const char *modules[] = { * post-Commit B; lib/errors.errno references os.errno / os.E* / * os.strerror (ww folds Hare's sys role into os); lib/strings.iterator * + lib/strings.next reference utf8.decoder / utf8.done; - * lib/bytes.tokenize references os.assert + types.I64_MAX/MIN per + * lib/bytes.tokenize references the assert builtin + types.I64_MAX/MIN per * ref/hare/bytes/tokenize.ha:23-24,42-43; lib/encoding/hex and * lib/encoding/base64 graduated to Hare's io-streaming surface * (hex references io.handle / fmt.fprint / memio.dynamic / strconv /