mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 05:43:53 +01:00
[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.
This commit is contained in:
parent
18cd3ee0ae
commit
50928cca1d
@ -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 }
|
||||
|
@ -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.
|
||||
|
@ -15,7 +15,10 @@ use super::{Data, MersData, MersType, Type};
|
||||
pub struct Function {
|
||||
pub info: Info,
|
||||
pub info_check: Arc<Mutex<CheckInfo>>,
|
||||
pub out: Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>,
|
||||
pub out: Result<
|
||||
Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>,
|
||||
Arc<Vec<(Type, Type)>>,
|
||||
>,
|
||||
pub run:
|
||||
Arc<dyn Fn(Data, &mut crate::program::run::Info) -> Result<Data, CheckError> + 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<Data, CheckError> + 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<Type, CheckError> + Send + Sync + 'static,
|
||||
run: impl Fn(Data) -> Result<Data, CheckError> + 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<Type, CheckError> {
|
||||
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<Data, CheckError> {
|
||||
(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<Box<dyn crate::program::run::MersStatement>>,
|
||||
Arc<Box<dyn crate::program::run::MersStatement>>,
|
||||
)> {
|
||||
&self.inner_statements
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +151,7 @@ impl MersData for Function {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FunctionT(
|
||||
pub Result<Arc<dyn Fn(&Type) -> Result<Type, CheckError> + Send + Sync>, Vec<(Type, Type)>>,
|
||||
pub Result<Arc<dyn Fn(&Type) -> Result<Type, CheckError> + Send + Sync>, Arc<Vec<(Type, Type)>>>,
|
||||
);
|
||||
impl FunctionT {
|
||||
/// get output type
|
||||
|
@ -246,10 +246,13 @@ pub fn type_from_parsed(
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
))),
|
||||
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::<Result<_, CheckError>>()?)))),
|
||||
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::<Result<_, CheckError>>()?,
|
||||
)))))
|
||||
}
|
||||
ParsedType::Type(name) => match info
|
||||
.scopes
|
||||
.iter()
|
||||
|
90
mers_lib/src/program/configs/gen/function.rs
Normal file
90
mers_lib/src/program/configs/gen/function.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData, Type},
|
||||
errors::CheckError,
|
||||
};
|
||||
|
||||
use super::{FromMersData, ToMersData};
|
||||
|
||||
pub fn func<I: FromMersData + 'static, O: ToMersData + 'static>(
|
||||
f: fn(I) -> Result<O, CheckError>,
|
||||
) -> data::function::Function {
|
||||
Box::new(f).mers_func()
|
||||
}
|
||||
|
||||
// fn this_works() {
|
||||
// let cfg = ();
|
||||
// // type: `(Int -> Float, Byte -> Int)`
|
||||
// // todo: maybe add an Iterable<T> "type" that we can use like `[Itarable<Int>] (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<Result<Data, CheckError>>;
|
||||
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<A: StaticMersFunc, B: StaticMersFunc>(pub A, pub B);
|
||||
|
||||
pub trait Func: Send + Sync + 'static {
|
||||
type I: FromMersData;
|
||||
type O: ToMersData;
|
||||
fn run_func(&self, i: Self::I) -> Result<Self::O, CheckError>;
|
||||
}
|
||||
impl<I: FromMersData + 'static, O: ToMersData + 'static> Func for fn(I) -> Result<O, CheckError> {
|
||||
type I = I;
|
||||
type O = O;
|
||||
fn run_func(&self, i: Self::I) -> Result<Self::O, CheckError> {
|
||||
self(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Func + ?Sized> StaticMersFunc for Box<F> {
|
||||
fn types() -> Vec<(Type, Type)> {
|
||||
vec![(F::I::as_type_from(), F::O::as_type_to())]
|
||||
}
|
||||
fn run(&self, a: &(impl MersData + ?Sized)) -> Option<Result<Data, CheckError>> {
|
||||
F::I::try_represent(a, |v| v.map(|v| self.run_func(v).map(|v| v.represent())))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: StaticMersFunc, B: StaticMersFunc> StaticMersFunc for TwoFuncs<A, B> {
|
||||
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<Result<Data, CheckError>> {
|
||||
self.0.run(a).or_else(|| self.1.run(a))
|
||||
}
|
||||
}
|
453
mers_lib/src/program/configs/gen/mod.rs
Normal file
453
mers_lib/src/program/configs/gen/mod.rs
Normal file
@ -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, F: FnOnce(Option<Self>) -> 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<A>(pub Option<A>);
|
||||
/// Mainly used to generate types like `(A, B)/()` where `OneOrNone` would generate `((A, B))/()`, but can also generate `A/()`
|
||||
pub struct AnyOrNone<A>(pub Option<A>);
|
||||
impl<A: FromMersData> FromMersData for OneOrNone<A> {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d
|
||||
.as_any()
|
||||
.downcast_ref::<data::tuple::Tuple>()
|
||||
.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<A: ToMersData> ToMersData for OneOrNone<A> {
|
||||
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<A: FromMersData> FromMersData for AnyOrNone<A> {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if d.as_any()
|
||||
.downcast_ref::<data::tuple::Tuple>()
|
||||
.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<A: ToMersData> ToMersData for AnyOrNone<A> {
|
||||
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, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
impl<A: FromMersData, B: FromMersData> FromMersData for OneOf<A, B> {
|
||||
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, F: FnOnce(Option<Self>) -> 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<A: ToMersData, B: ToMersData> ToMersData for OneOf<A, B> {
|
||||
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<T: ToMersData, I: Iterator<Item = T>>(pub I);
|
||||
impl<T: ToMersData, I: Iterator<Item = T>> ToMersData for IterToList<T, I> {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
f(d.as_any()
|
||||
.downcast_ref::<data::tuple::Tuple>()
|
||||
.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<A: FromMersData> 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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d
|
||||
.as_any()
|
||||
.downcast_ref::<data::tuple::Tuple>()
|
||||
.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<A: ToMersData> 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<A: FromMersData, B: FromMersData> 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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d
|
||||
.as_any()
|
||||
.downcast_ref::<data::tuple::Tuple>()
|
||||
.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<A: ToMersData, B: ToMersData> 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<A: FromMersData, B: FromMersData, C: FromMersData> 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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d
|
||||
.as_any()
|
||||
.downcast_ref::<data::tuple::Tuple>()
|
||||
.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<A: ToMersData, B: ToMersData, C: ToMersData> 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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d.as_any().downcast_ref::<data::bool::Bool>() {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d.as_any().downcast_ref::<data::byte::Byte>() {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d.as_any().downcast_ref::<data::int::Int>() {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d.as_any().downcast_ref::<data::float::Float>() {
|
||||
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, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
|
||||
if let Some(v) = d.as_any().downcast_ref::<data::string::String>() {
|
||||
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))
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ use crate::{
|
||||
program::run::CheckInfo,
|
||||
};
|
||||
|
||||
pub mod gen;
|
||||
pub mod util;
|
||||
pub mod with_base;
|
||||
pub mod with_command_running;
|
||||
|
@ -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<Data, CheckError> + 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(
|
||||
|
@ -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::<data::tuple::TupleT>() {
|
||||
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::<data::tuple::Tuple>().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::<data::int::Int>().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::<data::string::StringT>().is_none() && t.as_any().downcast_ref::<data::tuple::TupleT>().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::<data::tuple::Tuple>() {
|
||||
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()
|
||||
|
@ -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::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
|
||||
Ok(Type::newm(vec![
|
||||
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<String>))").into());
|
||||
}
|
||||
}),
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
let a = a.get();
|
||||
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().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::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(ChildProcessT),
|
||||
@ -93,7 +93,7 @@ impl Config {
|
||||
} else {
|
||||
return Err(format!("spawn_command called with invalid arguments (must be (String, Iter<String>))").into());
|
||||
}
|
||||
}),
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
let a = a.get();
|
||||
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().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::<ChildProcess>().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::<ChildProcess>().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::<data::tuple::TupleT>().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<Byte>)` type {a}").into());
|
||||
}
|
||||
}),
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
let a = a.get();
|
||||
let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().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::<data::tuple::Tuple>().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::<ChildProcess>().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::<ChildProcess>().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::<ChildProcess>().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::<ChildProcess>().unwrap();
|
||||
|
@ -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::<data::tuple::TupleT>() {
|
||||
@ -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)) {
|
||||
|
@ -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::<data::tuple::TupleT>() {
|
||||
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::<data::tuple::Tuple>() {
|
||||
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::<data::tuple::Tuple>() {
|
||||
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
|
||||
@ -256,7 +256,9 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
|
||||
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::<data::tuple::Tuple>() {
|
||||
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,
|
||||
}
|
||||
|
@ -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::<data::tuple::TupleT>() {
|
||||
@ -71,7 +71,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}),
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
let t = a.get();
|
||||
let t = t.as_any().downcast_ref::<data::tuple::Tuple>().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::<data::tuple::TupleT>() {
|
||||
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::<data::tuple::Tuple>().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::<Result<_, _>>()?)))
|
||||
|
@ -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::<data::int::Int>() {
|
||||
@ -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() {
|
||||
|
@ -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::<ThreadT>() {
|
||||
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::<Thread>().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::<ThreadT>() {
|
||||
@ -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::<Thread>().unwrap().0.lock().unwrap();
|
||||
|
@ -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())
|
||||
|
@ -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::<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(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::<data::tuple::TupleT>() {
|
||||
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::<data::tuple::Tuple>().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::<data::string::String>().unwrap().0;
|
||||
let start = start.get();
|
||||
let start = start.as_any().downcast_ref::<data::int::Int>().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::<data::int::Int>().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::<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(util::to_mers_func(
|
||||
// |a| {
|
||||
// for t in a.types.iter() {
|
||||
// if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
// 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::<data::tuple::Tuple>().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::<data::string::String>().unwrap().0;
|
||||
// let start = start.get();
|
||||
// let start = start.as_any().downcast_ref::<data::int::Int>().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::<data::int::Int>().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())
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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![]
|
||||
|
Loading…
Reference in New Issue
Block a user