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

@@ -6,14 +6,14 @@ use std::{
use crate::{
errors::CheckError,
info::Local,
program::run::{CheckInfo, Info},
};
use super::{Data, MersData, MersType, Type};
#[derive(Clone)]
pub struct Function {
pub info: Arc<Info>,
pub info: Info,
pub info_check: Arc<Mutex<CheckInfo>>,
pub out: Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>,
pub run:
@@ -23,20 +23,31 @@ pub struct Function {
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 {
pub fn new(
out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> Self {
Self {
info: Arc::new(crate::info::Info::neverused()),
info: crate::info::Info::neverused(),
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
out: Arc::new(move |a, _| out(a)),
run: Arc::new(move |a, _| run(a)),
inner_statements: None,
}
}
pub fn with_info_run(&self, info: Arc<Info>) -> Self {
pub fn with_info_run(&self, info: Info) -> Self {
Self {
info,
info_check: Arc::clone(&self.info_check),
@@ -57,8 +68,11 @@ impl Function {
drop(lock);
(self.out)(arg, &mut info)
}
pub fn run(&self, arg: Data) -> Result<Data, CheckError> {
(self.run)(arg, &mut self.info.as_ref().clone())
pub fn run_mut(&mut self, arg: Data) -> Result<Data, CheckError> {
(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 {
let out = Arc::clone(&self.out);
@@ -73,10 +87,16 @@ impl 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>>>> {
let s = Clone::clone(self);
let mut s = Clone::clone(self);
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)),
Ok(v) => {
if let Some(v) = v.one_tuple_content() {
@@ -122,6 +142,9 @@ impl FunctionT {
}
}
impl MersType for FunctionT {
fn executable(&self) -> Option<crate::data::function::FunctionT> {
Some(self.clone())
}
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 let Ok(t) = self.o(&Type::empty_tuple()) {

View File

@@ -19,6 +19,15 @@ pub mod tuple;
pub mod defs;
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>>>> {
None
}
@@ -38,6 +47,10 @@ pub trait MersData: 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
/// Should return Some(I), where I is an Iterator which only returns items of type T.
fn iterable(&self) -> Option<Type> {

View File

@@ -4,12 +4,63 @@ use std::{
sync::{Arc, RwLock},
};
use crate::errors::CheckError;
use super::{Data, MersData, MersType, Type};
#[derive(Debug, Clone)]
pub struct Reference(pub Arc<RwLock<Data>>);
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 {
if let Some(other) = other.as_any().downcast_ref::<Self>() {
*other.0.write().unwrap() == *self.0.write().unwrap()
@@ -37,6 +88,38 @@ impl MersData for Reference {
#[derive(Debug, Clone)]
pub struct ReferenceT(pub Type);
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 {
if let Some(o) = other.as_any().downcast_ref::<Self>() {
self.0.is_same_type_as(&o.0)
@@ -76,7 +159,7 @@ impl MersType for ReferenceT {
impl Display for Reference {
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 {