summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/array.rs62
-rw-r--r--src/eval/dict.rs60
-rw-r--r--src/eval/ops.rs16
-rw-r--r--src/eval/template.rs20
4 files changed, 94 insertions, 64 deletions
diff --git a/src/eval/array.rs b/src/eval/array.rs
index f62bda9f..38876c96 100644
--- a/src/eval/array.rs
+++ b/src/eval/array.rs
@@ -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,32 +106,53 @@ 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<'a> IntoIterator for &'a Array {
- type Item = &'a Value;
- type IntoIter = std::slice::Iter<'a, Value>;
-
- fn into_iter(self) -> Self::IntoIter {
- self.iter()
+impl Extend<Value> for Array {
+ fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
+ Rc::make_mut(&mut self.vec).extend(iter);
}
}
-impl Add<&Array> for Array {
- type Output = Self;
+impl IntoIterator for Array {
+ type Item = Value;
+ type IntoIter = std::vec::IntoIter<Value>;
- fn add(mut self, rhs: &Array) -> Self::Output {
- self.extend(rhs);
- self
+ fn into_iter(self) -> Self::IntoIter {
+ match Rc::try_unwrap(self.vec) {
+ Ok(vec) => vec.into_iter(),
+ Err(rc) => (*rc).clone().into_iter(),
+ }
}
}
-impl AddAssign<&Array> for Array {
- fn add_assign(&mut self, rhs: &Array) {
- self.extend(rhs);
+impl<'a> IntoIterator for &'a Array {
+ type Item = &'a Value;
+ type IntoIter = std::slice::Iter<'a, Value>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
}
}
diff --git a/src/eval/dict.rs b/src/eval/dict.rs
index c1c3f505..bc7df2b8 100644
--- a/src/eval/dict.rs
+++ b/src/eval/dict.rs
@@ -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,32 +87,53 @@ 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<'a> IntoIterator for &'a Dict {
- type Item = (&'a EcoString, &'a Value);
- type IntoIter = std::collections::btree_map::Iter<'a, EcoString, Value>;
-
- fn into_iter(self) -> Self::IntoIter {
- self.iter()
+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 Add<&Dict> for Dict {
- type Output = Self;
+impl IntoIterator for Dict {
+ type Item = (EcoString, Value);
+ type IntoIter = std::collections::btree_map::IntoIter<EcoString, Value>;
- fn add(mut self, rhs: &Dict) -> Self::Output {
- self.extend(rhs);
- self
+ fn into_iter(self) -> Self::IntoIter {
+ match Rc::try_unwrap(self.map) {
+ Ok(map) => map.into_iter(),
+ Err(rc) => (*rc).clone().into_iter(),
+ }
}
}
-impl AddAssign<&Dict> for Dict {
- fn add_assign(&mut self, rhs: &Dict) {
- self.extend(rhs);
+impl<'a> IntoIterator for &'a Dict {
+ type Item = (&'a EcoString, &'a Value);
+ type IntoIter = std::collections::btree_map::Iter<'a, EcoString, Value>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
}
}
diff --git a/src/eval/ops.rs b/src/eval/ops.rs
index 6408c6c3..df8babe2 100644
--- a/src/eval/ops.rs
+++ b/src/eval/ops.rs
@@ -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),
diff --git a/src/eval/template.rs b/src/eval/template.rs
index 0be2492b..33f2b896 100644
--- a/src/eval/template.rs
+++ b/src/eval/template.rs
@@ -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;