better now yay

This commit is contained in:
Mark 2024-07-03 12:54:57 +02:00
parent 08a82733e9
commit 3a53290f9b
11 changed files with 368 additions and 397 deletions

View File

@ -66,7 +66,7 @@ pub trait StaticMersFunc: Sized + 'static + Send + Sync {
} }
} }
pub struct TwoFuncs<A: StaticMersFunc, B: StaticMersFunc>(pub A, pub B); pub struct Funcs<A: StaticMersFunc, B: StaticMersFunc>(pub A, pub B);
pub trait Func: Send + Sync + 'static { pub trait Func: Send + Sync + 'static {
type I: FromMersData; type I: FromMersData;
@ -138,7 +138,7 @@ impl<F: Func + ?Sized> StaticMersFunc for Box<F> {
} }
} }
impl<A: StaticMersFunc, B: StaticMersFunc> StaticMersFunc for TwoFuncs<A, B> { impl<A: StaticMersFunc, B: StaticMersFunc> StaticMersFunc for Funcs<A, B> {
fn types() -> Vec<(Type, Type)> { fn types() -> Vec<(Type, Type)> {
let mut o = A::types(); let mut o = A::types();
for t in B::types() { for t in B::types() {

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use crate::{ use crate::{
data::{self, Data, Type}, data::{self, Data, MersData, Type},
errors::CheckError, errors::CheckError,
info::Local, info::Local,
program::run::CheckInfo, program::run::CheckInfo,
@ -89,11 +89,15 @@ impl Config {
} }
/// Add a variable. Its type will be that of the value stored in `val`. /// Add a variable. Its type will be that of the value stored in `val`.
pub fn add_var(self, name: String, val: Data) -> Self { pub fn add_var(self, name: impl Into<String>, val: impl MersData) -> Self {
let t = val.get().as_type(); let t = val.as_type();
self.add_var_arc(name, Arc::new(RwLock::new(val)), t) self.add_var_from_arc(name.into(), Arc::new(RwLock::new(Data::new(val))), t)
} }
pub fn add_var_arc( pub fn add_var_from_data(self, name: String, val: Data) -> Self {
let t = val.get().as_type();
self.add_var_from_arc(name, Arc::new(RwLock::new(val)), t)
}
pub fn add_var_from_arc(
mut self, mut self,
name: String, name: String,
val: Arc<RwLock<Data>>, val: Arc<RwLock<Data>>,

View File

@ -27,7 +27,7 @@ impl Config {
/// `lock_update: fn` locks the value of a reference so you can exclusively modify it: &var.lock_update(v -> (v, 1).sum) /// `lock_update: fn` locks the value of a reference so you can exclusively modify it: &var.lock_update(v -> (v, 1).sum)
pub fn with_base(self) -> Self { pub fn with_base(self) -> Self {
self self
.add_var("lock_update".to_string(), Data::new(data::function::Function { .add_var("lock_update", data::function::Function {
info: Info::neverused(), info: Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -74,8 +74,8 @@ impl Config {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
})) })
.add_var("sleep".to_owned(), Data::new(func(|dur: OneOf<isize, f64>, i| { .add_var("sleep", func(|dur: OneOf<isize, 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.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)),
@ -86,16 +86,16 @@ impl Config {
} }
std::thread::sleep(sleep_dur); std::thread::sleep(sleep_dur);
Ok(()) Ok(())
}))) }))
.add_var("exit".to_string(), Data::new(func_end(|code: isize, _| { .add_var("exit", func_end(|code: isize, _| {
std::process::exit(code.try_into().unwrap_or(255)); std::process::exit(code.try_into().unwrap_or(255));
}))) }))
.add_var("panic".to_string(), Data::new(func_err(|message: &str, _| { .add_var("panic", func_err(|message: &str, _| {
CheckError::from(message) CheckError::from(message)
}))) }))
.add_var( .add_var(
"len".to_string(), "len",
Data::new(data::function::Function { data::function::Function {
info: Info::neverused(), info: Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -119,11 +119,11 @@ impl Config {
}))) })))
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"eq".to_string(), "eq",
Data::new(data::function::Function { data::function::Function {
info: Info::neverused(), info: Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -155,11 +155,11 @@ impl Config {
}))) })))
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"mkref".to_string(), "mkref",
Data::new(data::function::Function { data::function::Function {
info: Info::neverused(), info: Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(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()))))),
@ -167,11 +167,11 @@ impl Config {
Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone()))))) Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone())))))
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"deref".to_string(), "deref",
Data::new(data::function::Function { data::function::Function {
info: Info::neverused(), info: Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(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())
@ -188,7 +188,7 @@ impl Config {
} }
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
} }
} }

