functions no longer modify state, funcrefs exist

you can use &func as a function, too.
this allows the function to mutate its
inner state.
This commit is contained in:
Mark 2024-07-01 20:51:09 +02:00
parent 7acaafaa2f
commit 18cd3ee0ae
21 changed files with 330 additions and 191 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.8.25" version = "0.9.0"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "dynamically typed but type-checked programming language" description = "dynamically typed but type-checked programming language"
@ -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.8.25" 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

@ -1,6 +1,6 @@
[package] [package]
name = "mers_lib" name = "mers_lib"
version = "0.8.25" version = "0.9.0"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "library to use the mers language in other projects" description = "library to use the mers language in other projects"

View File

@ -23,7 +23,7 @@ fn main() -> Result<(), CheckError> {
// use the function to decorate these 3 test strings // use the function to decorate these 3 test strings
for input in ["my test string", "Main Menu", "O.o"] { for input in ["my test string", "Main Menu", "O.o"] {
let result = func.run(Data::new(data::string::String(input.to_owned())))?; let result = func.run_immut(Data::new(data::string::String(input.to_owned())))?;
let result = result.get(); let result = result.get();
let result = &result let result = &result
.as_any() .as_any()

View File

@ -6,14 +6,14 @@ use std::{
use crate::{ use crate::{
errors::CheckError, errors::CheckError,
info::Local,
program::run::{CheckInfo, Info}, program::run::{CheckInfo, Info},
}; };
use super::{Data, MersData, MersType, Type}; use super::{Data, MersData, MersType, Type};
#[derive(Clone)]
pub struct Function { pub struct Function {
pub info: Arc<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: Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>,
pub run: pub run:
@ -23,20 +23,31 @@ pub struct Function {
Arc<Box<dyn crate::program::run::MersStatement>>, Arc<Box<dyn crate::program::run::MersStatement>>,
)>, )>,
} }
impl Clone for Function {
fn clone(&self) -> Self {
Self {
info: self.info.duplicate(),
info_check: self.info_check.clone(),
out: self.out.clone(),
run: self.run.clone(),
inner_statements: self.inner_statements.clone(),
}
}
}
impl Function { impl Function {
pub fn new( pub fn new(
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: Arc::new(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: 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,
} }
} }
pub fn with_info_run(&self, info: Arc<Info>) -> Self { pub fn with_info_run(&self, info: Info) -> Self {
Self { Self {
info, info,
info_check: Arc::clone(&self.info_check), info_check: Arc::clone(&self.info_check),
@ -57,8 +68,11 @@ impl Function {
drop(lock); drop(lock);
(self.out)(arg, &mut info) (self.out)(arg, &mut info)
} }
pub fn run(&self, arg: Data) -> Result<Data, CheckError> { pub fn run_mut(&mut self, arg: Data) -> Result<Data, CheckError> {
(self.run)(arg, &mut self.info.as_ref().clone()) (self.run)(arg, &mut self.info)
}
pub fn run_immut(&self, arg: Data) -> Result<Data, CheckError> {
(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); let out = Arc::clone(&self.out);
@ -73,10 +87,16 @@ impl Function {
} }
impl MersData for Function { impl MersData for Function {
fn executable(&self) -> Option<crate::data::function::FunctionT> {
Some(self.get_as_type())
}
fn execute(&self, arg: Data) -> Option<Result<Data, CheckError>> {
Some(self.run_immut(arg))
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
let s = Clone::clone(self); let mut s = Clone::clone(self);
Some(Box::new(std::iter::from_fn(move || { Some(Box::new(std::iter::from_fn(move || {
match s.run(Data::empty_tuple()) { match s.run_mut(Data::empty_tuple()) {
Err(e) => Some(Err(e)), Err(e) => Some(Err(e)),
Ok(v) => { Ok(v) => {
if let Some(v) = v.one_tuple_content() { if let Some(v) = v.one_tuple_content() {
@ -122,6 +142,9 @@ impl FunctionT {
} }
} }
impl MersType for FunctionT { impl MersType for FunctionT {
fn executable(&self) -> Option<crate::data::function::FunctionT> {
Some(self.clone())
}
fn iterable(&self) -> Option<Type> { fn iterable(&self) -> Option<Type> {
// if this function can be called with an empty tuple and returns `()` or `(T)`, it can act as an iterator with type `T`. // if this function can be called with an empty tuple and returns `()` or `(T)`, it can act as an iterator with type `T`.
if let Ok(t) = self.o(&Type::empty_tuple()) { if let Ok(t) = self.o(&Type::empty_tuple()) {

View File

@ -19,6 +19,15 @@ pub mod tuple;
pub mod defs; pub mod defs;
pub trait MersData: Any + Debug + Display + Send + Sync { pub trait MersData: Any + Debug + Display + Send + Sync {
/// must be the same as the `executable` impl on the MersType
#[allow(unused_variables)]
fn executable(&self) -> Option<crate::data::function::FunctionT> {
None
}
#[allow(unused_variables)]
fn execute(&self, arg: Data) -> Option<Result<Data, CheckError>> {
None
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
None None
} }
@ -38,6 +47,10 @@ pub trait MersData: Any + Debug + Display + Send + Sync {
} }
pub trait MersType: Any + Debug + Display + Send + Sync { pub trait MersType: Any + Debug + Display + Send + Sync {
#[allow(unused_variables)]
fn executable(&self) -> Option<crate::data::function::FunctionT> {
None
}
/// If Some(T), calling `iterable` on the MersData this MersType belongs to /// If Some(T), calling `iterable` on the MersData this MersType belongs to
/// Should return Some(I), where I is an Iterator which only returns items of type T. /// Should return Some(I), where I is an Iterator which only returns items of type T.
fn iterable(&self) -> Option<Type> { fn iterable(&self) -> Option<Type> {

View File

@ -4,12 +4,63 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use crate::errors::CheckError;
use super::{Data, MersData, MersType, Type}; use super::{Data, MersData, MersType, Type};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Reference(pub Arc<RwLock<Data>>); pub struct Reference(pub Arc<RwLock<Data>>);
impl MersData for Reference { impl MersData for Reference {
fn executable(&self) -> Option<crate::data::function::FunctionT> {
let inner = self.0.read().unwrap();
let inner = inner.get();
if let Some(func) = inner
.as_ref()
.as_any()
.downcast_ref::<crate::data::function::Function>()
{
Some(func.get_as_type())
} else {
None
}
}
fn execute(&self, arg: Data) -> Option<Result<Data, CheckError>> {
let mut inner = self.0.write().unwrap();
let mut inner = inner.get_mut();
if let Some(func) = inner
.as_mut()
.mut_any()
.downcast_mut::<crate::data::function::Function>()
{
Some(func.run_mut(arg))
} else {
None
}
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
let inner = Arc::clone(&self.0);
Some(Box::new(std::iter::from_fn(move || {
match inner
.write()
.unwrap()
.get_mut()
.mut_any()
.downcast_mut::<crate::data::function::Function>()
.unwrap()
.run_mut(Data::empty_tuple())
{
Err(e) => Some(Err(e)),
Ok(v) => {
if let Some(v) = v.one_tuple_content() {
Some(Ok(v))
} else {
None
}
}
}
})))
}
fn is_eq(&self, other: &dyn MersData) -> bool { fn is_eq(&self, other: &dyn MersData) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Self>() { if let Some(other) = other.as_any().downcast_ref::<Self>() {
*other.0.write().unwrap() == *self.0.write().unwrap() *other.0.write().unwrap() == *self.0.write().unwrap()
@ -37,6 +88,38 @@ impl MersData for Reference {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ReferenceT(pub Type); pub struct ReferenceT(pub Type);
impl MersType for ReferenceT { impl MersType for ReferenceT {
fn executable(&self) -> Option<crate::data::function::FunctionT> {
let mut funcs: Vec<crate::data::function::FunctionT> = vec![];
for func in self.0.types.iter() {
funcs.push(Clone::clone(
func.as_any()
.downcast_ref::<crate::data::function::FunctionT>()?,
));
}
Some(super::function::FunctionT(Ok(Arc::new(move |a| {
let mut out = Type::empty();
for func in funcs.iter() {
out.add_all(&func.o(a)?);
}
Ok(out)
}))))
}
fn iterable(&self) -> Option<Type> {
let mut out = Type::empty();
for func in self.0.types.iter() {
out.add_all(
&func
.as_any()
.downcast_ref::<crate::data::function::FunctionT>()?
.iterable()?,
);
}
if !out.types.is_empty() {
Some(out)
} else {
None
}
}
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
if let Some(o) = other.as_any().downcast_ref::<Self>() { if let Some(o) = other.as_any().downcast_ref::<Self>() {
self.0.is_same_type_as(&o.0) self.0.is_same_type_as(&o.0)
@ -76,7 +159,7 @@ impl MersType for ReferenceT {
impl Display for Reference { impl Display for Reference {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "&{}", self.0.write().unwrap().get()) write!(f, "&{}", self.0.read().unwrap().get())
} }
} }
impl Display for ReferenceT { impl Display for ReferenceT {

View File

@ -52,7 +52,7 @@ impl<L: Local> Local for Info<L> {
} }
fn duplicate(&self) -> Self { fn duplicate(&self) -> Self {
Self { Self {
scopes: vec![self.scopes[0].duplicate()], scopes: self.scopes.iter().map(|v| v.duplicate()).collect(),
global: self.global.clone(), global: self.global.clone(),
} }
} }

View File

@ -11,7 +11,7 @@ pub fn to_mers_func(
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 {
data::function::Function { data::function::Function {
info: Arc::new(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: Arc::new(move |a, _| out(a)),
run: Arc::new(move |a, _| run(a)), run: Arc::new(move |a, _| run(a)),

View File

@ -27,7 +27,7 @@ impl Config {
// .add_var("try".to_string(), get_try(false)) // .add_var("try".to_string(), get_try(false))
// .add_var("try_allow_unused".to_string(), get_try(true)) // .add_var("try_allow_unused".to_string(), get_try(true))
.add_var("lock_update".to_string(), Data::new(data::function::Function { .add_var("lock_update".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
for t in a.types.iter() { for t in a.types.iter() {
@ -37,7 +37,7 @@ impl Config {
if let Some(arg) = arg_ref.dereference() { if let Some(arg) = arg_ref.dereference() {
let func = &t.0[1]; let func = &t.0[1];
for func_t in func.types.iter() { for func_t in func.types.iter() {
if let Some(f) = func_t.as_any().downcast_ref::<data::function::FunctionT>() { if let Some(f) = func_t.executable() {
match f.o(&arg) { match f.o(&arg) {
Ok(out) => { Ok(out) => {
if !out.is_included_in(&arg) { if !out.is_included_in(&arg) {
@ -69,14 +69,13 @@ impl Config {
let arg_ref = arg_ref.as_any().downcast_ref::<data::reference::Reference>().unwrap(); let arg_ref = arg_ref.as_any().downcast_ref::<data::reference::Reference>().unwrap();
let mut arg = arg_ref.0.write().unwrap(); let mut arg = arg_ref.0.write().unwrap();
let func = a.0[1].get(); let func = a.0[1].get();
let func = func.as_any().downcast_ref::<data::function::Function>().unwrap(); *arg = func.execute(arg.clone()).unwrap()?;
*arg = func.run(arg.clone())?;
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
})) }))
.add_var("sleep".to_string(), Data::new(data::function::Function { .add_var("sleep".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| if a.is_included_in(&Type::newm(vec![
Arc::new(data::int::IntT), Arc::new(data::int::IntT),
@ -105,7 +104,7 @@ impl Config {
inner_statements: None, inner_statements: None,
})) }))
.add_var("exit".to_string(), Data::new(data::function::Function { .add_var("exit".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| if a.is_included_in_single(&data::int::IntT) {
Ok(Type::empty()) Ok(Type::empty())
@ -118,7 +117,7 @@ impl Config {
inner_statements: None, inner_statements: None,
})) }))
.add_var("panic".to_string(), Data::new(data::function::Function { .add_var("panic".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| if a.is_included_in_single(&data::string::StringT) {
Ok(Type::empty()) Ok(Type::empty())
@ -140,7 +139,7 @@ impl Config {
.add_var( .add_var(
"len".to_string(), "len".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
for t in &a.types { for t in &a.types {
@ -168,7 +167,7 @@ impl Config {
.add_var( .add_var(
"eq".to_string(), "eq".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
for t in &a.types { for t in &a.types {
@ -204,7 +203,7 @@ impl Config {
.add_var( .add_var(
"mkref".to_string(), "mkref".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone())))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
@ -216,7 +215,7 @@ impl Config {
.add_var( .add_var(
"deref".to_string(), "deref".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| if let Some(v) = a.dereference() { Ok(v) } else { Err(format!("cannot dereference type {a}").into())
}), }),
@ -239,7 +238,7 @@ impl Config {
// fn get_try(allow_unused_functions: bool) -> Data { // fn get_try(allow_unused_functions: bool) -> Data {
// Data::new(data::function::Function { // Data::new(data::function::Function {
// info: Arc::new(Info::neverused()), // info: 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: Arc::new(move |a, _i| {
// let mut out = Type::empty(); // let mut out = Type::empty();

View File

@ -27,7 +27,7 @@ impl Config {
.add_var( .add_var(
"run_command".to_string(), "run_command".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: 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)))) {
@ -82,7 +82,7 @@ impl Config {
.add_var( .add_var(
"spawn_command".to_string(), "spawn_command".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: 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)))) {
@ -126,7 +126,7 @@ impl Config {
.add_var( .add_var(
"childproc_exited".to_string(), "childproc_exited".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
@ -154,7 +154,7 @@ impl Config {
.add_var( .add_var(
"childproc_await".to_string(), "childproc_await".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
@ -187,7 +187,7 @@ impl Config {
.add_var( .add_var(
"childproc_write_bytes".to_string(), "childproc_write_bytes".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: 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)))) {
@ -216,7 +216,7 @@ impl Config {
.add_var( .add_var(
"childproc_write_string".to_string(), "childproc_write_string".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: 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)])) {
@ -245,7 +245,7 @@ impl Config {
.add_var( .add_var(
"childproc_read_byte".to_string(), "childproc_read_byte".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
@ -274,7 +274,7 @@ impl Config {
.add_var( .add_var(
"childproc_readerr_byte".to_string(), "childproc_readerr_byte".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
@ -303,7 +303,7 @@ impl Config {
.add_var( .add_var(
"childproc_read_line".to_string(), "childproc_read_line".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
@ -332,7 +332,7 @@ impl Config {
.add_var( .add_var(
"childproc_readerr_line".to_string(), "childproc_readerr_line".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {

View File

@ -13,7 +13,7 @@ impl Config {
self.add_var( self.add_var(
"get".to_string(), "get".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
let mut out = Type::empty(); let mut out = Type::empty();

View File

@ -47,7 +47,7 @@ impl Config {
.add_var( .add_var(
"for_each".to_string(), "for_each".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
for a in &a.types { for a in &a.types {
@ -58,7 +58,7 @@ impl Config {
f.types f.types
.iter() .iter()
.map(|t| { .map(|t| {
t.as_any().downcast_ref::<data::function::FunctionT>() t.executable()
}) })
.collect::<Option<Vec<_>>>(), .collect::<Option<Vec<_>>>(),
) { ) {
@ -88,17 +88,15 @@ impl Config {
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)) {
if let (Some(iter), Some(f)) = ( if let Some(iter) = v.get().iterable() {
v.get().iterable(), let f = f.get();
f.get().as_any().downcast_ref::<data::function::Function>(),
) {
for v in iter { for v in iter {
f.run(v?)?; f.execute(v?).unwrap()?;
} }
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
} else { } else {
return Err( return Err(
"for_each called on tuple not containing iterable and function".into() "for_each called on tuple not containing iterable and function (not an iterable)".into()
); );
} }
} else { } else {
@ -129,11 +127,11 @@ impl Config {
) )
.add_var("take".to_string(), Data::new(genfunc_iter_and_arg("take", |_: &data::int::IntT| ItersT::Take, |v: &data::int::Int| { .add_var("take".to_string(), Data::new(genfunc_iter_and_arg("take", |_: &data::int::IntT| ItersT::Take, |v: &data::int::Int| {
Iters::Take(v.0.max(0) as _) Iters::Take(v.0.max(0) as _)
}))) }, &data::int::IntT)))
.add_var( .add_var(
"enumerate".to_string(), "enumerate".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
let data = if let Some(a) = a.iterable() { let data = if let Some(a) = a.iterable() {
@ -150,7 +148,7 @@ impl Config {
.add_var( .add_var(
"chain".to_string(), "chain".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
let data = if let Some(a) = a.iterable() { let data = if let Some(a) = a.iterable() {
@ -167,10 +165,15 @@ impl Config {
} }
} }
fn iter_out_arg<T: MersType>( fn genfunc_iter_and_func(
name: &'static str,
ft: impl Fn(FunctionT) -> ItersT + Send + Sync + 'static,
fd: impl Fn(Data) -> Iters + Send + Sync + 'static,
) -> data::function::Function {
fn iter_out_arg(
a: &Type, a: &Type,
name: &str, name: &str,
func: impl Fn(&T) -> ItersT + Sync + Send, func: impl Fn(FunctionT) -> ItersT + Sync + Send,
) -> Result<Type, CheckError> { ) -> Result<Type, CheckError> {
let mut out = Type::empty(); let mut out = Type::empty();
for t in a.types.iter() { for t in a.types.iter() {
@ -180,7 +183,7 @@ fn iter_out_arg<T: MersType>(
} }
if let Some(v) = t.0[0].iterable() { if let Some(v) = t.0[0].iterable() {
for f in t.0[1].types.iter() { for f in t.0[1].types.iter() {
if let Some(f) = f.as_any().downcast_ref::<T>() { if let Some(f) = f.executable() {
out.add(Arc::new(IterT::new(func(f), v.clone())?)); out.add(Arc::new(IterT::new(func(f), v.clone())?));
} else { } else {
return Err(format!("cannot call {name} on tuple that isn't (_, function): got {} instead of function as part of {a}", t.0[1]).into()); return Err(format!("cannot call {name} on tuple that isn't (_, function): got {} instead of function as part of {a}", t.0[1]).into());
@ -196,27 +199,64 @@ fn iter_out_arg<T: MersType>(
} }
Ok(out) Ok(out)
} }
data::function::Function {
fn genfunc_iter_and_func( info: program::run::Info::neverused(),
name: &'static str, info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
ft: impl Fn(FunctionT) -> ItersT + Send + Sync + 'static, out: Arc::new(move |a, _i| iter_out_arg(a, name, |f| ft(f))),
fd: impl Fn(Function) -> Iters + Send + Sync + 'static, run: Arc::new(move |a, _i| {
) -> data::function::Function { if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
genfunc_iter_and_arg( if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
name, Ok(Data::new(Iter(fd(f.clone()), v.clone())))
move |v| ft(Clone::clone(v)), } else {
move |v| fd(Clone::clone(v)), return Err("{name} called on tuple with len < 2".into());
) }
} else {
return Err("{name} called on non-tuple".into());
}
}),
inner_statements: None,
}
} }
fn genfunc_iter_and_arg<T: MersType, D: MersData>( fn genfunc_iter_and_arg<T: MersType, D: MersData>(
name: &'static str, name: &'static str,
ft: impl Fn(&T) -> ItersT + Send + Sync + 'static, ft: impl Fn(&T) -> ItersT + Send + Sync + 'static,
fd: impl Fn(&D) -> Iters + Send + Sync + 'static, fd: impl Fn(&D) -> Iters + Send + Sync + 'static,
type_sample: &'static T,
) -> data::function::Function { ) -> data::function::Function {
fn iter_out_arg<T: MersType>(
a: &Type,
name: &str,
func: impl Fn(&T) -> ItersT + Sync + Send,
type_sample: &T,
) -> Result<Type, CheckError> {
let mut out = Type::empty();
for t in a.types.iter() {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
if t.0.len() != 2 {
return Err(format!("cannot call {name} on tuple where len != 2").into());
}
if let Some(v) = t.0[0].iterable() {
for f in t.0[1].types.iter() {
if let Some(f) = f.as_any().downcast_ref::<T>() {
out.add(Arc::new(IterT::new(func(f), v.clone())?));
} else {
return Err(format!("cannot call {name} on tuple that isn't (_, {type_sample}): got {} instead of {type_sample} as part of {a}", t.0[1]).into());
}
}
} else {
return Err(format!(
"cannot call {name} on non-iterable type {t}, which is part of {a}."
)
.into());
}
}
}
Ok(out)
}
data::function::Function { data::function::Function {
info: Arc::new(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))), out: 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)) {
@ -238,10 +278,10 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Iters { pub enum Iters {
Map(data::function::Function), Map(Data),
Filter(data::function::Function), Filter(Data),
FilterMap(data::function::Function), FilterMap(Data),
MapWhile(data::function::Function), MapWhile(Data),
Take(usize), Take(usize),
Enumerate, Enumerate,
Chained, Chained,
@ -268,14 +308,18 @@ impl MersData for Iter {
Some(match &self.0 { Some(match &self.0 {
Iters::Map(f) => { Iters::Map(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.map(move |v| f.run(v?))) Box::new(self.1.get().iterable()?.map(move |v| {
f.get()
.execute(v?)
.ok_or_else(|| CheckError::from("called map with non-function argument"))?
}))
} }
Iters::Filter(f) => { Iters::Filter(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.filter_map(move |v| { Box::new(self.1.get().iterable()?.filter_map(move |v| {
match v { match v {
Ok(v) => match f.run(v.clone()) { Ok(v) => match f.get().execute(v.clone()) {
Ok(f) => { Some(Ok(f)) => {
if f.get() if f.get()
.as_any() .as_any()
.downcast_ref::<data::bool::Bool>() .downcast_ref::<data::bool::Bool>()
@ -286,7 +330,10 @@ impl MersData for Iter {
None None
} }
} }
Err(e) => Some(Err(e)), Some(Err(e)) => Some(Err(e)),
None => Some(Err(CheckError::from(
"called filter with non-function argument",
))),
}, },
Err(e) => Some(Err(e)), Err(e) => Some(Err(e)),
} }
@ -295,9 +342,12 @@ impl MersData for Iter {
Iters::FilterMap(f) => { Iters::FilterMap(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.filter_map(move |v| match v { Box::new(self.1.get().iterable()?.filter_map(move |v| match v {
Ok(v) => match f.run(v) { Ok(v) => match f.get().execute(v) {
Ok(r) => Some(Ok(r.one_tuple_content()?)), Some(Ok(r)) => Some(Ok(r.one_tuple_content()?)),
Err(e) => Some(Err(e)), Some(Err(e)) => Some(Err(e)),
None => Some(Err(CheckError::from(
"called filter_map with non-function argument",
))),
}, },
Err(e) => Some(Err(e)), Err(e) => Some(Err(e)),
})) }))
@ -305,9 +355,12 @@ impl MersData for Iter {
Iters::MapWhile(f) => { Iters::MapWhile(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.map_while(move |v| match v { Box::new(self.1.get().iterable()?.map_while(move |v| match v {
Ok(v) => match f.run(v) { Ok(v) => match f.get().execute(v) {
Ok(r) => Some(Ok(r.one_tuple_content()?)), Some(Ok(r)) => Some(Ok(r.one_tuple_content()?)),
Err(e) => Some(Err(e)), Some(Err(e)) => Some(Err(e)),
None => Some(Err(CheckError::from(
"called map_while with non-function argument",
))),
}, },
Err(e) => Some(Err(e)), Err(e) => Some(Err(e)),
})) }))
@ -449,10 +502,10 @@ impl Display for IterT {
impl Iters { impl Iters {
fn as_type(&self) -> ItersT { fn as_type(&self) -> ItersT {
match self { match self {
Self::Map(f) => ItersT::Map(f.get_as_type()), Self::Map(f) => ItersT::Map(f.get().executable().unwrap()),
Self::Filter(f) => ItersT::Filter(f.get_as_type()), Self::Filter(f) => ItersT::Filter(f.get().executable().unwrap()),
Self::FilterMap(f) => ItersT::FilterMap(f.get_as_type()), Self::FilterMap(f) => ItersT::FilterMap(f.get().executable().unwrap()),
Self::MapWhile(f) => ItersT::MapWhile(f.get_as_type()), Self::MapWhile(f) => ItersT::MapWhile(f.get().executable().unwrap()),
Self::Take(_) => ItersT::Take, Self::Take(_) => ItersT::Take,
Self::Enumerate => ItersT::Enumerate, Self::Enumerate => ItersT::Enumerate,
Self::Chained => ItersT::Chained, Self::Chained => ItersT::Chained,
@ -470,7 +523,7 @@ fn genfunc_iter_in_val_out(
+ 'static, + 'static,
) -> Function { ) -> Function {
Function { Function {
info: Arc::new(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: Arc::new(move |a, _i| {
if let Some(iter_over) = a.iterable() { if let Some(iter_over) = a.iterable() {

View File

@ -32,7 +32,7 @@ impl Config {
let t = crate::parsing::types::parse_type(&mut src, &srca)?; let t = crate::parsing::types::parse_type(&mut src, &srca)?;
Ok(Arc::new(Type::new(ListT(crate::parsing::types::type_from_parsed(&t, i)?))))}))) Ok(Arc::new(Type::new(ListT(crate::parsing::types::type_from_parsed(&t, i)?))))})))
.add_var("get_mut".to_string(), Data::new(data::function::Function { .add_var("get_mut".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
let mut out = Type::empty_tuple(); let mut out = Type::empty_tuple();
@ -101,7 +101,7 @@ impl Config {
.add_var( .add_var(
"pop".to_string(), "pop".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if let Some(a) = a.dereference() { if let Some(a) = a.dereference() {
@ -149,7 +149,7 @@ impl Config {
.add_var( .add_var(
"push".to_string(), "push".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
for t in a.types.iter() { for t in a.types.iter() {
@ -212,7 +212,7 @@ impl Config {
.add_var( .add_var(
"as_list".to_string(), "as_list".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if let Some(v) = a.iterable() { if let Some(v) = a.iterable() {

View File

@ -71,7 +71,7 @@ impl Config {
.add_var( .add_var(
"parse_float".to_string(), "parse_float".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) { if a.is_included_in(&Type::new(data::string::StringT)) {
@ -105,7 +105,7 @@ impl Config {
.add_var( .add_var(
"parse_int".to_string(), "parse_int".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) { if a.is_included_in(&Type::new(data::string::StringT)) {
@ -139,7 +139,7 @@ impl Config {
.add_var( .add_var(
"signum".to_string(), "signum".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_included_in(&Type::newm(vec![ if a.is_included_in(&Type::newm(vec![
@ -255,7 +255,7 @@ fn num_iter_to_num(
func: impl Fn(Result<isize, f64>, Result<isize, f64>) -> Result<isize, f64> + Send + Sync + 'static, func: impl Fn(Result<isize, f64>, Result<isize, f64>) -> Result<isize, f64> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
data::function::Function { data::function::Function {
info: Arc::new(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: Arc::new(move |a, _i| {
if let Some(a) = a.iterable() { if let Some(a) = a.iterable() {
@ -320,7 +320,7 @@ fn two_num_tuple_to_num(
func_ff: impl Fn(f64, f64) -> Result<f64, CheckError> + Send + Sync + 'static, func_ff: impl Fn(f64, f64) -> Result<f64, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
data::function::Function { data::function::Function {
info: Arc::new(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: 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| {
@ -406,7 +406,7 @@ fn ltgtoe_function(
op: impl Fn(IntOrFloatOrNothing, IntOrFloatOrNothing) -> bool + Send + Sync + 'static, op: impl Fn(IntOrFloatOrNothing, IntOrFloatOrNothing) -> bool + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
data::function::Function { data::function::Function {
info: Arc::new(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: Arc::new(move |a, _i| {
if let Some(iter_type) = a.iterable() { if let Some(iter_type) = a.iterable() {

View File

@ -30,12 +30,12 @@ impl Config {
.add_var( .add_var(
"thread".to_string(), "thread".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: 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.as_any().downcast_ref::<data::function::FunctionT>() { if let Some(f) = t.executable() {
match f.o(&Type::empty_tuple()) { match f.o(&Type::empty_tuple()) {
Ok(t) => out.add_all(&t), Ok(t) => out.add_all(&t),
Err(e) => return Err(CheckError::new().msg_str(format!("Can't call thread on a function which can't be called on an empty tuple: ")).err(e)) Err(e) => return Err(CheckError::new().msg_str(format!("Can't call thread on a function which can't be called on an empty tuple: ")).err(e))
@ -47,24 +47,15 @@ impl Config {
Ok(Type::new(ThreadT(out))) Ok(Type::new(ThreadT(out)))
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get();
if let Some(f) = a
.as_any()
.downcast_ref::<data::function::Function>()
.cloned()
{
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 || f.run(Data::empty_tuple()), move || a.get().execute(Data::empty_tuple()).unwrap(),
))))))) )))))))
} else {
return Err("thread called, but arg wasn't a function".into());
}
}), }),
inner_statements: None, inner_statements: None,
}), }),
) )
.add_var("thread_finished".to_string(), Data::new(data::function::Function { .add_var("thread_finished".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
for t in a.types.iter() { for t in a.types.iter() {
@ -85,7 +76,7 @@ impl Config {
inner_statements: None, inner_statements: None,
})) }))
.add_var("thread_await".to_string(), Data::new(data::function::Function { .add_var("thread_await".to_string(), Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
let mut out = Type::empty(); let mut out = Type::empty();

View File

@ -22,7 +22,7 @@ impl Config {
self.add_var( self.add_var(
"read_line".to_string(), "read_line".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| {
if a.is_zero_tuple() { if a.is_zero_tuple() {
@ -50,7 +50,7 @@ impl Config {
.add_var( .add_var(
"debug".to_string(), "debug".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|a, _i| Ok(a.clone())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
@ -65,7 +65,7 @@ impl Config {
.add_var( .add_var(
"eprint".to_string(), "eprint".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
@ -79,7 +79,7 @@ impl Config {
.add_var( .add_var(
"eprintln".to_string(), "eprintln".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
@ -92,7 +92,7 @@ impl Config {
.add_var( .add_var(
"print".to_string(), "print".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
@ -106,7 +106,7 @@ impl Config {
.add_var( .add_var(
"println".to_string(), "println".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {
info: Arc::new(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: Arc::new(|_a, _i| Ok(Type::empty_tuple())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {

View File

@ -36,7 +36,7 @@ impl MersStatement for Function {
Ok(Box::new(program::run::function::Function { Ok(Box::new(program::run::function::Function {
pos_in_src: self.pos_in_src.clone(), pos_in_src: self.pos_in_src.clone(),
func_no_info: data::function::Function { func_no_info: data::function::Function {
info: Arc::new(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: Arc::new(move |a, i| {
arg2.check(i, Some(a))?; arg2.check(i, Some(a))?;

View File

@ -54,7 +54,7 @@ impl MersStatement for IncludeMers {
chained: Box::new(program::run::function::Function { chained: Box::new(program::run::function::Function {
pos_in_src: self.pos_in_src.clone(), pos_in_src: self.pos_in_src.clone(),
func_no_info: data::function::Function { func_no_info: data::function::Function {
info: Arc::new(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: 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())),

View File

@ -31,10 +31,7 @@ impl MersStatement for Chain {
info.global.enable_hooks = prev_enable_hooks; info.global.enable_hooks = prev_enable_hooks;
let mut o = Type::empty(); let mut o = Type::empty();
for func in &func.types { for func in &func.types {
if let Some(func) = func if let Some(func) = func.executable() {
.as_any()
.downcast_ref::<crate::data::function::FunctionT>()
{
match func.o(&arg) { match func.o(&arg) {
Ok(t) => o.add_all(&t), Ok(t) => o.add_all(&t),
Err(e) => { Err(e) => {
@ -89,10 +86,9 @@ impl MersStatement for Chain {
let f = self.first.run(info)?; let f = self.first.run(info)?;
let c = self.chained.run(info)?; let c = self.chained.run(info)?;
let c = c.get(); let c = c.get();
if let Some(func) = c.as_any().downcast_ref::<crate::data::function::Function>() { match c.execute(f) {
match func.run(f) { Some(Ok(v)) => Ok(v),
Ok(v) => Ok(v), Some(Err(e)) => Err(if let Some(_) = &self.as_part_of_include {
Err(e) => Err(if let Some(_) = &self.as_part_of_include {
CheckError::new().err_with_diff_src(e).src(vec![( CheckError::new().err_with_diff_src(e).src(vec![(
self.pos_in_src.clone(), self.pos_in_src.clone(),
Some(EColor::StacktraceDescendHashInclude), Some(EColor::StacktraceDescendHashInclude),
@ -103,14 +99,12 @@ impl MersStatement for Chain {
(self.source_range(), Some(EColor::StacktraceDescend)), (self.source_range(), Some(EColor::StacktraceDescend)),
]) ])
}), }),
} None => Err(CheckError::new()
} else {
Err(CheckError::new()
.msg_str("tried to chain with non-function".to_owned()) .msg_str("tried to chain with non-function".to_owned())
.src(vec![( .src(vec![(
self.chained.source_range(), self.chained.source_range(),
Some(EColor::ChainWithNonFunction), Some(EColor::ChainWithNonFunction),
)])) )])),
} }
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {

View File

@ -1,8 +1,7 @@
use std::sync::Arc;
use crate::{ use crate::{
data::{self, Data, MersData, Type}, data::{self, Data, MersData, Type},
errors::{CheckError, SourceRange}, errors::{CheckError, SourceRange},
info::Local,
}; };
use super::MersStatement; use super::MersStatement;
@ -26,9 +25,7 @@ impl MersStatement for Function {
Ok(self.func_no_info.as_type()) Ok(self.func_no_info.as_type())
} }
fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
Ok(Data::new( Ok(Data::new(self.func_no_info.with_info_run(info.duplicate())))
self.func_no_info.with_info_run(Arc::new(info.clone())),
))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
true true

View File

@ -53,7 +53,7 @@ impl MersStatement for Try {
let mut func_res = Type::empty(); let mut func_res = Type::empty();
let mut func_err = None; let mut func_err = None;
for ft in func.types.iter() { for ft in func.types.iter() {
if let Some(ft) = ft.as_any().downcast_ref::<data::function::FunctionT>() { if let Some(ft) = ft.executable() {
match ft.o(&Type::newm(vec![Arc::clone(arg)])) { match ft.o(&Type::newm(vec![Arc::clone(arg)])) {
Ok(res) => { Ok(res) => {
func_res.add_all(&res); func_res.add_all(&res);
@ -107,32 +107,18 @@ impl MersStatement for Try {
let ar = arg.get(); let ar = arg.get();
let a = ar.as_ref(); let a = ar.as_ref();
let arg_type = a.as_type(); let arg_type = a.as_type();
let functions = self for func in self.funcs.iter() {
.funcs let func = func.run(info)?;
.iter() let func = func.get();
.map(|v| { match func.executable().map(|func| func.o(&arg_type)) {
Ok::<_, CheckError>( Some(Ok(_)) => {
v.run(info)?
.get()
.as_any()
.downcast_ref::<data::function::Function>()
.unwrap()
.clone(),
)
})
.collect::<Result<Vec<_>, _>>()?;
let mut found = None;
for (i, func) in functions.iter().enumerate() {
match func.get_as_type().o(&arg_type) {
Ok(_) => {
found = Some(i);
break;
}
Err(_) => (),
}
}
drop(ar); drop(ar);
functions[found.expect("try: no function found")].run(arg) return func.execute(arg).unwrap();
}
None | Some(Err(_)) => (),
}
}
panic!("try: no function found")
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
true true