add get_mut function for lists

This commit is contained in:
Mark
2023-11-29 16:26:51 +01:00
parent 479b619388
commit 782460e472
4 changed files with 134 additions and 28 deletions

View File

@@ -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)

View File

@@ -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(())