hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git

```commit 9f2a23b73fce3f0175de54939ad59655e9414fca
parent d858829e8243c0ff4d3c5c025553450b24036741
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun, 20 Feb 2022 16:56:38 +0100

math: make absi* functions return an unsigned integer

This allows to avoid abs actually returning a negative integer while also
avoiding overflows.

Signed-off-by: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mmath/ints.ha | 93++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
```
```1 file changed, 54 insertions(+), 39 deletions(-)
diff --git a/math/ints.ha b/math/ints.ha
@@ -1,74 +1,89 @@
use types;

// Returns the absolute value of signed integer n.
-export fn absi8(n: i8) i8 = {
+export fn absi8(n: i8) u8 = {
if (n < 0i8) {
-		return -n;
+		return -n: u8;
} else {
-		return n;
+		return n: u8;
};
};

// Returns the absolute value of signed integer n.
-export fn absi16(n: i16) i16 = {
+export fn absi16(n: i16) u16 = {
if (n < 0i16) {
-		return -n;
+		return -n: u16;
} else {
-		return n;
+		return n: u16;
};
};

// Returns the absolute value of signed integer n.
-export fn absi32(n: i32) i32 = {
+export fn absi32(n: i32) u32 = {
if (n < 0i32) {
-		return -n;
+		return -n: u32;
} else {
-		return n;
+		return n: u32;
};
};

// Returns the absolute value of signed integer n.
-export fn absi64(n: i64) i64 = {
+export fn absi64(n: i64) u64 = {
if (n < 0i64) {
-		return -n;
+		return -n: u64;
} else {
-		return n;
+		return n: u64;
};
};

// Returns the absolute value of signed integer n.
-export fn absi(n: types::integer) i64 = {
+export fn absi(n: types::integer) u64 = {
match (n) {
case let n: i8 =>
-		return (absi8(n): i64);
+		return absi8(n): u64;
case let n: i16 =>
-		return (absi16(n): i64);
+		return absi16(n): u64;
case let n: i32 =>
-		return (absi32(n): i64);
+		return absi32(n): u64;
case let n: i64 =>
-		return (absi64(n): i64);
+		return absi64(n): u64;
case let n: int =>
-		return (absi64(n): i64);
+		return absi64(n): u64;
};
};

@test fn absi() void = {
-	assert(absi8(2i8) == 2i8);
-	assert(absi8(-2i8) == 2i8);
-	assert(absi16(2i16) == 2i16);
-	assert(absi16(-2i16) == 2i16);
-	assert(absi32(2i32) == 2i32);
-	assert(absi32(-2i32) == 2i32);
-	assert(absi64(2i64) == 2i64);
-	assert(absi64(-2i64) == 2i64);
-	assert(absi(2i8) == 2i64);
-	assert(absi(-2i8) == 2i64);
-	assert(absi(2i16) == 2i64);
-	assert(absi(-2i16) == 2i64);
-	assert(absi(2i32) == 2i64);
-	assert(absi(-2i32) == 2i64);
-	assert(absi(2i64) == 2i64);
-	assert(absi(-2i64) == 2i64);
+	// Workaround casting issue where (-types::I8_MIN: u8) has a value not
+	// equal to (-types::I8_MIN: u16)
+	let m8 = (-types::I8_MIN: u8);
+	let m16 = (-types::I16_MIN: u16);
+	let m32 = (-types::I32_MIN: u32);
+	let m64 = (-types::I64_MIN: u64);
+
+	assert(absi8(2i8) == 2u8);
+	assert(absi8(-2i8) == 2u8);
+	assert(absi8(types::I8_MIN) == m8);
+	assert(absi16(2i16) == 2u16);
+	assert(absi16(-2i16) == 2u16);
+	assert(absi16(types::I16_MIN) == m16);
+	assert(absi32(2i32) == 2u32);
+	assert(absi32(-2i32) == 2u32);
+	assert(absi32(types::I32_MIN) == m32);
+	assert(absi64(2i64) == 2u64);
+	assert(absi64(-2i64) == 2u64);
+	assert(absi64(types::I64_MIN) == m64);
+	assert(absi(2i8) == 2u64);
+	assert(absi(-2i8) == 2u64);
+	assert(absi(types::I8_MIN) == (m8: u64));
+	assert(absi(2i16) == 2u64);
+	assert(absi(-2i16) == 2u64);
+	assert(absi(types::I16_MIN) == (m16: u64));
+	assert(absi(2i32) == 2u64);
+	assert(absi(-2i32) == 2u64);
+	assert(absi(types::I32_MIN) == (m32: u64));
+	assert(absi(2i64) == 2u64);
+	assert(absi(-2i64) == 2u64);
+	assert(absi(types::I64_MIN) == (m64: u64));
};

// Return 1 if n is positive, -1 if it's negative and 0 if it's 0.
@@ -119,15 +134,15 @@ export fn signi64(n: i64) i64 = {
export fn signi(n: types::integer) i64 = {
match (n) {
case let n: i8 =>
-		return (signi8(n): i64);
+		return signi8(n): i64;
case let n: i16 =>
-		return (signi16(n): i64);
+		return signi16(n): i64;
case let n: i32 =>
-		return (signi32(n): i64);
+		return signi32(n): i64;
case let n: i64 =>
-		return (signi64(n): i64);
+		return signi64(n): i64;
case let n: int =>
-		return (signi64(n): i64);
+		return signi64(n): i64;
};
};

```