View File

@ -25,8 +25,8 @@ impl Config {
self self
.add_type("ChildProcess".to_owned(), Ok(Arc::new(Type::new(ChildProcessT)))) .add_type("ChildProcess".to_owned(), Ok(Arc::new(Type::new(ChildProcessT))))
.add_var( .add_var(
"run_command".to_string(), "run_command",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -77,11 +77,11 @@ impl Config {
} }
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"spawn_command".to_string(), "spawn_command",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -121,11 +121,11 @@ impl Config {
} }
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_exited".to_string(), "childproc_exited",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -149,11 +149,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_await".to_string(), "childproc_await",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -182,11 +182,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_write_bytes".to_string(), "childproc_write_bytes",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -211,11 +211,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_write_string".to_string(), "childproc_write_string",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -240,11 +240,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_read_byte".to_string(), "childproc_read_byte",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -269,11 +269,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_readerr_byte".to_string(), "childproc_readerr_byte",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -298,11 +298,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_read_line".to_string(), "childproc_read_line",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -327,11 +327,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"childproc_readerr_line".to_string(), "childproc_readerr_line",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new( CheckInfo::neverused())), info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -356,7 +356,7 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
} }
} }

View File

@ -11,8 +11,8 @@ impl Config {
/// `get: fn` is used to retrieve elements from collections /// `get: fn` is used to retrieve elements from collections
pub fn with_get(self) -> Self { pub fn with_get(self) -> Self {
self.add_var( self.add_var(
"get".to_string(), "get",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -70,7 +70,7 @@ impl Config {
} }
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
} }
} }

View File

@ -28,25 +28,25 @@ impl Config {
/// `all: fn` returns true if all elements of the iterator are true /// `all: fn` returns true if all elements of the iterator are true
pub fn with_iters(self) -> Self { pub fn with_iters(self) -> Self {
self self
.add_var("any".to_string(), Data::new(genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| { .add_var("any", genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| {
for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) { for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
if v? { if v? {
return Ok(Data::new(data::bool::Bool(true))); return Ok(Data::new(data::bool::Bool(true)));
} }
} }
Ok(Data::new(data::bool::Bool(false))) Ok(Data::new(data::bool::Bool(false)))
}))) }))
.add_var("all".to_string(), Data::new(genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| { .add_var("all", genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| {
for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) { for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
if !v? { if !v? {
return Ok(Data::new(data::bool::Bool(false))); return Ok(Data::new(data::bool::Bool(false)));
} }
} }
Ok(Data::new(data::bool::Bool(true))) Ok(Data::new(data::bool::Bool(true)))
}))) }))
.add_var( .add_var(
"for_each".to_string(), "for_each",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -107,30 +107,30 @@ impl Config {
} }
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"map".to_string(), "map",
Data::new(genfunc_iter_and_func("map", ItersT::Map, Iters::Map)) genfunc_iter_and_func("map", ItersT::Map, Iters::Map)
) )
.add_var( .add_var(
"filter".to_string(), "filter",
Data::new(genfunc_iter_and_func("filter", ItersT::Filter, Iters::Filter)), genfunc_iter_and_func("filter", ItersT::Filter, Iters::Filter),
) )
.add_var( .add_var(
"filter_map".to_string(), "filter_map",
Data::new(genfunc_iter_and_func("filter_map", ItersT::FilterMap, Iters::FilterMap)), genfunc_iter_and_func("filter_map", ItersT::FilterMap, Iters::FilterMap),
) )
.add_var( .add_var(
"map_while".to_string(), "map_while",
Data::new(genfunc_iter_and_func("map_while", ItersT::MapWhile, Iters::MapWhile)), genfunc_iter_and_func("map_while", ItersT::MapWhile, Iters::MapWhile),
) )
.add_var("take".to_string(), Data::new(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) as _)
}, &data::int::IntT))) }, &data::int::IntT))
.add_var( .add_var(
"enumerate".to_string(), "enumerate",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -143,11 +143,11 @@ impl Config {
})), })),
run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Enumerate, a.clone())))), run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Enumerate, a.clone())))),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"chain".to_string(), "chain",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -160,7 +160,7 @@ impl Config {
})), })),
run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Chained, a.clone())))), run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Chained, a.clone())))),
inner_statements: None, inner_statements: None,
}), },
) )
} }
} }

