[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:
Mark 2024-07-02 22:04:42 +02:00
parent 18cd3ee0ae
commit 50928cca1d
21 changed files with 841 additions and 184 deletions

View File

@ -1,3 +1,7 @@
# IN CODE
rm mers_lib/src/program/configs/util.rs
# Objects # Objects
``` ```

View File

@ -15,7 +15,7 @@ default = ["colored-output"]
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"] colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
[dependencies] [dependencies]
mers_lib = "0.9.0" # mers_lib = "0.9.0"
# mers_lib = { path = "../mers_lib" } mers_lib = { path = "../mers_lib" }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
colored = { version = "2.1.0", optional = true } colored = { version = "2.1.0", optional = true }

View File

@ -30,7 +30,7 @@ fn run(src: String) -> Result<(), CheckError> {
) )
.add_var( .add_var(
"rust_func".to_owned(), "rust_func".to_owned(),
Data::new(data::function::Function::new( Data::new(data::function::Function::new_generic(
|arg| { |arg| {
// If the input is a string, the output is a string. // If the input is a string, the output is a string.
// Otherwise, the function is used incorrectly. // Otherwise, the function is used incorrectly.

View File

@ -15,7 +15,10 @@ use super::{Data, MersData, MersType, Type};
pub struct Function { pub struct Function {
pub info: Info, pub info: Info,
pub info_check: Arc<Mutex<CheckInfo>>, 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: pub run:
Arc<dyn Fn(Data, &mut crate::program::run::Info) -> Result<Data, CheckError> + Send + Sync>, Arc<dyn Fn(Data, &mut crate::program::run::Info) -> Result<Data, CheckError> + Send + Sync>,
pub inner_statements: Option<( pub inner_statements: Option<(
@ -35,14 +38,26 @@ impl Clone for Function {
} }
} }
impl 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, out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static, run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> Self { ) -> Self {
Self { Self {
info: crate::info::Info::neverused(), info: crate::info::Info::neverused(),
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())), info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
out: Arc::new(move |a, _| out(a)), out: Ok(Arc::new(move |a, _| out(a))),
run: Arc::new(move |a, _| run(a)), run: Arc::new(move |a, _| run(a)),
inner_statements: None, inner_statements: None,
} }
@ -51,7 +66,7 @@ impl Function {
Self { Self {
info, info,
info_check: Arc::clone(&self.info_check), info_check: Arc::clone(&self.info_check),
out: Arc::clone(&self.out), out: self.out.clone(),
run: Arc::clone(&self.run), run: Arc::clone(&self.run),
inner_statements: self inner_statements: self
.inner_statements .inner_statements
@ -63,10 +78,7 @@ impl Function {
*self.info_check.lock().unwrap() = check; *self.info_check.lock().unwrap() = check;
} }
pub fn check(&self, arg: &Type) -> Result<Type, CheckError> { pub fn check(&self, arg: &Type) -> Result<Type, CheckError> {
let lock = self.info_check.lock().unwrap(); self.get_as_type().o(arg)
let mut info = lock.clone();
drop(lock);
(self.out)(arg, &mut info)
} }
pub fn run_mut(&mut self, arg: Data) -> Result<Data, CheckError> { pub fn run_mut(&mut self, arg: Data) -> Result<Data, CheckError> {
(self.run)(arg, &mut self.info) (self.run)(arg, &mut self.info)
@ -75,14 +87,23 @@ impl Function {
(self.run)(arg, &mut self.info.duplicate()) (self.run)(arg, &mut self.info.duplicate())
} }
pub fn get_as_type(&self) -> FunctionT { pub fn get_as_type(&self) -> FunctionT {
let out = Arc::clone(&self.out); match &self.out {
let info = Arc::clone(&self.info_check); Ok(out) => {
FunctionT(Ok(Arc::new(move |a| { let out = Arc::clone(out);
let lock = info.lock().unwrap(); let info = self.info_check.lock().unwrap().clone();
let mut info = lock.clone(); FunctionT(Ok(Arc::new(move |a| out(a, &mut info.clone()))))
drop(lock); }
out(a, &mut info) 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)] #[derive(Clone)]
pub struct FunctionT( 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 { impl FunctionT {
/// get output type /// get output type

View File

@ -246,10 +246,13 @@ pub fn type_from_parsed(
}) })
.collect::<Result<_, _>>()?, .collect::<Result<_, _>>()?,
))), ))),
ParsedType::Function(v) => as_type.add(Arc::new(data::function::FunctionT(Err(v ParsedType::Function(v) => {
.iter() 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)?))) .map(|(i, o)| Ok((type_from_parsed(i, info)?, type_from_parsed(o, info)?)))
.collect::<Result<_, CheckError>>()?)))), .collect::<Result<_, CheckError>>()?,
)))))
}
ParsedType::Type(name) => match info ParsedType::Type(name) => match info
.scopes .scopes
.iter() .iter()

View 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))
}
}

