hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit ebfbd177278350b9bef485063c09b09dc545e3bb
parent 2d00164aec76d18da24bb53f63e1ac868607b433
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri,  5 Feb 2021 12:05:12 -0500

fmt: implement numbered arguments

Diffstat:
Mfmt/fmt.ha | 50+++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 41 insertions(+), 9 deletions(-)

diff --git a/fmt/fmt.ha b/fmt/fmt.ha @@ -9,6 +9,7 @@ // manner: '{0:x} will print a number in hexadecimal. // // TODO: More detail +use ascii; use encoding::utf8; use io; use os; @@ -19,6 +20,14 @@ use types; // Tagged union of all types which are formattable. export type formattable = (...types::numeric | uintptr | str | *void); +// Formats text for printing writes it to [os::stdout]. +export fn printf(fmt: str, args: formattable...) (io::error | size) = + fprintf(os::stdout, fmt, args...); + +// Formats text for printing writes it to [os::stderr]. +export fn errorf(fmt: str, args: formattable...) (io::error | size) = + fprintf(os::stderr, fmt, args...); + // Formats text for printing and writes it to an [io::stream]. export fn fprintf( s: *io::stream, @@ -38,8 +47,18 @@ export fn fprintf( void => abort("Invalid format string (unterminated '{')"), r: rune => r, }; - assert(r == '}'); // TODO - format(s, args[i]); + + let arg = args[i]; + switch (r) { + ':' => abort(), // TODO: format specifiers + '}' => void, + * => { + i -= 1z; + arg = args[scan_uint(r, &iter)]; + }, + }; + + format(s, arg); i += 1z; continue; }; @@ -55,13 +74,26 @@ export fn fprintf( return n; }; -// Formats text for printing writes it to [os::stdout]. -export fn printf(fmt: str, args: formattable...) (io::error | size) = - fprintf(os::stdout, fmt, args...); - -// Formats text for printing writes it to [os::stderr]. -export fn errorf(fmt: str, args: formattable...) (io::error | size) = - fprintf(os::stderr, fmt, args...); +fn scan_uint(r: rune, iter: *strings::iterator) uint = { + assert(ascii::isdigit(r)); + let num = alloc([]u8, [r: u32: u8], 1z); // XXX: alloc slice w/o cap + for (true) { + r = match (strings::next(iter)) { + void => abort("Invalid format string (unterminated '(')"), + r: rune => r, + }; + switch (r) { + * => append(num, r: u32: u8), + ':' => abort(), // TODO: Format specifiers + '}' => match (strconv::stou(strings::from_utf8(num))) { + (strconv::invalid | strconv::overflow) => + abort("Invalid format string (invalid index)"), + u: uint => return u, + }, + }; + }; + abort("unreachable"); +}; fn format(out: *io::stream, arg: formattable) void = match (arg) { s: str => io::write(out, strings::to_utf8(s)),