View File

@ -31,7 +31,7 @@ impl Config {
let srca = Arc::new(src.clone()); let srca = Arc::new(src.clone());
let t = crate::parsing::types::parse_type(&mut src, &srca)?; let t = crate::parsing::types::parse_type(&mut src, &srca)?;
Ok(Arc::new(Type::new(ListT(crate::parsing::types::type_from_parsed(&t, i)?))))}))) Ok(Arc::new(Type::new(ListT(crate::parsing::types::type_from_parsed(&t, i)?))))})))
.add_var("get_mut".to_string(), Data::new(data::function::Function { .add_var("get_mut", data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -97,10 +97,10 @@ impl Config {
Ok(o) Ok(o)
}), }),
inner_statements: None, inner_statements: None,
})) })
.add_var( .add_var(
"pop".to_string(), "pop",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -144,11 +144,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"push".to_string(), "push",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -207,11 +207,11 @@ impl Config {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"as_list".to_string(), "as_list",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -231,7 +231,7 @@ impl Config {
} }
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
} }
} }

View File

@ -11,7 +11,7 @@ use crate::{
use super::{ use super::{
gen::{ gen::{
function::{fun, func, StaticMersFunc, TwoFuncs}, function::{fun, func, Funcs, StaticMersFunc},
OneOf, OneOrNone, OneOf, OneOrNone,
}, },
Config, Config,
@ -50,60 +50,60 @@ impl Config {
/// `round_ties_even_to_int: fn` round ties (x.5) to the nearest even number, return the result as an Int (saturates at the Int boundaries, hence the to_int instead of as_int) /// `round_ties_even_to_int: fn` round ties (x.5) to the nearest even number, return the result as an Int (saturates at the Int boundaries, hence the to_int instead of as_int)
pub fn with_math(self) -> Self { pub fn with_math(self) -> Self {
self.add_var( self.add_var(
"parse_float".to_owned(), "parse_float",
Data::new(func(|n: &str, _| Ok(OneOrNone(n.parse::<f64>().ok())))), func(|n: &str, _| Ok(OneOrNone(n.parse::<f64>().ok()))),
) )
.add_var( .add_var(
"parse_int".to_owned(), "parse_int",
Data::new(func(|n: &str, _| Ok(OneOrNone(n.parse::<isize>().ok())))), func(|n: &str, _| Ok(OneOrNone(n.parse::<isize>().ok()))),
) )
.add_var( .add_var(
"lt".to_string(), "lt",
Data::new(func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| { func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| {
Ok(match v { Ok(match v {
(OneOf::A(a), OneOf::A(b)) => a < b, (OneOf::A(a), OneOf::A(b)) => a < b,
(OneOf::A(a), OneOf::B(b)) => (a as f64) < b, (OneOf::A(a), OneOf::B(b)) => (a as f64) < b,
(OneOf::B(a), OneOf::A(b)) => a < (b as f64), (OneOf::B(a), OneOf::A(b)) => a < (b as f64),
(OneOf::B(a), OneOf::B(b)) => a < b, (OneOf::B(a), OneOf::B(b)) => a < b,
}) })
})), }),
) )
.add_var( .add_var(
"gt".to_string(), "gt",
Data::new(func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| { func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| {
Ok(match v { Ok(match v {
(OneOf::A(a), OneOf::A(b)) => a > b, (OneOf::A(a), OneOf::A(b)) => a > b,
(OneOf::A(a), OneOf::B(b)) => (a as f64) > b, (OneOf::A(a), OneOf::B(b)) => (a as f64) > b,
(OneOf::B(a), OneOf::A(b)) => a > (b as f64), (OneOf::B(a), OneOf::A(b)) => a > (b as f64),
(OneOf::B(a), OneOf::B(b)) => a > b, (OneOf::B(a), OneOf::B(b)) => a > b,
}) })
})), }),
) )
.add_var( .add_var(
"ltoe".to_string(), "ltoe",
Data::new(func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| { func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| {
Ok(match v { Ok(match v {
(OneOf::A(a), OneOf::A(b)) => a <= b, (OneOf::A(a), OneOf::A(b)) => a <= b,
(OneOf::A(a), OneOf::B(b)) => (a as f64) <= b, (OneOf::A(a), OneOf::B(b)) => (a as f64) <= b,
(OneOf::B(a), OneOf::A(b)) => a <= (b as f64), (OneOf::B(a), OneOf::A(b)) => a <= (b as f64),
(OneOf::B(a), OneOf::B(b)) => a <= b, (OneOf::B(a), OneOf::B(b)) => a <= b,
}) })
})), }),
) )
.add_var( .add_var(
"gtoe".to_string(), "gtoe",
Data::new(func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| { func(|v: (OneOf<isize, f64>, OneOf<isize, f64>), _| {
Ok(match v { Ok(match v {
(OneOf::A(a), OneOf::A(b)) => a >= b, (OneOf::A(a), OneOf::A(b)) => a >= b,
(OneOf::A(a), OneOf::B(b)) => (a as f64) >= b, (OneOf::A(a), OneOf::B(b)) => (a as f64) >= b,
(OneOf::B(a), OneOf::A(b)) => a >= (b as f64), (OneOf::B(a), OneOf::A(b)) => a >= (b as f64),
(OneOf::B(a), OneOf::B(b)) => a >= b, (OneOf::B(a), OneOf::B(b)) => a >= b,
}) })
})), }),
) )
.add_var( .add_var(
"signum".to_string(), "signum",
Data::new(func(|n: OneOf<isize, f64>, _| { func(|n: OneOf<isize, f64>, _| {
Ok(match n { Ok(match n {
OneOf::A(n) => n.signum(), OneOf::A(n) => n.signum(),
OneOf::B(n) => { OneOf::B(n) => {
@ -116,216 +116,192 @@ impl Config {
} }
} }
}) })
})), }),
) )
.add_var( .add_var(
"add".to_string(), "add",
Data::new(num_iter_to_num("sum", Ok(0), |a, v| match (a, v) { num_iter_to_num("sum", Ok(0), |a, v| match (a, v) {
(Ok(a), Ok(v)) => Ok(a + v), (Ok(a), Ok(v)) => Ok(a + v),
(Ok(a), Err(v)) => Err(a as f64 + v), (Ok(a), Err(v)) => Err(a as f64 + v),
(Err(a), Ok(v)) => Err(a + v as f64), (Err(a), Ok(v)) => Err(a + v as f64),
(Err(a), Err(v)) => Err(a + v), (Err(a), Err(v)) => Err(a + v),
})), }),
) )
.add_var( .add_var(
"sub".to_string(), "sub",
Data::new( Funcs(
TwoFuncs( fun(|(n, d): (isize, isize), _| Ok(n.wrapping_sub(d))),
fun(|(n, d): (isize, isize), _| Ok(n.wrapping_sub(d))), fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| {
fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| { let n = match n {
let n = match n { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; let d = match d {
let d = match d { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; Ok(n - d)
Ok(n - d) }),
}), )
) .mers_func(),
.mers_func(),
),
) )
.add_var( .add_var(
"mul".to_string(), "mul",
Data::new(num_iter_to_num("sum", Ok(1), |a, v| match (a, v) { num_iter_to_num("sum", Ok(1), |a, v| match (a, v) {
(Ok(a), Ok(v)) => Ok(a * v), (Ok(a), Ok(v)) => Ok(a * v),
(Ok(a), Err(v)) => Err(a as f64 * v), (Ok(a), Err(v)) => Err(a as f64 * v),
(Err(a), Ok(v)) => Err(a * v as f64), (Err(a), Ok(v)) => Err(a * v as f64),
(Err(a), Err(v)) => Err(a * v), (Err(a), Err(v)) => Err(a * v),
})), }),
) )
.add_var( .add_var(
"div".to_string(), "div",
Data::new( Funcs(
TwoFuncs( fun(|(n, d): (isize, isize), _| {
fun(|(n, d): (isize, isize), _| { n.checked_div(d)
n.checked_div(d) .ok_or_else(|| CheckError::from("attempted to divide by zero"))
.ok_or_else(|| CheckError::from("attempted to divide by zero")) }),
}), fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| {
fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| { let n = match n {
let n = match n { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; let d = match d {
let d = match d { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; Ok(n / d)
Ok(n / d) }),
}), )
) .mers_func(),
.mers_func(),
),
) )
.add_var( .add_var(
"remainder".to_string(), "remainder",
Data::new( Funcs(
TwoFuncs( fun(|(n, d): (isize, isize), _| {
fun(|(n, d): (isize, isize), _| { n.checked_rem(d).ok_or_else(|| {
n.checked_rem(d).ok_or_else(|| { CheckError::from(
CheckError::from( "attempted to calculate remainder with zero, or overflow occured",
"attempted to calculate remainder with zero, or overflow occured", )
) })
}) }),
}), fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| {
fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| { let n = match n {
let n = match n { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; let d = match d {
let d = match d { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; Ok(n.rem(d))
Ok(n.rem(d)) }),
}), )
) .mers_func(),
.mers_func(),
),
) )
.add_var( .add_var(
"modulo".to_string(), "modulo",
Data::new( Funcs(
TwoFuncs( fun(|(n, d): (isize, isize), _| {
fun(|(n, d): (isize, isize), _| { n.checked_rem_euclid(d).ok_or_else(|| {
n.checked_rem_euclid(d).ok_or_else(|| { CheckError::from(
CheckError::from( "attempted to perform modulo with zero, or overflow occured",
"attempted to perform modulo with zero, or overflow occured", )
) })
}) }),
}), fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| {
fun(|(n, d): (OneOf<isize, f64>, OneOf<isize, f64>), _| { let n = match n {
let n = match n { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; let d = match d {
let d = match d { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; Ok(n.rem_euclid(d))
Ok(n.rem_euclid(d)) }),
}), )
) .mers_func(),
.mers_func(),
),
) )
.add_var( .add_var(
"abs".to_string(), "abs",
Data::new( Funcs(
TwoFuncs( fun(|v: isize, _| Ok(v.saturating_abs())),
fun(|v: isize, _| Ok(v.saturating_abs())), fun(|v: f64, _| Ok(v.abs())),
fun(|v: f64, _| Ok(v.abs())), )
) .mers_func(),
.mers_func(),
),
) )
.add_var( .add_var(
"pow".to_string(), "pow",
Data::new( Funcs(
TwoFuncs( fun(|(l, r): (isize, isize), _| Ok(l.pow(r.try_into().unwrap_or(u32::MAX)))),
fun(|(l, r): (isize, isize), _| Ok(l.pow(r.try_into().unwrap_or(u32::MAX)))), fun(|(l, r): (OneOf<isize, f64>, OneOf<isize, f64>), _| {
fun(|(l, r): (OneOf<isize, f64>, OneOf<isize, f64>), _| { let l = match l {
let l = match l { OneOf::A(v) => v as f64,
OneOf::A(v) => v as f64, OneOf::B(v) => v,
OneOf::B(v) => v, };
}; Ok(match r {
Ok(match r { OneOf::A(r) => {
OneOf::A(r) => { if let Ok(r) = r.try_into() {
if let Ok(r) = r.try_into() { l.powi(r)
l.powi(r) } else {
} else { l.powf(r as f64)
l.powf(r as f64)
}
} }
OneOf::B(r) => l.powf(r), }
}) OneOf::B(r) => l.powf(r),
}), })
) }),
.mers_func(), )
), .mers_func(),
) )
.add_var( .add_var(
"as_float".to_owned(), "as_float",
Data::new(func(|v: OneOf<isize, f64>, _| { func(|v: OneOf<isize, f64>, _| {
Ok(match v { Ok(match v {
OneOf::A(v) => v as f64, OneOf::A(v) => v as f64,
OneOf::B(v) => v, OneOf::B(v) => v,
}) })
})), }),
) )
.add_var( .add_var(
"round_as_float".to_owned(), "round_as_float",
Data::new(func(|v: f64, _| -> Result<f64, _> { Ok(v.round()) })), func(|v: f64, _| -> Result<f64, _> { Ok(v.round()) }),
) )
.add_var( .add_var(
"ceil_as_float".to_owned(), "ceil_as_float",
Data::new(func(|v: f64, _| -> Result<f64, _> { Ok(v.ceil()) })), func(|v: f64, _| -> Result<f64, _> { Ok(v.ceil()) }),
) )
.add_var( .add_var(
"floor_as_float".to_owned(), "floor_as_float",
Data::new(func(|v: f64, _| -> Result<f64, _> { Ok(v.floor()) })), func(|v: f64, _| -> Result<f64, _> { Ok(v.floor()) }),
) )
.add_var( .add_var(
"truncate_as_float".to_owned(), "truncate_as_float",
Data::new(func(|v: f64, _| -> Result<f64, _> { Ok(v.trunc()) })), func(|v: f64, _| -> Result<f64, _> { Ok(v.trunc()) }),
) )
.add_var( .add_var(
"round_ties_even_as_float".to_owned(), "round_ties_even_as_float",
Data::new(func(|v: f64, _| -> Result<f64, _> { func(|v: f64, _| -> Result<f64, _> { Ok(v.round_ties_even()) }),
Ok(v.round_ties_even())
})),
) )
.add_var( .add_var(
"round_to_int".to_owned(), "round_to_int",
Data::new(func(|v: f64, _| -> Result<isize, _> { func(|v: f64, _| -> Result<isize, _> { Ok(isize_from(v.round())) }),
Ok(isize_from(v.round()))
})),
) )
.add_var( .add_var(
"ceil_to_int".to_owned(), "ceil_to_int",
Data::new(func(|v: f64, _| -> Result<isize, _> { func(|v: f64, _| -> Result<isize, _> { Ok(isize_from(v.ceil())) }),
Ok(isize_from(v.ceil()))
})),
) )
.add_var( .add_var(
"floor_to_int".to_owned(), "floor_to_int",
Data::new(func(|v: f64, _| -> Result<isize, _> { func(|v: f64, _| -> Result<isize, _> { Ok(isize_from(v.floor())) }),
Ok(isize_from(v.floor()))
})),
) )
.add_var( .add_var(
"truncate_to_int".to_owned(), "truncate_to_int",
Data::new(func(|v: f64, _| -> Result<isize, _> { func(|v: f64, _| -> Result<isize, _> { Ok(isize_from(v.trunc())) }),
Ok(isize_from(v.trunc()))
})),
) )
.add_var( .add_var(
"round_ties_even_to_int".to_owned(), "round_ties_even_to_int".to_owned(),
Data::new(func(|v: f64, _| -> Result<isize, _> { func(|v: f64, _| -> Result<isize, _> { Ok(isize_from(v.round_ties_even())) }),
Ok(isize_from(v.round_ties_even()))
})),
) )
} }
} }

View File

@ -28,8 +28,8 @@ impl Config {
})), })),
) )
.add_var( .add_var(
"thread".to_string(), "thread",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -52,9 +52,9 @@ impl Config {
))))))) )))))))
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var("thread_finished".to_string(), Data::new(data::function::Function { .add_var("thread_finished", data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -74,8 +74,8 @@ impl Config {
}))) })))
}), }),
inner_statements: None, inner_statements: None,
})) })
.add_var("thread_await".to_string(), Data::new(data::function::Function { .add_var("thread_await", data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -100,7 +100,7 @@ impl Config {
d d
}), }),
inner_statements: None, inner_statements: None,
})) })
} }
} }