View 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))
}
}

View File

@ -7,6 +7,7 @@ use crate::{
program::run::CheckInfo, program::run::CheckInfo,
}; };
pub mod gen;
pub mod util; pub mod util;
pub mod with_base; pub mod with_base;
pub mod with_command_running; pub mod with_command_running;

View File

@ -13,7 +13,7 @@ pub fn to_mers_func(
data::function::Function { data::function::Function {
info: Info::neverused(), info: Info::neverused(),
info_check: Arc::new(Mutex::new(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)), run: Arc::new(move |a, _| run(a)),
inner_statements: None, inner_statements: None,
} }
@ -41,16 +41,7 @@ pub fn to_mers_func_with_in_out_types(
out_type: Type, out_type: Type,
run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static, run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func( data::function::Function::new_static(vec![(in_type, out_type)], run)
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,
)
} }
pub fn to_mers_func_concrete_string_to_any( pub fn to_mers_func_concrete_string_to_any(

View File

@ -29,7 +29,7 @@ impl Config {
.add_var("lock_update".to_string(), Data::new(data::function::Function { .add_var("lock_update".to_string(), Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
for t in a.types.iter() { for t in a.types.iter() {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() { if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
if t.0.len() == 2 { if t.0.len() == 2 {
@ -61,7 +61,7 @@ impl Config {
} }
} }
Ok(Type::empty_tuple()) Ok(Type::empty_tuple())
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); 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 { .add_var("sleep".to_string(), Data::new(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: 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::int::IntT),
Arc::new(data::float::FloatT), Arc::new(data::float::FloatT),
])) { ])) {
Ok(Type::empty_tuple()) Ok(Type::empty_tuple())
} else { } else {
Err(format!("cannot call sleep with non-int or non-float argument.").into()) Err(format!("cannot call sleep with non-int or non-float argument.").into())
}), })),
run: Arc::new(|a, i| { run: Arc::new(|a, i| {
let a = a.get(); let a = a.get();
let mut sleep_dur = if let Some(data::int::Int(n)) = a.as_any().downcast_ref() { 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 { .add_var("exit".to_string(), Data::new(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: 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()) Ok(Type::empty())
} else { } else {
Err(format!("cannot call exit with non-int argument").into()) Err(format!("cannot call exit with non-int argument").into())
}), })),
run: Arc::new(|a, _i| { 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)); 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 { .add_var("panic".to_string(), Data::new(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: 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()) Ok(Type::empty())
} else { } else {
Err(format!("cannot call panic with non-string argument").into()) Err(format!("cannot call panic with non-string argument").into())
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Err( Err(
a a
@ -141,14 +141,14 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
for t in &a.types { 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() { 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()); return Err(format!("cannot get length of {t} (must be a tuple, string or iterable)").into());
} }
} }
Ok(Type::new(data::int::IntT)) Ok(Type::new(data::int::IntT))
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
t.0.len() as _ t.0.len() as _
@ -169,14 +169,14 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
for t in &a.types { for t in &a.types {
if t.iterable().is_none() { if t.iterable().is_none() {
return Err(format!("called eq on non-iterable").into()) return Err(format!("called eq on non-iterable").into())
} }
} }
Ok(Type::new(data::bool::BoolT)) Ok(Type::new(data::bool::BoolT))
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() { Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() {
if let Some(f) = i.next() { if let Some(f) = i.next() {
@ -205,7 +205,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: 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| { run: Arc::new(|a, _i| {
Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone()))))) Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone())))))
}), }),
@ -217,8 +217,8 @@ impl Config {
Data::new(data::function::Function { Data::new(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: 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| { run: Arc::new(|a, _i| {
if let Some(r) = a if let Some(r) = a
.get() .get()

View File

@ -29,7 +29,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: 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)))) { if a.types.iter().all(|t| t.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![ Arc::new(data::tuple::TupleT(vec![
@ -42,7 +42,7 @@ impl Config {
} else { } else {
return Err(format!("run_command called with invalid arguments (must be (String, Iter<String>))").into()); return Err(format!("run_command called with invalid arguments (must be (String, Iter<String>))").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
@ -84,7 +84,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: 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)))) { if a.types.iter().all(|t| t.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(ChildProcessT), Arc::new(ChildProcessT),
@ -93,7 +93,7 @@ impl Config {
} else { } else {
return Err(format!("spawn_command called with invalid arguments (must be (String, Iter<String>))").into()); return Err(format!("spawn_command called with invalid arguments (must be (String, Iter<String>))").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
@ -128,7 +128,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::bool::BoolT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::bool::BoolT)])),
@ -137,7 +137,7 @@ impl Config {
} else { } else {
return Err(format!("childproc_exited called on non-ChildProcess type {a}").into()); return Err(format!("childproc_exited called on non-ChildProcess type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
@ -156,7 +156,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::int::IntT), Arc::new(data::int::IntT),
@ -166,7 +166,7 @@ impl Config {
} else { } else {
return Err(format!("childproc_await called on non-ChildProcess type {a}").into()); return Err(format!("childproc_await called on non-ChildProcess type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
@ -189,13 +189,13 @@ impl Config {
Data::new(data::function::Function { Data::new(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: 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)))) { 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)) Ok(Type::new(data::bool::BoolT))
} else { } else {
return Err(format!("childproc_write_bytes called on non-`(ChildProcess, Iter<Byte>)` type {a}").into()); return Err(format!("childproc_write_bytes called on non-`(ChildProcess, Iter<Byte>)` type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
@ -218,13 +218,13 @@ impl Config {
Data::new(data::function::Function { Data::new(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: 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)])) { if a.is_included_in_single(&data::tuple::TupleT(vec![Type::new(ChildProcessT), Type::new(data::string::StringT)])) {
Ok(Type::new(data::bool::BoolT)) Ok(Type::new(data::bool::BoolT))
} else { } else {
return Err(format!("childproc_write_string called on non-`(ChildProcess, String)` type {a}").into()); return Err(format!("childproc_write_string called on non-`(ChildProcess, String)` type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
@ -247,7 +247,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])),
@ -256,7 +256,7 @@ impl Config {
} else { } else {
return Err(format!("childproc_read_byte called on non-ChildProcess type {a}").into()); return Err(format!("childproc_read_byte called on non-ChildProcess type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
@ -276,7 +276,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])),
@ -285,7 +285,7 @@ impl Config {
} else { } else {
return Err(format!("childproc_readerr_byte called on non-ChildProcess type {a}").into()); return Err(format!("childproc_readerr_byte called on non-ChildProcess type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
@ -305,7 +305,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])),
@ -314,7 +314,7 @@ impl Config {
} else { } else {
return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into()); return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
@ -334,7 +334,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])),
@ -343,7 +343,7 @@ impl Config {
} else { } else {
return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into()); return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();

View File

@ -15,7 +15,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
let mut out = Type::empty(); let mut out = Type::empty();
for a in a.types.iter() { for a in a.types.iter() {
if let Some(t) = a.as_any().downcast_ref::<data::tuple::TupleT>() { 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![out])),
Arc::new(data::tuple::TupleT(vec![])), Arc::new(data::tuple::TupleT(vec![])),
])) ]))
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
if let (Some(v), Some(i)) = (a.get(0), a.get(1)) { if let (Some(v), Some(i)) = (a.get(0), a.get(1)) {

View File

@ -49,7 +49,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
for a in &a.types { for a in &a.types {
if let Some(tuple) = a.as_any().downcast_ref::<data::tuple::TupleT>() { 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)) { if let (Some(v), Some(f)) = (tuple.0.get(0), tuple.0.get(1)) {
@ -84,7 +84,7 @@ impl Config {
} }
} }
Ok(Type::empty_tuple()) Ok(Type::empty_tuple())
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { 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)) { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
@ -133,14 +133,14 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
let data = if let Some(a) = a.iterable() { let data = if let Some(a) = a.iterable() {
a a
} else { } else {
return Err(format!("cannot call enumerate on non-iterable type {a}.").into()); return Err(format!("cannot call enumerate on non-iterable type {a}.").into());
}; };
Ok(Type::new(IterT::new(ItersT::Enumerate, data)?)) Ok(Type::new(IterT::new(ItersT::Enumerate, data)?))
}), })),
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,
}), }),
@ -150,14 +150,14 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
let data = if let Some(a) = a.iterable() { let data = if let Some(a) = a.iterable() {
a a
} else { } else {
return Err(format!("cannot call chain on non-iterable type {a}.").into()); return Err(format!("cannot call chain on non-iterable type {a}.").into());
}; };
Ok(Type::new(IterT::new(ItersT::Chained, data)?)) Ok(Type::new(IterT::new(ItersT::Chained, data)?))
}), })),
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,
}), }),
@ -202,7 +202,7 @@ fn genfunc_iter_and_func(
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: 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| { run: Arc::new(move |a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { 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)) { 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 { 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: 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| { run: Arc::new(move |a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { 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)) { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
@ -525,7 +527,7 @@ fn genfunc_iter_in_val_out(
Function { Function {
info: crate::info::Info::neverused(), info: crate::info::Info::neverused(),
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())), info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
out: Arc::new(move |a, _i| { out: Ok(Arc::new(move |a, _i| {
if let Some(iter_over) = a.iterable() { if let Some(iter_over) = a.iterable() {
if iter_over.is_included_in_single(&iter_type) { if iter_over.is_included_in_single(&iter_type) {
Ok(out_type.clone()) Ok(out_type.clone())
@ -535,7 +537,7 @@ fn genfunc_iter_in_val_out(
} else { } else {
Err(format!("Cannot call function {name} on non-iterable type {a}.").into()) Err(format!("Cannot call function {name} on non-iterable type {a}.").into())
} }
}), })),
run: Arc::new(run), run: Arc::new(run),
inner_statements: None, inner_statements: None,
} }

View File

@ -34,7 +34,7 @@ impl Config {
.add_var("get_mut".to_string(), Data::new(data::function::Function { .add_var("get_mut".to_string(), Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
let mut out = Type::empty_tuple(); let mut out = Type::empty_tuple();
for t in a.types.iter() { for t in a.types.iter() {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() { if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
@ -71,7 +71,7 @@ impl Config {
} }
} }
Ok(out) Ok(out)
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let t = a.get(); let t = a.get();
let t = t.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let t = t.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
@ -103,7 +103,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if let Some(a) = a.dereference() { if let Some(a) = a.dereference() {
let mut out = Type::empty(); let mut out = Type::empty();
for t in a.types.iter() { for t in a.types.iter() {
@ -122,7 +122,7 @@ impl Config {
} else { } else {
return Err(format!("pop: not a reference: {a}").into()); return Err(format!("pop: not a reference: {a}").into());
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(match a Ok(match a
.get() .get()
@ -151,7 +151,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
for t in a.types.iter() { for t in a.types.iter() {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() { if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
if t.0.len() != 2 { if t.0.len() != 2 {
@ -186,7 +186,7 @@ impl Config {
} }
} }
Ok(Type::empty_tuple()) Ok(Type::empty_tuple())
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let tuple = a.get(); let tuple = a.get();
let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
@ -214,7 +214,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if let Some(v) = a.iterable() { if let Some(v) = a.iterable() {
Ok(Type::new(ListT(v))) Ok(Type::new(ListT(v)))
} else { } else {
@ -222,7 +222,7 @@ impl Config {
"cannot iterate over type {a}" "cannot iterate over type {a}"
).into()) ).into())
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() { if let Some(i) = a.get().iterable() {
Ok(Data::new(List(i.map(|v| Ok::<_, CheckError>(Arc::new(RwLock::new(v?)))).collect::<Result<_, _>>()?))) Ok(Data::new(List(i.map(|v| Ok::<_, CheckError>(Arc::new(RwLock::new(v?)))).collect::<Result<_, _>>()?)))

View File

@ -73,7 +73,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) { if a.is_included_in(&Type::new(data::string::StringT)) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::float::FloatT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::float::FloatT)])),
@ -82,7 +82,7 @@ impl Config {
} else { } else {
Err(format!("parse_float called on non-string type").into()) Err(format!("parse_float called on non-string type").into())
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok( Ok(
if let Ok(n) = a if let Ok(n) = a
@ -107,7 +107,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) { if a.is_included_in(&Type::new(data::string::StringT)) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])),
@ -116,7 +116,7 @@ impl Config {
} else { } else {
Err(format!("parse_float called on non-string type").into()) Err(format!("parse_float called on non-string type").into())
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok( Ok(
if let Ok(n) = a if let Ok(n) = a
@ -141,7 +141,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in(&Type::newm(vec![ if a.is_included_in(&Type::newm(vec![
Arc::new(data::int::IntT), Arc::new(data::int::IntT),
Arc::new(data::float::FloatT), Arc::new(data::float::FloatT),
@ -150,7 +150,7 @@ impl Config {
} else { } else {
Err(format!("signum called on non-number type").into()) Err(format!("signum called on non-number type").into())
} }
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(Data::new(data::int::Int( Ok(Data::new(data::int::Int(
if let Some(n) = a.get().as_any().downcast_ref::<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 { 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: Arc::new(move |a, _i| { out: Ok(Arc::new(move |a, _i| {
if let Some(a) = a.iterable() { if let Some(a) = a.iterable() {
let int_type = Type::new(data::int::IntT); let int_type = Type::new(data::int::IntT);
if a.is_included_in(&int_type) { if a.is_included_in(&int_type) {
@ -281,7 +281,7 @@ fn num_iter_to_num(
} else { } else {
Err(format!("argument passed to {func_name} must be an iterator").into()) Err(format!("argument passed to {func_name} must be an iterator").into())
} }
}), })),
run: Arc::new(move |a, _i| { run: Arc::new(move |a, _i| {
let mut out = init; let mut out = init;
for v in a.get().iterable().unwrap() { for v in a.get().iterable().unwrap() {
@ -322,7 +322,7 @@ fn two_num_tuple_to_num(
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: 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| { run: Arc::new(move |a, _i| {
two_tuple_to_num_impl_run(a, func_name, &func_ii, &func_if, &func_fi, &func_ff) 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 { 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: Arc::new(move |a, _i| { out: Ok(Arc::new(move |a, _i| {
if let Some(iter_type) = a.iterable() { if let Some(iter_type) = a.iterable() {
let iter_required_type = Type::newm(vec![ let iter_required_type = Type::newm(vec![
Arc::new(data::int::IntT), Arc::new(data::int::IntT),
@ -422,7 +422,7 @@ fn ltgtoe_function(
} else { } else {
Err(CheckError::from(format!("Cannot use {func_name}"))) Err(CheckError::from(format!("Cannot use {func_name}")))
} }
}), })),
run: Arc::new(move |a, _i| { run: Arc::new(move |a, _i| {
let mut prev = IntOrFloatOrNothing::Nothing; let mut prev = IntOrFloatOrNothing::Nothing;
for item in a.get().iterable().unwrap() { for item in a.get().iterable().unwrap() {

View File

@ -32,7 +32,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
let mut out = Type::empty(); let mut out = Type::empty();
for t in a.types.iter() { for t in a.types.iter() {
if let Some(f) = t.executable() { if let Some(f) = t.executable() {
@ -45,7 +45,7 @@ impl Config {
} }
} }
Ok(Type::new(ThreadT(out))) Ok(Type::new(ThreadT(out)))
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(Data::new(Thread(Arc::new(Mutex::new(Ok(std::thread::spawn( Ok(Data::new(Thread(Arc::new(Mutex::new(Ok(std::thread::spawn(
move || a.get().execute(Data::empty_tuple()).unwrap(), 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 { .add_var("thread_finished".to_string(), Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
for t in a.types.iter() { for t in a.types.iter() {
if !t.as_any().is::<ThreadT>() { 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}."))); 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)) Ok(Type::new(data::bool::BoolT))
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let t = a.as_any().downcast_ref::<Thread>().unwrap().0.lock().unwrap(); 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 { .add_var("thread_await".to_string(), Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
let mut out = Type::empty(); let mut out = Type::empty();
for t in a.types.iter() { for t in a.types.iter() {
if let Some(t) = t.as_any().downcast_ref::<ThreadT>() { if let Some(t) = t.as_any().downcast_ref::<ThreadT>() {
@ -88,7 +88,7 @@ impl Config {
} }
} }
Ok(out) Ok(out)
}), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let mut t = a.as_any().downcast_ref::<Thread>().unwrap().0.lock().unwrap(); let mut t = a.as_any().downcast_ref::<Thread>().unwrap().0.lock().unwrap();

View File

@ -24,7 +24,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_zero_tuple() { if a.is_zero_tuple() {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])),
@ -36,7 +36,7 @@ impl Config {
(a.to_string(), Some(EColor::FunctionArgument)), (a.to_string(), Some(EColor::FunctionArgument)),
])) ]))
} }
}), })),
run: Arc::new(|_a, _i| { run: Arc::new(|_a, _i| {
Ok(if let Some(Ok(line)) = std::io::stdin().lines().next() { Ok(if let Some(Ok(line)) = std::io::stdin().lines().next() {
Data::one_tuple(Data::new(data::string::String(line))) Data::one_tuple(Data::new(data::string::String(line)))
@ -52,7 +52,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|a, _i| Ok(a.clone())), out: Ok(Arc::new(|a, _i| Ok(a.clone()))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a2 = a.get(); let a2 = a.get();
eprintln!("{} :: {}", a2.as_type(), a2); eprintln!("{} :: {}", a2.as_type(), a2);
@ -67,7 +67,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
eprint!("{}", a.get()); eprint!("{}", a.get());
_ = std::io::stderr().lock().flush(); _ = std::io::stderr().lock().flush();
@ -81,7 +81,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
eprintln!("{}", a.get()); eprintln!("{}", a.get());
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
@ -94,7 +94,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
print!("{}", a.get()); print!("{}", a.get());
_ = std::io::stdout().lock().flush(); _ = std::io::stdout().lock().flush();
@ -108,7 +108,7 @@ impl Config {
Data::new(data::function::Function { Data::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
println!("{}", a.get()); println!("{}", a.get());
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())

View File

@ -1,8 +1,9 @@
use std::sync::{Arc, RwLock};
use crate::data::{self, Data, Type}; use crate::data::{self, Data, Type};
use super::{util, Config}; use super::{
gen::{function::func, AnyOrNone, IterToList, OneOf, OneOrNone},
util, Config,
};
impl Config { impl Config {
/// `trim: fn` removes leading and trailing whitespace from a string /// `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 /// `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 self.add_var(
.add_var("trim".to_string(), Data::new(util::to_mers_func_concrete_string_to_string(|v| v.trim().to_owned()))) "trim".to_string(),
.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 _)))) Data::new(func(|v: &str| Ok(v.trim().to_owned()))),
.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("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("ends_with".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_bool(|v, p| v.ends_with(p)))) .add_var(
.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()))))) "index_of".to_string(),
.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()))))) Data::new(func(|(v, p): (&str, &str)| {
.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())))))) Ok(OneOrNone(v.find(p).map(|v| v as isize)))
.add_var("concat".to_string(), Data::new(util::to_mers_func( })),
|a| if a.iterable().is_some() { )
// .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| {
if a.iterable().is_some() {
Ok(Type::new(data::string::StringT)) Ok(Type::new(data::string::StringT))
} else { } else {
Err(format!("concat called on non-iterable type {a}").into()) 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<_, _>>()?)))), |a| {
)) Ok(Data::new(data::string::String(
.add_var("to_string".to_string(), Data::new(util::to_mers_func(|_a| Ok(Type::new(data::string::StringT)), a.get()
|a| Ok(Data::new(data::string::String(a.get().to_string()))) .iterable()
.unwrap()
.map(|v| v.map(|v| v.get().to_string()))
.collect::<Result<_, _>>()?,
))) )))
.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"); .add_var(
let (s, start, end) = (&tuple.0[0], &tuple.0[1], tuple.0.get(2)); "to_string".to_string(),
let s = s.get(); Data::new(util::to_mers_func(
let s = &s.as_any().downcast_ref::<data::string::String>().unwrap().0; |_a| Ok(Type::new(data::string::StringT)),
let start = start.get(); |a| Ok(Data::new(data::string::String(a.get().to_string()))),
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 }; )
// .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 let end = end
.map(|end| end.get()) .map(|i| {
.map(|end| end.as_any().downcast_ref::<data::int::Int>().unwrap().0) if i < 0 {
.map(|i| if i < 0 { s.len().saturating_sub(i.abs() as usize) } else { i as usize }) s.len().saturating_sub(i.abs() as usize)
} else {
i as usize
}
})
.unwrap_or(usize::MAX); .unwrap_or(usize::MAX);
let end = end.min(s.len()); let end = end.min(s.len());
if end < start { if end < start {
return Ok(Data::new(data::string::String(String::new()))); return Ok(String::new());
} }
Ok(Data::new(data::string::String(s[start..end].to_owned()))) Ok(s[start..end].to_owned())
}) })),
)) )
} }
} }

View File

@ -38,10 +38,10 @@ impl MersStatement for Function {
func_no_info: data::function::Function { func_no_info: 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: Arc::new(move |a, i| { out: Ok(Arc::new(move |a, i| {
arg2.check(i, Some(a))?; arg2.check(i, Some(a))?;
Ok(run2.check(i, None)?) Ok(run2.check(i, None)?)
}), })),
run: Arc::new(move |arg, info| { run: Arc::new(move |arg, info| {
data::defs::assign(&arg, &arg_target.run(info)?); data::defs::assign(&arg, &arg_target.run(info)?);
run.run(info) run.run(info)

View File

@ -56,7 +56,9 @@ impl MersStatement for IncludeMers {
func_no_info: data::function::Function { func_no_info: data::function::Function {
info: info::Info::neverused(), info: info::Info::neverused(),
info_check: Arc::new(Mutex::new(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())), run: Arc::new(move |_, i| compiled2.run(&mut i.duplicate())),
inner_statements: None, inner_statements: None,
}, },

View File

@ -34,7 +34,7 @@ impl MersStatement for Function {
self.pos_in_src.clone() self.pos_in_src.clone()
} }
fn inner_statements(&self) -> Vec<&dyn MersStatement> { 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()] vec![a.as_ref().as_ref(), b.as_ref().as_ref()]
} else { } else {
vec![] vec![]