diff --git a/mers/src/main.rs b/mers/src/main.rs index b2a7f43..03b58fb 100755 --- a/mers/src/main.rs +++ b/mers/src/main.rs @@ -92,8 +92,6 @@ fn main() { std::process::exit(36); } }; - #[cfg(debug_assertions)] - dbg!(&return_type); if args.check == Check::Yes { run.run(&mut info_run); } else { diff --git a/mers_lib/src/data/defs.rs b/mers_lib/src/data/defs.rs index 0d5da2a..ba61a6f 100755 --- a/mers_lib/src/data/defs.rs +++ b/mers_lib/src/data/defs.rs @@ -6,7 +6,7 @@ pub fn assign(from: &Data, target: &Data) { .as_any() .downcast_ref::() { - *r.0.lock().unwrap() = from.clone(); + *r.0.write().unwrap() = from.clone(); } else if let (Some(from), Some(target)) = ( from.get() .as_any() diff --git a/mers_lib/src/data/reference.rs b/mers_lib/src/data/reference.rs index 09e8670..e9dad41 100755 --- a/mers_lib/src/data/reference.rs +++ b/mers_lib/src/data/reference.rs @@ -1,18 +1,18 @@ use std::{ any::Any, fmt::Display, - sync::{Arc, Mutex}, + sync::{Arc, RwLock}, }; use super::{Data, MersData, MersType, Type}; #[derive(Debug, Clone)] -pub struct Reference(pub Arc>); +pub struct Reference(pub Arc>); impl MersData for Reference { fn is_eq(&self, other: &dyn MersData) -> bool { if let Some(other) = other.as_any().downcast_ref::() { - *other.0.lock().unwrap() == *self.0.lock().unwrap() + *other.0.write().unwrap() == *self.0.write().unwrap() } else { false } @@ -21,7 +21,7 @@ impl MersData for Reference { Box::new(Clone::clone(self)) } fn as_type(&self) -> Type { - Type::new(ReferenceT(self.0.lock().unwrap().get().as_type())) + Type::new(ReferenceT(self.0.write().unwrap().get().as_type())) } fn as_any(&self) -> &dyn Any { self @@ -69,7 +69,7 @@ impl MersType for ReferenceT { impl Display for Reference { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "&{}", self.0.lock().unwrap().get()) + write!(f, "&{}", self.0.write().unwrap().get()) } } impl Display for ReferenceT { diff --git a/mers_lib/src/program/configs/mod.rs b/mers_lib/src/program/configs/mod.rs index a0b1f40..1ebf805 100755 --- a/mers_lib/src/program/configs/mod.rs +++ b/mers_lib/src/program/configs/mod.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; use crate::{ data::{Data, Type}, @@ -69,7 +69,7 @@ impl Config { pub fn add_var(mut self, name: String, val: Data) -> Self { let t = val.get().as_type(); self.info_parsed.scopes[0].init_var(name, (0, self.globals)); - self.info_run.scopes[0].init_var(self.globals, Arc::new(Mutex::new(val))); + self.info_run.scopes[0].init_var(self.globals, Arc::new(RwLock::new(val))); self.info_check.scopes[0].init_var(self.globals, t); self.globals += 1; self diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index 2f086ad..c8345ec 100755 --- a/mers_lib/src/program/configs/with_base.rs +++ b/mers_lib/src/program/configs/with_base.rs @@ -19,6 +19,7 @@ impl Config { /// `len: fn` gets the length of strings or tuples /// `sleep: fn` sleeps for n seconds (pauses the current thread) /// `panic: fn` exits the program with the given exit code + /// `lock_update: fn` locks the value of a reference so you can exclusively modify it: &var.lock_update(v -> (v, 1).sum) pub fn with_base(self) -> Self { self.add_var("try".to_string(), Data::new(data::function::Function { info: Arc::new(Info::neverused()), @@ -112,6 +113,54 @@ impl Config { unreachable!("try: no function found") }) })) + .add_var("lock_update".to_string(), Data::new(data::function::Function { + info: Arc::new(Info::neverused()), + info_check: Arc::new(Mutex::new(CheckInfo::neverused())), + out: Arc::new(|a, _i| { + for t in a.types.iter() { + if let Some(t) = t.as_any().downcast_ref::() { + if t.0.len() == 2 { + let arg_ref = &t.0[0]; + if let Some(arg) = arg_ref.dereference() { + let func = &t.0[1]; + for func_t in func.types.iter() { + if let Some(f) = func_t.as_any().downcast_ref::() { + match (f.0)(&arg) { + Ok(out) => { + if !out.is_included_in(&arg) { + return Err(format!("Function returns a value of type {out}, which isn't included in the type of the reference, {arg}.").into()); + } + }, + Err(e) => return Err(CheckError::new().msg(format!("Invalid argument type {arg} for function")).err(e)), + } + } else { + return Err(format!("Arguments must be (reference, function)").into()); + } + } + } else { + return Err(format!("Arguments must be (reference, function), but {arg_ref} isn't a reference").into()); + } + } else { + return Err(format!("Can't call lock_update on tuple type {t} with length != 2, which is part of the argument type {a}.").into()); + } + } else { + return Err(format!("Can't call lock_update on non-tuple type {t}, which is part of the argument type {a}.").into()); + } + } + Ok(Type::empty_tuple()) + }), + run: Arc::new(|a, _i| { + let a = a.get(); + let a = a.as_any().downcast_ref::().unwrap(); + let arg_ref = a.0[0].get(); + let arg_ref = arg_ref.as_any().downcast_ref::().unwrap(); + let mut arg = arg_ref.0.write().unwrap(); + let func = a.0[1].get(); + let func = func.as_any().downcast_ref::().unwrap(); + *arg = func.run(arg.clone()); + Data::empty_tuple() + }) + })) .add_var("sleep".to_string(), Data::new(data::function::Function { info: Arc::new(Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), @@ -268,7 +317,7 @@ impl Config { .as_any() .downcast_ref::() { - r.0.lock().unwrap().clone() + r.0.write().unwrap().clone() } else { unreachable!("called deref on non-reference") } diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs index 1d98bd5..0e75ed6 100755 --- a/mers_lib/src/program/configs/with_list.rs +++ b/mers_lib/src/program/configs/with_list.rs @@ -53,7 +53,7 @@ impl Config { .downcast_ref::() .unwrap() .0 - .lock() + .write() .unwrap() .get_mut() .mut_any() @@ -118,7 +118,7 @@ impl Config { .downcast_ref::() .unwrap() .0 - .lock() + .write() .unwrap() .get_mut() .mut_any() diff --git a/mers_lib/src/program/run/mod.rs b/mers_lib/src/program/run/mod.rs index 8118d5e..e82c894 100755 --- a/mers_lib/src/program/run/mod.rs +++ b/mers_lib/src/program/run/mod.rs @@ -1,6 +1,6 @@ use std::{ fmt::{Debug, Display}, - sync::{Arc, Mutex}, + sync::{Arc, RwLock}, }; use colored::Colorize; @@ -240,7 +240,7 @@ pub type CheckInfo = info::Info; #[derive(Default, Clone, Debug)] pub struct Local { - vars: Vec>>, + vars: Vec>>, } #[derive(Default, Clone, Debug)] pub struct CheckLocal { @@ -248,9 +248,9 @@ pub struct CheckLocal { } impl info::Local for Local { type VariableIdentifier = usize; - type VariableData = Arc>; + type VariableData = Arc>; fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) { - let nothing = Arc::new(Mutex::new(Data::new(data::bool::Bool(false)))); + let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false)))); while self.vars.len() <= id { self.vars.push(Arc::clone(¬hing)); } diff --git a/mers_lib/src/program/run/variable.rs b/mers_lib/src/program/run/variable.rs index 3f4454d..2917087 100755 --- a/mers_lib/src/program/run/variable.rs +++ b/mers_lib/src/program/run/variable.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; use crate::data::{self, Data, Type}; @@ -40,7 +40,7 @@ impl MersStatement for Variable { } fn run_custom(&self, info: &mut super::Info) -> Data { if self.is_init { - let nothing = Arc::new(Mutex::new(Data::new(data::bool::Bool(false)))); + let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false)))); while info.scopes[self.var.0].vars.len() <= self.var.1 { info.scopes[self.var.0].vars.push(Arc::clone(¬hing)); } @@ -52,7 +52,7 @@ impl MersStatement for Variable { ))) } else { info.scopes[self.var.0].vars[self.var.1] - .lock() + .write() .unwrap() .clone() }