mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-24 23:46:32 +01:00
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:
@@ -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()) {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user