mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 05:43:53 +01:00
add get_mut function for lists
This commit is contained in:
parent
479b619388
commit
782460e472
@ -101,6 +101,9 @@ impl Data {
|
||||
data: Arc::new(RwLock::new(data)),
|
||||
}
|
||||
}
|
||||
pub fn is_mut(&self) -> bool {
|
||||
self.is_mut
|
||||
}
|
||||
pub fn empty_tuple() -> Self {
|
||||
Self::new(tuple::Tuple(vec![]))
|
||||
}
|
||||
@ -166,20 +169,27 @@ impl Data {
|
||||
}
|
||||
self.get_mut_unchecked()
|
||||
}
|
||||
pub fn mkref(&self) -> Self {
|
||||
/// If self is already mut, returns `(Data, false)`. If not, inner data will be cloned and `(Data, true)` will be returned.
|
||||
pub fn mkref(&self) -> (Self, bool) {
|
||||
if self.is_mut {
|
||||
self.counts
|
||||
.1
|
||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
Self {
|
||||
is_mut: true,
|
||||
counts: Arc::clone(&self.counts),
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
(
|
||||
Self {
|
||||
is_mut: true,
|
||||
counts: Arc::clone(&self.counts),
|
||||
data: Arc::clone(&self.data),
|
||||
},
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("[mers:data:cow] cloning! mkref called on immutable data");
|
||||
Self::new_boxed(self.data.read().unwrap().clone(), true)
|
||||
(
|
||||
Self::new_boxed(self.data.read().unwrap().clone(), true),
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,11 +22,29 @@ pub mod prelude_compile {
|
||||
/// with this, you can add values (usually functions),
|
||||
/// or add your own types to the language:
|
||||
///
|
||||
/// use mers_lib::prelude_extend_config::Config;
|
||||
/// fn add_thing(cfg: Config) -> Config {
|
||||
/// /// use the methods on Config to add things (see the Config source code for examples)
|
||||
/// // use the methods on Config to add things (see the Config source code for examples)
|
||||
/// cfg.add_var("my_var".to_owned(), todo!())
|
||||
/// }
|
||||
///
|
||||
/// then use the Config when compiling and running your code, and your customizations will be available.
|
||||
pub mod prelude_extend_config {
|
||||
pub use crate::program::configs::Config;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
for example in std::fs::read_dir("../examples").unwrap() {
|
||||
let path = example.unwrap().path();
|
||||
eprintln!("Checking file {path:?}.");
|
||||
let src = prelude_compile::Source::new_from_file(path).unwrap();
|
||||
let (mut i1, _, mut i3) = prelude_compile::Config::new().bundle_std().infos();
|
||||
prelude_compile::parse(&mut src.clone(), &std::sync::Arc::new(src))
|
||||
.unwrap()
|
||||
.compile(&mut i1, prelude_compile::CompInfo::default())
|
||||
.unwrap()
|
||||
.check(&mut i3, None)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,15 @@ use crate::{
|
||||
program::run::CheckInfo,
|
||||
};
|
||||
|
||||
mod with_base;
|
||||
mod with_command_running;
|
||||
mod with_get;
|
||||
mod with_iters;
|
||||
mod with_list;
|
||||
mod with_math;
|
||||
mod with_multithreading;
|
||||
mod with_stdio;
|
||||
mod with_string;
|
||||
pub mod with_base;
|
||||
pub mod with_command_running;
|
||||
pub mod with_get;
|
||||
pub mod with_iters;
|
||||
pub mod with_list;
|
||||
pub mod with_math;
|
||||
pub mod with_multithreading;
|
||||
pub mod with_stdio;
|
||||
pub mod with_string;
|
||||
|
||||
/// Usage: create an empty Config using Config::new(), use the methods to customize it, then get the Infos using Config::infos()
|
||||
/// bundle_* for bundles (combines multiple groups or even bundles)
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -17,16 +17,84 @@ impl Config {
|
||||
/// `as_list: fn` turns a tuple into a list
|
||||
/// `push: fn` adds an element to a list
|
||||
/// `pop: fn` removes the last element from a list. returns (element) or ().
|
||||
/// TODO!
|
||||
/// `get_mut: fn` like get, but returns a reference to the object
|
||||
/// TODO!
|
||||
/// `remove_at: fn` [TODO]
|
||||
/// `insert_at: fn` [TODO]
|
||||
pub fn with_list(self) -> Self {
|
||||
// TODO: Type with generics
|
||||
self.add_type("List".to_string(),
|
||||
self
|
||||
.add_type("List".to_string(),
|
||||
Err(Arc::new(|s, i| {
|
||||
let mut src = Source::new_from_string_raw(s.to_owned());
|
||||
let srca = Arc::new(src.clone());
|
||||
let t = crate::parsing::types::parse_type(&mut src, &srca)?;
|
||||
Ok(Arc::new(ListT(crate::parsing::types::type_from_parsed(&t, i)?)))})))
|
||||
.add_var("get_mut".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(program::run::Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Arc::new(|a, _i| {
|
||||
let mut out = Type::empty_tuple();
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if t.0.len() != 2 {
|
||||
return Err(format!(
|
||||
"get_mut: argument must be a 2-tuple `(&List<_>, Int)`."
|
||||
).into());
|
||||
}
|
||||
if t.0[1].is_included_in_single(&data::int::IntT) {
|
||||
if let Some(t) = t.0[0].dereference() {
|
||||
for t in t.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<ListT>() {
|
||||
out.add(Arc::new(data::reference::ReferenceT(t.0.clone())));
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: first argument in tuple {t} isn't `&List<_>`."
|
||||
).into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: first type in tuple {t} isn't a reference."
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: Second type in tuple {t} wasn't `Int`."
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: argument must be a 2-tuple `(&List<_>, Int)`."
|
||||
).into());
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}),
|
||||
run: Arc::new(|a, _i| {
|
||||
let t = a.get();
|
||||
let t = t.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
|
||||
let i = t.0[1].get().as_any().downcast_ref::<data::int::Int>().unwrap().0.max(0) as usize;
|
||||
let o = match t.0[0].get()
|
||||
.as_any()
|
||||
.downcast_ref::<data::reference::Reference>()
|
||||
.unwrap()
|
||||
.0
|
||||
.read()
|
||||
.unwrap()
|
||||
.get()
|
||||
.as_any()
|
||||
.downcast_ref::<List>()
|
||||
.unwrap().0.get(i)
|
||||
{
|
||||
Some(data) => {
|
||||
Data::new(data::reference::Reference(Arc::clone(data)))
|
||||
}
|
||||
None => Data::empty_tuple(),
|
||||
};
|
||||
o
|
||||
}),
|
||||
}))
|
||||
.add_var(
|
||||
"pop".to_string(),
|
||||
Data::new(data::function::Function {
|
||||
@ -68,7 +136,7 @@ impl Config {
|
||||
.0
|
||||
.pop()
|
||||
{
|
||||
Some(data) => Data::one_tuple(data),
|
||||
Some(data) => Data::one_tuple(data.read().unwrap().clone()),
|
||||
None => Data::empty_tuple(),
|
||||
}
|
||||
}),
|
||||
@ -131,7 +199,7 @@ impl Config {
|
||||
.downcast_mut::<List>()
|
||||
.unwrap()
|
||||
.0
|
||||
.push(tuple.0[1].clone());
|
||||
.push(Arc::new(RwLock::new(tuple.0[1].clone())));
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
}),
|
||||
@ -152,7 +220,7 @@ impl Config {
|
||||
}),
|
||||
run: Arc::new(|a, _i| {
|
||||
if let Some(i) = a.get().iterable() {
|
||||
Data::new(List(i.collect()))
|
||||
Data::new(List(i.map(|v| Arc::new(RwLock::new(v))).collect()))
|
||||
} else {
|
||||
unreachable!("as_list called on non-iterable")
|
||||
}
|
||||
@ -163,19 +231,29 @@ impl Config {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct List(Vec<Data>);
|
||||
pub struct List(Vec<Arc<RwLock<Data>>>);
|
||||
#[derive(Debug)]
|
||||
pub struct ListT(Type);
|
||||
impl MersData for List {
|
||||
fn is_eq(&self, other: &dyn MersData) -> bool {
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
other.0 == self.0
|
||||
other.0.len() == self.0.len()
|
||||
&& self
|
||||
.0
|
||||
.iter()
|
||||
.zip(other.0.iter())
|
||||
.all(|(s, o)| *s.read().unwrap() == *o.read().unwrap())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> {
|
||||
Some(Box::new(self.0.clone().into_iter()))
|
||||
Some(Box::new(
|
||||
self.0
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|v| v.read().unwrap().clone()),
|
||||
))
|
||||
}
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
@ -183,7 +261,7 @@ impl MersData for List {
|
||||
fn as_type(&self) -> Type {
|
||||
let mut t = Type::empty();
|
||||
for el in &self.0 {
|
||||
t.add(Arc::new(el.get().as_type()));
|
||||
t.add(Arc::new(el.read().unwrap().get().as_type()));
|
||||
}
|
||||
Type::new(ListT(t))
|
||||
}
|
||||
@ -235,7 +313,7 @@ impl Display for List {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", c.get())?;
|
||||
write!(f, "{}", c.read().unwrap().get())?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user