View File

@ -20,8 +20,8 @@ impl Config {
/// `read_line: fn` reads a line from stdin and returns it /// `read_line: fn` reads a line from stdin and returns it
pub fn with_stdio(self) -> Self { pub fn with_stdio(self) -> Self {
self.add_var( self.add_var(
"read_line".to_string(), "read_line",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
@ -45,11 +45,11 @@ impl Config {
}) })
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"debug".to_string(), "debug",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|a, _i| Ok(a.clone()))), out: Ok(Arc::new(|a, _i| Ok(a.clone()))),
@ -60,11 +60,11 @@ impl Config {
Ok(a) Ok(a)
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"eprint".to_string(), "eprint",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
@ -74,11 +74,11 @@ impl Config {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"eprintln".to_string(), "eprintln",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
@ -87,11 +87,11 @@ impl Config {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"print".to_string(), "print",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
@ -101,11 +101,11 @@ impl Config {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
.add_var( .add_var(
"println".to_string(), "println",
Data::new(data::function::Function { data::function::Function {
info: program::run::Info::neverused(), info: program::run::Info::neverused(),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
@ -114,7 +114,7 @@ impl Config {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), },
) )
} }
} }

View File

@ -18,107 +18,98 @@ impl Config {
/// `to_string: fn` turns any argument into a (more or less useful) string representation /// `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 /// `concat: fn` concatenates all arguments given to it. arg must be an enumerable
pub fn with_string(self) -> Self { pub fn with_string(self) -> Self {
self.add_var( self.add_var("trim", func(|v: &str, _| Ok(v.trim().to_owned())))
"trim".to_string(), .add_var(
Data::new(func(|v: &str, _| Ok(v.trim().to_owned()))), "index_of",
) func(|(v, p): (&str, &str), _| Ok(OneOrNone(v.find(p).map(|v| v as isize)))),
.add_var( )
"index_of".to_string(), .add_var(
Data::new(func(|(v, p): (&str, &str), _| { "index_of_rev",
Ok(OneOrNone(v.find(p).map(|v| v as isize))) func(|(v, p): (&str, &str), _| Ok(OneOrNone(v.rfind(p).map(|v| v as isize)))),
})), )
) .add_var(
.add_var( "starts_with",
"index_of_rev".to_string(), func(|(v, p): (&str, &str), _| Ok(v.starts_with(p))),
Data::new(func(|(v, p): (&str, &str), _| { )
Ok(OneOrNone(v.rfind(p).map(|v| v as isize))) .add_var(
})), "ends_with",
) func(|(v, p): (&str, &str), _| Ok(v.ends_with(p))),
.add_var( )
"starts_with".to_string(), .add_var(
Data::new(func(|(v, p): (&str, &str), _| Ok(v.starts_with(p)))), "str_split_once",
) func(|(v, p): (&str, &str), _| {
.add_var( Ok(AnyOrNone(
"ends_with".to_string(), v.split_once(p).map(|(a, b)| (a.to_owned(), b.to_owned())),
Data::new(func(|(v, p): (&str, &str), _| Ok(v.ends_with(p)))), ))
) }),
.add_var( )
"str_split_once".to_string(), .add_var(
Data::new(func(|(v, p): (&str, &str), _| { "str_split_once_rev",
Ok(AnyOrNone( func(|(v, p): (&str, &str), _| {
v.split_once(p).map(|(a, b)| (a.to_owned(), b.to_owned())), Ok(AnyOrNone(
)) v.rsplit_once(p).map(|(a, b)| (a.to_owned(), b.to_owned())),
})), ))
) }),
.add_var( )
"str_split_once_rev".to_string(), .add_var(
Data::new(func(|(v, p): (&str, &str), _| { "str_split",
Ok(AnyOrNone( func(|(v, p): (&str, &str), _| Ok(IterToList(v.split(p).map(|v| v.to_owned())))),
v.rsplit_once(p).map(|(a, b)| (a.to_owned(), b.to_owned())), )
)) .add_var(
})), "concat",
) util::to_mers_func(
.add_var( |a| {
"str_split".to_string(), if a.iterable().is_some() {
Data::new(func(|(v, p): (&str, &str), _| { Ok(Type::new(data::string::StringT))
Ok(IterToList(v.split(p).map(|v| v.to_owned())))
})),
)
.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::<Result<_, _>>()?,
)))
},
)),
)
.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(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 { } else {
i as usize Err(format!("concat called on non-iterable type {a}").into())
} }
}) },
.unwrap_or(usize::MAX); |a| {
let end = end.min(s.len()); Ok(Data::new(data::string::String(
if end < start { a.get()
return Ok(String::new()); .iterable()
} .unwrap()
Ok(s[start..end].to_owned()) .map(|v| v.map(|v| v.get().to_string()))
})), .collect::<Result<_, _>>()?,
) )))
},
),
)
.add_var(
"to_string",
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",
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())
}),
)
} }
} }