Better addition and iteration for array, dict and template

This commit is contained in:
Laurenz 2021-07-29 12:01:06 +02:00
parent 312dcd070c
commit 853361338b
5 changed files with 104 additions and 68 deletions

View File

@ -73,11 +73,6 @@ impl Array {
Rc::make_mut(&mut self.vec).push(value);
}
/// Extend the array with the values from another array.
pub fn extend(&mut self, other: &Array) {
Rc::make_mut(&mut self.vec).extend(other.into_iter())
}
/// Clear the array.
pub fn clear(&mut self) {
if Rc::strong_count(&mut self.vec) == 1 {
@ -90,19 +85,13 @@ impl Array {
/// Repeat this array `n` times.
pub fn repeat(&self, n: usize) -> Self {
let len = self.len().checked_mul(n).expect("capacity overflow");
self.into_iter().cycle().take(len).collect()
self.iter().cloned().cycle().take(len).collect()
}
/// Iterate over references to the contained values.
pub fn iter(&self) -> std::slice::Iter<Value> {
self.vec.iter()
}
/// Iterate over the contained values.
pub fn into_iter(&self) -> impl Iterator<Item = Value> + Clone + '_ {
// TODO: Actually consume the vector if the ref-count is 1?
self.iter().cloned()
}
}
impl Default for Array {
@ -117,12 +106,48 @@ impl Debug for Array {
}
}
impl Add for Array {
type Output = Self;
fn add(mut self, rhs: Array) -> Self::Output {
self += rhs;
self
}
}
impl AddAssign for Array {
fn add_assign(&mut self, rhs: Array) {
match Rc::try_unwrap(rhs.vec) {
Ok(vec) => self.extend(vec),
Err(rc) => self.extend(rc.iter().cloned()),
}
}
}
impl FromIterator<Value> for Array {
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
Array { vec: Rc::new(iter.into_iter().collect()) }
}
}
impl Extend<Value> for Array {
fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
Rc::make_mut(&mut self.vec).extend(iter);
}
}
impl IntoIterator for Array {
type Item = Value;
type IntoIter = std::vec::IntoIter<Value>;
fn into_iter(self) -> Self::IntoIter {
match Rc::try_unwrap(self.vec) {
Ok(vec) => vec.into_iter(),
Err(rc) => (*rc).clone().into_iter(),
}
}
}
impl<'a> IntoIterator for &'a Array {
type Item = &'a Value;
type IntoIter = std::slice::Iter<'a, Value>;
@ -131,18 +156,3 @@ impl<'a> IntoIterator for &'a Array {
self.iter()
}
}
impl Add<&Array> for Array {
type Output = Self;
fn add(mut self, rhs: &Array) -> Self::Output {
self.extend(rhs);
self
}
}
impl AddAssign<&Array> for Array {
fn add_assign(&mut self, rhs: &Array) {
self.extend(rhs);
}
}

View File

@ -60,11 +60,6 @@ impl Dict {
Rc::make_mut(&mut self.map).insert(key, value);
}
/// Extend the dictionary with the values from another dictionary.
pub fn extend(&mut self, other: &Dict) {
Rc::make_mut(&mut self.map).extend(other.into_iter())
}
/// Clear the dictionary.
pub fn clear(&mut self) {
if Rc::strong_count(&mut self.map) == 1 {
@ -74,12 +69,6 @@ impl Dict {
}
}
/// Iterate over pairs of the contained keys and values.
pub fn into_iter(&self) -> impl Iterator<Item = (EcoString, Value)> + Clone + '_ {
// TODO: Actually consume the map if the ref-count is 1?
self.iter().map(|(k, v)| (k.clone(), v.clone()))
}
/// Iterate over pairs of references to the contained keys and values.
pub fn iter(&self) -> std::collections::btree_map::Iter<EcoString, Value> {
self.map.iter()
@ -98,12 +87,48 @@ impl Debug for Dict {
}
}
impl Add for Dict {
type Output = Self;
fn add(mut self, rhs: Dict) -> Self::Output {
self += rhs;
self
}
}
impl AddAssign for Dict {
fn add_assign(&mut self, rhs: Dict) {
match Rc::try_unwrap(rhs.map) {
Ok(map) => self.extend(map),
Err(rc) => self.extend(rc.iter().map(|(k, v)| (k.clone(), v.clone()))),
}
}
}
impl FromIterator<(EcoString, Value)> for Dict {
fn from_iter<T: IntoIterator<Item = (EcoString, Value)>>(iter: T) -> Self {
Dict { map: Rc::new(iter.into_iter().collect()) }
}
}
impl Extend<(EcoString, Value)> for Dict {
fn extend<T: IntoIterator<Item = (EcoString, Value)>>(&mut self, iter: T) {
Rc::make_mut(&mut self.map).extend(iter);
}
}
impl IntoIterator for Dict {
type Item = (EcoString, Value);
type IntoIter = std::collections::btree_map::IntoIter<EcoString, Value>;
fn into_iter(self) -> Self::IntoIter {
match Rc::try_unwrap(self.map) {
Ok(map) => map.into_iter(),
Err(rc) => (*rc).clone().into_iter(),
}
}
}
impl<'a> IntoIterator for &'a Dict {
type Item = (&'a EcoString, &'a Value);
type IntoIter = std::collections::btree_map::Iter<'a, EcoString, Value>;
@ -112,18 +137,3 @@ impl<'a> IntoIterator for &'a Dict {
self.iter()
}
}
impl Add<&Dict> for Dict {
type Output = Self;
fn add(mut self, rhs: &Dict) -> Self::Output {
self.extend(rhs);
self
}
}
impl AddAssign<&Dict> for Dict {
fn add_assign(&mut self, rhs: &Dict) {
self.extend(rhs);
}
}

