diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index 1afd53a..a3b7fbb 100755 --- a/mers_lib/src/program/configs/with_base.rs +++ b/mers_lib/src/program/configs/with_base.rs @@ -11,13 +11,37 @@ impl Config { /// `deref: fn` clones the value from a reference /// `eq: fn` returns true if all the values are equal, otherwise false. /// `loop: fn` runs a function until it returns (T) instead of (), then returns T. + /// `len: fn` gets the length of strings or tuples pub fn with_base(self) -> Self { self.add_var( + "len".to_string(), + Data::new(data::function::Function { + info: Arc::new(Info::neverused()), + info_check: Arc::new(Mutex::new(CheckInfo::neverused())), + out: Arc::new(|a, _i| { + for t in &a.types { + if t.as_any().downcast_ref::().is_none() && t.as_any().downcast_ref::().is_none() { + return Err(crate::program::run::CheckError(format!("cannot get length of {t} (must be a tuple or a string)"))); + } + } + Ok(Type::new(data::int::IntT)) + }), + run: Arc::new(|a, _i| { + if let Some(t) = a.get().as_any().downcast_ref::() { + Data::new(data::int::Int(t.0.len() as _)) + } else if let Some(s) = a.get().as_any().downcast_ref::() { + Data::new(data::int::Int(s.0.len() as _)) + } else { + unreachable!("called len on {a:?}, which isn't a tuple or a string") + } + }), + }), + ).add_var( "loop".to_string(), Data::new(data::function::Function { info: Arc::new(Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, i| { + out: Arc::new(|a, _i| { let mut o = Type::empty(); for t in &a.types { if let Some(t) = t.as_any().downcast_ref::() { @@ -56,7 +80,7 @@ impl Config { Data::new(data::function::Function { info: Arc::new(Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, i| { + out: Arc::new(|a, _i| { for t in &a.types { if t.iterable().is_none() { return Err(crate::program::run::CheckError(format!("called eq on non-iterable"))) @@ -89,7 +113,7 @@ impl Config { Data::new(data::function::Function { info: Arc::new(Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, i| if let Some(v) = a.dereference() { Ok(v) } else { Err(crate::program::run::CheckError(format!("cannot dereference type {a}")))}), + out: Arc::new(|a, _i| if let Some(v) = a.dereference() { Ok(v) } else { Err(crate::program::run::CheckError(format!("cannot dereference type {a}")))}), run: Arc::new(|a, _i| { if let Some(r) = a .get()