~sircmpwn/hare-dev

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
5 4

[RFC PATCH hare] Correctly convert strconv::base::DEC -> 10

Details
Message ID
<20230602173559.8522-1-yyp@disroot.org>
DKIM signature
pass
Download raw message
Patch: +41 -34
Signed-off-by: Alexey Yerin <yyp@disroot.org>
---
 hare/lex/lex.ha | 25 ++++++++++++++-----------
 strconv/itos.ha |  4 ++++
 strconv/stoi.ha | 13 ++++++++-----
 strconv/stou.ha | 33 +++++++++++++++------------------
 4 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha
index acf8925a..4b10cd6e 100644
--- a/hare/lex/lex.ha
+++ b/hare/lex/lex.ha
@@ -410,7 +410,7 @@ fn lex_literal(lex: *lexer) (token | error) = {
	};

	let started = false;
	let base = 10u;
	let base = strconv::base::DEC;
	if (r.0 == '0') {
		append(chars, utf8::encoderune(r.0)...);
		r = match (next(lex)?) {
@@ -421,11 +421,11 @@ fn lex_literal(lex: *lexer) (token | error) = {
		};
		switch (r.0) {
		case 'b' =>
			base = 2;
			base = strconv::base::BIN;
		case 'o' =>
			base = 8;
			base = strconv::base::OCT;
		case 'x' =>
			base = 16;
			base = strconv::base::HEX;
		case =>
			if (ascii::isdigit(r.0)) {
				return syntaxerr(loc,
@@ -436,13 +436,13 @@ fn lex_literal(lex: *lexer) (token | error) = {
		};
	} else unget(lex, r);
	let basechrs = switch (base) {
	case 2 =>
	case strconv::base::BIN =>
		yield "01";
	case 8 =>
	case strconv::base::OCT =>
		yield "01234567";
	case 10 =>
	case strconv::base::DEC =>
		yield "0123456789";
	case 16 =>
	case strconv::base::HEX =>
		yield "0123456789ABCDEFabcdef";
	};

@@ -464,7 +464,8 @@ fn lex_literal(lex: *lexer) (token | error) = {
					"Expected integer literal");
			};
			if (float || exp is size || suff is size
					|| base != 10 || lex.require_int) {
					|| base != strconv::base::DEC
					|| lex.require_int) {
				unget(lex, r);
				break;
			} else {
@@ -492,7 +493,8 @@ fn lex_literal(lex: *lexer) (token | error) = {
				return syntaxerr(loc,
					"Expected integer literal");
			};
			if (exp is size || suff is size || base != 10) {
			if (exp is size || suff is size
					|| base != strconv::base::DEC) {
				unget(lex, r);
				break;
			} else {
@@ -519,7 +521,8 @@ fn lex_literal(lex: *lexer) (token | error) = {
					"Expected integer literal");
			};
			if (suff is size || r.0 != 'f' && float
					|| r.0 == 'f' && base != 10) {
					|| r.0 == 'f'
					&& base != strconv::base::DEC) {
				unget(lex, r);
				break;
			} else {
diff --git a/strconv/itos.ha b/strconv/itos.ha
index b4db8565..8ce80640 100644
--- a/strconv/itos.ha
+++ b/strconv/itos.ha
@@ -11,6 +11,10 @@ use strings;
// duplicate the result.
export fn i64tosb(i: i64, b: base) const str = {
	static assert(types::I64_MAX == 9223372036854775807);
	if (b == base::DEC) {
		b = 10;
	};

	if (i >= 0) return u64tosb(i: u64, b);

	static let buf: [65]u8 = [0...]; // 64 binary digits plus -
diff --git a/strconv/stoi.ha b/strconv/stoi.ha
index 9dc0334c..72732343 100644
--- a/strconv/stoi.ha
+++ b/strconv/stoi.ha
@@ -10,7 +10,7 @@ use strings;
// non-numeric characters, except '-' or '+' at the start, or if it's empty,
// [[invalid]] is returned. If the number is too large to be represented by an
// i64, [[overflow]] is returned.
export fn stoi64b(s: str, base: uint) (i64 | invalid | overflow) = {
export fn stoi64b(s: str, base: base) (i64 | invalid | overflow) = {
	if (len(s) == 0) return 0: invalid;
	let b = strings::toutf8(s);
	let sign = 1i64;
@@ -23,6 +23,9 @@ export fn stoi64b(s: str, base: uint) (i64 | invalid | overflow) = {
	} else if (b[0] == '+') {
		start = 1;
	};
	if (base == base::DEC) {
		base = 10;
	};
	let u = stou64b(strings::fromutf8_unsafe(b[start..]), base);
	let n = u?;
	if (n > max) {
@@ -35,7 +38,7 @@ export fn stoi64b(s: str, base: uint) (i64 | invalid | overflow) = {
// non-numeric characters, except '-' or '+' at the start, or if it's empty,
// [[invalid]] is returned. If the number is too large to be represented by an
// i32, [[overflow]] is returned.
export fn stoi32b(s: str, base: uint) (i32 | invalid | overflow) = {
export fn stoi32b(s: str, base: base) (i32 | invalid | overflow) = {
	let n = stoi64b(s, base)?;
	if (n >= types::I32_MIN: i64 && n <= types::I32_MAX: i64) {
		return n: i32;
@@ -47,7 +50,7 @@ export fn stoi32b(s: str, base: uint) (i32 | invalid | overflow) = {
// non-numeric characters, except '-' or '+' at the start, or if it's empty,
// [[invalid]] is returned. If the number is too large to be represented by an
// i16, [[overflow]] is returned.
export fn stoi16b(s: str, base: uint) (i16 | invalid | overflow) = {
export fn stoi16b(s: str, base: base) (i16 | invalid | overflow) = {
	let n = stoi64b(s, base)?;
	if (n >= types::I16_MIN: i64 && n <= types::I16_MAX: i64) {
		return n: i16;
@@ -59,7 +62,7 @@ export fn stoi16b(s: str, base: uint) (i16 | invalid | overflow) = {
// non-numeric characters, except '-' or '+' at the start, or if it's empty,
// [[invalid]] is returned. If the number is too large to be represented by an
// i8, [[overflow]] is returned.
export fn stoi8b(s: str, base: uint) (i8 | invalid | overflow) = {
export fn stoi8b(s: str, base: base) (i8 | invalid | overflow) = {
	let n= stoi64b(s, base)?;
	if (n >= types::I8_MIN: i64 && n <= types::I8_MAX: i64) {
		return n: i8;
@@ -71,7 +74,7 @@ export fn stoi8b(s: str, base: uint) (i8 | invalid | overflow) = {
// non-numeric characters, except '-' or '+' at the start, or if it's empty,
// [[invalid]] is returned. If the number is too large to be represented by an
// int, [[overflow]] is returned.
export fn stoib(s: str, base: uint) (int | invalid | overflow) = {
export fn stoib(s: str, base: base) (int | invalid | overflow) = {
	static assert(size(int) == size(i32) || size(int) == size(i64));
	return
		if (size(int) == size(i32)) stoi32b(s, base)?: int
diff --git a/strconv/stou.ha b/strconv/stou.ha
index 71025b03..5db9c55f 100644
--- a/strconv/stou.ha
+++ b/strconv/stou.ha
@@ -19,8 +19,10 @@ fn rune_to_integer(r: rune) (u64 | void) = {
// Converts a string to a u64 in the given base, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u64, [[overflow]] is returned.
// Supported bases are 2, 8, 10 and 16.
export fn stou64b(s: str, base: uint) (u64 | invalid | overflow) = {
export fn stou64b(s: str, base: base) (u64 | invalid | overflow) = {
	if (base == base::DEC) {
		base = 10;
	};
	assert(base == 2 || base == 8 || base == 10 || base == 16);

	if (len(s) == 0) {
@@ -63,8 +65,7 @@ export fn stou64b(s: str, base: uint) (u64 | invalid | overflow) = {
// Converts a string to a u32 in the given base, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u32, [[overflow]] is returned.
// Supported bases are 2, 8, 10 and 16.
export fn stou32b(s: str, base: uint) (u32 | invalid | overflow) = {
export fn stou32b(s: str, base: base) (u32 | invalid | overflow) = {
	let n = stou64b(s, base)?;
	if (n <= types::U32_MAX: u64) {
		return n: u32;
@@ -75,8 +76,7 @@ export fn stou32b(s: str, base: uint) (u32 | invalid | overflow) = {
// Converts a string to a u16 in the given base, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u16, [[overflow]] is returned.
// Supported bases are 2, 8, 10 and 16.
export fn stou16b(s: str, base: uint) (u16 | invalid | overflow) = {
export fn stou16b(s: str, base: base) (u16 | invalid | overflow) = {
	let n = stou64b(s, base)?;
	if (n <= types::U16_MAX: u64) {
		return n: u16;
@@ -87,8 +87,7 @@ export fn stou16b(s: str, base: uint) (u16 | invalid | overflow) = {
// Converts a string to a u8 in the given base, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u8, [[overflow]] is returned.
// Supported bases are 2, 8, 10 and 16.
export fn stou8b(s: str, base: uint) (u8 | invalid | overflow) = {
export fn stou8b(s: str, base: base) (u8 | invalid | overflow) = {
	let n = stou64b(s, base)?;
	if (n <= types::U8_MAX: u64) {
		return n: u8;
@@ -99,8 +98,7 @@ export fn stou8b(s: str, base: uint) (u8 | invalid | overflow) = {
// Converts a string to a uint in the given base, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a uint, [[overflow]] is returned.
// Supported bases are 2, 8, 10 and 16.
export fn stoub(s: str, base: uint) (uint | invalid | overflow) = {
export fn stoub(s: str, base: base) (uint | invalid | overflow) = {
	static assert(size(uint) == size(u32) || size(uint) == size(u64));
	return
		if (size(uint) == size(u32)) stou32b(s, base)?: uint
@@ -110,8 +108,7 @@ export fn stoub(s: str, base: uint) (uint | invalid | overflow) = {
// Converts a string to a size in the given base, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a size, [[overflow]] is returned.
// Supported bases are 2, 8, 10 and 16.
export fn stozb(s: str, base: uint) (size | invalid | overflow) = {
export fn stozb(s: str, base: base) (size | invalid | overflow) = {
	static assert(size(size) == size(u32) || size(size) == size(u64));
	if (size(size) == size(u32)) {
		match (stou32b(s, base)) {
@@ -133,29 +130,29 @@ export fn stozb(s: str, base: uint) (size | invalid | overflow) = {
// Converts a string to a u64 in base 10, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u64, [[overflow]] is returned.
export fn stou64(s: str) (u64 | invalid | overflow) = stou64b(s, 10);
export fn stou64(s: str) (u64 | invalid | overflow) = stou64b(s, base::DEC);

// Converts a string to a u32 in base 10, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u32, [[overflow]] is returned.
export fn stou32(s: str) (u32 | invalid | overflow) = stou32b(s, 10);
export fn stou32(s: str) (u32 | invalid | overflow) = stou32b(s, base::DEC);

// Converts a string to a u16 in base 10, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u16, [[overflow]] is returned.
export fn stou16(s: str) (u16 | invalid | overflow) = stou16b(s, 10);
export fn stou16(s: str) (u16 | invalid | overflow) = stou16b(s, base::DEC);

// Converts a string to a u8 in base 10, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a u8, [[overflow]] is returned.
export fn stou8(s: str) (u8 | invalid | overflow) = stou8b(s, 10);
export fn stou8(s: str) (u8 | invalid | overflow) = stou8b(s, base::DEC);

// Converts a string to a uint in base 10, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a uint, [[overflow]] is returned.
export fn stou(s: str) (uint | invalid | overflow) = stoub(s, 10);
export fn stou(s: str) (uint | invalid | overflow) = stoub(s, base::DEC);

// Converts a string to a size in base 10, If the string contains any
// non-numeric characters, or if it's empty, [[invalid]] is returned. If the
// number is too large to be represented by a size, [[overflow]] is returned.
export fn stoz(s: str) (size | invalid | overflow) = stozb(s, 10);
export fn stoz(s: str) (size | invalid | overflow) = stozb(s, base::DEC);
-- 
2.41.0

[hare/patches] build success

builds.sr.ht <builds@sr.ht>
Details
Message ID
<CT2CIJF20FHE.1LEN8P4YJZG9P@cirno2>
In-Reply-To
<20230602173559.8522-1-yyp@disroot.org> (view parent)
DKIM signature
missing
Download raw message
hare/patches: SUCCESS in 1m39s

[Correctly convert strconv::base::DEC -> 10][0] from [Alexey Yerin][1]

[0]: https://lists.sr.ht/~sircmpwn/hare-dev/patches/41597
[1]: yyp@disroot.org

✓ #1000299 SUCCESS hare/patches/freebsd.yml https://builds.sr.ht/~sircmpwn/job/1000299
✓ #1000298 SUCCESS hare/patches/alpine.yml  https://builds.sr.ht/~sircmpwn/job/1000298
Details
Message ID
<CT7SLDXLEIGI.1J1RFNB7LLF51@monch>
In-Reply-To
<20230602173559.8522-1-yyp@disroot.org> (view parent)
DKIM signature
pass
Download raw message
would prefer to do this properly, generalizing strconv to arbitrary
(<= 36) bases, with 1-36 being lowercase for output and case-insensitive
for input, 37-62 being lowercase for both input and output, and 63-88
being uppercase for both input and output. should also stick a TODO on
base for @default(base::DEC) + base::DEC = 10
Details
Message ID
<CT7ZC6N3SDV4.1IWF7I67WVPPU@notmylaptop>
In-Reply-To
<CT7SLDXLEIGI.1J1RFNB7LLF51@monch> (view parent)
DKIM signature
pass
Download raw message
On Thu Jun 8, 2023 at 11:17 PM EDT, Ember Sawady wrote:
> would prefer to do this properly, generalizing strconv to arbitrary
> (<= 36) bases, with 1-36 being lowercase for output and case-insensitive
> for input, 37-62 being lowercase for both input and output, and 63-88
> being uppercase for both input and output. should also stick a TODO on
> base for @default(base::DEC) + base::DEC = 10

I think this should still be merged, since as of now lots of things are
just broken. We can still do all of this later, but I don't see anything
wrong with this patch, since it just fixes stuff that was regressed when
strconv::base was changed.
Details
Message ID
<CTDKQAKQ4DZ1.O4HXII56XBM7@monch>
In-Reply-To
<20230602173559.8522-1-yyp@disroot.org> (view parent)
DKIM signature
pass
Download raw message
seb convinced me that merging this is the right thing to do, is there a
reason this is marked as rfc?
Details
Message ID
<CU1QXXGYTUWZ.2MLEP12AJU8ST@taiga>
In-Reply-To
<20230602173559.8522-1-yyp@disroot.org> (view parent)
DKIM signature
pass
Download raw message
Going ahead and taking this patch. Thanks!

To git@git.sr.ht:~sircmpwn/hare
   cd735b6b..6f9b6114  master -> master
Reply to thread Export thread (mbox)