From 50928cca1dde6d06f940f977937e10643a2a1866 Mon Sep 17 00:00:00 2001 From: Mark <> Date: Tue, 2 Jul 2024 22:04:42 +0200 Subject: [PATCH] [no version bump yet] better and safer stdlib impl only transformed configs/with_string so far, but other configs/* should follow soon. also, this will help with implementing new stdlib functions in the future. --- TODO.md | 4 + mers/Cargo.toml | 4 +- mers_lib/examples/02_own_variable.rs | 2 +- mers_lib/src/data/function.rs | 55 ++- mers_lib/src/parsing/types.rs | 11 +- mers_lib/src/program/configs/gen/function.rs | 90 ++++ mers_lib/src/program/configs/gen/mod.rs | 453 ++++++++++++++++++ mers_lib/src/program/configs/mod.rs | 1 + mers_lib/src/program/configs/util.rs | 13 +- mers_lib/src/program/configs/with_base.rs | 30 +- .../program/configs/with_command_running.rs | 40 +- mers_lib/src/program/configs/with_get.rs | 4 +- mers_lib/src/program/configs/with_iters.rs | 22 +- mers_lib/src/program/configs/with_list.rs | 16 +- mers_lib/src/program/configs/with_math.rs | 22 +- .../program/configs/with_multithreading.rs | 12 +- mers_lib/src/program/configs/with_stdio.rs | 14 +- mers_lib/src/program/configs/with_string.rs | 222 ++++++--- mers_lib/src/program/parsed/function.rs | 4 +- mers_lib/src/program/parsed/include_mers.rs | 4 +- mers_lib/src/program/run/function.rs | 2 +- 21 files changed, 841 insertions(+), 184 deletions(-) create mode 100644 mers_lib/src/program/configs/gen/function.rs create mode 100644 mers_lib/src/program/configs/gen/mod.rs diff --git a/TODO.md b/TODO.md index dbcc730..abbeceb 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,7 @@ +# IN CODE + +rm mers_lib/src/program/configs/util.rs + # Objects ``` diff --git a/mers/Cargo.toml b/mers/Cargo.toml index 445334c..17b3fcc 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -15,7 +15,7 @@ default = ["colored-output"] colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"] [dependencies] -mers_lib = "0.9.0" -# mers_lib = { path = "../mers_lib" } +# mers_lib = "0.9.0" +mers_lib = { path = "../mers_lib" } clap = { version = "4.3.19", features = ["derive"] } colored = { version = "2.1.0", optional = true } diff --git a/mers_lib/examples/02_own_variable.rs b/mers_lib/examples/02_own_variable.rs index 9dafb0c..2fa302e 100644 --- a/mers_lib/examples/02_own_variable.rs +++ b/mers_lib/examples/02_own_variable.rs @@ -30,7 +30,7 @@ fn run(src: String) -> Result<(), CheckError> { ) .add_var( "rust_func".to_owned(), - Data::new(data::function::Function::new( + Data::new(data::function::Function::new_generic( |arg| { // If the input is a string, the output is a string. // Otherwise, the function is used incorrectly. diff --git a/mers_lib/src/data/function.rs b/mers_lib/src/data/function.rs index 1c94779..fefeb29 100755 --- a/mers_lib/src/data/function.rs +++ b/mers_lib/src/data/function.rs @@ -15,7 +15,10 @@ use super::{Data, MersData, MersType, Type}; pub struct Function { pub info: Info, pub info_check: Arc>, - pub out: Arc Result + Send + Sync>, + pub out: Result< + Arc Result + Send + Sync>, + Arc>, + >, pub run: Arc Result + Send + Sync>, pub inner_statements: Option<( @@ -35,14 +38,26 @@ impl Clone for Function { } } impl Function { - pub fn new( + pub fn new_static( + out: Vec<(Type, Type)>, + run: impl Fn(Data) -> Result + Send + Sync + 'static, + ) -> Self { + Self { + info: crate::info::Info::neverused(), + info_check: Arc::new(Mutex::new(crate::info::Info::neverused())), + out: Err(Arc::new(out)), + run: Arc::new(move |a, _| run(a)), + inner_statements: None, + } + } + pub fn new_generic( out: impl Fn(&Type) -> Result + Send + Sync + 'static, run: impl Fn(Data) -> Result + Send + Sync + 'static, ) -> Self { Self { info: crate::info::Info::neverused(), info_check: Arc::new(Mutex::new(crate::info::Info::neverused())), - out: Arc::new(move |a, _| out(a)), + out: Ok(Arc::new(move |a, _| out(a))), run: Arc::new(move |a, _| run(a)), inner_statements: None, } @@ -51,7 +66,7 @@ impl Function { Self { info, info_check: Arc::clone(&self.info_check), - out: Arc::clone(&self.out), + out: self.out.clone(), run: Arc::clone(&self.run), inner_statements: self .inner_statements @@ -63,10 +78,7 @@ impl Function { *self.info_check.lock().unwrap() = check; } pub fn check(&self, arg: &Type) -> Result { - let lock = self.info_check.lock().unwrap(); - let mut info = lock.clone(); - drop(lock); - (self.out)(arg, &mut info) + self.get_as_type().o(arg) } pub fn run_mut(&mut self, arg: Data) -> Result { (self.run)(arg, &mut self.info) @@ -75,14 +87,23 @@ impl Function { (self.run)(arg, &mut self.info.duplicate()) } pub fn get_as_type(&self) -> FunctionT { - let out = Arc::clone(&self.out); - let info = Arc::clone(&self.info_check); - FunctionT(Ok(Arc::new(move |a| { - let lock = info.lock().unwrap(); - let mut info = lock.clone(); - drop(lock); - out(a, &mut info) - }))) + match &self.out { + Ok(out) => { + let out = Arc::clone(out); + let info = self.info_check.lock().unwrap().clone(); + FunctionT(Ok(Arc::new(move |a| out(a, &mut info.clone())))) + } + Err(types) => FunctionT(Err(Arc::clone(types))), + } + } + + pub fn inner_statements( + &self, + ) -> &Option<( + Arc>, + Arc>, + )> { + &self.inner_statements } } @@ -130,7 +151,7 @@ impl MersData for Function { #[derive(Clone)] pub struct FunctionT( - pub Result Result + Send + Sync>, Vec<(Type, Type)>>, + pub Result Result + Send + Sync>, Arc>>, ); impl FunctionT { /// get output type diff --git a/mers_lib/src/parsing/types.rs b/mers_lib/src/parsing/types.rs index 35ff7f9..e476a51 100755 --- a/mers_lib/src/parsing/types.rs +++ b/mers_lib/src/parsing/types.rs @@ -246,10 +246,13 @@ pub fn type_from_parsed( }) .collect::>()?, ))), - ParsedType::Function(v) => as_type.add(Arc::new(data::function::FunctionT(Err(v - .iter() - .map(|(i, o)| Ok((type_from_parsed(i, info)?, type_from_parsed(o, info)?))) - .collect::>()?)))), + ParsedType::Function(v) => { + as_type.add(Arc::new(data::function::FunctionT(Err(Arc::new( + v.iter() + .map(|(i, o)| Ok((type_from_parsed(i, info)?, type_from_parsed(o, info)?))) + .collect::>()?, + ))))) + } ParsedType::Type(name) => match info .scopes .iter() diff --git a/mers_lib/src/program/configs/gen/function.rs b/mers_lib/src/program/configs/gen/function.rs new file mode 100644 index 0000000..ff5c54f --- /dev/null +++ b/mers_lib/src/program/configs/gen/function.rs @@ -0,0 +1,90 @@ +use std::sync::Arc; + +use crate::{ + data::{self, Data, MersData, Type}, + errors::CheckError, +}; + +use super::{FromMersData, ToMersData}; + +pub fn func( + f: fn(I) -> Result, +) -> data::function::Function { + Box::new(f).mers_func() +} + +// fn this_works() { +// let cfg = (); +// // type: `(Int -> Float, Byte -> Int)` +// // todo: maybe add an Iterable "type" that we can use like `[Itarable] (1, 2, 3)` +// cfg.add_var( +// "test".to_owned(), +// Data::new( +// TwoFuncs( +// OneFunc::new(|num: isize| Ok(num as f64 / 2.0)), +// OneFunc::new(|num: u8| Ok(num as isize)), +// ) +// .to_mers_func(), +// ), +// ); +// } + +pub trait StaticMersFunc: Sized + 'static + Send + Sync { + fn types() -> Vec<(Type, Type)>; + fn run(&self, a: &(impl MersData + ?Sized)) -> Option>; + fn mers_func(self) -> data::function::Function { + data::function::Function::new_static(Self::types(), move |a| { + match self.run(a.get().as_ref()) { + Some(Ok(v)) => Ok(v), + Some(Err(e)) => Err(e), + None => Err(CheckError::from(format!( + "unexpected argument of type {}, expected {}", + a.get().as_type(), + Type::new(data::function::FunctionT(Err(Arc::new(Self::types())))) + ))), + } + }) + } +} + +pub struct TwoFuncs(pub A, pub B); + +pub trait Func: Send + Sync + 'static { + type I: FromMersData; + type O: ToMersData; + fn run_func(&self, i: Self::I) -> Result; +} +impl Func for fn(I) -> Result { + type I = I; + type O = O; + fn run_func(&self, i: Self::I) -> Result { + self(i) + } +} + +impl StaticMersFunc for Box { + fn types() -> Vec<(Type, Type)> { + vec![(F::I::as_type_from(), F::O::as_type_to())] + } + fn run(&self, a: &(impl MersData + ?Sized)) -> Option> { + F::I::try_represent(a, |v| v.map(|v| self.run_func(v).map(|v| v.represent()))) + } +} + +impl StaticMersFunc for TwoFuncs { + fn types() -> Vec<(Type, Type)> { + let mut o = A::types(); + for t in B::types() { + if o.iter().any(|o| t.0.is_included_in(&o.0)) { + // other function fully covers this case already, + // ignore it in type signature as we will always call the first function instead of the 2nd one + } else { + o.push(t); + } + } + o + } + fn run(&self, a: &(impl MersData + ?Sized)) -> Option> { + self.0.run(a).or_else(|| self.1.run(a)) + } +} diff --git a/mers_lib/src/program/configs/gen/mod.rs b/mers_lib/src/program/configs/gen/mod.rs new file mode 100644 index 0000000..463abb6 --- /dev/null +++ b/mers_lib/src/program/configs/gen/mod.rs @@ -0,0 +1,453 @@ +pub mod function; + +use std::sync::{Arc, RwLock}; + +use crate::data::{self, Data, MersData, Type}; + +pub trait FromMersData: Sized { + fn as_type_from() -> Type; + fn can_represent(t: &Type) -> bool; + /// **NOTE: `f` may only used the passed value of type `Self` during the call to `f`**. + /// Storing the value anywhere, moving it to a thread or otherwise assuming that it lives longer than the function call + /// violates Rust's lifetime rules, but is allowed by the compiler because of some `unsafe` code which + /// calls `f` with a `Self` type with a lifetime that is incorrect on purpose (but seemingly necessary for this to work at all). + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O; +} +pub trait ToMersData { + /// what type this will become when `represent` is called + fn as_type_to() -> Type; + fn represent(self) -> Data; +} + +/// Generates types like `(A)/()`. If `A` is a tuple-type, consider using `AnyOrNone` instead. +pub struct OneOrNone(pub Option); +/// Mainly used to generate types like `(A, B)/()` where `OneOrNone` would generate `((A, B))/()`, but can also generate `A/()` +pub struct AnyOrNone(pub Option); +impl FromMersData for OneOrNone { + fn as_type_from() -> Type { + Type::newm(vec![ + Arc::new(data::tuple::TupleT(vec![A::as_type_from()])), + Arc::new(data::tuple::TupleT(vec![])), + ]) + } + fn can_represent(t: &Type) -> bool { + t.one_tuple_possible_content() + .is_some_and(|t| A::can_represent(&t)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d + .as_any() + .downcast_ref::() + .filter(|v| v.0.len() <= 1) + { + if v.0.is_empty() { + f(Some(Self(None))) + } else { + A::try_represent(v.0[0].get().as_ref(), |v1| { + if let Some(va) = v1 { + f(Some(Self(Some(va)))) + } else { + f(None) + } + }) + } + } else { + f(None) + } + } +} +impl ToMersData for OneOrNone { + fn as_type_to() -> Type { + Type::newm(vec![ + Arc::new(data::tuple::TupleT(vec![A::as_type_to()])), + Arc::new(data::tuple::TupleT(vec![])), + ]) + } + fn represent(self) -> Data { + if let Some(v) = self.0 { + Data::one_tuple(v.represent()) + } else { + Data::empty_tuple() + } + } +} +impl FromMersData for AnyOrNone { + fn as_type_from() -> Type { + Type::newm(vec![ + Arc::new(data::tuple::TupleT(vec![A::as_type_from()])), + Arc::new(data::tuple::TupleT(vec![])), + ]) + } + fn can_represent(t: &Type) -> bool { + t.one_tuple_possible_content() + .is_some_and(|t| A::can_represent(&t)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if d.as_any() + .downcast_ref::() + .is_some_and(|v| v.0.is_empty()) + { + f(Some(Self(None))) + } else { + A::try_represent(d, |v1| { + if let Some(va) = v1 { + f(Some(Self(Some(va)))) + } else { + f(None) + } + }) + } + } +} +impl ToMersData for AnyOrNone { + fn as_type_to() -> Type { + let mut o = A::as_type_to(); + o.add_all(&Type::empty_tuple()); + o + } + fn represent(self) -> Data { + if let Some(v) = self.0 { + v.represent() + } else { + Data::empty_tuple() + } + } +} + +pub enum OneOf { + A(A), + B(B), +} +impl FromMersData for OneOf { + fn as_type_from() -> Type { + let mut o = A::as_type_from(); + o.add_all(&B::as_type_from()); + o + } + fn can_represent(t: &Type) -> bool { + A::can_represent(t) || B::can_represent(t) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + A::try_represent(d, |v| { + if let Some(v) = v { + f(Some(OneOf::A(v))) + } else { + B::try_represent(d, |v| { + if let Some(v) = v { + f(Some(OneOf::B(v))) + } else { + f(None) + } + }) + } + }) + } +} +impl ToMersData for OneOf { + fn as_type_to() -> Type { + let mut o = A::as_type_to(); + o.add_all(&B::as_type_to()); + o + } + fn represent(self) -> Data { + match self { + Self::A(v) => v.represent(), + Self::B(v) => v.represent(), + } + } +} + +pub struct IterToList>(pub I); +impl> ToMersData for IterToList { + fn as_type_to() -> Type { + Type::new(super::with_list::ListT(T::as_type_to())) + } + fn represent(self) -> Data { + Data::new(super::with_list::List( + self.0 + .map(|v| Arc::new(RwLock::new(v.represent()))) + .collect(), + )) + } +} + +impl FromMersData for () { + fn as_type_from() -> Type { + Self::as_type_to() + } + fn can_represent(t: &Type) -> bool { + t.is_zero_tuple() + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + f(d.as_any() + .downcast_ref::() + .is_some_and(|v| v.0.is_empty()) + .then_some(())) + } +} +impl ToMersData for () { + fn as_type_to() -> Type { + Type::empty_tuple() + } + fn represent(self) -> Data { + Data::empty_tuple() + } +} + +impl FromMersData for (A,) { + fn as_type_from() -> Type { + Type::new(data::tuple::TupleT(vec![A::as_type_from()])) + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Self::as_type_from()) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d + .as_any() + .downcast_ref::() + .filter(|v| v.0.len() == 1) + { + A::try_represent(v.0[0].get().as_ref(), |v1| { + if let Some(va) = v1 { + f(Some((va,))) + } else { + f(None) + } + }) + } else { + f(None) + } + } +} +impl ToMersData for (A,) { + fn as_type_to() -> Type { + Type::new(data::tuple::TupleT(vec![A::as_type_to()])) + } + fn represent(self) -> Data { + Data::new(data::tuple::Tuple(vec![self.0.represent()])) + } +} + +impl FromMersData for (A, B) { + fn as_type_from() -> Type { + Type::new(data::tuple::TupleT(vec![ + A::as_type_from(), + B::as_type_from(), + ])) + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Self::as_type_from()) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d + .as_any() + .downcast_ref::() + .filter(|v| v.0.len() == 2) + { + A::try_represent(v.0[0].get().as_ref(), |v1| { + if let Some(va) = v1 { + B::try_represent(v.0[1].get().as_ref(), |v2| { + if let Some(vb) = v2 { + f(Some((va, vb))) + } else { + f(None) + } + }) + } else { + f(None) + } + }) + } else { + f(None) + } + } +} +impl ToMersData for (A, B) { + fn as_type_to() -> Type { + Type::new(data::tuple::TupleT(vec![A::as_type_to(), B::as_type_to()])) + } + fn represent(self) -> Data { + Data::new(data::tuple::Tuple(vec![ + self.0.represent(), + self.1.represent(), + ])) + } +} +impl FromMersData for (A, B, C) { + fn as_type_from() -> Type { + Type::new(data::tuple::TupleT(vec![ + A::as_type_from(), + B::as_type_from(), + C::as_type_from(), + ])) + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Self::as_type_from()) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d + .as_any() + .downcast_ref::() + .filter(|v| v.0.len() == 2) + { + A::try_represent(v.0[0].get().as_ref(), |v1| { + if let Some(va) = v1 { + B::try_represent(v.0[1].get().as_ref(), |v2| { + if let Some(vb) = v2 { + C::try_represent(v.0[2].get().as_ref(), |v3| { + if let Some(vc) = v3 { + f(Some((va, vb, vc))) + } else { + f(None) + } + }) + } else { + f(None) + } + }) + } else { + f(None) + } + }) + } else { + f(None) + } + } +} +impl ToMersData for (A, B, C) { + fn as_type_to() -> Type { + Type::new(data::tuple::TupleT(vec![ + A::as_type_to(), + B::as_type_to(), + C::as_type_to(), + ])) + } + fn represent(self) -> Data { + Data::new(data::tuple::Tuple(vec![ + self.0.represent(), + self.1.represent(), + self.2.represent(), + ])) + } +} + +impl FromMersData for bool { + fn as_type_from() -> Type { + Self::as_type_to() + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Type::new(data::bool::BoolT)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d.as_any().downcast_ref::() { + f(Some(v.0)) + } else { + f(None) + } + } +} +impl ToMersData for bool { + fn as_type_to() -> Type { + Type::new(data::bool::BoolT) + } + fn represent(self) -> Data { + Data::new(data::bool::Bool(self)) + } +} + +impl FromMersData for u8 { + fn as_type_from() -> Type { + Self::as_type_to() + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Type::new(data::byte::ByteT)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d.as_any().downcast_ref::() { + f(Some(v.0)) + } else { + f(None) + } + } +} +impl ToMersData for u8 { + fn as_type_to() -> Type { + Type::new(data::byte::ByteT) + } + fn represent(self) -> Data { + Data::new(data::byte::Byte(self)) + } +} + +impl FromMersData for isize { + fn as_type_from() -> Type { + Self::as_type_to() + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Type::new(data::int::IntT)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d.as_any().downcast_ref::() { + f(Some(v.0)) + } else { + f(None) + } + } +} +impl ToMersData for isize { + fn as_type_to() -> Type { + Type::new(data::int::IntT) + } + fn represent(self) -> Data { + Data::new(data::int::Int(self)) + } +} + +impl FromMersData for f64 { + fn as_type_from() -> Type { + Self::as_type_to() + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Type::new(data::float::FloatT)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d.as_any().downcast_ref::() { + f(Some(v.0)) + } else { + f(None) + } + } +} +impl ToMersData for f64 { + fn as_type_to() -> Type { + Type::new(data::float::FloatT) + } + fn represent(self) -> Data { + Data::new(data::float::Float(self)) + } +} + +impl FromMersData for &str { + fn as_type_from() -> Type { + String::as_type_to() + } + fn can_represent(t: &Type) -> bool { + t.is_included_in(&Type::new(data::string::StringT)) + } + fn try_represent) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { + if let Some(v) = d.as_any().downcast_ref::() { + let v = v.0.as_str(); + unsafe { f(Some(std::ptr::from_ref(v).as_ref().unwrap())) } + } else { + f(None) + } + } +} +impl ToMersData for String { + fn as_type_to() -> Type { + Type::new(data::string::StringT) + } + fn represent(self) -> Data { + Data::new(data::string::String(self)) + } +} diff --git a/mers_lib/src/program/configs/mod.rs b/mers_lib/src/program/configs/mod.rs index 9b9f56a..8e24df7 100755 --- a/mers_lib/src/program/configs/mod.rs +++ b/mers_lib/src/program/configs/mod.rs @@ -7,6 +7,7 @@ use crate::{ program::run::CheckInfo, }; +pub mod gen; pub mod util; pub mod with_base; pub mod with_command_running; diff --git a/mers_lib/src/program/configs/util.rs b/mers_lib/src/program/configs/util.rs index eb02940..8bd077a 100644 --- a/mers_lib/src/program/configs/util.rs +++ b/mers_lib/src/program/configs/util.rs @@ -13,7 +13,7 @@ pub fn to_mers_func( data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(Info::neverused())), - out: Arc::new(move |a, _| out(a)), + out: Ok(Arc::new(move |a, _| out(a))), run: Arc::new(move |a, _| run(a)), inner_statements: None, } @@ -41,16 +41,7 @@ pub fn to_mers_func_with_in_out_types( out_type: Type, run: impl Fn(Data) -> Result + Send + Sync + 'static, ) -> data::function::Function { - to_mers_func( - move |a| { - if a.is_included_in(&in_type) { - Ok(out_type.clone()) - } else { - Err(format!("Function argument must be {in_type}, but was {a}.").into()) - } - }, - run, - ) + data::function::Function::new_static(vec![(in_type, out_type)], run) } pub fn to_mers_func_concrete_string_to_any( diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index 30a4332..de571bf 100755 --- a/mers_lib/src/program/configs/with_base.rs +++ b/mers_lib/src/program/configs/with_base.rs @@ -29,7 +29,7 @@ impl Config { .add_var("lock_update".to_string(), Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { for t in a.types.iter() { if let Some(t) = t.as_any().downcast_ref::() { if t.0.len() == 2 { @@ -61,7 +61,7 @@ impl Config { } } Ok(Type::empty_tuple()) - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let a = a.as_any().downcast_ref::().unwrap(); @@ -77,14 +77,14 @@ impl Config { .add_var("sleep".to_string(), Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| if a.is_included_in(&Type::newm(vec![ + out: Ok(Arc::new(|a, _i| if a.is_included_in(&Type::newm(vec![ Arc::new(data::int::IntT), Arc::new(data::float::FloatT), ])) { Ok(Type::empty_tuple()) } else { Err(format!("cannot call sleep with non-int or non-float argument.").into()) - }), + })), run: Arc::new(|a, i| { let a = a.get(); let mut sleep_dur = if let Some(data::int::Int(n)) = a.as_any().downcast_ref() { @@ -106,11 +106,11 @@ impl Config { .add_var("exit".to_string(), Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| if a.is_included_in_single(&data::int::IntT) { + out: Ok(Arc::new(|a, _i| if a.is_included_in_single(&data::int::IntT) { Ok(Type::empty()) } else { Err(format!("cannot call exit with non-int argument").into()) - }), + })), run: Arc::new(|a, _i| { std::process::exit(a.get().as_any().downcast_ref::().map(|i| i.0 as _).unwrap_or(1)); }), @@ -119,11 +119,11 @@ impl Config { .add_var("panic".to_string(), Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| if a.is_included_in_single(&data::string::StringT) { + out: Ok(Arc::new(|a, _i| if a.is_included_in_single(&data::string::StringT) { Ok(Type::empty()) } else { Err(format!("cannot call panic with non-string argument").into()) - }), + })), run: Arc::new(|a, _i| { Err( a @@ -141,14 +141,14 @@ impl Config { Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { for t in &a.types { if t.as_any().downcast_ref::().is_none() && t.as_any().downcast_ref::().is_none() && t.iterable().is_none() { return Err(format!("cannot get length of {t} (must be a tuple, string or iterable)").into()); } } Ok(Type::new(data::int::IntT)) - }), + })), run: Arc::new(|a, _i| { Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::() { t.0.len() as _ @@ -169,14 +169,14 @@ impl Config { Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { for t in &a.types { if t.iterable().is_none() { return Err(format!("called eq on non-iterable").into()) } } Ok(Type::new(data::bool::BoolT)) - }), + })), run: Arc::new(|a, _i| { Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() { if let Some(f) = i.next() { @@ -205,7 +205,7 @@ impl Config { Data::new(data::function::Function { info: Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone())))), + out: Ok(Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone()))))), run: Arc::new(|a, _i| { Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone()))))) }), @@ -217,8 +217,8 @@ impl Config { Data::new(data::function::Function { info: 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(format!("cannot dereference type {a}").into()) - }), + out: Ok(Arc::new(|a, _i| if let Some(v) = a.dereference() { Ok(v) } else { Err(format!("cannot dereference type {a}").into()) + })), run: Arc::new(|a, _i| { if let Some(r) = a .get() diff --git a/mers_lib/src/program/configs/with_command_running.rs b/mers_lib/src/program/configs/with_command_running.rs index c1648e8..f97f3da 100755 --- a/mers_lib/src/program/configs/with_command_running.rs +++ b/mers_lib/src/program/configs/with_command_running.rs @@ -29,7 +29,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.types.iter().all(|t| t.as_any().downcast_ref::().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![ Arc::new(data::tuple::TupleT(vec![ @@ -42,7 +42,7 @@ impl Config { } else { return Err(format!("run_command called with invalid arguments (must be (String, Iter))").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let cmd = a.as_any().downcast_ref::().unwrap(); @@ -84,7 +84,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.types.iter().all(|t| t.as_any().downcast_ref::().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![ Arc::new(ChildProcessT), @@ -93,7 +93,7 @@ impl Config { } else { return Err(format!("spawn_command called with invalid arguments (must be (String, Iter))").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let cmd = a.as_any().downcast_ref::().unwrap(); @@ -128,7 +128,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&ChildProcessT) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::bool::BoolT)])), @@ -137,7 +137,7 @@ impl Config { } else { return Err(format!("childproc_exited called on non-ChildProcess type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); @@ -156,7 +156,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&ChildProcessT) { Ok(Type::newm(vec![ Arc::new(data::int::IntT), @@ -166,7 +166,7 @@ impl Config { } else { return Err(format!("childproc_await called on non-ChildProcess type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); @@ -189,13 +189,13 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.types.iter().all(|a| a.as_any().downcast_ref::().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&ChildProcessT) && t.0[1].iterable().is_some_and(|i| i.is_included_in_single(&data::byte::ByteT)))) { Ok(Type::new(data::bool::BoolT)) } else { return Err(format!("childproc_write_bytes called on non-`(ChildProcess, Iter)` type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let tuple = a.as_any().downcast_ref::().unwrap(); @@ -218,13 +218,13 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&data::tuple::TupleT(vec![Type::new(ChildProcessT), Type::new(data::string::StringT)])) { Ok(Type::new(data::bool::BoolT)) } else { return Err(format!("childproc_write_string called on non-`(ChildProcess, String)` type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let tuple = a.as_any().downcast_ref::().unwrap(); @@ -247,7 +247,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&ChildProcessT) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])), @@ -256,7 +256,7 @@ impl Config { } else { return Err(format!("childproc_read_byte called on non-ChildProcess type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); @@ -276,7 +276,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&ChildProcessT) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])), @@ -285,7 +285,7 @@ impl Config { } else { return Err(format!("childproc_readerr_byte called on non-ChildProcess type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); @@ -305,7 +305,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&ChildProcessT) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), @@ -314,7 +314,7 @@ impl Config { } else { return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); @@ -334,7 +334,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new( CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in_single(&ChildProcessT) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), @@ -343,7 +343,7 @@ impl Config { } else { return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into()); } - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); diff --git a/mers_lib/src/program/configs/with_get.rs b/mers_lib/src/program/configs/with_get.rs index 9730fe1..1a5a27a 100755 --- a/mers_lib/src/program/configs/with_get.rs +++ b/mers_lib/src/program/configs/with_get.rs @@ -15,7 +15,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { let mut out = Type::empty(); for a in a.types.iter() { if let Some(t) = a.as_any().downcast_ref::() { @@ -45,7 +45,7 @@ impl Config { Arc::new(data::tuple::TupleT(vec![out])), Arc::new(data::tuple::TupleT(vec![])), ])) - }), + })), run: Arc::new(|a, _i| { let a = a.get(); if let (Some(v), Some(i)) = (a.get(0), a.get(1)) { diff --git a/mers_lib/src/program/configs/with_iters.rs b/mers_lib/src/program/configs/with_iters.rs index d932117..447c640 100755 --- a/mers_lib/src/program/configs/with_iters.rs +++ b/mers_lib/src/program/configs/with_iters.rs @@ -49,7 +49,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { for a in &a.types { if let Some(tuple) = a.as_any().downcast_ref::() { if let (Some(v), Some(f)) = (tuple.0.get(0), tuple.0.get(1)) { @@ -84,7 +84,7 @@ impl Config { } } Ok(Type::empty_tuple()) - }), + })), run: Arc::new(|a, _i| { if let Some(tuple) = a.get().as_any().downcast_ref::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { @@ -133,14 +133,14 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { let data = if let Some(a) = a.iterable() { a } else { return Err(format!("cannot call enumerate on non-iterable type {a}.").into()); }; Ok(Type::new(IterT::new(ItersT::Enumerate, data)?)) - }), + })), run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Enumerate, a.clone())))), inner_statements: None, }), @@ -150,14 +150,14 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { let data = if let Some(a) = a.iterable() { a } else { return Err(format!("cannot call chain on non-iterable type {a}.").into()); }; Ok(Type::new(IterT::new(ItersT::Chained, data)?)) - }), + })), run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Chained, a.clone())))), inner_statements: None, }), @@ -202,7 +202,7 @@ fn genfunc_iter_and_func( data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(move |a, _i| iter_out_arg(a, name, |f| ft(f))), + out: Ok(Arc::new(move |a, _i| iter_out_arg(a, name, |f| ft(f)))), run: Arc::new(move |a, _i| { if let Some(tuple) = a.get().as_any().downcast_ref::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { @@ -256,7 +256,9 @@ fn genfunc_iter_and_arg( data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(move |a, _i| iter_out_arg(a, name, |f: &T| ft(f), type_sample)), + out: Ok(Arc::new(move |a, _i| { + iter_out_arg(a, name, |f: &T| ft(f), type_sample) + })), run: Arc::new(move |a, _i| { if let Some(tuple) = a.get().as_any().downcast_ref::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { @@ -525,7 +527,7 @@ fn genfunc_iter_in_val_out( Function { info: crate::info::Info::neverused(), info_check: Arc::new(Mutex::new(crate::info::Info::neverused())), - out: Arc::new(move |a, _i| { + out: Ok(Arc::new(move |a, _i| { if let Some(iter_over) = a.iterable() { if iter_over.is_included_in_single(&iter_type) { Ok(out_type.clone()) @@ -535,7 +537,7 @@ fn genfunc_iter_in_val_out( } else { Err(format!("Cannot call function {name} on non-iterable type {a}.").into()) } - }), + })), run: Arc::new(run), inner_statements: None, } diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs index 8931853..fb42ff5 100755 --- a/mers_lib/src/program/configs/with_list.rs +++ b/mers_lib/src/program/configs/with_list.rs @@ -34,7 +34,7 @@ impl Config { .add_var("get_mut".to_string(), Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { let mut out = Type::empty_tuple(); for t in a.types.iter() { if let Some(t) = t.as_any().downcast_ref::() { @@ -71,7 +71,7 @@ impl Config { } } Ok(out) - }), + })), run: Arc::new(|a, _i| { let t = a.get(); let t = t.as_any().downcast_ref::().unwrap(); @@ -103,7 +103,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if let Some(a) = a.dereference() { let mut out = Type::empty(); for t in a.types.iter() { @@ -122,7 +122,7 @@ impl Config { } else { return Err(format!("pop: not a reference: {a}").into()); } - }), + })), run: Arc::new(|a, _i| { Ok(match a .get() @@ -151,7 +151,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { for t in a.types.iter() { if let Some(t) = t.as_any().downcast_ref::() { if t.0.len() != 2 { @@ -186,7 +186,7 @@ impl Config { } } Ok(Type::empty_tuple()) - }), + })), run: Arc::new(|a, _i| { let tuple = a.get(); let tuple = tuple.as_any().downcast_ref::().unwrap(); @@ -214,7 +214,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if let Some(v) = a.iterable() { Ok(Type::new(ListT(v))) } else { @@ -222,7 +222,7 @@ impl Config { "cannot iterate over type {a}" ).into()) } - }), + })), run: Arc::new(|a, _i| { if let Some(i) = a.get().iterable() { Ok(Data::new(List(i.map(|v| Ok::<_, CheckError>(Arc::new(RwLock::new(v?)))).collect::>()?))) diff --git a/mers_lib/src/program/configs/with_math.rs b/mers_lib/src/program/configs/with_math.rs index 5b4bca6..4516f3a 100755 --- a/mers_lib/src/program/configs/with_math.rs +++ b/mers_lib/src/program/configs/with_math.rs @@ -73,7 +73,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in(&Type::new(data::string::StringT)) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::float::FloatT)])), @@ -82,7 +82,7 @@ impl Config { } else { Err(format!("parse_float called on non-string type").into()) } - }), + })), run: Arc::new(|a, _i| { Ok( if let Ok(n) = a @@ -107,7 +107,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in(&Type::new(data::string::StringT)) { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])), @@ -116,7 +116,7 @@ impl Config { } else { Err(format!("parse_float called on non-string type").into()) } - }), + })), run: Arc::new(|a, _i| { Ok( if let Ok(n) = a @@ -141,7 +141,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_included_in(&Type::newm(vec![ Arc::new(data::int::IntT), Arc::new(data::float::FloatT), @@ -150,7 +150,7 @@ impl Config { } else { Err(format!("signum called on non-number type").into()) } - }), + })), run: Arc::new(|a, _i| { Ok(Data::new(data::int::Int( if let Some(n) = a.get().as_any().downcast_ref::() { @@ -257,7 +257,7 @@ fn num_iter_to_num( data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(move |a, _i| { + out: Ok(Arc::new(move |a, _i| { if let Some(a) = a.iterable() { let int_type = Type::new(data::int::IntT); if a.is_included_in(&int_type) { @@ -281,7 +281,7 @@ fn num_iter_to_num( } else { Err(format!("argument passed to {func_name} must be an iterator").into()) } - }), + })), run: Arc::new(move |a, _i| { let mut out = init; for v in a.get().iterable().unwrap() { @@ -322,7 +322,7 @@ fn two_num_tuple_to_num( data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| two_tuple_to_num_impl_check(a, func_name)), + out: Ok(Arc::new(|a, _i| two_tuple_to_num_impl_check(a, func_name))), run: Arc::new(move |a, _i| { two_tuple_to_num_impl_run(a, func_name, &func_ii, &func_if, &func_fi, &func_ff) }), @@ -408,7 +408,7 @@ fn ltgtoe_function( data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(move |a, _i| { + out: Ok(Arc::new(move |a, _i| { if let Some(iter_type) = a.iterable() { let iter_required_type = Type::newm(vec![ Arc::new(data::int::IntT), @@ -422,7 +422,7 @@ fn ltgtoe_function( } else { Err(CheckError::from(format!("Cannot use {func_name}"))) } - }), + })), run: Arc::new(move |a, _i| { let mut prev = IntOrFloatOrNothing::Nothing; for item in a.get().iterable().unwrap() { diff --git a/mers_lib/src/program/configs/with_multithreading.rs b/mers_lib/src/program/configs/with_multithreading.rs index 2de9bf5..68ef6fb 100755 --- a/mers_lib/src/program/configs/with_multithreading.rs +++ b/mers_lib/src/program/configs/with_multithreading.rs @@ -32,7 +32,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { let mut out = Type::empty(); for t in a.types.iter() { if let Some(f) = t.executable() { @@ -45,7 +45,7 @@ impl Config { } } Ok(Type::new(ThreadT(out))) - }), + })), run: Arc::new(|a, _i| { Ok(Data::new(Thread(Arc::new(Mutex::new(Ok(std::thread::spawn( move || a.get().execute(Data::empty_tuple()).unwrap(), @@ -57,14 +57,14 @@ impl Config { .add_var("thread_finished".to_string(), Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { for t in a.types.iter() { if !t.as_any().is::() { return Err(CheckError::new().msg_str(format!("Cannot call thread_finished on a value of type {t}, which isn't a thread but part of the argument {a}."))); } } Ok(Type::new(data::bool::BoolT)) - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let t = a.as_any().downcast_ref::().unwrap().0.lock().unwrap(); @@ -78,7 +78,7 @@ impl Config { .add_var("thread_await".to_string(), Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { let mut out = Type::empty(); for t in a.types.iter() { if let Some(t) = t.as_any().downcast_ref::() { @@ -88,7 +88,7 @@ impl Config { } } Ok(out) - }), + })), run: Arc::new(|a, _i| { let a = a.get(); let mut t = a.as_any().downcast_ref::().unwrap().0.lock().unwrap(); diff --git a/mers_lib/src/program/configs/with_stdio.rs b/mers_lib/src/program/configs/with_stdio.rs index 5d4ce0a..fef043e 100755 --- a/mers_lib/src/program/configs/with_stdio.rs +++ b/mers_lib/src/program/configs/with_stdio.rs @@ -24,7 +24,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| { + out: Ok(Arc::new(|a, _i| { if a.is_zero_tuple() { Ok(Type::newm(vec![ Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), @@ -36,7 +36,7 @@ impl Config { (a.to_string(), Some(EColor::FunctionArgument)), ])) } - }), + })), run: Arc::new(|_a, _i| { Ok(if let Some(Ok(line)) = std::io::stdin().lines().next() { Data::one_tuple(Data::new(data::string::String(line))) @@ -52,7 +52,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| Ok(a.clone())), + out: Ok(Arc::new(|a, _i| Ok(a.clone()))), run: Arc::new(|a, _i| { let a2 = a.get(); eprintln!("{} :: {}", a2.as_type(), a2); @@ -67,7 +67,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), + out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, _i| { eprint!("{}", a.get()); _ = std::io::stderr().lock().flush(); @@ -81,7 +81,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), + out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, _i| { eprintln!("{}", a.get()); Ok(Data::empty_tuple()) @@ -94,7 +94,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), + out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, _i| { print!("{}", a.get()); _ = std::io::stdout().lock().flush(); @@ -108,7 +108,7 @@ impl Config { Data::new(data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), + out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, _i| { println!("{}", a.get()); Ok(Data::empty_tuple()) diff --git a/mers_lib/src/program/configs/with_string.rs b/mers_lib/src/program/configs/with_string.rs index 371017e..9f6b25a 100755 --- a/mers_lib/src/program/configs/with_string.rs +++ b/mers_lib/src/program/configs/with_string.rs @@ -1,8 +1,9 @@ -use std::sync::{Arc, RwLock}; - use crate::data::{self, Data, Type}; -use super::{util, Config}; +use super::{ + gen::{function::func, AnyOrNone, IterToList, OneOf, OneOrNone}, + util, Config, +}; impl Config { /// `trim: fn` removes leading and trailing whitespace from a string @@ -17,72 +18,161 @@ impl Config { /// `to_string: fn` turns any argument into a (more or less useful) string representation /// `concat: fn` concatenates all arguments given to it. arg must be an enumerable pub fn with_string(self) -> Self { - self - .add_var("trim".to_string(), Data::new(util::to_mers_func_concrete_string_to_string(|v| v.trim().to_owned()))) - .add_var("index_of".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_int(|v, p| v.find(p).map(|v| v as _)))) - .add_var("index_of_rev".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_int(|v, p| v.rfind(p).map(|v| v as _) ))) - .add_var("starts_with".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_bool(|v, p| v.starts_with(p)))) - .add_var("ends_with".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_bool(|v, p| v.ends_with(p)))) - .add_var("str_split_once".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_string_string(|v, p| v.split_once(p).map(|(a, b)| (a.to_owned(), b.to_owned()))))) - .add_var("str_split_once_rev".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_string_string(|v, p| v.rsplit_once(p).map(|(a, b)| (a.to_owned(), b.to_owned()))))) - .add_var("str_split".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_any(Type::new(super::with_list::ListT(Type::new(data::string::StringT))), |v, p| Ok(Data::new(super::with_list::List(v.split(p).map(|v| Arc::new(RwLock::new(Data::new(data::string::String(v.to_owned()))))).collect())))))) - .add_var("concat".to_string(), Data::new(util::to_mers_func( - |a| if a.iterable().is_some() { - Ok(Type::new(data::string::StringT)) - } else { - Err(format!("concat called on non-iterable type {a}").into()) - }, - |a| Ok(Data::new(data::string::String(a.get().iterable().unwrap().map(|v| v.map(|v| v.get().to_string())).collect::>()?)))), - )) - .add_var("to_string".to_string(), Data::new(util::to_mers_func(|_a| Ok(Type::new(data::string::StringT)), - |a| Ok(Data::new(data::string::String(a.get().to_string()))) - ))) - .add_var("substring".to_string(), Data::new(util::to_mers_func( + self.add_var( + "trim".to_string(), + Data::new(func(|v: &str| Ok(v.trim().to_owned()))), + ) + // .add_var("index_of".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_int(|v, p| v.find(p).map(|v| v as _)))) + .add_var( + "index_of".to_string(), + Data::new(func(|(v, p): (&str, &str)| { + Ok(OneOrNone(v.find(p).map(|v| v as isize))) + })), + ) + // .add_var("index_of_rev".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_int(|v, p| v.rfind(p).map(|v| v as _) ))) + .add_var( + "index_of_rev".to_string(), + Data::new(func(|(v, p): (&str, &str)| { + Ok(OneOrNone(v.rfind(p).map(|v| v as isize))) + })), + ) + // .add_var("starts_with".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_bool(|v, p| v.starts_with(p)))) + .add_var( + "starts_with".to_string(), + Data::new(func(|(v, p): (&str, &str)| Ok(v.starts_with(p)))), + ) + // .add_var("ends_with".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_bool(|v, p| v.ends_with(p)))) + .add_var( + "ends_with".to_string(), + Data::new(func(|(v, p): (&str, &str)| Ok(v.ends_with(p)))), + ) + // .add_var("str_split_once".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_string_string(|v, p| v.split_once(p).map(|(a, b)| (a.to_owned(), b.to_owned()))))) + .add_var( + "str_split_once".to_string(), + Data::new(func(|(v, p): (&str, &str)| { + Ok(AnyOrNone( + v.split_once(p).map(|(a, b)| (a.to_owned(), b.to_owned())), + )) + })), + ) + // .add_var("str_split_once_rev".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_string_string(|v, p| v.rsplit_once(p).map(|(a, b)| (a.to_owned(), b.to_owned()))))) + .add_var( + "str_split_once_rev".to_string(), + Data::new(func(|(v, p): (&str, &str)| { + Ok(AnyOrNone( + v.rsplit_once(p).map(|(a, b)| (a.to_owned(), b.to_owned())), + )) + })), + ) + .add_var( + "str_split".to_string(), + Data::new(func(|(v, p): (&str, &str)| { + Ok(IterToList(v.split(p).map(|v| v.to_owned()))) + })), + ) + // .add_var("str_split".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_any(Type::new(super::with_list::ListT(Type::new(data::string::StringT))), |v, p| Ok(Data::new(super::with_list::List(v.split(p).map(|v| Arc::new(RwLock::new(Data::new(data::string::String(v.to_owned()))))).collect())))))) + .add_var( + "concat".to_string(), + Data::new(util::to_mers_func( |a| { - for t in a.types.iter() { - if let Some(t) = t.as_any().downcast_ref::() { - if t.0.len() != 2 && t.0.len() != 3 { - return Err(format!("cannot call substring with tuple argument of len != 3").into()); - } - if !t.0[0].is_included_in_single(&data::string::StringT) { - return Err(format!("cannot call substring with tuple argument that isn't (*string*, int, int)").into()); - } - if !t.0[1].is_included_in_single(&data::int::IntT) { - return Err(format!("cannot call substring with tuple argument that isn't (string, *int*, int)").into()); - } - if t.0.len() > 2 && !t.0[2].is_included_in_single(&data::int::IntT) { - return Err(format!("cannot call substring with tuple argument that isn't (string, int, *int*)").into()); - } - } else { - return Err(format!("cannot call substring with non-tuple argument.").into()); - } - } - Ok(if a.types.is_empty() { - Type::empty() + if a.iterable().is_some() { + Ok(Type::new(data::string::StringT)) } else { - Type::new(data::string::StringT) - }) + Err(format!("concat called on non-iterable type {a}").into()) + } }, |a| { - let tuple = a.get(); - let tuple = tuple.as_any().downcast_ref::().expect("called substring with non-tuple arg"); - let (s, start, end) = (&tuple.0[0], &tuple.0[1], tuple.0.get(2)); - let s = s.get(); - let s = &s.as_any().downcast_ref::().unwrap().0; - let start = start.get(); - let start = start.as_any().downcast_ref::().unwrap().0; - let start = if start < 0 { s.len().saturating_sub(start.abs() as usize) } else { start as usize }; - let end = end - .map(|end| end.get()) - .map(|end| end.as_any().downcast_ref::().unwrap().0) - .map(|i| if i < 0 { s.len().saturating_sub(i.abs() as usize) } else { i as usize }) - .unwrap_or(usize::MAX); - let end = end.min(s.len()); - if end < start { - return Ok(Data::new(data::string::String(String::new()))); - } - Ok(Data::new(data::string::String(s[start..end].to_owned()))) - }) - )) + Ok(Data::new(data::string::String( + a.get() + .iterable() + .unwrap() + .map(|v| v.map(|v| v.get().to_string())) + .collect::>()?, + ))) + }, + )), + ) + .add_var( + "to_string".to_string(), + Data::new(util::to_mers_func( + |_a| Ok(Type::new(data::string::StringT)), + |a| Ok(Data::new(data::string::String(a.get().to_string()))), + )), + ) + // .add_var("substring".to_string(), Data::new(util::to_mers_func( + // |a| { + // for t in a.types.iter() { + // if let Some(t) = t.as_any().downcast_ref::() { + // if t.0.len() != 2 && t.0.len() != 3 { + // return Err(format!("cannot call substring with tuple argument of len != 3").into()); + // } + // if !t.0[0].is_included_in_single(&data::string::StringT) { + // return Err(format!("cannot call substring with tuple argument that isn't (*string*, int, int)").into()); + // } + // if !t.0[1].is_included_in_single(&data::int::IntT) { + // return Err(format!("cannot call substring with tuple argument that isn't (string, *int*, int)").into()); + // } + // if t.0.len() > 2 && !t.0[2].is_included_in_single(&data::int::IntT) { + // return Err(format!("cannot call substring with tuple argument that isn't (string, int, *int*)").into()); + // } + // } else { + // return Err(format!("cannot call substring with non-tuple argument.").into()); + // } + // } + // Ok(if a.types.is_empty() { + // Type::empty() + // } else { + // Type::new(data::string::StringT) + // }) + // }, + // |a| { + // let tuple = a.get(); + // let tuple = tuple.as_any().downcast_ref::().expect("called substring with non-tuple arg"); + // let (s, start, end) = (&tuple.0[0], &tuple.0[1], tuple.0.get(2)); + // let s = s.get(); + // let s = &s.as_any().downcast_ref::().unwrap().0; + // let start = start.get(); + // let start = start.as_any().downcast_ref::().unwrap().0; + // let start = if start < 0 { s.len().saturating_sub(start.abs() as usize) } else { start as usize }; + // let end = end + // .map(|end| end.get()) + // .map(|end| end.as_any().downcast_ref::().unwrap().0) + // .map(|i| if i < 0 { s.len().saturating_sub(i.abs() as usize) } else { i as usize }) + // .unwrap_or(usize::MAX); + // let end = end.min(s.len()); + // if end < start { + // return Ok(Data::new(data::string::String(String::new()))); + // } + // Ok(Data::new(data::string::String(s[start..end].to_owned()))) + // }) + // )) + .add_var( + "substring".to_string(), + Data::new(func(|v: OneOf<(&str, isize), (&str, isize, isize)>| { + let (s, start, end) = match v { + OneOf::A((t, s)) => (t, s, None), + OneOf::B((t, s, e)) => (t, s, Some(e)), + }; + let start = if start < 0 { + s.len().saturating_sub(start.abs() as usize) + } else { + start as usize + }; + let end = end + .map(|i| { + if i < 0 { + s.len().saturating_sub(i.abs() as usize) + } else { + i as usize + } + }) + .unwrap_or(usize::MAX); + let end = end.min(s.len()); + if end < start { + return Ok(String::new()); + } + Ok(s[start..end].to_owned()) + })), + ) } } diff --git a/mers_lib/src/program/parsed/function.rs b/mers_lib/src/program/parsed/function.rs index c7b5bbc..25562b6 100755 --- a/mers_lib/src/program/parsed/function.rs +++ b/mers_lib/src/program/parsed/function.rs @@ -38,10 +38,10 @@ impl MersStatement for Function { func_no_info: data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(move |a, i| { + out: Ok(Arc::new(move |a, i| { arg2.check(i, Some(a))?; Ok(run2.check(i, None)?) - }), + })), run: Arc::new(move |arg, info| { data::defs::assign(&arg, &arg_target.run(info)?); run.run(info) diff --git a/mers_lib/src/program/parsed/include_mers.rs b/mers_lib/src/program/parsed/include_mers.rs index cbb93a9..170a629 100644 --- a/mers_lib/src/program/parsed/include_mers.rs +++ b/mers_lib/src/program/parsed/include_mers.rs @@ -56,7 +56,9 @@ impl MersStatement for IncludeMers { func_no_info: data::function::Function { info: info::Info::neverused(), info_check: Arc::new(Mutex::new(info::Info::neverused())), - out: Arc::new(move |_, i| compiled.check(&mut i.duplicate(), None)), + out: Ok(Arc::new(move |_, i| { + compiled.check(&mut i.duplicate(), None) + })), run: Arc::new(move |_, i| compiled2.run(&mut i.duplicate())), inner_statements: None, }, diff --git a/mers_lib/src/program/run/function.rs b/mers_lib/src/program/run/function.rs index 838cd23..61fea62 100755 --- a/mers_lib/src/program/run/function.rs +++ b/mers_lib/src/program/run/function.rs @@ -34,7 +34,7 @@ impl MersStatement for Function { self.pos_in_src.clone() } fn inner_statements(&self) -> Vec<&dyn MersStatement> { - if let Some((a, b)) = &self.func_no_info.inner_statements { + if let Some((a, b)) = &self.func_no_info.inner_statements() { vec![a.as_ref().as_ref(), b.as_ref().as_ref()] } else { vec![]