From 945e19e10a4f36b87b7936129eadae0d3bffce55 Mon Sep 17 00:00:00 2001 From: Mark <> Date: Tue, 30 Apr 2024 13:58:40 +0200 Subject: [PATCH] fix list cloning not cloning inner values this would allow mutating values through a list passed by value, but now it doesn't, which is how it always should have been. --- mers/Cargo.toml | 4 ++-- mers_lib/Cargo.toml | 2 +- mers_lib/src/data/reference.rs | 4 ++-- mers_lib/src/program/configs/with_base.rs | 15 ++++++++++++++- mers_lib/src/program/configs/with_list.rs | 20 +++++++++++++++----- mers_lib/src/program/run/variable.rs | 12 ++++-------- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/mers/Cargo.toml b/mers/Cargo.toml index aadade0..e455c4b 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers" -version = "0.8.2" +version = "0.8.3" edition = "2021" license = "MIT OR Apache-2.0" description = "dynamically typed but type-checked programming language" @@ -11,7 +11,7 @@ repository = "https://github.com/Dummi26/mers" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -mers_lib = "0.8.2" +mers_lib = "0.8.3" # mers_lib = { path = "../mers_lib" } clap = { version = "4.3.19", features = ["derive"] } colored = "2.1.0" diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml index 634832a..1da9484 100755 --- a/mers_lib/Cargo.toml +++ b/mers_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers_lib" -version = "0.8.2" +version = "0.8.3" 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/reference.rs b/mers_lib/src/data/reference.rs index c69a36f..89c7aab 100755 --- a/mers_lib/src/data/reference.rs +++ b/mers_lib/src/data/reference.rs @@ -7,7 +7,7 @@ use std::{ use super::{Data, MersData, MersType, Type}; #[derive(Debug, Clone)] -pub struct Reference(pub Arc>, pub Type); +pub struct Reference(pub Arc>); impl MersData for Reference { fn is_eq(&self, other: &dyn MersData) -> bool { @@ -21,7 +21,7 @@ impl MersData for Reference { Box::new(Clone::clone(self)) } fn as_type(&self) -> Type { - Type::new(ReferenceT(self.1.clone())) + Type::new(ReferenceT(self.0.read().unwrap().get().as_type())) } fn as_any(&self) -> &dyn Any { self diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index b3c0440..a80596d 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}, + sync::{Arc, Mutex, RwLock}, time::Duration, }; @@ -13,6 +13,7 @@ use super::Config; impl Config { /// `deref: fn` clones the value from a reference + /// `mkref: fn` returns a reference to a copy of the value /// `eq: fn` returns true if all the values are equal, otherwise false. /// `loop: fn` runs a function until it returns (T) instead of (), then returns T. Also works with ((), f) instead of f for ().loop(() -> { ... }) syntax, which may be more readable /// `try: fn` runs the first valid function with the argument. usage: (arg, (f1, f2, f3)).try @@ -173,6 +174,18 @@ impl Config { inner_statements: None, }), ) + .add_var( + "mkref".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| Ok(Type::new(data::reference::ReferenceT(a.clone())))), + run: Arc::new(|a, _i| { + Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone())))) + }), + inner_statements: None, + }), + ) .add_var( "deref".to_string(), Data::new(data::function::Function { diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs index aa715fe..ada337a 100755 --- a/mers_lib/src/program/configs/with_list.rs +++ b/mers_lib/src/program/configs/with_list.rs @@ -80,16 +80,16 @@ impl Config { .as_any() .downcast_ref::() .unwrap().0; - let list = list - .read() + let mut list = list + .write() .unwrap(); - let list = list.get(); + let list = list.get_mut(); let list = list.as_any() .downcast_ref::() .unwrap(); let o = match list.0.get(i) { Some(data) => { - Data::one_tuple(Data::new(data::reference::Reference(Arc::clone(data), list.inner_type()))) + Data::one_tuple(Data::new(data::reference::Reference(Arc::clone(data)))) } None => Data::empty_tuple(), }; @@ -235,8 +235,18 @@ impl Config { } } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct List(pub Vec>>); +impl Clone for List { + fn clone(&self) -> Self { + Self( + self.0 + .iter() + .map(|v| Arc::new(RwLock::new(v.read().unwrap().clone()))) + .collect(), + ) + } +} #[derive(Debug)] pub struct ListT(pub Type); impl MersData for List { diff --git a/mers_lib/src/program/run/variable.rs b/mers_lib/src/program/run/variable.rs index 34e15a8..c8c5922 100755 --- a/mers_lib/src/program/run/variable.rs +++ b/mers_lib/src/program/run/variable.rs @@ -60,18 +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 Data::new(data::reference::Reference( - Arc::new(RwLock::new(Data::empty_tuple())), - Type::empty(), - )); + return Data::new(data::reference::Reference(Arc::new(RwLock::new( + Data::empty_tuple(), + )))); } } 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), - v.read().unwrap().get().as_type(), - )) + Data::new(data::reference::Reference(Arc::clone(v))) } else { info.scopes[self.var.0].vars[self.var.1] .write()