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.
This commit is contained in:
Mark 2024-04-30 13:58:40 +02:00
parent 1554453eb9
commit 945e19e10a
6 changed files with 38 additions and 19 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.8.2" version = "0.8.3"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "dynamically typed but type-checked programming language" 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 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
mers_lib = "0.8.2" mers_lib = "0.8.3"
# mers_lib = { path = "../mers_lib" } # mers_lib = { path = "../mers_lib" }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
colored = "2.1.0" colored = "2.1.0"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers_lib" name = "mers_lib"
version = "0.8.2" version = "0.8.3"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "library to use the mers language in other projects" description = "library to use the mers language in other projects"

View File

@ -7,7 +7,7 @@ use std::{
use super::{Data, MersData, MersType, Type}; use super::{Data, MersData, MersType, Type};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Reference(pub Arc<RwLock<Data>>, pub Type); pub struct Reference(pub Arc<RwLock<Data>>);
impl MersData for Reference { impl MersData for Reference {
fn is_eq(&self, other: &dyn MersData) -> bool { fn is_eq(&self, other: &dyn MersData) -> bool {
@ -21,7 +21,7 @@ impl MersData for Reference {
Box::new(Clone::clone(self)) Box::new(Clone::clone(self))
} }
fn as_type(&self) -> Type { 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 { fn as_any(&self) -> &dyn Any {
self self

View File

@ -1,5 +1,5 @@
use std::{ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex, RwLock},
time::Duration, time::Duration,
}; };
@ -13,6 +13,7 @@ use super::Config;
impl Config { impl Config {
/// `deref: fn` clones the value from a reference /// `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. /// `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 /// `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 /// `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, 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( .add_var(
"deref".to_string(), "deref".to_string(),
Data::new(data::function::Function { Data::new(data::function::Function {

View File

@ -80,16 +80,16 @@ impl Config {
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
.unwrap().0; .unwrap().0;
let list = list let mut list = list
.read() .write()
.unwrap(); .unwrap();
let list = list.get(); let list = list.get_mut();
let list = list.as_any() let list = list.as_any()
.downcast_ref::<List>() .downcast_ref::<List>()
.unwrap(); .unwrap();
let o = match list.0.get(i) { let o = match list.0.get(i) {
Some(data) => { 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(), None => Data::empty_tuple(),
}; };
@ -235,8 +235,18 @@ impl Config {
} }
} }
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct List(pub Vec<Arc<RwLock<Data>>>); pub struct List(pub Vec<Arc<RwLock<Data>>>);
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)] #[derive(Debug)]
pub struct ListT(pub Type); pub struct ListT(pub Type);
impl MersData for List { impl MersData for List {

View File

@ -60,18 +60,14 @@ impl MersStatement for Variable {
info.scopes[self.var.0].vars[self.var.1] = nothing; info.scopes[self.var.0].vars[self.var.1] = nothing;
} else { } else {
// (reference to) data which will never be referenced again // (reference to) data which will never be referenced again
return Data::new(data::reference::Reference( return Data::new(data::reference::Reference(Arc::new(RwLock::new(
Arc::new(RwLock::new(Data::empty_tuple())), Data::empty_tuple(),
Type::empty(), ))));
));
} }
} }
if self.is_ref_not_ignore { if self.is_ref_not_ignore {
let v = &info.scopes[self.var.0].vars[self.var.1]; let v = &info.scopes[self.var.0].vars[self.var.1];
Data::new(data::reference::Reference( Data::new(data::reference::Reference(Arc::clone(v)))
Arc::clone(v),
v.read().unwrap().get().as_type(),
))
} else { } else {
info.scopes[self.var.0].vars[self.var.1] info.scopes[self.var.0].vars[self.var.1]
.write() .write()