update to edition 2024 and 1.90-nightly

This commit is contained in:
Janis 2025-07-14 17:52:03 +02:00
parent aeab786fe3
commit bbaa9cb671
6 changed files with 129 additions and 338 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "compiler" name = "compiler"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
ansi_term = "0.12.1" ansi_term = "0.12.1"
@ -16,3 +16,5 @@ paste = "1.0.15"
petgraph = "0.6.5" petgraph = "0.6.5"
thiserror = "1.0.63" thiserror = "1.0.63"
unicode-xid = "0.2.4" unicode-xid = "0.2.4"
werkzeug = { path = "../../rust/werkzeug" }

View file

@ -12,10 +12,7 @@ pub mod bigint {
pub struct BigInt(Vec<u32>); pub struct BigInt(Vec<u32>);
impl BigInt { impl BigInt {
pub fn parse_digits<C: IntoIterator<Item = char>>( pub fn parse_digits<C: IntoIterator<Item = char>>(text: C, radix: Radix) -> BigInt {
text: C,
radix: Radix,
) -> BigInt {
Self(parse_bigint(text.into_iter(), radix)) Self(parse_bigint(text.into_iter(), radix))
} }
pub fn from_u32(v: u32) -> BigInt { pub fn from_u32(v: u32) -> BigInt {
@ -240,13 +237,9 @@ pub mod bigint {
fn sub(mut self, rhs: Self) -> Self::Output { fn sub(mut self, rhs: Self) -> Self::Output {
if self.0.len() < rhs.0.len() { if self.0.len() < rhs.0.len() {
println!( println!("extending self by {} zeroes", rhs.0.len() - self.0.len());
"extending self by {} zeroes", self.0
rhs.0.len() - self.0.len() .extend(core::iter::repeat(0).take(rhs.0.len() - self.0.len()));
);
self.0.extend(
core::iter::repeat(0).take(rhs.0.len() - self.0.len()),
);
println!("self: {self:?}"); println!("self: {self:?}");
} }
sub_bigint(&mut self.0, &rhs.0); sub_bigint(&mut self.0, &rhs.0);
@ -504,10 +497,7 @@ pub mod bigint {
_ => { _ => {
if scalar.is_power_of_two() { if scalar.is_power_of_two() {
lhs.push(0); lhs.push(0);
shl_bitint( shl_bitint(lhs.as_mut_slice(), scalar.trailing_zeros() as usize);
lhs.as_mut_slice(),
scalar.trailing_zeros() as usize,
);
} else { } else {
let mut carry = 0; let mut carry = 0;
for a in lhs.iter_mut() { for a in lhs.iter_mut() {
@ -580,7 +570,7 @@ pub mod bigint {
fn trailing_zeros(lhs: &[u32]) -> usize { fn trailing_zeros(lhs: &[u32]) -> usize {
lhs.iter() lhs.iter()
.enumerate() .enumerate()
.find(|(_, &c)| c != 0) .find(|&(_, &c)| c != 0)
.map(|(i, &c)| i * u32::BITS as usize + c.trailing_zeros() as usize) .map(|(i, &c)| i * u32::BITS as usize + c.trailing_zeros() as usize)
.unwrap_or(0) .unwrap_or(0)
} }
@ -593,10 +583,7 @@ pub mod bigint {
#[allow(dead_code)] #[allow(dead_code)]
/// divident must be at least as wide as divisor /// divident must be at least as wide as divisor
/// returns (quotient, remainder) /// returns (quotient, remainder)
pub fn div_rem_bigint_ref( pub fn div_rem_bigint_ref(divident: &BigInt, divisor: &BigInt) -> (BigInt, BigInt) {
divident: &BigInt,
divisor: &BigInt,
) -> (BigInt, BigInt) {
if bigint_is_zero(&divisor.0) { if bigint_is_zero(&divisor.0) {
panic!("divide by zero!"); panic!("divide by zero!");
} }
@ -614,8 +601,7 @@ pub mod bigint {
if divisor.is_power_of_two() { if divisor.is_power_of_two() {
let exp = divisor.trailing_zeros(); let exp = divisor.trailing_zeros();
let (div, rem) = let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize));
divident.0.split_at(exp.div_floor(u32::BITS as usize));
let (mut div, mut rem) = (div.to_vec(), rem.to_vec()); let (mut div, mut rem) = (div.to_vec(), rem.to_vec());
shr_bitint(&mut div, exp % u32::BITS as usize); shr_bitint(&mut div, exp % u32::BITS as usize);
@ -641,10 +627,7 @@ pub mod bigint {
if shift == 0 { if shift == 0 {
div_rem_core(divident.clone(), &divisor.0) div_rem_core(divident.clone(), &divisor.0)
} else { } else {
let (q, r) = div_rem_core( let (q, r) = div_rem_core(divident.clone() << shift, &(divisor.clone() << shift).0);
divident.clone() << shift,
&(divisor.clone() << shift).0,
);
(q, r >> shift) (q, r >> shift)
} }
@ -653,10 +636,7 @@ pub mod bigint {
#[allow(dead_code)] #[allow(dead_code)]
/// divident must be at least as wide as divisor /// divident must be at least as wide as divisor
/// returns (quotient, remainder) /// returns (quotient, remainder)
pub fn div_rem_bigint( pub fn div_rem_bigint(divident: BigInt, divisor: BigInt) -> (BigInt, BigInt) {
divident: BigInt,
divisor: BigInt,
) -> (BigInt, BigInt) {
let divident = divident.normalised(); let divident = divident.normalised();
let mut divisor = divisor.normalised(); let mut divisor = divisor.normalised();
@ -677,8 +657,7 @@ pub mod bigint {
if divisor.is_power_of_two() { if divisor.is_power_of_two() {
let exp = divisor.trailing_zeros(); let exp = divisor.trailing_zeros();
let (div, rem) = let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize));
divident.0.split_at(exp.div_floor(u32::BITS as usize));
let (mut div, mut rem) = (div.to_vec(), rem.to_vec()); let (mut div, mut rem) = (div.to_vec(), rem.to_vec());
shr_bitint(&mut div, exp % u32::BITS as usize); shr_bitint(&mut div, exp % u32::BITS as usize);
@ -810,9 +789,7 @@ pub mod bigint {
// q0 is too large if: // q0 is too large if:
// [a2,a1,a0] < q0 * [b1,b0] // [a2,a1,a0] < q0 * [b1,b0]
// (r << BITS) + a2 < q0 * b1 // (r << BITS) + a2 < q0 * b1
while r <= u32::MAX as u64 while r <= u32::MAX as u64 && from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 as u64 {
&& from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 as u64
{
q0 -= 1; q0 -= 1;
r += b0 as u64; r += b0 as u64;
} }
@ -1041,10 +1018,7 @@ pub mod bigint {
carry carry
} }
pub fn parse_bigint( pub fn parse_bigint(text: impl Iterator<Item = char>, radix: Radix) -> Vec<u32> {
text: impl Iterator<Item = char>,
radix: Radix,
) -> Vec<u32> {
let digits = text let digits = text
.filter_map(|c| match c { .filter_map(|c| match c {
'_' => None, '_' => None,
@ -1112,20 +1086,14 @@ pub mod bigint {
#[test] #[test]
fn parse() { fn parse() {
let bigint = BigInt::parse_digits( let bigint = BigInt::parse_digits("2_cafe_babe_dead_beef".chars(), Radix::Hex);
"2_cafe_babe_dead_beef".chars(),
Radix::Hex,
);
println!("{:#x?}", bigint); println!("{:#x?}", bigint);
let bigint = BigInt::parse_digits("f".chars(), Radix::Hex); let bigint = BigInt::parse_digits("f".chars(), Radix::Hex);
println!("{:#x?}", bigint); println!("{:#x?}", bigint);
} }
#[test] #[test]
fn add() { fn add() {
let a = BigInt::parse_digits( let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex);
"2_0000_0000_0000_0000".chars(),
Radix::Hex,
);
println!("{:#x?}", a); println!("{:#x?}", a);
let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex); let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex);
println!("{:#x?}", b); println!("{:#x?}", b);
@ -1143,10 +1111,7 @@ pub mod bigint {
} }
#[test] #[test]
fn overflowing_sub() { fn overflowing_sub() {
let a = BigInt::parse_digits( let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex);
"2_0000_0000_0000_0000".chars(),
Radix::Hex,
);
println!("{:#x?}", a); println!("{:#x?}", a);
let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex); let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex);
println!("{:#x?}", b); println!("{:#x?}", b);
@ -1155,8 +1120,7 @@ pub mod bigint {
} }
#[test] #[test]
fn shr() { fn shr() {
let mut a = let mut a = BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex);
BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex);
print!("{:0>8x?} >> 32 ", a); print!("{:0>8x?} >> 32 ", a);
shr_bitint(&mut a.0, 32); shr_bitint(&mut a.0, 32);
println!("{:0>8x?}", a); println!("{:0>8x?}", a);
@ -1188,9 +1152,7 @@ pub mod bigint {
pub mod bigsint { pub mod bigsint {
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
ops::{ ops::{Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign},
Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign,
},
}; };
use super::bigint::{self, *}; use super::bigint::{self, *};
@ -1333,13 +1295,11 @@ pub mod bigsint {
match (self.sign, rhs.sign) { match (self.sign, rhs.sign) {
(_, Sign::None) => self, (_, Sign::None) => self,
(Sign::None, _) => rhs, (Sign::None, _) => rhs,
(Sign::Positive, Sign::Positive) (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => Self {
| (Sign::Negative, Sign::Negative) => Self {
sign: self.sign, sign: self.sign,
bigint: self.bigint + rhs.bigint, bigint: self.bigint + rhs.bigint,
}, },
(Sign::Positive, Sign::Negative) (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
| (Sign::Negative, Sign::Positive) => {
match self.bigint.cmp(&rhs.bigint) { match self.bigint.cmp(&rhs.bigint) {
Ordering::Less => Self { Ordering::Less => Self {
sign: rhs.sign, sign: rhs.sign,
@ -1361,13 +1321,11 @@ pub mod bigsint {
fn add(self, rhs: u32) -> Self::Output { fn add(self, rhs: u32) -> Self::Output {
match self.sign { match self.sign {
Sign::Negative => { Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() {
match self.bigint.partial_cmp(&rhs).unwrap() { Ordering::Less => Self::positive(rhs - self.bigint),
Ordering::Less => Self::positive(rhs - self.bigint), Ordering::Equal => Self::zero(),
Ordering::Equal => Self::zero(), Ordering::Greater => -Self::positive(self.bigint - rhs),
Ordering::Greater => -Self::positive(self.bigint - rhs), },
}
}
Sign::None => Self::from_u32(rhs), Sign::None => Self::from_u32(rhs),
Sign::Positive => Self::positive(self.bigint + rhs), Sign::Positive => Self::positive(self.bigint + rhs),
} }
@ -1379,13 +1337,11 @@ pub mod bigsint {
fn add(self, rhs: u64) -> Self::Output { fn add(self, rhs: u64) -> Self::Output {
match self.sign { match self.sign {
Sign::Negative => { Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() {
match self.bigint.partial_cmp(&rhs).unwrap() { Ordering::Less => Self::positive(rhs - self.bigint),
Ordering::Less => Self::positive(rhs - self.bigint), Ordering::Equal => Self::zero(),
Ordering::Equal => Self::zero(), Ordering::Greater => -Self::positive(self.bigint - rhs),
Ordering::Greater => -Self::positive(self.bigint - rhs), },
}
}
Sign::None => Self::from_u64(rhs), Sign::None => Self::from_u64(rhs),
Sign::Positive => Self::positive(self.bigint + rhs), Sign::Positive => Self::positive(self.bigint + rhs),
} }
@ -1406,13 +1362,11 @@ pub mod bigsint {
match (self.sign, rhs.sign) { match (self.sign, rhs.sign) {
(_, Sign::None) => self, (_, Sign::None) => self,
(Sign::None, _) => -rhs, (Sign::None, _) => -rhs,
(Sign::Positive, Sign::Negative) (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => Self {
| (Sign::Negative, Sign::Positive) => Self {
sign: self.sign, sign: self.sign,
bigint: self.bigint + rhs.bigint, bigint: self.bigint + rhs.bigint,
}, },
(Sign::Positive, Sign::Positive) (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
| (Sign::Negative, Sign::Negative) => {
match self.bigint.cmp(&rhs.bigint) { match self.bigint.cmp(&rhs.bigint) {
Ordering::Less => Self { Ordering::Less => Self {
sign: -self.sign, sign: -self.sign,
@ -1516,11 +1470,7 @@ pub mod bigsint {
bigint: r, bigint: r,
}; };
if rhs.is_negative() { if rhs.is_negative() { (-q, r) } else { (q, r) }
(-q, r)
} else {
(q, r)
}
} }
fn shr_rounding(lhs: &BigSInt, shift: usize) -> bool { fn shr_rounding(lhs: &BigSInt, shift: usize) -> bool {
@ -1548,7 +1498,7 @@ use std::{
}; };
use num_bigint::{BigInt, BigUint, Sign}; use num_bigint::{BigInt, BigUint, Sign};
use num_traits::{cast::ToPrimitive, ToBytes}; use num_traits::{ToBytes, cast::ToPrimitive};
use crate::ast::{FloatingType, IntegralType, Type}; use crate::ast::{FloatingType, IntegralType, Type};
@ -1585,20 +1535,14 @@ impl ComptimeInt {
pub fn add(self, other: Self) -> Result<Self> { pub fn add(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_add(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_add(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a + b; let bits = a + b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1607,9 +1551,7 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a + b)),
Ok(Self::Comptime(a + b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1619,20 +1561,14 @@ impl ComptimeInt {
pub fn sub(self, other: Self) -> Result<Self> { pub fn sub(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_sub(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_sub(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a - b; let bits = a - b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1641,9 +1577,7 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a - b)),
Ok(Self::Comptime(a - b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1653,20 +1587,14 @@ impl ComptimeInt {
pub fn mul(self, other: Self) -> Result<Self> { pub fn mul(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_mul(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_mul(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a * b; let bits = a * b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1675,9 +1603,7 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a * b)),
Ok(Self::Comptime(a * b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1687,20 +1613,14 @@ impl ComptimeInt {
pub fn div(self, other: Self) -> Result<Self> { pub fn div(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_div(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_div(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a / b; let bits = a / b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1709,9 +1629,7 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a / b)),
Ok(Self::Comptime(a / b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1721,20 +1639,14 @@ impl ComptimeInt {
pub fn rem(self, other: Self) -> Result<Self> { pub fn rem(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_rem(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_rem(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a % b; let bits = a % b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1743,9 +1655,7 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a % b)),
Ok(Self::Comptime(a % b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1755,23 +1665,15 @@ impl ComptimeInt {
pub fn bitand(self, other: Self) -> Result<Self> { pub fn bitand(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.bitand(b); let bits = a.bitand(b);
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let bits = a & b; let bits = a & b;
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a & b)),
Ok(Self::Comptime(a & b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1781,23 +1683,15 @@ impl ComptimeInt {
pub fn bitor(self, other: Self) -> Result<Self> { pub fn bitor(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.bitor(b); let bits = a.bitor(b);
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let bits = a | b; let bits = a | b;
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a | b)),
Ok(Self::Comptime(a | b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1807,23 +1701,15 @@ impl ComptimeInt {
pub fn bitxor(self, other: Self) -> Result<Self> { pub fn bitxor(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
( (ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => {
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.bitxor(b); let bits = a.bitxor(b);
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
( (ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let bits = a ^ b; let bits = a ^ b;
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => { (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a ^ b)),
Ok(Self::Comptime(a ^ b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1832,14 +1718,8 @@ impl ComptimeInt {
pub fn cmp(self, other: Self) -> Result<Ordering> { pub fn cmp(self, other: Self) -> Result<Ordering> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
let ord = match (a, b) { let ord = match (a, b) {
( (ComptimeInt::Native { bits: a, .. }, ComptimeInt::Native { bits: b, .. }) => a.cmp(&b),
ComptimeInt::Native { bits: a, .. }, (ComptimeInt::BigInt { bits: a, .. }, ComptimeInt::BigInt { bits: b, .. }) => a.cmp(&b),
ComptimeInt::Native { bits: b, .. },
) => a.cmp(&b),
(
ComptimeInt::BigInt { bits: a, .. },
ComptimeInt::BigInt { bits: b, .. },
) => a.cmp(&b),
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => a.cmp(&b), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => a.cmp(&b),
_ => { _ => {
unreachable!() unreachable!()
@ -1857,13 +1737,11 @@ impl ComptimeInt {
let bits = if ty.signed { let bits = if ty.signed {
(bits as i128) (bits as i128)
.checked_shl(shift) .checked_shl(shift)
.ok_or(Error::IntegerOverflow)? .ok_or(Error::IntegerOverflow)? as u128
as u128
} else { } else {
(bits as u128) (bits as u128)
.checked_shl(shift) .checked_shl(shift)
.ok_or(Error::IntegerOverflow)? .ok_or(Error::IntegerOverflow)? as u128
as u128
} & ty.u128_bitmask(); } & ty.u128_bitmask();
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
@ -1888,13 +1766,11 @@ impl ComptimeInt {
let bits = if ty.signed { let bits = if ty.signed {
(bits as i128) (bits as i128)
.checked_shr(shift) .checked_shr(shift)
.ok_or(Error::IntegerOverflow)? .ok_or(Error::IntegerOverflow)? as u128
as u128
} else { } else {
(bits as u128) (bits as u128)
.checked_shr(shift) .checked_shr(shift)
.ok_or(Error::IntegerOverflow)? .ok_or(Error::IntegerOverflow)? as u128
as u128
}; };
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
@ -1913,9 +1789,7 @@ impl ComptimeInt {
if ty.signed { if ty.signed {
return Err(Error::UnsignedNegation); return Err(Error::UnsignedNegation);
} }
let bits = let bits = (a as i128).checked_neg().ok_or(Error::IntegerOverflow)? as u128;
(a as i128).checked_neg().ok_or(Error::IntegerOverflow)?
as u128;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
@ -1933,9 +1807,7 @@ impl ComptimeInt {
bits: !bits | ty.u128_bitmask(), bits: !bits | ty.u128_bitmask(),
ty, ty,
}), }),
ComptimeInt::BigInt { bits, ty } => { ComptimeInt::BigInt { bits, ty } => Ok(Self::BigInt { bits: !bits, ty }),
Ok(Self::BigInt { bits: !bits, ty })
}
ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)), ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)),
} }
} }
@ -1951,14 +1823,8 @@ impl ComptimeInt {
fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> { fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> {
match (self, other) { match (self, other) {
( (lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::Comptime(b))
lhs @ ComptimeInt::Native { ty: a_ty, .. }, | (lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::BigInt { bits: b, .. }) => {
ComptimeInt::Comptime(b),
)
| (
lhs @ ComptimeInt::Native { ty: a_ty, .. },
ComptimeInt::BigInt { bits: b, .. },
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !a_ty.signed && b_signed { if !a_ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -1975,14 +1841,8 @@ impl ComptimeInt {
}; };
Ok((lhs, Self::Native { bits: b, ty: a_ty })) Ok((lhs, Self::Native { bits: b, ty: a_ty }))
} }
( (ComptimeInt::Comptime(b), rhs @ ComptimeInt::Native { ty: a_ty, .. })
ComptimeInt::Comptime(b), | (ComptimeInt::BigInt { bits: b, .. }, rhs @ ComptimeInt::Native { ty: a_ty, .. }) => {
rhs @ ComptimeInt::Native { ty: a_ty, .. },
)
| (
ComptimeInt::BigInt { bits: b, .. },
rhs @ ComptimeInt::Native { ty: a_ty, .. },
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !a_ty.signed && b_signed { if !a_ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -1999,10 +1859,7 @@ impl ComptimeInt {
}; };
Ok((Self::Native { bits: b, ty: a_ty }, rhs)) Ok((Self::Native { bits: b, ty: a_ty }, rhs))
} }
( (lhs @ ComptimeInt::BigInt { ty, .. }, ComptimeInt::Comptime(b)) => {
lhs @ ComptimeInt::BigInt { ty, .. },
ComptimeInt::Comptime(b),
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !ty.signed && b_signed { if !ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -2014,10 +1871,7 @@ impl ComptimeInt {
} }
Ok((lhs, Self::BigInt { bits: b, ty })) Ok((lhs, Self::BigInt { bits: b, ty }))
} }
( (ComptimeInt::Comptime(b), rhs @ ComptimeInt::BigInt { ty, .. }) => {
ComptimeInt::Comptime(b),
rhs @ ComptimeInt::BigInt { ty, .. },
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !ty.signed && b_signed { if !ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -2029,20 +1883,14 @@ impl ComptimeInt {
} }
Ok((Self::BigInt { bits: b, ty }, rhs)) Ok((Self::BigInt { bits: b, ty }, rhs))
} }
( (lhs @ ComptimeInt::Native { ty: a, .. }, rhs @ ComptimeInt::Native { ty: b, .. }) => {
lhs @ ComptimeInt::Native { ty: a, .. },
rhs @ ComptimeInt::Native { ty: b, .. },
) => {
if a == b { if a == b {
Ok((lhs, rhs)) Ok((lhs, rhs))
} else { } else {
Err(Error::IncompatibleTypes) Err(Error::IncompatibleTypes)
} }
} }
( (lhs @ ComptimeInt::BigInt { ty: a, .. }, rhs @ ComptimeInt::BigInt { ty: b, .. }) => {
lhs @ ComptimeInt::BigInt { ty: a, .. },
rhs @ ComptimeInt::BigInt { ty: b, .. },
) => {
if a == b { if a == b {
Ok((lhs, rhs)) Ok((lhs, rhs))
} else { } else {
@ -2063,56 +1911,36 @@ pub enum ComptimeFloat {
impl ComptimeFloat { impl ComptimeFloat {
pub fn add(self, other: Self) -> Result<ComptimeFloat> { pub fn add(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a + b)),
Ok(Self::Binary32(a + b)) (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a + b)),
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a + b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn sub(self, other: Self) -> Result<ComptimeFloat> { pub fn sub(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a - b)),
Ok(Self::Binary32(a - b)) (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a - b)),
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a - b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn mul(self, other: Self) -> Result<ComptimeFloat> { pub fn mul(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a * b)),
Ok(Self::Binary32(a * b)) (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a * b)),
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a * b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn div(self, other: Self) -> Result<ComptimeFloat> { pub fn div(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a / b)),
Ok(Self::Binary32(a / b)) (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a / b)),
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a / b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn rem(self, other: Self) -> Result<ComptimeFloat> { pub fn rem(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a % b)),
Ok(Self::Binary32(a % b)) (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a % b)),
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a % b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2124,12 +1952,8 @@ impl ComptimeFloat {
} }
pub fn cmp(self, other: Self) -> Result<Ordering> { pub fn cmp(self, other: Self) -> Result<Ordering> {
let ord = match (self, other) { let ord = match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => { (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => a.partial_cmp(&b),
a.partial_cmp(&b) (ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => a.partial_cmp(&b),
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
a.partial_cmp(&b)
}
_ => { _ => {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
} }
@ -2281,9 +2105,7 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.sub(b)?)) // Ok(Self::Floating(a.sub(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitand(b))),
Ok(Self::Bool(a.bitand(b)))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2295,9 +2117,7 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitor(b)?)) // Ok(Self::Floating(a.bitor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitor(b))),
Ok(Self::Bool(a.bitor(b)))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2309,9 +2129,7 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitxor(b)?)) // Ok(Self::Floating(a.bitxor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitxor(b))),
Ok(Self::Bool(a.bitxor(b)))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2347,9 +2165,7 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitxor(b)?)) // Ok(Self::Floating(a.bitxor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a || b)),
Ok(Self::Bool(a || b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2361,35 +2177,23 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitxor(b)?)) // Ok(Self::Floating(a.bitxor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => { (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a && b)),
Ok(Self::Bool(a && b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn eq(self, other: Self) -> Result<Self> { pub fn eq(self, other: Self) -> Result<Self> {
match (self, other) { match (self, other) {
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => { (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => Ok(Self::Bool(a == b)),
Ok(Self::Bool(a == b)) (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => Ok(Self::Bool(a == b)),
} (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a == b)),
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
Ok(Self::Bool(a == b))
}
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a == b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn cmp(self, other: Self) -> Result<Ordering> { pub fn cmp(self, other: Self) -> Result<Ordering> {
let ord = match (self, other) { let ord = match (self, other) {
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => { (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => a.cmp(b)?,
a.cmp(b)? (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => a.cmp(b)?,
}
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
a.cmp(b)?
}
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b),
_ => { _ => {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -2429,17 +2233,12 @@ impl ComptimeNumber {
match self { match self {
ComptimeNumber::Integral(i) => match i { ComptimeNumber::Integral(i) => match i {
ComptimeInt::Native { bits, .. } => Ok((bits != 0).into()), ComptimeInt::Native { bits, .. } => Ok((bits != 0).into()),
ComptimeInt::Comptime(bits) ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
| ComptimeInt::BigInt { bits, .. } => {
Ok((bits.sign() != Sign::NoSign).into()) Ok((bits.sign() != Sign::NoSign).into())
} }
}, },
ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => { ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => Ok((f != 0.0).into()),
Ok((f != 0.0).into()) ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => Ok((f != 0.0).into()),
}
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => {
Ok((f != 0.0).into())
}
a => Ok(a), a => Ok(a),
} }
} }
@ -2447,29 +2246,19 @@ impl ComptimeNumber {
pub fn into_int(self, ty: IntegralType) -> Result<Self> { pub fn into_int(self, ty: IntegralType) -> Result<Self> {
match self { match self {
ComptimeNumber::Integral(i) => match i { ComptimeNumber::Integral(i) => match i {
ComptimeInt::Native { bits, .. } => { ComptimeInt::Native { bits, .. } => Ok((bits & ty.u128_bitmask(), ty).into()),
Ok((bits & ty.u128_bitmask(), ty).into()) ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
} let max = BigUint::from(2u32).pow((ty.bits - ty.signed as u16) as u32);
ComptimeInt::Comptime(bits)
| ComptimeInt::BigInt { bits, .. } => {
let max = BigUint::from(2u32)
.pow((ty.bits - ty.signed as u16) as u32);
let (sign, data) = bits.into_parts(); let (sign, data) = bits.into_parts();
let data = data.clamp(BigUint::ZERO, max); let data = data.clamp(BigUint::ZERO, max);
Ok((BigInt::from_biguint(sign, data), ty).into()) Ok((BigInt::from_biguint(sign, data), ty).into())
} }
}, },
ComptimeNumber::Bool(b) => { ComptimeNumber::Bool(b) => Ok((b as u128 & ty.u128_bitmask(), ty).into()),
Ok((b as u128 & ty.u128_bitmask(), ty).into())
}
ComptimeNumber::Floating(f) => match f { ComptimeNumber::Floating(f) => match f {
ComptimeFloat::Binary32(f) => { ComptimeFloat::Binary32(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()),
Ok((f as u128 & ty.u128_bitmask(), ty).into()) ComptimeFloat::Binary64(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()),
}
ComptimeFloat::Binary64(f) => {
Ok((f as u128 & ty.u128_bitmask(), ty).into())
}
}, },
ComptimeNumber::Void => { ComptimeNumber::Void => {
return Err(Error::VoidConversion); return Err(Error::VoidConversion);
@ -2480,8 +2269,7 @@ impl ComptimeNumber {
let f = match self { let f = match self {
ComptimeNumber::Integral(i) => match i { ComptimeNumber::Integral(i) => match i {
ComptimeInt::Native { bits, .. } => bits as f64, ComptimeInt::Native { bits, .. } => bits as f64,
ComptimeInt::Comptime(bits) ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
| ComptimeInt::BigInt { bits, .. } => {
bits.to_f64().unwrap_or(f64::NAN) bits.to_f64().unwrap_or(f64::NAN)
} }
}, },

View file

@ -8,9 +8,10 @@
int_roundings, int_roundings,
if_let_guard, if_let_guard,
debug_closure_helpers, debug_closure_helpers,
box_vec_non_null,
macro_metavar_expr macro_metavar_expr
)] )]
#![allow(unused_macros)] #![allow(unused_macros, unsafe_op_in_unsafe_fn)]
pub mod asm; pub mod asm;
pub mod ast; pub mod ast;

View file

@ -2,6 +2,7 @@ use itertools::Itertools;
use num_bigint::{BigInt, BigUint}; use num_bigint::{BigInt, BigUint};
use crate::{ use crate::{
BitSize,
ast::{self, FloatingType, IntegralType, LetOrVar, Node, Tag, Type}, ast::{self, FloatingType, IntegralType, LetOrVar, Node, Tag, Type},
ast2::intern::{self, AMD64_POINTER_BITS}, ast2::intern::{self, AMD64_POINTER_BITS},
common::NextIf, common::NextIf,
@ -9,8 +10,7 @@ use crate::{
error::{AnalysisError, AnalysisErrorTag}, error::{AnalysisError, AnalysisErrorTag},
lexer::{Radix, TokenIterator}, lexer::{Radix, TokenIterator},
symbol_table::{SymbolKind, SymbolTable}, symbol_table::{SymbolKind, SymbolTable},
tokens::{Token, PRECEDENCE_MAP}, tokens::{PRECEDENCE_MAP, Token},
BitSize,
}; };
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
@ -1767,10 +1767,10 @@ impl Tree {
} }
pub fn peer_type_of_nodes_unwrap(&self, lhs: Node, rhs: Node) -> Type { pub fn peer_type_of_nodes_unwrap(&self, lhs: Node, rhs: Node) -> Type {
self.peer_type_of_nodes(lhs, rhs).expect({ self.peer_type_of_nodes(lhs, rhs).expect(&{
let at = self.type_of_node(lhs); let at = self.type_of_node(lhs);
let bt = self.type_of_node(rhs); let bt = self.type_of_node(rhs);
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})") format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
}) })
} }
@ -1844,10 +1844,10 @@ impl Tree {
} => { } => {
let ty = match (explicit_type.as_ref(), assignment) { let ty = match (explicit_type.as_ref(), assignment) {
(None, b) => self.type_of_node(*b), (None, b) => self.type_of_node(*b),
(Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({ (Some(a), b) => self.peer_type_of_nodes(*a, *b).expect(&{
let at = self.type_of_node(*a); let at = self.type_of_node(*a);
let bt = self.type_of_node(*b); let bt = self.type_of_node(*b);
&format!("incompatible types for %{a}({at}) and %{b}({bt})") format!("incompatible types for %{a}({at}) and %{b}({bt})")
}), }),
}; };
@ -1863,10 +1863,10 @@ impl Tree {
(None, None) => panic!("%{node}: no type specified?"), (None, None) => panic!("%{node}: no type specified?"),
(None, Some(b)) => self.type_of_node(*b), (None, Some(b)) => self.type_of_node(*b),
(Some(a), None) => self.type_of_node(*a), (Some(a), None) => self.type_of_node(*a),
(Some(a), Some(b)) => self.peer_type_of_nodes(*a, *b).expect({ (Some(a), Some(b)) => self.peer_type_of_nodes(*a, *b).expect(&{
let at = self.type_of_node(*a); let at = self.type_of_node(*a);
let bt = self.type_of_node(*b); let bt = self.type_of_node(*b);
&format!("incompatible types for %{a}({at}) and %{b}({bt})") format!("incompatible types for %{a}({at}) and %{b}({bt})")
}), }),
}; };
@ -1888,10 +1888,10 @@ impl Tree {
| Tag::And { lhs, rhs } | Tag::And { lhs, rhs }
| Tag::BitOr { lhs, rhs } | Tag::BitOr { lhs, rhs }
| Tag::BitAnd { lhs, rhs } | Tag::BitAnd { lhs, rhs }
| Tag::BitXOr { lhs, rhs } => self.peer_type_of_nodes(*lhs, *rhs).expect({ | Tag::BitXOr { lhs, rhs } => self.peer_type_of_nodes(*lhs, *rhs).expect(&{
let at = self.type_of_node(*lhs); let at = self.type_of_node(*lhs);
let bt = self.type_of_node(*rhs); let bt = self.type_of_node(*rhs);
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})") format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
}), }),
Tag::Shl { lhs, .. } => self.type_of_node(*lhs), Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
Tag::Shr { lhs, .. } => self.type_of_node(*lhs), Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
@ -1906,11 +1906,11 @@ impl Tree {
Tag::IfExpr { .. } => Type::void(), Tag::IfExpr { .. } => Type::void(),
Tag::IfElseExpr { Tag::IfElseExpr {
body, else_expr, .. body, else_expr, ..
} => self.peer_type_of_nodes(*body, *else_expr).expect({ } => self.peer_type_of_nodes(*body, *else_expr).expect(&{
let (lhs, rhs) = (body, else_expr); let (lhs, rhs) = (body, else_expr);
let at = self.type_of_node(*lhs); let at = self.type_of_node(*lhs);
let bt = self.type_of_node(*rhs); let bt = self.type_of_node(*rhs);
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})") format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
}), }),
_ => Type::void(), _ => Type::void(),
} }

View file

@ -69,11 +69,11 @@ impl InnerSymbolTable {
Self::new_with(Self::new_inner) Self::new_with(Self::new_inner)
} }
fn new_with<G>(gen: G) -> NonNull<InnerSymbolTable> fn new_with<G>(r#gen: G) -> NonNull<InnerSymbolTable>
where where
G: FnOnce() -> Self, G: FnOnce() -> Self,
{ {
NonNull::new(Box::leak(Box::new(gen())) as *mut _).unwrap() Box::into_non_null(Box::new(r#gen()))
} }
fn new_inner() -> InnerSymbolTable { fn new_inner() -> InnerSymbolTable {
@ -404,8 +404,8 @@ pub mod syms2 {
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::Debug; use std::fmt::Debug;
use crate::ast2::intern::Index as InternIndex;
use crate::ast2::Index as AstIndex; use crate::ast2::Index as AstIndex;
use crate::ast2::intern::Index as InternIndex;
use crate::lexer::SourceLocation; use crate::lexer::SourceLocation;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]

View file

@ -7,7 +7,7 @@ use std::{
use crate::{ use crate::{
ast::{Node as AstNode, Tag, Type}, ast::{Node as AstNode, Tag, Type},
ast2::intern::{self, InternPool, AMD64_POINTER_BITS, AMD64_POINTER_TYPE_INFO}, ast2::intern::{self, AMD64_POINTER_BITS, AMD64_POINTER_TYPE_INFO, InternPool},
parser::Tree, parser::Tree,
variant, write_indented, writeln_indented, variant, write_indented, writeln_indented,
}; };
@ -608,10 +608,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
let ty = self let ty = self
.tree .tree
.peer_type_of_nodes(*lhs, *rhs) .peer_type_of_nodes(*lhs, *rhs)
.expect({ .expect(&{
let at = self.tree.type_of_node(*lhs); let at = self.tree.type_of_node(*lhs);
let bt = self.tree.type_of_node(*rhs); let bt = self.tree.type_of_node(*rhs);
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})") format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
}) })
.into(); .into();