mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-24 23:46:32 +01:00
the math does math... at compile time, in types
This commit is contained in:
@@ -51,13 +51,13 @@ impl Function {
|
||||
}
|
||||
}
|
||||
pub fn new_generic(
|
||||
out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
|
||||
out: impl Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync + 'static,
|
||||
run: impl Fn(Data, &mut Info) -> Result<Data, CheckError> + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
info: crate::info::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
|
||||
out: Ok(Arc::new(move |a, _| out(a))),
|
||||
out: Ok(Arc::new(move |a, i| out(a, i))),
|
||||
run: Arc::new(run),
|
||||
inner_statements: None,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,43 @@ use crate::info::DisplayInfo;
|
||||
|
||||
use super::{MersData, MersType, Type};
|
||||
|
||||
/// The smallest representable integer.
|
||||
/// Depends on the system for which mers is being compiled, as mers uses pointer-sized signed integers.
|
||||
/// `-2^W`, `W` is the bit-width of a pointer on the system, often `32` or `64`.
|
||||
pub const INT_MIN: isize = isize::MIN;
|
||||
/// The largest representable integer.
|
||||
/// Depends on the system for which mers is being compiled, as mers uses pointer-sized signed integers.
|
||||
/// `2^W-1`, `W` is the bit-width of a pointer on the system, often `32` or `64`.
|
||||
pub const INT_MAX: isize = isize::MAX;
|
||||
/// The smallest integer representable by mers and by a signed 32-bit number.
|
||||
/// `max(INT_MIN, -2^31)`
|
||||
pub const INT32S_MIN: isize = if isize::BITS > i32::BITS {
|
||||
i32::MIN as isize
|
||||
} else {
|
||||
isize::MIN
|
||||
};
|
||||
/// The largest integer representable by mers and by a signed 32-bit number.
|
||||
/// `min(INT_MAX, 2^31-1)`
|
||||
pub const INT32S_MAX: isize = if isize::BITS > i32::BITS {
|
||||
i32::MAX as isize
|
||||
} else {
|
||||
isize::MAX
|
||||
};
|
||||
/// The smallest integer representable by mers and by an unsigned 32-bit number, assuming its value was negative.
|
||||
/// `max(INT_MIN, -(2^32-1))`
|
||||
pub const INT32U_MIN: isize = if isize::BITS > u32::BITS {
|
||||
-(u32::MAX as isize)
|
||||
} else {
|
||||
isize::MIN
|
||||
};
|
||||
/// The largest integer representable by mers and by an unsigned 32-bit number.
|
||||
/// `min(INT_MAX, 2^32-1)`
|
||||
pub const INT32U_MAX: isize = if isize::BITS > u32::BITS {
|
||||
u32::MAX as isize
|
||||
} else {
|
||||
isize::MAX
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Int(pub isize);
|
||||
|
||||
@@ -22,7 +59,7 @@ impl MersData for Int {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_type(&self) -> super::Type {
|
||||
Type::new(IntT)
|
||||
Type::new(IntT(self.0, self.0))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@@ -35,8 +72,8 @@ impl MersData for Int {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IntT;
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IntT(pub isize, pub isize);
|
||||
impl MersType for IntT {
|
||||
fn display(
|
||||
&self,
|
||||
@@ -46,13 +83,35 @@ impl MersType for IntT {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
self == other
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
if let Some(target) = target.as_any().downcast_ref::<Self>() {
|
||||
target.0 <= self.0 && self.1 <= target.1
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
// INT_MIN .. INT32U_MIN .. INT32S_MIN .. 0 .. INT32S_MAX .. INT32U_MAX .. INT_MAX
|
||||
let mut add_range = |min, max| {
|
||||
// the range is non-empty, self starts before or where the range ends, and self ends after or where the range starts.
|
||||
if min <= max && self.0 <= max && self.1 >= min {
|
||||
acc.add(Arc::new(IntT(self.0.max(min), self.1.min(max))));
|
||||
}
|
||||
};
|
||||
add_range(INT_MIN, INT32U_MIN - 1);
|
||||
add_range(INT32U_MIN, INT32S_MIN - 1);
|
||||
add_range(INT32S_MIN, -1);
|
||||
add_range(0, 0);
|
||||
add_range(1, INT32S_MAX);
|
||||
add_range(INT32S_MAX + 1, INT32U_MAX);
|
||||
add_range(INT32U_MAX + 1, INT_MAX);
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@@ -72,6 +131,12 @@ impl Display for Int {
|
||||
}
|
||||
impl Display for IntT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Int")
|
||||
match (self.0, self.1) {
|
||||
(isize::MIN, isize::MAX) => write!(f, "Int"),
|
||||
(val, val2) if val == val2 => write!(f, "Int<{val}>"),
|
||||
(min, isize::MAX) => write!(f, "Int<{min}..>"),
|
||||
(isize::MIN, max) => write!(f, "Int<..{max}>"),
|
||||
(min, max) => write!(f, "Int<{min}..{max}>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,6 +413,39 @@ impl Type {
|
||||
let n = new.as_any();
|
||||
if let Some(s) = n.downcast_ref::<Self>() {
|
||||
self.add_all(s);
|
||||
} else if let Some(n) = n.downcast_ref::<crate::data::int::IntT>() {
|
||||
let n = n.clone();
|
||||
let mut newt = None;
|
||||
for a in &self.types {
|
||||
if let Some(t) = a.as_any().downcast_ref::<crate::data::int::IntT>() {
|
||||
if t.0 <= n.0 && n.1 <= t.1 {
|
||||
// we are included in this type
|
||||
return;
|
||||
}
|
||||
if t.0 <= n.1.saturating_add(1) && n.0.saturating_sub(1) <= t.1 {
|
||||
// this type will be added instead of the original `new`, and `t` will be removed from `self.types`.
|
||||
newt = Some(crate::data::int::IntT(t.0.min(n.0), t.1.max(n.1)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let newt2 = newt.is_some();
|
||||
// remove types that are included in `self` before adding `self`
|
||||
let newt = newt.unwrap_or(n);
|
||||
let mut rmstack = vec![];
|
||||
for (i, a) in self.types.iter().enumerate() {
|
||||
if let Some(t) = a.as_any().downcast_ref::<crate::data::int::IntT>() {
|
||||
if newt.0 <= t.0 && t.1 <= newt.1 {
|
||||
rmstack.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for i in rmstack.into_iter().rev() {
|
||||
self.types.remove(i);
|
||||
}
|
||||
if !newt2 {
|
||||
self.types.push(new);
|
||||
}
|
||||
} else {
|
||||
if !self.types.iter().any(|t| new.is_included_in(t.as_ref())) {
|
||||
self.types.push(new);
|
||||
|
||||
Reference in New Issue
Block a user