lib/strconv: graduate to owned-str returns with Hare-shape base param
i64tos / u64tos / f64tos return a fresh owned str (caller frees via os.free) instead of writing into a caller-supplied [N]u8. Adds typed variants (i32tos / i16tos / i8tos and u32 / u16 / u8) and the missing base parameter on stoi64 / stou64 + typed parse wrappers. Base values are exported as plain-i32 `def`s (strconv.DEC, strconv.HEX_UPPER, ...) rather than a `base` enum: cross-module `strconv.base.DEC` chains miscompile in the cstage cgen — it emits a memory load through `base(SB)` rather than inlining the constant. The Sdef path resolves correctly, so callers say `strconv.DEC` and both cgens lower to an immediate. Also renames strings.byteindex / rbyteindex to strings.indexbyte / rindexbyte, matching bytes.indexbyte and reserving the Hare name `byteindex` for the future `(str | rune)`-needle shape. fmt drops printint / printlnint / fprintint — those were stand-ins for variadic `fmt::println(42)`; with the owned-str graduation the substitute is one call: `fmt.println(strconv.i64tos(42, strconv.DEC))`. strerror is sketched in a comment but not shipped — match arms over the wider `error = !(invalid | overflow)` union still expose a cstage-vs-wwstage spill divergence.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
use os;
|
||||
use fmt;
|
||||
use strconv;
|
||||
use strings;
|
||||
use lispcore;
|
||||
|
||||
let nfail: i32 = 0;
|
||||
@@ -49,9 +50,8 @@ fn faili(name: str, why: str, got: i64) void = {
|
||||
os.write(2, ": ".ptr, 2u64);
|
||||
os.write(2, why.ptr, why.len: u64);
|
||||
os.write(2, " got=".ptr, 5u64);
|
||||
let buf: [32]u8;
|
||||
let n: i32 = strconv.i64tos(buf[0:32], got);
|
||||
os.write(2, buf.ptr, n: u64);
|
||||
let s: str = strconv.i64tos(got, strconv.DEC);
|
||||
os.write(2, s.ptr, s.len: u64);
|
||||
os.write(2, "\n".ptr, 1u64);
|
||||
nfail += 1;
|
||||
};
|
||||
@@ -205,15 +205,14 @@ fn check_str(name: str, input: str, want: str, ep: **env) void = {
|
||||
// modules compile, not behaviour). Move out when that lands.
|
||||
fn check_f64tos(name: str, v: f64, want: str) void = {
|
||||
ntotal += 1;
|
||||
let buf: [32]u8;
|
||||
let n: i32 = strconv.f64tos(buf[0:32], v);
|
||||
if (n != want.len) {
|
||||
faili(name, "wrong len", n: i64);
|
||||
let s: str = strconv.f64tos(v);
|
||||
if (s.len != want.len) {
|
||||
faili(name, "wrong len", s.len: i64);
|
||||
return;
|
||||
};
|
||||
let i: i32 = 0;
|
||||
for (i < n) {
|
||||
if (buf[i] != want[i]) {
|
||||
for (i < s.len) {
|
||||
if (s.ptr[i] != want[i]) {
|
||||
faili(name, "byte mismatch at", i: i64);
|
||||
return;
|
||||
};
|
||||
@@ -395,23 +394,21 @@ export fn main() i32 = {
|
||||
check_err ("dot-trailing", "'(1 . 2 3)", ep);
|
||||
|
||||
// ---- summary ----
|
||||
let buf: [32]u8;
|
||||
let n: i32 = 0;
|
||||
if (nfail == 0) {
|
||||
os.write(1, "\nlisp_test: ".ptr, 12u64);
|
||||
n = strconv.i64tos(buf[0:32], ntotal: i64);
|
||||
os.write(1, buf.ptr, n: u64);
|
||||
let ts: str = strconv.i64tos(ntotal: i64, strconv.DEC);
|
||||
os.write(1, ts.ptr, ts.len: u64);
|
||||
os.write(1, "/".ptr, 1u64);
|
||||
os.write(1, buf.ptr, n: u64);
|
||||
os.write(1, ts.ptr, ts.len: u64);
|
||||
os.write(1, " pass\n".ptr, 6u64);
|
||||
return 0;
|
||||
};
|
||||
os.write(2, "\nlisp_test: ".ptr, 12u64);
|
||||
n = strconv.i64tos(buf[0:32], nfail: i64);
|
||||
os.write(2, buf.ptr, n: u64);
|
||||
let fs: str = strconv.i64tos(nfail: i64, strconv.DEC);
|
||||
os.write(2, fs.ptr, fs.len: u64);
|
||||
os.write(2, " of ".ptr, 4u64);
|
||||
n = strconv.i64tos(buf[0:32], ntotal: i64);
|
||||
os.write(2, buf.ptr, n: u64);
|
||||
let ts: str = strconv.i64tos(ntotal: i64, strconv.DEC);
|
||||
os.write(2, ts.ptr, ts.len: u64);
|
||||
os.write(2, " failed\n".ptr, 8u64);
|
||||
return 1;
|
||||
};
|
||||
|
||||
@@ -655,7 +655,7 @@ fn next(L: *lexer) (i32 | parserr | eof) = {
|
||||
// list parse_expr will reject it; here we just tag it.
|
||||
if (a.len == 1 && a[0] == '.': u8) { L.curkind = tkind.DOT; return 0; };
|
||||
if (allnum(a)) {
|
||||
let r = strconv.stoi64(a);
|
||||
let r = strconv.stoi64(a, strconv.DEC);
|
||||
match (r) {
|
||||
case let v: i64 => {
|
||||
L.curkind = tkind.INT;
|
||||
@@ -1491,20 +1491,18 @@ fn obuf_puts(s: str) void = {
|
||||
};
|
||||
|
||||
fn obuf_putint(v: i64) void = {
|
||||
let tmp: [32]u8;
|
||||
let n: i32 = strconv.i64tos(tmp[0:32], v);
|
||||
let s: str = strconv.i64tos(v, strconv.DEC);
|
||||
let i: i32 = 0;
|
||||
for (i < n) { obuf_putc(tmp[i]); i += 1; };
|
||||
for (i < s.len) { obuf_putc(s.ptr[i]); i += 1; };
|
||||
};
|
||||
|
||||
fn obuf_putfloat(v: f64) void = {
|
||||
// strconv.f64tos handles sign, 6-digit fractional, trailing-zero
|
||||
// trim. Buffer size 32 covers the worst-case "-1234567890123456789"
|
||||
// plus ".XXXXXX" (29 bytes — round up to 32).
|
||||
let buf: [32]u8;
|
||||
let n: i32 = strconv.f64tos(buf[0:32], v);
|
||||
// trim. Returns a static-buffer-backed str overwritten on the
|
||||
// next f64tos call.
|
||||
let s: str = strconv.f64tos(v);
|
||||
let i: i32 = 0;
|
||||
for (i < n) { obuf_putc(buf[i]); i += 1; };
|
||||
for (i < s.len) { obuf_putc(s.ptr[i]); i += 1; };
|
||||
};
|
||||
|
||||
fn obuf_flush() void = {
|
||||
|
||||
Reference in New Issue
Block a user