diff --git a/mers/Cargo.toml b/mers/Cargo.toml index de973e7..abc024e 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers" -version = "0.9.26" +version = "0.9.28" edition = "2021" license = "MIT OR Apache-2.0" 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"] [dependencies] -mers_lib = "0.9.26" +mers_lib = "0.9.28" # mers_lib = { path = "../mers_lib" } clap = { version = "4.3.19", features = ["derive"] } colored = { version = "2.1.0", optional = true } diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml index bbb929d..3a8cc96 100755 --- a/mers_lib/Cargo.toml +++ b/mers_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers_lib" -version = "0.9.26" +version = "0.9.28" edition = "2021" license = "MIT OR Apache-2.0" description = "library to use the mers language in other projects" diff --git a/mers_lib/src/data/defs.rs b/mers_lib/src/data/defs.rs index ebbe160..b86f3ff 100755 --- a/mers_lib/src/data/defs.rs +++ b/mers_lib/src/data/defs.rs @@ -6,33 +6,70 @@ pub fn assign(from: &Data, target: &Data) { .as_any() .downcast_ref::() { - *r.0.write().unwrap() = from.clone(); - } else if let (Some(from), Some(target)) = ( + *r.write() = from.clone(); + } else if let (Some((from, from_ref)), Some(target)) = ( from.get() .as_any() - .downcast_ref::(), + .downcast_ref::() + .map(|v| (v.clone(), false)) + .or_else(|| { + from.get() + .as_any() + .downcast_ref::() + .and_then(|r| { + r.read() + .get() + .as_any() + .downcast_ref::() + .map(|v| (v.clone_refs(), true)) + }) + }), target .get() .as_any() .downcast_ref::(), ) { - for (from, target) in from.0.iter().zip(target.0.iter()) { - assign(from, target); + for (from, target) in from.0.into_iter().zip(target.0.iter()) { + if from_ref { + assign(&Data::new(from), &*target.read()); + } else { + assign(&*from.read(), &*target.read()); + } } - } else if let (Some(from), Some(target)) = ( + } else if let (Some((from, from_ref)), Some(target)) = ( from.get() .as_any() - .downcast_ref::(), + .downcast_ref::() + .map(|v| (v.clone(), false)) + .or_else(|| { + from.get() + .as_any() + .downcast_ref::() + .and_then(|r| { + r.read() + .get() + .as_any() + .downcast_ref::() + .map(|v| (v.clone_refs(), true)) + }) + }), target .get() .as_any() .downcast_ref::(), ) { for (field, target) in target.iter() { - let from = from - .get(*field) - .expect("type-checks should guarantee that from has every field of target"); - assign(from, target); + if from_ref { + let from = from + .get_mut(*field) + .expect("type-checks should guarantee that from has every field of target"); + assign(&Data::new(from.clone_ref()), &*target.read()); + } else { + let from = from + .get(*field) + .expect("type-checks should guarantee that from has every field of target"); + assign(&from, &*target.read()); + } } } else { unreachable!("invalid assignment") diff --git a/mers_lib/src/data/mod.rs b/mers_lib/src/data/mod.rs index 724babe..bb3b906 100755 --- a/mers_lib/src/data/mod.rs +++ b/mers_lib/src/data/mod.rs @@ -225,7 +225,7 @@ impl Data { Self::new(tuple::Tuple(vec![])) } pub fn one_tuple(v: Self) -> Self { - Self::new(tuple::Tuple(vec![v])) + Self::new(tuple::Tuple::from([v])) } /// Returns true if self is `()`. pub fn is_zero_tuple(&self) -> bool { @@ -253,13 +253,13 @@ impl Data { None } } - pub fn get(&self) -> RwLockReadGuard> { + pub fn get(&'_ self) -> RwLockReadGuard<'_, Box> { self.data.read().unwrap() } - pub fn get_mut_unchecked(&self) -> RwLockWriteGuard> { + pub fn get_mut_unchecked(&'_ self) -> RwLockWriteGuard<'_, Box> { self.data.write().unwrap() } - pub fn try_get_mut(&self) -> Option>> { + pub fn try_get_mut(&'_ self) -> Option>> { if self.is_mut && self.counts.0.load(std::sync::atomic::Ordering::Relaxed) == 0 { Some(self.get_mut_unchecked()) } else { @@ -268,7 +268,7 @@ impl Data { } /// like try_get_mut, but instead of returning `None` this function `get()`s the data and clones it. /// When cloning data, this transforms `self` into a `Data` with `is_mut: true`, hence the `&mut self` parameter. - pub fn get_mut(&mut self) -> RwLockWriteGuard> { + pub fn get_mut(&'_ mut self) -> RwLockWriteGuard<'_, Box> { if self.try_get_mut().is_none() { #[cfg(debug_assertions)] eprintln!( diff --git a/mers_lib/src/data/object.rs b/mers_lib/src/data/object.rs index c387b55..3f3399f 100644 --- a/mers_lib/src/data/object.rs +++ b/mers_lib/src/data/object.rs @@ -7,18 +7,33 @@ use crate::info::DisplayInfo; use super::{Data, MersData, MersDataWInfo, MersType, Type}; -#[derive(Debug, PartialEq, Clone)] -pub struct Object(Vec<(usize, Data)>); +#[derive(Debug, PartialEq)] +pub struct Object(Vec<(usize, super::reference::Reference)>); impl Object { - pub fn new(v: Vec<(usize, Data)>) -> Self { - Self(v) + pub fn new(v: impl IntoIterator) -> Self { + Self( + v.into_iter() + .map(|(i, d)| (i, super::reference::Reference::from(d))) + .collect(), + ) } - pub fn get(&self, f: usize) -> Option<&Data> { - self.iter().find(|v| v.0 == f).map(|v| &v.1) + pub fn get(&self, f: usize) -> Option { + self.iter().find(|v| v.0 == f).map(|v| v.1.read().clone()) } - pub fn iter(&self) -> std::slice::Iter<(usize, Data)> { + pub fn get_mut(&self, f: usize) -> Option<&super::reference::Reference> { + self.iter().find(|v| v.0 == f).map(|(_, v)| v) + } + pub fn iter(&'_ self) -> std::slice::Iter<'_, (usize, super::reference::Reference)> { self.0.iter() } + pub fn clone_refs(&self) -> Self { + Self(self.0.iter().map(|(i, r)| (*i, r.clone_ref())).collect()) + } +} +impl Clone for Object { + fn clone(&self) -> Self { + Self(self.0.iter().map(|(i, r)| (*i, r.clone_data())).collect()) + } } #[derive(Debug, Clone)] pub struct ObjectT(Vec<(usize, Type)>); @@ -29,7 +44,7 @@ impl ObjectT { pub fn get(&self, f: usize) -> Option<&Type> { self.iter().find(|v| v.0 == f).map(|v| &v.1) } - pub fn iter(&self) -> std::slice::Iter<(usize, Type)> { + pub fn iter(&'_ self) -> std::slice::Iter<'_, (usize, Type)> { self.0.iter() } fn len(&self) -> usize { @@ -49,7 +64,7 @@ impl MersData for Object { f, "{}: {}", info.get_object_field_name(*field), - val.get().with_display(info) + val.read().get().with_display(info) )?; comma_sep = true; } @@ -69,7 +84,7 @@ impl MersData for Object { fn as_type(&self) -> Type { Type::new(ObjectT( self.iter() - .map(|(n, v)| (n.clone(), v.get().as_type())) + .map(|(n, v)| (n.clone(), v.read().get().as_type())) .collect(), )) } diff --git a/mers_lib/src/data/reference.rs b/mers_lib/src/data/reference.rs index 1cd6303..c6f00a4 100755 --- a/mers_lib/src/data/reference.rs +++ b/mers_lib/src/data/reference.rs @@ -1,14 +1,32 @@ use std::{ any::Any, - sync::{Arc, RwLock}, + sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, }; use crate::{errors::CheckError, info::DisplayInfo}; use super::{Data, MersData, MersType, Type}; -#[derive(Debug, Clone)] -pub struct Reference(pub Arc>); +#[derive(Debug)] +pub struct Reference(Arc>); + +impl Reference { + /// Creates a reference from data, + /// so that the original data can't be + /// modified through the new reference. + pub fn from(data: Data) -> Self { + Self(Arc::new(RwLock::new(data.mkref().0))) + } + pub fn raw(reference: Arc>) -> Self { + Self(reference) + } + pub fn read(&'_ self) -> RwLockReadGuard<'_, Data> { + self.0.read().unwrap() + } + pub fn write(&'_ self) -> RwLockWriteGuard<'_, Data> { + self.0.write().unwrap() + } +} impl MersData for Reference { fn display(&self, info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -79,7 +97,7 @@ impl MersData for Reference { } } fn clone(&self) -> Box { - Box::new(Clone::clone(self)) + Box::new(self.clone_ref()) } fn as_type(&self) -> Type { Type::new(ReferenceT(self.0.read().unwrap().get().as_type())) @@ -95,6 +113,23 @@ impl MersData for Reference { } } +impl Reference { + pub fn clone_ref(&self) -> Self { + Self(Arc::clone(&self.0)) + } + pub fn clone_data(&self) -> Self { + Self(Arc::new(RwLock::new( + self.0.read().unwrap().clone().mkref().0, + ))) + } +} + +impl PartialEq for Reference { + fn eq(&self, other: &Self) -> bool { + *self.0.read().unwrap() == *other.0.read().unwrap() + } +} + #[derive(Debug, Clone)] pub struct ReferenceT(pub Type); impl MersType for ReferenceT { diff --git a/mers_lib/src/data/tuple.rs b/mers_lib/src/data/tuple.rs index e4ab58b..55faba1 100755 --- a/mers_lib/src/data/tuple.rs +++ b/mers_lib/src/data/tuple.rs @@ -4,15 +4,38 @@ use crate::{errors::CheckError, info::DisplayInfo}; use super::{Data, MersData, MersType, Type}; -#[derive(Debug, Clone)] -pub struct Tuple(pub Vec); +#[derive(Debug)] +pub struct Tuple(pub Vec); impl Tuple { + pub fn empty() -> Self { + Self(vec![]) + } + pub fn from(elems: impl IntoIterator) -> Self { + Self( + elems + .into_iter() + .map(|d| super::reference::Reference::from(d)) + .collect(), + ) + } pub fn len(&self) -> usize { self.0.len() } - pub fn get(&self, i: usize) -> Option<&Data> { - self.0.get(i) + pub fn get(&self, i: usize) -> Option { + self.0.get(i).map(|v| v.read().clone()) + } + pub fn get_mut(&self, i: usize) -> Option { + self.0.get(i).map(|v| v.clone_ref()) + } + pub fn clone_refs(&self) -> Self { + Self(self.0.iter().map(|r| r.clone_ref()).collect()) + } +} + +impl Clone for Tuple { + fn clone(&self) -> Self { + Self(self.0.iter().map(|r| r.clone_data()).collect()) } } @@ -23,7 +46,7 @@ impl MersData for Tuple { if i > 0 { write!(f, ", ")?; } - c.get().display(info, f)?; + c.read().get().display(info, f)?; } write!(f, ")")?; Ok(()) @@ -39,13 +62,21 @@ impl MersData for Tuple { &self, _gi: &crate::program::run::RunLocalGlobalInfo, ) -> Option>>> { - Some(Box::new(self.0.clone().into_iter().map(Ok))) + Some(Box::new( + Clone::clone(self) + .0 + .into_iter() + .map(|r| r.read().clone()) + .map(Ok), + )) } fn clone(&self) -> Box { Box::new(Clone::clone(self)) } fn as_type(&self) -> Type { - Type::new(TupleT(self.0.iter().map(|v| v.get().as_type()).collect())) + Type::new(TupleT( + self.0.iter().map(|v| v.read().get().as_type()).collect(), + )) } fn as_any(&self) -> &dyn Any { self diff --git a/mers_lib/src/errors/mod.rs b/mers_lib/src/errors/mod.rs index affd25a..0fc507b 100644 --- a/mers_lib/src/errors/mod.rs +++ b/mers_lib/src/errors/mod.rs @@ -178,7 +178,7 @@ impl CheckErrorHRConfig { .color(s, EColor::Indent(self.color_index), &mut t); return t; } - pub fn indent_start(&self, right: bool) -> IndentStr { + pub fn indent_start(&'_ self, right: bool) -> IndentStr<'_> { IndentStr( &self.idt_start, self.color( @@ -186,13 +186,13 @@ impl CheckErrorHRConfig { ), ) } - pub fn indent_default(&self, right: bool) -> IndentStr { + pub fn indent_default(&'_ self, right: bool) -> IndentStr<'_> { IndentStr( &self.idt_default, self.color(Self::CHARS[self.style as usize][1][right as usize]), ) } - pub fn indent_end(&self, right: bool) -> IndentStr { + pub fn indent_end(&'_ self, right: bool) -> IndentStr<'_> { IndentStr( &self.idt_end, self.color( @@ -200,7 +200,7 @@ impl CheckErrorHRConfig { ), ) } - pub fn indent_single(&self, right: bool) -> IndentStr { + pub fn indent_single(&'_ self, right: bool) -> IndentStr<'_> { IndentStr( &self.idt_single, self.color(if self.is_inner { diff --git a/mers_lib/src/program/configs/gen/mod.rs b/mers_lib/src/program/configs/gen/mod.rs index 8963176..0be93af 100644 --- a/mers_lib/src/program/configs/gen/mod.rs +++ b/mers_lib/src/program/configs/gen/mod.rs @@ -43,7 +43,7 @@ impl FromMersData for OneOrNone { if v.0.is_empty() { f(Some(Self(None))) } else { - A::try_represent(v.0[0].get().as_ref(), |v1| { + A::try_represent(v.0[0].read().get().as_ref(), |v1| { if let Some(va) = v1 { f(Some(Self(Some(va)))) } else { @@ -205,7 +205,7 @@ impl FromMersData for (A,) { .downcast_ref::() .filter(|v| v.0.len() == 1) { - A::try_represent(v.0[0].get().as_ref(), |v1| { + A::try_represent(v.0[0].read().get().as_ref(), |v1| { if let Some(va) = v1 { f(Some((va,))) } else { @@ -222,7 +222,7 @@ impl ToMersData for (A,) { Type::new(data::tuple::TupleT(vec![A::as_type_to()])) } fn represent(self) -> Data { - Data::new(data::tuple::Tuple(vec![self.0.represent()])) + Data::new(data::tuple::Tuple::from([self.0.represent()])) } } @@ -242,9 +242,9 @@ impl FromMersData for (A, B) { .downcast_ref::() .filter(|v| v.0.len() == 2) { - A::try_represent(v.0[0].get().as_ref(), |v1| { + A::try_represent(v.0[0].read().get().as_ref(), |v1| { if let Some(va) = v1 { - B::try_represent(v.0[1].get().as_ref(), |v2| { + B::try_represent(v.0[1].read().get().as_ref(), |v2| { if let Some(vb) = v2 { f(Some((va, vb))) } else { @@ -265,7 +265,7 @@ impl ToMersData for (A, B) { Type::new(data::tuple::TupleT(vec![A::as_type_to(), B::as_type_to()])) } fn represent(self) -> Data { - Data::new(data::tuple::Tuple(vec![ + Data::new(data::tuple::Tuple::from([ self.0.represent(), self.1.represent(), ])) @@ -288,11 +288,11 @@ impl FromMersData for (A, B, .downcast_ref::() .filter(|v| v.0.len() == 3) { - A::try_represent(v.0[0].get().as_ref(), |v1| { + A::try_represent(v.0[0].read().get().as_ref(), |v1| { if let Some(va) = v1 { - B::try_represent(v.0[1].get().as_ref(), |v2| { + B::try_represent(v.0[1].read().get().as_ref(), |v2| { if let Some(vb) = v2 { - C::try_represent(v.0[2].get().as_ref(), |v3| { + C::try_represent(v.0[2].read().get().as_ref(), |v3| { if let Some(vc) = v3 { f(Some((va, vb, vc))) } else { @@ -321,7 +321,7 @@ impl ToMersData for (A, B, C) { ])) } fn represent(self) -> Data { - Data::new(data::tuple::Tuple(vec![ + Data::new(data::tuple::Tuple::from([ self.0.represent(), self.1.represent(), self.2.represent(), diff --git a/mers_lib/src/program/configs/util.rs b/mers_lib/src/program/configs/util.rs index 438d949..b07d71b 100644 --- a/mers_lib/src/program/configs/util.rs +++ b/mers_lib/src/program/configs/util.rs @@ -100,8 +100,10 @@ pub fn to_mers_func_concrete_string_string_to_any( move |a, _| { let a = a.get(); let a = &a.as_any().downcast_ref::().unwrap().0; - let l = a[0].get(); - let r = a[1].get(); + let l = a[0].read(); + let l = l.get(); + let r = a[1].read(); + let r = r.get(); f( l.as_any() .downcast_ref::() diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index 5325bcd..61c94b6 100755 --- a/mers_lib/src/program/configs/with_base.rs +++ b/mers_lib/src/program/configs/with_base.rs @@ -1,5 +1,5 @@ use std::{ - sync::{Arc, Mutex, RwLock}, + sync::{Arc, Mutex}, time::{Duration, Instant}, }; @@ -68,10 +68,12 @@ impl Config { 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 = a.0[0].read(); + let arg_ref = arg_ref.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 mut arg = arg_ref.write(); + let func = a.0[1].read(); + let func = func.get(); *arg = func.execute(arg.clone(), &i.global).unwrap()?; Ok(Data::empty_tuple()) }), @@ -168,7 +170,7 @@ impl Config { fixed_type_out: Arc::new(Mutex::new(None)), out: Ok(Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone()))))), run: Arc::new(|a, _i| { - Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone()))))) + Ok(Data::new(data::reference::Reference::from(a))) }), inner_statements: None, }, @@ -188,7 +190,7 @@ impl Config { .as_any() .downcast_ref::() { - Ok(r.0.write().unwrap().clone()) + Ok(r.read().clone()) } else { Err("called deref on non-reference".into()) } diff --git a/mers_lib/src/program/configs/with_command_running.rs b/mers_lib/src/program/configs/with_command_running.rs index 6c8e98a..1bf9a1f 100755 --- a/mers_lib/src/program/configs/with_command_running.rs +++ b/mers_lib/src/program/configs/with_command_running.rs @@ -53,7 +53,7 @@ impl Config { run: Arc::new(|a, i| { let a = a.get(); let cmd = a.as_any().downcast_ref::().unwrap(); - let (cmd, args) = (&cmd.0[0], &cmd.0[1]); + let (cmd, args) = (&cmd.0[0].read(), &cmd.0[1].read()); let cmd = cmd.get(); let (cmd, args) = ( cmd.as_any().downcast_ref::().unwrap(), @@ -74,7 +74,7 @@ impl Config { String::from_utf8_lossy(&output.stdout).into_owned(); let stderr = String::from_utf8_lossy(&output.stderr).into_owned(); - Ok(Data::new(data::tuple::Tuple(vec![ + Ok(Data::new(data::tuple::Tuple::from([ status, Data::new(data::string::String(stdout)), Data::new(data::string::String(stderr)), @@ -106,7 +106,7 @@ impl Config { run: Arc::new(|a, i| { let a = a.get(); let cmd = a.as_any().downcast_ref::().unwrap(); - let (cmd, args) = (&cmd.0[0], &cmd.0[1]); + let (cmd, args) = (&cmd.0[0].read(), &cmd.0[1].read()); let cmd = cmd.get(); let (cmd, args) = ( cmd.as_any().downcast_ref::().unwrap(), @@ -215,8 +215,10 @@ impl Config { run: Arc::new(|a, i| { let a = a.get(); let tuple = a.as_any().downcast_ref::().unwrap(); - let child = tuple.0[0].get(); - let bytes = tuple.0[1].get(); + let child = tuple.0[0].read(); + let child = child.get(); + let bytes = tuple.0[1].read(); + let bytes = bytes.get(); let child = child.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let buf = bytes.iterable(&i.global).unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::().unwrap().0)).collect::, _>>()?; @@ -246,8 +248,10 @@ impl Config { run: Arc::new(|a, _i| { let a = a.get(); let tuple = a.as_any().downcast_ref::().unwrap(); - let child = tuple.0[0].get(); - let string = tuple.0[1].get(); + let child = tuple.0[0].read(); + let child = child.get(); + let string = tuple.0[1].read(); + let string = string.get(); let child = child.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let buf = string.as_any().downcast_ref::().unwrap().0.as_bytes(); diff --git a/mers_lib/src/program/configs/with_fs.rs b/mers_lib/src/program/configs/with_fs.rs index 14443d0..e0ff7c4 100644 --- a/mers_lib/src/program/configs/with_fs.rs +++ b/mers_lib/src/program/configs/with_fs.rs @@ -76,7 +76,8 @@ impl Config { .as_any() .downcast_ref::() .expect("got non-tuple argument to fs_read_text"); - let (a, b) = (a.0[0].get(), a.0[1].get()); + let (a, b) = (a.0[0].read(), a.0[1].read()); + let (a, b) = (a.get(), b.get()); let a = a .as_any() .downcast_ref::() diff --git a/mers_lib/src/program/configs/with_iters.rs b/mers_lib/src/program/configs/with_iters.rs index 7b256fa..c83079b 100755 --- a/mers_lib/src/program/configs/with_iters.rs +++ b/mers_lib/src/program/configs/with_iters.rs @@ -74,7 +74,8 @@ impl Config { }, |a, _| { let a = a.get(); let a = a.as_any().downcast_ref::().unwrap(); - let (v, e) = (a.0[0].get(), a.0[1].get()); + let (v, e) = (a.0[0].read(), a.0[1].read()); + let (v, e) = (v.get(), e.get()); let (v, e) = (v.as_any().downcast_ref::().unwrap(), e.as_any().downcast_ref::().unwrap()); Ok(Data::new(Range(v.0, e.0))) } @@ -114,7 +115,8 @@ impl Config { }, |a, _| { let a = a.get(); let a = a.as_any().downcast_ref::().unwrap(); - let (v, e) = (a.0[0].get(), a.0[1].get()); + let (v, e) = (a.0[0].read(), a.0[1].read()); + let (v, e) = (v.get(), e.get()); let (v, e) = (v.as_any().downcast_ref::().unwrap(), e.as_any().downcast_ref::().unwrap()); if let Some(e) = e.0.checked_sub(1) { Ok(Data::new(Range(v.0, e))) @@ -495,7 +497,7 @@ impl MersData for Iter { .iterable(&gi)? .enumerate() .map(|(i, v)| match v { - Ok(v) => Ok(Data::new(data::tuple::Tuple(vec![ + Ok(v) => Ok(Data::new(data::tuple::Tuple::from([ Data::new(data::int::Int(i as _)), v, ]))), diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs index 9638536..5b28ad4 100755 --- a/mers_lib/src/program/configs/with_list.rs +++ b/mers_lib/src/program/configs/with_list.rs @@ -65,9 +65,7 @@ impl Config { .as_any() .downcast_ref::() .unwrap() - .0 .write() - .unwrap() .get_mut() .mut_any() .downcast_mut::() @@ -128,20 +126,18 @@ impl Config { run: Arc::new(|a, _i| { let tuple = a.get(); let tuple = tuple.as_any().downcast_ref::().unwrap(); - tuple.0[0] + tuple.0[0].read() .get() .as_any() .downcast_ref::() .unwrap() - .0 .write() - .unwrap() .get_mut() .mut_any() .downcast_mut::() .unwrap() .0 - .push(tuple.0[1].clone()); + .push(tuple.0[1].read().clone()); Ok(Data::empty_tuple()) }), inner_statements: None, @@ -197,15 +193,14 @@ impl Config { run: Arc::new(|a, _i| { let tuple = a.get(); let tuple = tuple.as_any().downcast_ref::().unwrap(); - let index = tuple.0[1].get().as_any().downcast_ref::().unwrap().0 as usize; - let list = tuple.0[0] - .get(); + let index = tuple.0[1].read().get().as_any().downcast_ref::().unwrap().0 as usize; + let list = tuple.0[0].read(); + let list = list.get(); let mut list = list .as_any() .downcast_ref::() .unwrap() - .0 - .write().unwrap(); + .write(); let mut list = list .get_mut(); let list = list @@ -215,7 +210,7 @@ impl Config { if index > list.0.len() { Ok(Data::new(data::bool::Bool(false))) } else { - list.0.insert(index, tuple.0[2].clone()); + list.0.insert(index, tuple.0[2].read().clone()); Ok(Data::new(data::bool::Bool(true))) } }), @@ -277,15 +272,14 @@ impl Config { run: Arc::new(|a, _i| { let tuple = a.get(); let tuple = tuple.as_any().downcast_ref::().unwrap(); - let index = tuple.0[1].get().as_any().downcast_ref::().unwrap().0 as usize; - let list = tuple.0[0] - .get(); + let index = tuple.0[1].read().get().as_any().downcast_ref::().unwrap().0 as usize; + let list = tuple.0[0].read(); + let list = list.get(); let mut list = list .as_any() .downcast_ref::() .unwrap() - .0 - .write().unwrap(); + .write(); let mut list = list .get_mut(); let list = list @@ -293,7 +287,7 @@ impl Config { .downcast_mut::() .unwrap(); if index < list.0.len() { - Ok(Data::one_tuple(std::mem::replace(&mut list.0[index], tuple.0[2].clone()))) + Ok(Data::one_tuple(std::mem::replace(&mut list.0[index], tuple.0[2].read().clone()))) } else { Ok(Data::empty_tuple()) } @@ -350,15 +344,14 @@ impl Config { run: Arc::new(|a, _i| { let tuple = a.get(); let tuple = tuple.as_any().downcast_ref::().unwrap(); - let index = tuple.0[1].get().as_any().downcast_ref::().unwrap().0 as usize; - let list = tuple.0[0] - .get(); + let index = tuple.0[1].read().get().as_any().downcast_ref::().unwrap().0 as usize; + let list = tuple.0[0].read(); + let list = list.get(); let mut list = list .as_any() .downcast_ref::() .unwrap() - .0 - .write().unwrap(); + .write(); let mut list = list .get_mut(); let list = list diff --git a/mers_lib/src/program/configs/with_math.rs b/mers_lib/src/program/configs/with_math.rs index 2f8917a..103d907 100755 --- a/mers_lib/src/program/configs/with_math.rs +++ b/mers_lib/src/program/configs/with_math.rs @@ -805,7 +805,7 @@ fn func_math_op( .map(|v| &v.0) .filter(|v| v.len() == 2) { - let (a, b) = (&a[0], &a[1]); + let (a, b) = (&a[0].read(), &a[1].read()); let (a, b) = (a.get(), b.get()); let a = a .as_any() diff --git a/mers_lib/src/program/run/block.rs b/mers_lib/src/program/run/block.rs index 22ba127..4d96a1a 100755 --- a/mers_lib/src/program/run/block.rs +++ b/mers_lib/src/program/run/block.rs @@ -30,7 +30,7 @@ impl MersStatement for Block { .iter() .map(|s| s.run(info)) .last() - .unwrap_or_else(|| Ok(Data::new(data::tuple::Tuple(vec![])))) + .unwrap_or_else(|| Ok(Data::new(data::tuple::Tuple::empty()))) } fn has_scope(&self) -> bool { true diff --git a/mers_lib/src/program/run/field_chain.rs b/mers_lib/src/program/run/field_chain.rs index e3930b1..9457b43 100644 --- a/mers_lib/src/program/run/field_chain.rs +++ b/mers_lib/src/program/run/field_chain.rs @@ -95,7 +95,7 @@ impl MersStatement for FieldChain { .as_any() .downcast_ref::() { - obj_ref = r.0.read().unwrap(); + obj_ref = r.read(); obj_in_ref = obj_ref.get(); obj_in_ref.as_any().downcast_ref::() } else { @@ -126,7 +126,7 @@ impl MersStatement for FieldChain { for res in more_args.iter().map(|arg| arg.run(info)) { args.push(res?); } - Data::new(Tuple(args)) + Data::new(Tuple::from(args)) } else { object }; diff --git a/mers_lib/src/program/run/object.rs b/mers_lib/src/program/run/object.rs index e552583..d95d04f 100644 --- a/mers_lib/src/program/run/object.rs +++ b/mers_lib/src/program/run/object.rs @@ -1,7 +1,7 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; use crate::{ - data::{self, object::ObjectT, Data, Type}, + data::{self, object::ObjectT, reference::ReferenceT, Data, Type}, errors::{CheckError, EColor, SourceRange}, }; @@ -23,7 +23,19 @@ impl MersStatement for Object { init_to_is_empty_type = init_to.types.is_empty(); let print_is_part_of = init_to.types.len() > 1; let mut init_fields = HashMap::new(); - for t in init_to.types.iter() { + for (t, init_to_ref) in init_to + .types + .iter() + .filter_map(|t| t.as_any().downcast_ref::()) + .flat_map(|r| r.0.types.iter().map(|t| (t, true))) + .chain( + init_to + .types + .iter() + .filter(|t| !t.as_any().is::()) + .map(|t| (t, false)), + ) + { if let Some(ot) = t.as_any().downcast_ref::() { let mut fields = self.fields.iter().map(|(t, _)| *t).collect::>(); fields.sort(); @@ -31,10 +43,12 @@ impl MersStatement for Object { if let Ok(i) = fields.binary_search(field) { fields.remove(i); } - init_fields - .entry(*field) - .or_insert_with(Type::empty) - .add_all(t); + let init_fields = init_fields.entry(*field).or_insert_with(Type::empty); + if init_to_ref { + init_fields.add(Arc::new(ReferenceT(t.clone()))); + } else { + init_fields.add_all(t); + } } if !fields.is_empty() { return Err(CheckError::new().msg(vec![ @@ -136,7 +150,7 @@ impl MersStatement for Object { self.fields .iter() .map(|(n, s)| Ok::<_, CheckError>((n.clone(), s.run(info)?))) - .collect::>()?, + .collect::, _>>()?, ))) } fn has_scope(&self) -> bool { diff --git a/mers_lib/src/program/run/tuple.rs b/mers_lib/src/program/run/tuple.rs index ae19a51..0360789 100755 --- a/mers_lib/src/program/run/tuple.rs +++ b/mers_lib/src/program/run/tuple.rs @@ -1,7 +1,7 @@ -use std::collections::VecDeque; +use std::{collections::VecDeque, sync::Arc}; use crate::{ - data::{self, tuple::TupleT, Data, MersType, Type}, + data::{self, reference::ReferenceT, tuple::TupleT, Data, MersType, Type}, errors::{CheckError, EColor, SourceRange}, }; @@ -23,11 +23,27 @@ impl MersStatement for Tuple { .map(|_| Type::empty()) .collect::>(); let print_is_part_of = init_to.types.len() > 1; - for t in init_to.types.iter() { + for (t, init_to_ref) in init_to + .types + .iter() + .filter_map(|t| t.as_any().downcast_ref::()) + .flat_map(|r| r.0.types.iter().map(|t| (t, true))) + .chain( + init_to + .types + .iter() + .filter(|t| !t.as_any().is::()) + .map(|t| (t, false)), + ) + { if let Some(t) = t.as_any().downcast_ref::() { if t.0.len() == self.elems.len() { for (i, e) in t.0.iter().enumerate() { - vec[i].add_all(&e); + if init_to_ref { + vec[i].add(Arc::new(ReferenceT(e.clone()))); + } else { + vec[i].add_all(e); + } } } else { return Err(CheckError::new().msg(vec![ @@ -102,11 +118,11 @@ impl MersStatement for Tuple { ))) } fn run_custom(&self, info: &mut super::Info) -> Result { - Ok(Data::new(data::tuple::Tuple( + Ok(Data::new(data::tuple::Tuple::from( self.elems .iter() .map(|s| Ok(s.run(info)?)) - .collect::>()?, + .collect::, CheckError>>()?, ))) } fn has_scope(&self) -> bool { diff --git a/mers_lib/src/program/run/variable.rs b/mers_lib/src/program/run/variable.rs index a38f86c..64f370f 100755 --- a/mers_lib/src/program/run/variable.rs +++ b/mers_lib/src/program/run/variable.rs @@ -60,14 +60,14 @@ impl MersStatement for Variable { info.scopes[self.var.0].vars[self.var.1] = nothing; } else { // (reference to) data which will never be referenced again - return Ok(Data::new(data::reference::Reference(Arc::new( - RwLock::new(Data::empty_tuple()), - )))); + return Ok(Data::new(data::reference::Reference::from( + Data::empty_tuple(), + ))); } } Ok(if self.is_ref_not_ignore { let v = &info.scopes[self.var.0].vars[self.var.1]; - Data::new(data::reference::Reference(Arc::clone(v))) + Data::new(data::reference::Reference::raw(Arc::clone(v))) } else { info.scopes[self.var.0].vars[self.var.1] .write() diff --git a/merslsp/Cargo.toml b/merslsp/Cargo.toml index 63bfd3c..5122d3d 100644 --- a/merslsp/Cargo.toml +++ b/merslsp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.15" edition = "2021" [dependencies] -mers_lib = "0.9.18" +mers_lib = "0.9.28" lspower = "1.5.0" tokio = { version = "1.36.0", features = ["full"] } line-span = "0.1.5"