mirror of
				https://github.com/Dummi26/mers.git
				synced 2025-11-04 05:16:17 +01:00 
			
		
		
		
	the math does math... at compile time, in types
This commit is contained in:
		
							parent
							
								
									c357e192a0
								
							
						
					
					
						commit
						754dd5df40
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "mers"
 | 
					name = "mers"
 | 
				
			||||||
version = "0.9.3"
 | 
					version = "0.9.4"
 | 
				
			||||||
edition = "2021"
 | 
					edition = "2021"
 | 
				
			||||||
license = "MIT OR Apache-2.0"
 | 
					license = "MIT OR Apache-2.0"
 | 
				
			||||||
description = "dynamically typed but type-checked programming language"
 | 
					description = "dynamically typed but type-checked programming language"
 | 
				
			||||||
@ -15,7 +15,7 @@ default = ["colored-output"]
 | 
				
			|||||||
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
 | 
					colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
mers_lib = "0.9.3"
 | 
					mers_lib = "0.9.4"
 | 
				
			||||||
# mers_lib = { path = "../mers_lib" }
 | 
					# mers_lib = { path = "../mers_lib" }
 | 
				
			||||||
clap = { version = "4.3.19", features = ["derive"] }
 | 
					clap = { version = "4.3.19", features = ["derive"] }
 | 
				
			||||||
colored = { version = "2.1.0", optional = true }
 | 
					colored = { version = "2.1.0", optional = true }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "mers_lib"
 | 
					name = "mers_lib"
 | 
				
			||||||
version = "0.9.3"
 | 
					version = "0.9.4"
 | 
				
			||||||
edition = "2021"
 | 
					edition = "2021"
 | 
				
			||||||
license = "MIT OR Apache-2.0"
 | 
					license = "MIT OR Apache-2.0"
 | 
				
			||||||
description = "library to use the mers language in other projects"
 | 
					description = "library to use the mers language in other projects"
 | 
				
			||||||
 | 
				
			|||||||
