diff options
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/dict.rs | 86 | ||||
| -rw-r--r-- | src/eval/value.rs | 4 |
2 files changed, 68 insertions, 22 deletions
diff --git a/src/eval/dict.rs b/src/eval/dict.rs index 7f4426ff..b0d5fb82 100644 --- a/src/eval/dict.rs +++ b/src/eval/dict.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::fmt::{self, Debug, Display, Formatter}; +use std::iter::Extend; use std::ops::Index; use crate::syntax::{Span, Spanned}; @@ -117,9 +118,7 @@ impl<V> Dict<V> { /// Iterator over all borrowed keys and values. pub fn iter(&self) -> impl Iterator<Item = (RefKey, &V)> { - self.nums() - .map(|(&k, v)| (RefKey::Num(k), v)) - .chain(self.strs().map(|(k, v)| (RefKey::Str(k), v))) + self.into_iter() } /// Iterate over all values in the dictionary. @@ -137,14 +136,6 @@ impl<V> Dict<V> { self.strs.iter() } - /// Move into an owned iterator over owned keys and values. - pub fn into_iter(self) -> impl Iterator<Item = (DictKey, V)> { - self.nums - .into_iter() - .map(|(k, v)| (DictKey::Num(k), v)) - .chain(self.strs.into_iter().map(|(k, v)| (DictKey::Str(k), v))) - } - /// Move into an owned iterator over all values in the dictionary. pub fn into_values(self) -> impl Iterator<Item = V> { self.nums @@ -164,17 +155,6 @@ impl<V> Dict<V> { } } -impl<'a, K, V> Index<K> for Dict<V> -where - K: Into<RefKey<'a>>, -{ - type Output = V; - - fn index(&self, index: K) -> &Self::Output { - self.get(index).expect("key not in dict") - } -} - impl<V> Default for Dict<V> { fn default() -> Self { Self::new() @@ -189,6 +169,68 @@ impl<V: PartialEq> PartialEq for Dict<V> { } } +impl<V> IntoIterator for Dict<V> { + type Item = (DictKey, V); + type IntoIter = std::iter::Chain< + std::iter::Map< + std::collections::btree_map::IntoIter<u64, V>, + fn((u64, V)) -> (DictKey, V), + >, + std::iter::Map< + std::collections::btree_map::IntoIter<String, V>, + fn((String, V)) -> (DictKey, V), + >, + >; + + fn into_iter(self) -> Self::IntoIter { + let nums = self.nums.into_iter().map((|(k, v)| (DictKey::Num(k), v)) as _); + let strs = self.strs.into_iter().map((|(k, v)| (DictKey::Str(k), v)) as _); + nums.chain(strs) + } +} + +impl<'a, V> IntoIterator for &'a Dict<V> { + type Item = (RefKey<'a>, &'a V); + type IntoIter = std::iter::Chain< + std::iter::Map< + std::collections::btree_map::Iter<'a, u64, V>, + fn((&'a u64, &'a V)) -> (RefKey<'a>, &'a V), + >, + std::iter::Map< + std::collections::btree_map::Iter<'a, String, V>, + fn((&'a String, &'a V)) -> (RefKey<'a>, &'a V), + >, + >; + + fn into_iter(self) -> Self::IntoIter { + let strs = self.strs().map((|(k, v): (&'a String, _)| (RefKey::Str(k), v)) as _); + let nums = self.nums().map((|(k, v): (&u64, _)| (RefKey::Num(*k), v)) as _); + nums.chain(strs) + } +} + +impl<V> Extend<(DictKey, V)> for Dict<V> { + fn extend<T>(&mut self, iter: T) + where + T: IntoIterator<Item = (DictKey, V)>, + { + for (key, value) in iter.into_iter() { + self.insert(key, value); + } + } +} + +impl<'a, K, V> Index<K> for Dict<V> +where + K: Into<RefKey<'a>>, +{ + type Output = V; + + fn index(&self, index: K) -> &Self::Output { + self.get(index).expect("key not in dict") + } +} + impl<V: Debug> Debug for Dict<V> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { if self.is_empty() { diff --git a/src/eval/value.rs b/src/eval/value.rs index 51bc55ab..85ac2367 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -17,6 +17,8 @@ use crate::{DynFuture, Feedback, Pass}; /// A computational value. #[derive(Clone, PartialEq)] pub enum Value { + /// The result of invalid operations. + Error, /// An identifier: `ident`. Ident(Ident), /// A boolean: `true, false`. @@ -54,6 +56,7 @@ impl Value { /// The natural-language name of this value for use in error messages. pub fn name(&self) -> &'static str { match self { + Self::Error => "error", Self::Ident(_) => "identifier", Self::Bool(_) => "bool", Self::Int(_) => "integer", @@ -111,6 +114,7 @@ impl Spanned<Value> { impl Debug for Value { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { + Self::Error => f.pad("<error>"), Self::Ident(i) => i.fmt(f), Self::Bool(b) => b.fmt(f), Self::Int(i) => i.fmt(f), |