View File

@ -11,10 +11,10 @@ pub fn join(lhs: Value, rhs: Value) -> Result<Value, Value> {
(a, None) => a,
(None, b) => b,
(Str(a), Str(b)) => Str(a + &b),
(Array(a), Array(b)) => Array(a + &b),
(Dict(a), Dict(b)) => Dict(a + &b),
(Template(a), Template(b)) => Template(a + &b),
(Str(a), Str(b)) => Str(a + b),
(Array(a), Array(b)) => Array(a + b),
(Dict(a), Dict(b)) => Dict(a + b),
(Template(a), Template(b)) => Template(a + b),
(Template(a), Str(b)) => Template(a + b),
(Str(a), Template(b)) => Template(a + b),
@ -74,10 +74,10 @@ pub fn add(lhs: Value, rhs: Value) -> Value {
(Fractional(a), Fractional(b)) => Fractional(a + b),
(Str(a), Str(b)) => Str(a + &b),
(Array(a), Array(b)) => Array(a + &b),
(Dict(a), Dict(b)) => Dict(a + &b),
(Template(a), Template(b)) => Template(a + &b),
(Str(a), Str(b)) => Str(a + b),
(Array(a), Array(b)) => Array(a + b),
(Dict(a), Dict(b)) => Dict(a + b),
(Template(a), Template(b)) => Template(a + b),
(Template(a), Str(b)) => Template(a + b),
(Str(a), Template(b)) => Template(a + b),

View File

@ -1,12 +1,12 @@
use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::ops::{Add, Deref};
use std::ops::{Add, AddAssign, Deref};
use std::rc::Rc;
use super::Value;
use crate::util::EcoString;
use crate::exec::ExecContext;
use crate::syntax::{Expr, SyntaxTree};
use crate::util::EcoString;
/// A template value: `[*Hi* there]`.
#[derive(Default, Debug, Clone)]
@ -50,15 +50,25 @@ impl PartialEq for Template {
}
}
impl Add<&Template> for Template {
impl Add for Template {
type Output = Self;
fn add(mut self, rhs: &Self) -> Self::Output {
Rc::make_mut(&mut self.nodes).extend(rhs.nodes.iter().cloned());
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl AddAssign for Template {
fn add_assign(&mut self, rhs: Template) {
let sink = Rc::make_mut(&mut self.nodes);
match Rc::try_unwrap(rhs.nodes) {
Ok(source) => sink.extend(source),
Err(rc) => sink.extend(rc.iter().cloned()),
}
}
}
impl Add<EcoString> for Template {
type Output = Self;

View File

@ -274,14 +274,20 @@ impl PartialOrd for EcoString {
}
}
impl Add<&Self> for EcoString {
impl Add for EcoString {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
fn add(self, rhs: Self) -> Self::Output {
self + rhs.as_str()
}
}
impl AddAssign for EcoString {
fn add_assign(&mut self, rhs: EcoString) {
self.push_str(&rhs);
}
}
impl Add<&str> for EcoString {
type Output = Self;