@ -51,13 +51,13 @@ impl Function {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn new_generic(
 | 
					    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,
 | 
					        run: impl Fn(Data, &mut Info) -> Result<Data, CheckError> + Send + Sync + 'static,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            info: crate::info::Info::neverused(),
 | 
					            info: crate::info::Info::neverused(),
 | 
				
			||||||
            info_check: Arc::new(Mutex::new(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),
 | 
					            run: Arc::new(run),
 | 
				
			||||||
            inner_statements: None,
 | 
					            inner_statements: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,43 @@ use crate::info::DisplayInfo;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use super::{MersData, MersType, Type};
 | 
					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)]
 | 
					#[derive(Debug, Clone, Copy)]
 | 
				
			||||||
pub struct Int(pub isize);
 | 
					pub struct Int(pub isize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -22,7 +59,7 @@ impl MersData for Int {
 | 
				
			|||||||
        Box::new(Clone::clone(self))
 | 
					        Box::new(Clone::clone(self))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn as_type(&self) -> super::Type {
 | 
					    fn as_type(&self) -> super::Type {
 | 
				
			||||||
        Type::new(IntT)
 | 
					        Type::new(IntT(self.0, self.0))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn as_any(&self) -> &dyn Any {
 | 
					    fn as_any(&self) -> &dyn Any {
 | 
				
			||||||
        self
 | 
					        self
 | 
				
			||||||
@ -35,8 +72,8 @@ impl MersData for Int {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
pub struct IntT;
 | 
					pub struct IntT(pub isize, pub isize);
 | 
				
			||||||
impl MersType for IntT {
 | 
					impl MersType for IntT {
 | 
				
			||||||
    fn display(
 | 
					    fn display(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
@ -46,13 +83,35 @@ impl MersType for IntT {
 | 
				
			|||||||
        write!(f, "{self}")
 | 
					        write!(f, "{self}")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn is_same_type_as(&self, other: &dyn MersType) -> bool {
 | 
					    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 {
 | 
					    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) {
 | 
					    fn subtypes(&self, acc: &mut Type) {
 | 
				
			||||||
        acc.add(Arc::new(self.clone()));
 | 
					        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 {
 | 
					    fn as_any(&self) -> &dyn Any {
 | 
				
			||||||
        self
 | 
					        self
 | 
				
			||||||
@ -72,6 +131,12 @@ impl Display for Int {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
impl Display for IntT {
 | 
					impl Display for IntT {
 | 
				
			||||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
					    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();
 | 
					        let n = new.as_any();
 | 
				
			||||||
        if let Some(s) = n.downcast_ref::<Self>() {
 | 
					        if let Some(s) = n.downcast_ref::<Self>() {
 | 
				
			||||||
            self.add_all(s);
 | 
					            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 {
 | 
					        } else {
 | 
				
			||||||
            if !self.types.iter().any(|t| new.is_included_in(t.as_ref())) {
 | 
					            if !self.types.iter().any(|t| new.is_included_in(t.as_ref())) {
 | 
				
			||||||
                self.types.push(new);
 | 
					                self.types.push(new);
 | 
				
			||||||
 | 
				
			|||||||
@ -277,11 +277,11 @@ pub fn type_from_parsed(
 | 
				
			|||||||
                .find_map(|scope| scope.types.iter().find(|v| v.0 == name).map(|(_, v)| v))
 | 
					                .find_map(|scope| scope.types.iter().find(|v| v.0 == name).map(|(_, v)| v))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Some(Ok(t)) => as_type.add_all(&*t),
 | 
					                Some(Ok(t)) => as_type.add_all(&*t),
 | 
				
			||||||
                Some(Err(_)) => {
 | 
					                Some(Err(f)) => as_type.add_all(&*f("", info).map_err(|e| {
 | 
				
			||||||
                    return Err(CheckError::new().msg_str(format!(
 | 
					                    e.msg_str(format!(
 | 
				
			||||||
                        "Type: specified type without info, but type needs additional info"
 | 
					                        "Note: specified type `{name}` without info, but type needs additional info: `{name}<...>`"
 | 
				
			||||||
                    )))
 | 
					                    ))
 | 
				
			||||||
                }
 | 
					                })?),
 | 
				
			||||||
                None => return Err(CheckError::new().msg_str(format!("Unknown type '{name}'"))),
 | 
					                None => return Err(CheckError::new().msg_str(format!("Unknown type '{name}'"))),
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            ParsedType::TypeWithInfo(name, additional_info) => match info
 | 
					            ParsedType::TypeWithInfo(name, additional_info) => match info
 | 
				
			||||||
 | 
				
			|||||||
@ -379,27 +379,33 @@ impl ToMersData for u8 {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FromMersData for isize {
 | 
					/// An integer within the range `N..=M`
 | 
				
			||||||
 | 
					pub struct IntR<const N: isize, const M: isize>(pub isize);
 | 
				
			||||||
 | 
					impl<const N: isize, const M: isize> FromMersData for IntR<N, M> {
 | 
				
			||||||
    fn as_type_from() -> Type {
 | 
					    fn as_type_from() -> Type {
 | 
				
			||||||
        Self::as_type_to()
 | 
					        Self::as_type_to()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn can_represent(t: &Type) -> bool {
 | 
					    fn can_represent(t: &Type) -> bool {
 | 
				
			||||||
        t.is_included_in(&Type::new(data::int::IntT))
 | 
					        t.is_included_in(&Type::new(data::int::IntT(N, M)))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn try_represent<O, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
 | 
					    fn try_represent<O, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
 | 
				
			||||||
        if let Some(v) = d.as_any().downcast_ref::<data::int::Int>() {
 | 
					        if let Some(v) = d.as_any().downcast_ref::<data::int::Int>() {
 | 
				
			||||||
            f(Some(v.0))
 | 
					            if N <= v.0 && v.0 <= M {
 | 
				
			||||||
 | 
					                f(Some(Self(v.0)))
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                f(None)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            f(None)
 | 
					            f(None)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
impl ToMersData for isize {
 | 
					impl<const N: isize, const M: isize> ToMersData for IntR<N, M> {
 | 
				
			||||||
    fn as_type_to() -> Type {
 | 
					    fn as_type_to() -> Type {
 | 
				
			||||||
        Type::new(data::int::IntT)
 | 
					        Type::new(data::int::IntT(N, M))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn represent(self) -> Data {
 | 
					    fn represent(self) -> Data {
 | 
				
			||||||
        Data::new(data::int::Int(self))
 | 
					        Data::new(data::int::Int(self.0))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,11 @@
 | 
				
			|||||||
use std::sync::{Arc, RwLock};
 | 
					use std::sync::{Arc, RwLock};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    data::{self, Data, MersData, Type},
 | 
					    data::{
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        int::{INT_MAX, INT_MIN},
 | 
				
			||||||
 | 
					        Data, MersData, Type,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    errors::CheckError,
 | 
					    errors::CheckError,
 | 
				
			||||||
    info::Local,
 | 
					    info::Local,
 | 
				
			||||||
    program::run::{CheckInfo, CheckLocalGlobalInfo, RunLocalGlobalInfo},
 | 
					    program::run::{CheckInfo, CheckLocalGlobalInfo, RunLocalGlobalInfo},
 | 
				
			||||||
@ -92,7 +96,42 @@ impl Config {
 | 
				
			|||||||
            .types
 | 
					            .types
 | 
				
			||||||
            .insert("Bool".to_owned(), Ok(Arc::new(data::bool::bool_type())));
 | 
					            .insert("Bool".to_owned(), Ok(Arc::new(data::bool::bool_type())));
 | 
				
			||||||
        init_d!(data::byte::ByteT);
 | 
					        init_d!(data::byte::ByteT);
 | 
				
			||||||
        init_d!(data::int::IntT);
 | 
					        info_check.scopes.last_mut().unwrap().types.insert(
 | 
				
			||||||
 | 
					            "Int".to_owned(),
 | 
				
			||||||
 | 
					            // Ok(Arc::new(data::Type::new(data::int::INT_T_ALL))),
 | 
				
			||||||
 | 
					            Err(Arc::new(|range, _| {
 | 
				
			||||||
 | 
					                Ok(Arc::new(Type::new({
 | 
				
			||||||
 | 
					                    let range = range.trim();
 | 
				
			||||||
 | 
					                    if range.is_empty() {
 | 
				
			||||||
 | 
					                        data::int::IntT(INT_MIN, INT_MAX)
 | 
				
			||||||
 | 
					                    } else if let Some((min, max)) = range.split_once("..") {
 | 
				
			||||||
 | 
					                        let (min, max) = (min.trim(), max.trim());
 | 
				
			||||||
 | 
					                        let min = if min.is_empty() {
 | 
				
			||||||
 | 
					                            data::int::INT_MIN
 | 
				
			||||||
 | 
					                        } else if let Ok(v) = min.parse() {
 | 
				
			||||||
 | 
					                            v
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            return Err(CheckError::new().msg_str(format!("In type `Int<{min}..{max}>`: min was present but not a valid integer.")));
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        let max = if max.is_empty() {
 | 
				
			||||||
 | 
					                            data::int::INT_MAX
 | 
				
			||||||
 | 
					                        } else if let Ok(v) = max.parse() {
 | 
				
			||||||
 | 
					                            v
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            return Err(CheckError::new().msg_str(format!("In type `Int<{min}..{max}>`: max was present but not a valid integer.")));
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        if min > max {
 | 
				
			||||||
 | 
					                            return Err(CheckError::new().msg_str(format!("In type `Int<{min}..{max}>`: min ({min}) must be smaller than or equal to max ({max}). Did you mean `Int<{max}..{min}>`?")));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        crate::data::int::IntT(min, max)
 | 
				
			||||||
 | 
					                    } else if let Ok(v) = range.parse() {
 | 
				
			||||||
 | 
					                        crate::data::int::IntT(v, v)
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return Err(CheckError::new().msg_str(format!("In type `Int<{range}>`: Invalid range. Either use `Int` (or `Int<>` or `Int<..>`) for the entire integer range, `Int<n>` for a specific number, `Int<n..>` for all numbers `>=n`, `Int<..m>` for all numbers `<=m`, or `Int<n..m>` for all numbers `>=n` and `<= m`.")));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })))
 | 
				
			||||||
 | 
					            })),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
        init_d!(data::float::FloatT);
 | 
					        init_d!(data::float::FloatT);
 | 
				
			||||||
        init_d!(data::string::StringT);
 | 
					        init_d!(data::string::StringT);
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,12 @@ use std::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    data::{self, bool::bool_type, Data, MersTypeWInfo, Type},
 | 
					    data::{
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        bool::bool_type,
 | 
				
			||||||
 | 
					        int::{INT_MAX, INT_MIN},
 | 
				
			||||||
 | 
					        Data, MersTypeWInfo, Type,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    errors::CheckError,
 | 
					    errors::CheckError,
 | 
				
			||||||
    program::run::{CheckInfo, Info},
 | 
					    program::run::{CheckInfo, Info},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -12,7 +17,7 @@ use crate::{
 | 
				
			|||||||
use super::{
 | 
					use super::{
 | 
				
			||||||
    gen::{
 | 
					    gen::{
 | 
				
			||||||
        function::{func, func_end, func_err},
 | 
					        function::{func, func_end, func_err},
 | 
				
			||||||
        OneOf,
 | 
					        IntR, OneOf,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    Config,
 | 
					    Config,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -75,9 +80,9 @@ impl Config {
 | 
				
			|||||||
                }),
 | 
					                }),
 | 
				
			||||||
                inner_statements: None,
 | 
					                inner_statements: None,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .add_var("sleep", func(|dur: OneOf<isize, f64>, i| {
 | 
					            .add_var("sleep", func(|dur: OneOf<IntR<0, INT_MAX>, f64>, i| {
 | 
				
			||||||
                let mut sleep_dur = match dur {
 | 
					                let mut sleep_dur = match dur {
 | 
				
			||||||
                    OneOf::A(dur) => Duration::from_secs(dur.max(0).try_into().unwrap_or(u64::MAX)),
 | 
					                    OneOf::A(dur) => Duration::from_secs(dur.0.max(0).try_into().unwrap_or(u64::MAX)),
 | 
				
			||||||
                    OneOf::B(dur) => Duration::from_secs_f64(dur.max(0.0)),
 | 
					                    OneOf::B(dur) => Duration::from_secs_f64(dur.max(0.0)),
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                // limit how long sleep can take
 | 
					                // limit how long sleep can take
 | 
				
			||||||
@ -87,8 +92,8 @@ impl Config {
 | 
				
			|||||||
                std::thread::sleep(sleep_dur);
 | 
					                std::thread::sleep(sleep_dur);
 | 
				
			||||||
                Ok(())
 | 
					                Ok(())
 | 
				
			||||||
            }))
 | 
					            }))
 | 
				
			||||||
            .add_var("exit", func_end(|code: isize, _| {
 | 
					            .add_var("exit", func_end(|code: IntR<INT_MIN, INT_MAX>, _| {
 | 
				
			||||||
                std::process::exit(code.try_into().unwrap_or(255));
 | 
					                std::process::exit(code.0.try_into().unwrap_or(255));
 | 
				
			||||||
            }))
 | 
					            }))
 | 
				
			||||||
            .add_var("panic", func_err(|message: &str, _| {
 | 
					            .add_var("panic", func_err(|message: &str, _| {
 | 
				
			||||||
                CheckError::from(message)
 | 
					                CheckError::from(message)
 | 
				
			||||||
@ -104,18 +109,17 @@ impl Config {
 | 
				
			|||||||
                            return Err(format!("cannot get length of {} (must be a tuple, string or iterable)", t.with_info(i)).into());
 | 
					                            return Err(format!("cannot get length of {} (must be a tuple, string or iterable)", t.with_info(i)).into());
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Ok(Type::new(data::int::IntT))
 | 
					                    Ok(Type::new(data::int::IntT(0, INT_MAX)))
 | 
				
			||||||
                })),
 | 
					                })),
 | 
				
			||||||
                run: Arc::new(|a, _i| {
 | 
					                run: Arc::new(|a, _i| {
 | 
				
			||||||
                    Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
 | 
					                    Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
 | 
				
			||||||
                        t.0.len() as _
 | 
					                        t.0.len().try_into().unwrap_or(INT_MAX)
 | 
				
			||||||
                    } else if let Some(s) = a.get().as_any().downcast_ref::<data::string::String>() {
 | 
					                    } else if let Some(s) = a.get().as_any().downcast_ref::<data::string::String>() {
 | 
				
			||||||
                        s.0.len() as _
 | 
					                        s.0.len().try_into().unwrap_or(INT_MAX)
 | 
				
			||||||
                    } else if let Some(i) = a.get().iterable() {
 | 
					                    } else if let Some(i) = a.get().iterable() {
 | 
				
			||||||
                        // -1 if more elements than isize can represent
 | 
					                        i.count().try_into().unwrap_or(INT_MAX)
 | 
				
			||||||
                        i.take(isize::MAX as usize + 1).count().try_into().unwrap_or(-1)
 | 
					 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        return Err("called len on {a:?}, which isn't a tuple or a string".into());
 | 
					                        return Err("called len on {a:?}, which isn't a tuple, a string, or something iterable.".into());
 | 
				
			||||||
                    })))
 | 
					                    })))
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                inner_statements: None,
 | 
					                inner_statements: None,
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,12 @@ use std::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    data::{self, object::ObjectFieldsMap, Data, MersData, MersDataWInfo, MersType, Type},
 | 
					    data::{
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        int::{INT_MAX, INT_MIN},
 | 
				
			||||||
 | 
					        object::ObjectFieldsMap,
 | 
				
			||||||
 | 
					        Data, MersData, MersDataWInfo, MersType, Type,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    errors::CheckError,
 | 
					    errors::CheckError,
 | 
				
			||||||
    info::DisplayInfo,
 | 
					    info::DisplayInfo,
 | 
				
			||||||
    program::{self, run::CheckInfo},
 | 
					    program::{self, run::CheckInfo},
 | 
				
			||||||
@ -34,7 +39,7 @@ impl Config {
 | 
				
			|||||||
                    if a.types.iter().all(|t| t.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
 | 
					                    if a.types.iter().all(|t| t.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
 | 
				
			||||||
                        Ok(Type::newm(vec![
 | 
					                        Ok(Type::newm(vec![
 | 
				
			||||||
                            Arc::new(data::tuple::TupleT(vec![
 | 
					                            Arc::new(data::tuple::TupleT(vec![
 | 
				
			||||||
                                Type::newm(vec![Arc::new(data::int::IntT), Arc::new(data::bool::TrueT), Arc::new(data::bool::FalseT)]),
 | 
					                                Type::newm(vec![Arc::new(data::int::IntT(INT_MIN, INT_MAX)), Arc::new(data::bool::TrueT), Arc::new(data::bool::FalseT)]),
 | 
				
			||||||
                                Type::new(data::string::StringT),
 | 
					                                Type::new(data::string::StringT),
 | 
				
			||||||
                                Type::new(data::string::StringT),
 | 
					                                Type::new(data::string::StringT),
 | 
				
			||||||
                            ])),
 | 
					                            ])),
 | 
				
			||||||
@ -160,7 +165,7 @@ impl Config {
 | 
				
			|||||||
                out: Ok(Arc::new(|a, i| {
 | 
					                out: Ok(Arc::new(|a, i| {
 | 
				
			||||||
                    if a.is_included_in_single(&ChildProcessT) {
 | 
					                    if a.is_included_in_single(&ChildProcessT) {
 | 
				
			||||||
                        Ok(Type::newm(vec![
 | 
					                        Ok(Type::newm(vec![
 | 
				
			||||||
                            Arc::new(data::int::IntT),
 | 
					                            Arc::new(data::int::IntT(INT_MIN, INT_MAX)),
 | 
				
			||||||
                            Arc::new(data::bool::TrueT),
 | 
					                            Arc::new(data::bool::TrueT),
 | 
				
			||||||
                            Arc::new(data::bool::FalseT),
 | 
					                            Arc::new(data::bool::FalseT),
 | 
				
			||||||
                            Arc::new(data::tuple::TupleT(vec![])),
 | 
					                            Arc::new(data::tuple::TupleT(vec![])),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
use std::sync::{Arc, Mutex};
 | 
					use std::sync::{Arc, Mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    data::{self, Data, MersTypeWInfo, Type},
 | 
					    data::{self, int::INT_MAX, Data, MersTypeWInfo, Type},
 | 
				
			||||||
    program::{self, run::CheckInfo},
 | 
					    program::{self, run::CheckInfo},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -22,7 +22,7 @@ impl Config {
 | 
				
			|||||||
                            if t.0.len() != 2 {
 | 
					                            if t.0.len() != 2 {
 | 
				
			||||||
                                return Err(format!("called get on tuple with len != 2").into());
 | 
					                                return Err(format!("called get on tuple with len != 2").into());
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            if !t.0[1].is_included_in_single(&data::int::IntT) {
 | 
					                            if !t.0[1].is_included_in_single(&data::int::IntT(0, INT_MAX)) {
 | 
				
			||||||
                                return Err(format!(
 | 
					                                return Err(format!(
 | 
				
			||||||
                                    "called get with non-int index of type {}",
 | 
					                                    "called get with non-int index of type {}",
 | 
				
			||||||
                                    t.0[1].with_info(i)
 | 
					                                    t.0[1].with_info(i)
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ use crate::{
 | 
				
			|||||||
    data::{
 | 
					    data::{
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        function::{Function, FunctionT},
 | 
					        function::{Function, FunctionT},
 | 
				
			||||||
 | 
					        int::INT_MAX,
 | 
				
			||||||
        Data, MersData, MersType, MersTypeWInfo, Type,
 | 
					        Data, MersData, MersType, MersTypeWInfo, Type,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    errors::CheckError,
 | 
					    errors::CheckError,
 | 
				
			||||||
@ -128,8 +129,8 @@ impl Config {
 | 
				
			|||||||
            genfunc_iter_and_func("map_while", ItersT::MapWhile, Iters::MapWhile),
 | 
					            genfunc_iter_and_func("map_while", ItersT::MapWhile, Iters::MapWhile),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .add_var("take", genfunc_iter_and_arg("take", |_: &data::int::IntT| ItersT::Take, |v: &data::int::Int| {
 | 
					        .add_var("take", genfunc_iter_and_arg("take", |_: &data::int::IntT| ItersT::Take, |v: &data::int::Int| {
 | 
				
			||||||
            Iters::Take(v.0.max(0) as _)
 | 
					            Iters::Take(v.0.max(0).try_into().unwrap_or(usize::MAX))
 | 
				
			||||||
        }, &data::int::IntT))
 | 
					        }, &data::int::IntT(0, INT_MAX)))
 | 
				
			||||||
        .add_var(
 | 
					        .add_var(
 | 
				
			||||||
            "enumerate",
 | 
					            "enumerate",
 | 
				
			||||||
            data::function::Function {
 | 
					            data::function::Function {
 | 
				
			||||||
@ -463,7 +464,7 @@ impl IterT {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            ItersT::Take => data.clone(),
 | 
					            ItersT::Take => data.clone(),
 | 
				
			||||||
            ItersT::Enumerate => Type::new(data::tuple::TupleT(vec![
 | 
					            ItersT::Enumerate => Type::new(data::tuple::TupleT(vec![
 | 
				
			||||||
                Type::new(data::int::IntT),
 | 
					                Type::new(data::int::IntT(0, INT_MAX)),
 | 
				
			||||||
                data.clone(),
 | 
					                data.clone(),
 | 
				
			||||||
            ])),
 | 
					            ])),
 | 
				
			||||||
            ItersT::Chained => {
 | 
					            ItersT::Chained => {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
use std::sync::{Arc, Mutex, RwLock};
 | 
					use std::sync::{Arc, Mutex, RwLock};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    data::{self, Data, MersData, MersType, MersTypeWInfo, Type},
 | 
					    data::{self, int::INT_MAX, Data, MersData, MersType, MersTypeWInfo, Type},
 | 
				
			||||||
    errors::CheckError,
 | 
					    errors::CheckError,
 | 
				
			||||||
    info::DisplayInfo,
 | 
					    info::DisplayInfo,
 | 
				
			||||||
    parsing::{statements::to_string_literal, Source},
 | 
					    parsing::{statements::to_string_literal, Source},
 | 
				
			||||||
@ -41,7 +41,7 @@ impl Config {
 | 
				
			|||||||
                                            "get_mut: argument must be a 2-tuple `(&List<_>, Int)`."
 | 
					                                            "get_mut: argument must be a 2-tuple `(&List<_>, Int)`."
 | 
				
			||||||
                                        ).into());
 | 
					                                        ).into());
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                    if t.0[1].is_included_in_single(&data::int::IntT) {
 | 
					                                    if t.0[1].is_included_in_single(&data::int::IntT(0, INT_MAX)) {
 | 
				
			||||||
                                        if let Some(t) = t.0[0].dereference() {
 | 
					                                        if let Some(t) = t.0[0].dereference() {
 | 
				
			||||||
                                            for t in t.types.iter() {
 | 
					                                            for t in t.types.iter() {
 | 
				
			||||||
                                                if let Some(t) = t.as_any().downcast_ref::<ListT>() {
 | 
					                                                if let Some(t) = t.as_any().downcast_ref::<ListT>() {
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,7 +1,11 @@
 | 
				
			|||||||
use crate::data::{self, Data, MersDataWInfo, Type};
 | 
					use crate::data::{
 | 
				
			||||||
 | 
					    self,
 | 
				
			||||||
 | 
					    int::{INT_MAX, INT_MIN},
 | 
				
			||||||
 | 
					    Data, MersDataWInfo, Type,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{
 | 
					use super::{
 | 
				
			||||||
    gen::{function::func, AnyOrNone, IterToList, OneOf, OneOrNone},
 | 
					    gen::{function::func, AnyOrNone, IntR, IterToList, OneOf, OneOrNone},
 | 
				
			||||||
    util, Config,
 | 
					    util, Config,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,11 +25,17 @@ impl Config {
 | 
				
			|||||||
        self.add_var("trim", func(|v: &str, _| Ok(v.trim().to_owned())))
 | 
					        self.add_var("trim", func(|v: &str, _| Ok(v.trim().to_owned())))
 | 
				
			||||||
            .add_var(
 | 
					            .add_var(
 | 
				
			||||||
                "index_of",
 | 
					                "index_of",
 | 
				
			||||||
                func(|(v, p): (&str, &str), _| Ok(OneOrNone(v.find(p).map(|v| v as isize)))),
 | 
					                func(|(v, p): (&str, &str), _| {
 | 
				
			||||||
 | 
					                    Ok(OneOrNone(v.find(p).map(|v| IntR::<0, INT_MAX>(v as isize))))
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .add_var(
 | 
					            .add_var(
 | 
				
			||||||
                "index_of_rev",
 | 
					                "index_of_rev",
 | 
				
			||||||
                func(|(v, p): (&str, &str), _| Ok(OneOrNone(v.rfind(p).map(|v| v as isize)))),
 | 
					                func(|(v, p): (&str, &str), _| {
 | 
				
			||||||
 | 
					                    Ok(OneOrNone(
 | 
				
			||||||
 | 
					                        v.rfind(p).map(|v| IntR::<0, INT_MAX>(v as isize)),
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .add_var(
 | 
					            .add_var(
 | 
				
			||||||
                "starts_with",
 | 
					                "starts_with",
 | 
				
			||||||
@ -92,10 +102,15 @@ impl Config {
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
            .add_var(
 | 
					            .add_var(
 | 
				
			||||||
                "substring",
 | 
					                "substring",
 | 
				
			||||||
                func(|v: OneOf<(&str, isize), (&str, isize, isize)>, _| {
 | 
					                func(
 | 
				
			||||||
 | 
					                    |v: OneOf<
 | 
				
			||||||
 | 
					                        (&str, IntR<INT_MIN, INT_MAX>),
 | 
				
			||||||
 | 
					                        (&str, IntR<INT_MIN, INT_MAX>, IntR<INT_MIN, INT_MAX>),
 | 
				
			||||||
 | 
					                    >,
 | 
				
			||||||
 | 
					                     _| {
 | 
				
			||||||
                        let (s, start, end) = match v {
 | 
					                        let (s, start, end) = match v {
 | 
				
			||||||
                        OneOf::A((t, s)) => (t, s, None),
 | 
					                            OneOf::A((t, s)) => (t, s.0, None),
 | 
				
			||||||
                        OneOf::B((t, s, e)) => (t, s, Some(e)),
 | 
					                            OneOf::B((t, s, e)) => (t, s.0, Some(e.0)),
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        let start = if start < 0 {
 | 
					                        let start = if start < 0 {
 | 
				
			||||||
                            s.len().saturating_sub(start.abs() as usize)
 | 
					                            s.len().saturating_sub(start.abs() as usize)
 | 
				
			||||||
@ -116,7 +131,8 @@ impl Config {
 | 
				
			|||||||
                            return Ok(String::new());
 | 
					                            return Ok(String::new());
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        Ok(s[start..end].to_owned())
 | 
					                        Ok(s[start..end].to_owned())
 | 
				
			||||||
                }),
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,8 +15,8 @@ fn variable() -> Res {
 | 
				
			|||||||
        assert_eq!(
 | 
					        assert_eq!(
 | 
				
			||||||
            run_code(Config::new(), format!("x := {n}, x"))?,
 | 
					            run_code(Config::new(), format!("x := {n}, x"))?,
 | 
				
			||||||
            TypedData(
 | 
					            TypedData(
 | 
				
			||||||
                Type::new(data::int::IntT),
 | 
					                Type::new(data::int::IntT(n, n)),
 | 
				
			||||||
                Data::new(data::int::Int(n as _)),
 | 
					                Data::new(data::int::Int(n)),
 | 
				
			||||||
                mers_lib::info::Info::neverused(),
 | 
					                mers_lib::info::Info::neverused(),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
@ -27,9 +27,9 @@ fn variable() -> Res {
 | 
				
			|||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn mutating_a_variable() -> Res {
 | 
					fn mutating_a_variable() -> Res {
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(
 | 
				
			||||||
        run_code(Config::new(), "x := 5, &x = 2, x")?,
 | 
					        run_code(Config::new(), "x := [Int<2..5>] 5, &x = 2, x")?,
 | 
				
			||||||
        TypedData(
 | 
					        TypedData(
 | 
				
			||||||
            Type::new(data::int::IntT),
 | 
					            Type::new(data::int::IntT(2, 5)),
 | 
				
			||||||
            Data::new(data::int::Int(2)),
 | 
					            Data::new(data::int::Int(2)),
 | 
				
			||||||
            mers_lib::info::Info::neverused()
 | 
					            mers_lib::info::Info::neverused()
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
@ -40,9 +40,9 @@ fn mutating_a_variable() -> Res {
 | 
				
			|||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn variable_shadowing() -> Res {
 | 
					fn variable_shadowing() -> Res {
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(
 | 
				
			||||||
        run_code(Config::new(), "x := 5, { x := 2, &x = 3 }, x")?,
 | 
					        run_code(Config::new(), "x := 5, { x := 2, &x = 2 }, x")?,
 | 
				
			||||||
        TypedData(
 | 
					        TypedData(
 | 
				
			||||||
            Type::new(data::int::IntT),
 | 
					            Type::new(data::int::IntT(5, 5)),
 | 
				
			||||||
            Data::new(data::int::Int(5)),
 | 
					            Data::new(data::int::Int(5)),
 | 
				
			||||||
            mers_lib::info::Info::neverused()
 | 
					            mers_lib::info::Info::neverused()
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
@ -55,7 +55,7 @@ fn identity_function() -> Res {
 | 
				
			|||||||
    assert_eq!(
 | 
					    assert_eq!(
 | 
				
			||||||
        run_code(Config::new(), "id := x -> x, 4.id")?,
 | 
					        run_code(Config::new(), "id := x -> x, 4.id")?,
 | 
				
			||||||
        TypedData(
 | 
					        TypedData(
 | 
				
			||||||
            Type::new(data::int::IntT),
 | 
					            Type::new(data::int::IntT(4, 4)),
 | 
				
			||||||
            Data::new(data::int::Int(4)),
 | 
					            Data::new(data::int::Int(4)),
 | 
				
			||||||
            mers_lib::info::Info::neverused()
 | 
					            mers_lib::info::Info::neverused()
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user