1use hashbrown::{hash_map, HashMap};
4
5use core::{
6 iter::{self, FromIterator},
7 ops,
8};
9
10use crate::{
11 alloc::{String, ToOwned},
12 fns, NativeFn, Value,
13};
14
15#[derive(Debug)]
46pub struct Environment<'a, T> {
47 variables: HashMap<String, Value<'a, T>>,
48}
49
50impl<T> Default for Environment<'_, T> {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56impl<T: Clone> Clone for Environment<'_, T> {
57 fn clone(&self) -> Self {
58 Self {
59 variables: self.variables.clone(),
60 }
61 }
62}
63
64impl<T: PartialEq> PartialEq for Environment<'_, T> {
65 fn eq(&self, other: &Self) -> bool {
66 self.variables == other.variables
67 }
68}
69
70impl<'a, T> Environment<'a, T> {
71 pub fn new() -> Self {
73 Self {
74 variables: HashMap::new(),
75 }
76 }
77
78 pub fn get(&self, name: &str) -> Option<&Value<'a, T>> {
80 self.variables.get(name)
81 }
82
83 pub fn iter(&self) -> impl Iterator<Item = (&str, &Value<'a, T>)> + '_ {
85 self.variables
86 .iter()
87 .map(|(name, value)| (name.as_str(), value))
88 }
89
90 pub fn insert(&mut self, name: &str, value: Value<'a, T>) -> &mut Self {
92 self.variables.insert(name.to_owned(), value);
93 self
94 }
95
96 pub fn insert_native_fn(
98 &mut self,
99 name: &str,
100 native_fn: impl NativeFn<T> + 'static,
101 ) -> &mut Self {
102 self.insert(name, Value::native_fn(native_fn))
103 }
104
105 pub fn insert_wrapped_fn<Args, F>(&mut self, name: &str, fn_to_wrap: F) -> &mut Self
113 where
114 fns::FnWrapper<Args, F>: NativeFn<T> + 'static,
115 {
116 let wrapped = fns::wrap::<Args, _>(fn_to_wrap);
117 self.insert(name, Value::native_fn(wrapped))
118 }
119}
120
121impl<'a, T> ops::Index<&str> for Environment<'a, T> {
122 type Output = Value<'a, T>;
123
124 fn index(&self, index: &str) -> &Self::Output {
125 self.get(index)
126 .unwrap_or_else(|| panic!("Variable `{}` is not defined", index))
127 }
128}
129
130impl<'a, T> IntoIterator for Environment<'a, T> {
131 type Item = (String, Value<'a, T>);
132 type IntoIter = IntoIter<'a, T>;
133
134 fn into_iter(self) -> Self::IntoIter {
135 IntoIter {
136 inner: self.variables.into_iter(),
137 }
138 }
139}
140
141#[derive(Debug)]
143pub struct IntoIter<'a, T> {
144 inner: hash_map::IntoIter<String, Value<'a, T>>,
145}
146
147impl<'a, T> Iterator for IntoIter<'a, T> {
148 type Item = (String, Value<'a, T>);
149
150 fn next(&mut self) -> Option<Self::Item> {
151 self.inner.next()
152 }
153
154 fn size_hint(&self) -> (usize, Option<usize>) {
155 self.inner.size_hint()
156 }
157}
158
159impl<T> ExactSizeIterator for IntoIter<'_, T> {
160 fn len(&self) -> usize {
161 self.inner.len()
162 }
163}
164
165impl<'r, 'a, T> IntoIterator for &'r Environment<'a, T> {
166 type Item = (&'r str, &'r Value<'a, T>);
167 type IntoIter = Iter<'r, 'a, T>;
168
169 fn into_iter(self) -> Self::IntoIter {
170 Iter {
171 inner: self
172 .variables
173 .iter()
174 .map(|(name, value)| (name.as_str(), value)),
175 }
176 }
177}
178
179type MapFn<'r, 'a, T> = fn((&'r String, &'r Value<'a, T>)) -> (&'r str, &'r Value<'a, T>);
180
181#[derive(Debug)]
183pub struct Iter<'r, 'a, T> {
184 inner: iter::Map<hash_map::Iter<'r, String, Value<'a, T>>, MapFn<'r, 'a, T>>,
185}
186
187impl<'r, 'a, T> Iterator for Iter<'r, 'a, T> {
188 type Item = (&'r str, &'r Value<'a, T>);
189
190 fn next(&mut self) -> Option<Self::Item> {
191 self.inner.next()
192 }
193
194 fn size_hint(&self) -> (usize, Option<usize>) {
195 self.inner.size_hint()
196 }
197}
198
199impl<T> ExactSizeIterator for Iter<'_, '_, T> {
200 fn len(&self) -> usize {
201 self.inner.len()
202 }
203}
204
205impl<'a, T, S, V> FromIterator<(S, V)> for Environment<'a, T>
206where
207 S: Into<String>,
208 V: Into<Value<'a, T>>,
209{
210 fn from_iter<I: IntoIterator<Item = (S, V)>>(iter: I) -> Self {
211 let variables = iter
212 .into_iter()
213 .map(|(var_name, value)| (var_name.into(), value.into()));
214 Self {
215 variables: variables.collect(),
216 }
217 }
218}
219
220impl<'a, T, S, V> Extend<(S, V)> for Environment<'a, T>
221where
222 S: Into<String>,
223 V: Into<Value<'a, T>>,
224{
225 fn extend<I: IntoIterator<Item = (S, V)>>(&mut self, iter: I) {
226 let variables = iter
227 .into_iter()
228 .map(|(var_name, value)| (var_name.into(), value.into()));
229 self.variables.extend(variables);
230 }
231}