1use crate::Env;
22use crate::source::Location;
23use std::borrow::Borrow;
24use std::collections::HashSet;
25use std::fmt::Debug;
26use std::fmt::Display;
27use std::hash::Hash;
28use std::hash::Hasher;
29use std::iter::FusedIterator;
30use std::pin::Pin;
31use std::rc::Rc;
32use thiserror::Error;
33
34pub trait FunctionBody<S>: Debug + Display {
36 #[allow(async_fn_in_trait, reason = "we don't support Send")]
41 async fn execute(&self, env: &mut Env<S>) -> crate::semantics::Result;
42}
43
44pub trait FunctionBodyObject<S>: Debug + Display {
51 fn execute<'a>(
56 &'a self,
57 env: &'a mut Env<S>,
58 ) -> Pin<Box<dyn Future<Output = crate::semantics::Result> + 'a>>;
59}
60
61impl<S, T: FunctionBody<S> + ?Sized> FunctionBodyObject<S> for T {
62 fn execute<'a>(
63 &'a self,
64 env: &'a mut Env<S>,
65 ) -> Pin<Box<dyn Future<Output = crate::semantics::Result> + 'a>> {
66 Box::pin(self.execute(env))
67 }
68}
69
70pub struct Function<S> {
72 pub name: String,
74
75 pub body: Rc<dyn FunctionBodyObject<S>>,
82
83 pub origin: Location,
85
86 pub read_only_location: Option<Location>,
92}
93
94impl<S> Function<S> {
95 #[inline]
100 #[must_use]
101 pub fn new<N: Into<String>, B: Into<Rc<dyn FunctionBodyObject<S>>>>(
102 name: N,
103 body: B,
104 origin: Location,
105 ) -> Self {
106 Function {
107 name: name.into(),
108 body: body.into(),
109 origin,
110 read_only_location: None,
111 }
112 }
113
114 #[inline]
119 #[must_use]
120 pub fn make_read_only(mut self, location: Location) -> Self {
121 self.read_only_location = Some(location);
122 self
123 }
124
125 #[must_use]
127 pub const fn is_read_only(&self) -> bool {
128 self.read_only_location.is_some()
129 }
130}
131
132impl<S> Clone for Function<S> {
134 fn clone(&self) -> Self {
135 Self {
136 name: self.name.clone(),
137 body: self.body.clone(),
138 origin: self.origin.clone(),
139 read_only_location: self.read_only_location.clone(),
140 }
141 }
142}
143
144impl<S> PartialEq for Function<S> {
149 fn eq(&self, other: &Self) -> bool {
150 self.name == other.name
151 && Rc::ptr_eq(&self.body, &other.body)
152 && self.origin == other.origin
153 && self.read_only_location == other.read_only_location
154 }
155}
156
157impl<S> Eq for Function<S> {}
158
159impl<S> Debug for Function<S> {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 f.debug_struct("Function")
163 .field("name", &self.name)
164 .field("body", &self.body)
165 .field("origin", &self.origin)
166 .field("read_only_location", &self.read_only_location)
167 .finish()
168 }
169}
170
171struct HashEntry<S>(Rc<Function<S>>);
182
183impl<S> Clone for HashEntry<S> {
185 fn clone(&self) -> Self {
186 HashEntry(Rc::clone(&self.0))
187 }
188}
189
190impl<S> PartialEq for HashEntry<S> {
191 fn eq(&self, other: &HashEntry<S>) -> bool {
196 self.0.name == other.0.name
197 }
198}
199
200impl<S> Eq for HashEntry<S> {}
202
203impl<S> Hash for HashEntry<S> {
204 fn hash<H: Hasher>(&self, state: &mut H) {
209 self.0.name.hash(state)
210 }
211}
212
213impl<S> Borrow<str> for HashEntry<S> {
214 fn borrow(&self) -> &str {
215 &self.0.name
216 }
217}
218
219impl<S> Debug for HashEntry<S> {
221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222 f.debug_tuple("HashEntry").field(&self.0).finish()
223 }
224}
225
226pub struct FunctionSet<S> {
228 entries: HashSet<HashEntry<S>>,
229}
230
231impl<S> Debug for FunctionSet<S> {
233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 f.debug_struct("FunctionSet")
235 .field("entries", &self.entries)
236 .finish()
237 }
238}
239
240impl<S> Clone for FunctionSet<S> {
242 fn clone(&self) -> Self {
243 #[allow(
244 clippy::mutable_key_type,
245 reason = "we use Rc but it's effectively immutable"
246 )]
247 let entries = self.entries.clone();
248 Self { entries }
249 }
250}
251
252impl<S> Default for FunctionSet<S> {
254 fn default() -> Self {
255 #[allow(
256 clippy::mutable_key_type,
257 reason = "we use Rc but it's effectively immutable"
258 )]
259 let entries = HashSet::default();
260 Self { entries }
261 }
262}
263
264#[derive(Error)]
266#[error("cannot redefine read-only function `{}`", .existing.name)]
267#[non_exhaustive]
268pub struct DefineError<S> {
269 pub existing: Rc<Function<S>>,
271 pub new: Rc<Function<S>>,
273}
274
275impl<S> Clone for DefineError<S> {
277 fn clone(&self) -> Self {
278 Self {
279 existing: self.existing.clone(),
280 new: self.new.clone(),
281 }
282 }
283}
284
285impl<S> Debug for DefineError<S> {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 f.debug_struct("DefineError")
288 .field("existing", &self.existing)
289 .field("new", &self.new)
290 .finish()
291 }
292}
293
294impl<S> PartialEq for DefineError<S> {
295 fn eq(&self, other: &Self) -> bool {
296 self.existing == other.existing && self.new == other.new
297 }
298}
299
300impl<S> Eq for DefineError<S> {}
301
302#[derive(Error)]
304#[error("cannot unset read-only function `{}`", .existing.name)]
305#[non_exhaustive]
306pub struct UnsetError<S> {
307 pub existing: Rc<Function<S>>,
309}
310
311impl<S> Clone for UnsetError<S> {
313 fn clone(&self) -> Self {
314 Self {
315 existing: self.existing.clone(),
316 }
317 }
318}
319
320impl<S> Debug for UnsetError<S> {
321 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
322 f.debug_struct("UnsetError")
323 .field("existing", &self.existing)
324 .finish()
325 }
326}
327
328impl<S> PartialEq for UnsetError<S> {
329 fn eq(&self, other: &Self) -> bool {
330 self.existing == other.existing
331 }
332}
333
334impl<S> Eq for UnsetError<S> {}
335
336pub struct Iter<'a, S> {
340 inner: std::collections::hash_set::Iter<'a, HashEntry<S>>,
341}
342
343impl<S> Clone for Iter<'_, S> {
345 fn clone(&self) -> Self {
346 Self {
347 inner: self.inner.clone(),
348 }
349 }
350}
351
352impl<S> Debug for Iter<'_, S> {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354 f.debug_struct("Iter").field("inner", &self.inner).finish()
355 }
356}
357
358impl<S> FunctionSet<S> {
359 #[must_use]
361 pub fn new() -> Self {
362 FunctionSet::default()
363 }
364
365 #[must_use]
367 pub fn get(&self, name: &str) -> Option<&Rc<Function<S>>> {
368 self.entries.get(name).map(|entry| &entry.0)
369 }
370
371 #[inline]
373 #[must_use]
374 pub fn len(&self) -> usize {
375 self.entries.len()
376 }
377
378 #[inline]
380 #[must_use]
381 pub fn is_empty(&self) -> bool {
382 self.entries.is_empty()
383 }
384
385 pub fn define<F: Into<Rc<Function<S>>>>(
391 &mut self,
392 function: F,
393 ) -> Result<Option<Rc<Function<S>>>, DefineError<S>> {
394 #[allow(
395 clippy::mutable_key_type,
396 reason = "we use Rc but it's effectively immutable"
397 )]
398 fn inner<S>(
399 entries: &mut HashSet<HashEntry<S>>,
400 new: Rc<Function<S>>,
401 ) -> Result<Option<Rc<Function<S>>>, DefineError<S>> {
402 match entries.get(new.name.as_str()) {
403 Some(existing) if existing.0.is_read_only() => Err(DefineError {
404 existing: Rc::clone(&existing.0),
405 new,
406 }),
407
408 _ => Ok(entries.replace(HashEntry(new)).map(|entry| entry.0)),
409 }
410 }
411 inner(&mut self.entries, function.into())
412 }
413
414 pub fn unset(&mut self, name: &str) -> Result<Option<Rc<Function<S>>>, UnsetError<S>> {
419 match self.entries.get(name) {
420 Some(entry) if entry.0.is_read_only() => Err(UnsetError {
421 existing: Rc::clone(&entry.0),
422 }),
423
424 _ => Ok(self.entries.take(name).map(|entry| entry.0)),
425 }
426 }
427
428 pub fn iter(&self) -> Iter<'_, S> {
432 let inner = self.entries.iter();
433 Iter { inner }
434 }
435}
436
437impl<'a, S> Iterator for Iter<'a, S> {
438 type Item = &'a Rc<Function<S>>;
439
440 fn next(&mut self) -> Option<Self::Item> {
441 self.inner.next().map(|entry| &entry.0)
442 }
443}
444
445impl<S> ExactSizeIterator for Iter<'_, S> {
446 #[inline]
447 fn len(&self) -> usize {
448 self.inner.len()
449 }
450}
451
452impl<S> FusedIterator for Iter<'_, S> {}
453
454impl<'a, S> IntoIterator for &'a FunctionSet<S> {
455 type Item = &'a Rc<Function<S>>;
456 type IntoIter = Iter<'a, S>;
457 fn into_iter(self) -> Self::IntoIter {
458 self.iter()
459 }
460}
461
462#[cfg(test)]
463mod tests {
464 use super::*;
465
466 #[derive(Clone, Debug)]
467 struct FunctionBodyStub;
468
469 impl std::fmt::Display for FunctionBodyStub {
470 fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471 unreachable!()
472 }
473 }
474 impl<S> FunctionBody<S> for FunctionBodyStub {
475 async fn execute(&self, _: &mut Env<S>) -> crate::semantics::Result {
476 unreachable!()
477 }
478 }
479
480 fn function_body_stub<S>() -> Rc<dyn FunctionBodyObject<S>> {
481 Rc::new(FunctionBodyStub)
482 }
483
484 #[test]
485 fn defining_new_function() {
486 let mut set = FunctionSet::<()>::new();
487 let function = Rc::new(Function::new(
488 "foo",
489 function_body_stub(),
490 Location::dummy("foo"),
491 ));
492
493 let result = set.define(function.clone());
494 assert_eq!(result, Ok(None));
495 assert_eq!(set.get("foo"), Some(&function));
496 }
497
498 #[test]
499 fn redefining_existing_function() {
500 let mut set = FunctionSet::<()>::new();
501 let function1 = Rc::new(Function::new(
502 "foo",
503 function_body_stub(),
504 Location::dummy("foo 1"),
505 ));
506 let function2 = Rc::new(Function::new(
507 "foo",
508 function_body_stub(),
509 Location::dummy("foo 2"),
510 ));
511 set.define(function1.clone()).unwrap();
512
513 let result = set.define(function2.clone());
514 assert_eq!(result, Ok(Some(function1)));
515 assert_eq!(set.get("foo"), Some(&function2));
516 }
517
518 #[test]
519 fn redefining_readonly_function() {
520 let mut set = FunctionSet::<()>::new();
521 let function1 = Rc::new(
522 Function::new("foo", function_body_stub(), Location::dummy("foo 1"))
523 .make_read_only(Location::dummy("readonly")),
524 );
525 let function2 = Rc::new(Function::new(
526 "foo",
527 function_body_stub(),
528 Location::dummy("foo 2"),
529 ));
530 set.define(function1.clone()).unwrap();
531
532 let error = set.define(function2.clone()).unwrap_err();
533 assert_eq!(error.existing, function1);
534 assert_eq!(error.new, function2);
535 assert_eq!(set.get("foo"), Some(&function1));
536 }
537
538 #[test]
539 fn unsetting_existing_function() {
540 let mut set = FunctionSet::<()>::new();
541 let function = Rc::new(Function::new(
542 "foo",
543 function_body_stub(),
544 Location::dummy("foo"),
545 ));
546 set.define(function.clone()).unwrap();
547
548 let result = set.unset("foo").unwrap();
549 assert_eq!(result, Some(function));
550 assert_eq!(set.get("foo"), None);
551 }
552
553 #[test]
554 fn unsetting_nonexisting_function() {
555 let mut set = FunctionSet::<()>::new();
556
557 let result = set.unset("foo").unwrap();
558 assert_eq!(result, None);
559 assert_eq!(set.get("foo"), None);
560 }
561
562 #[test]
563 fn unsetting_readonly_function() {
564 let mut set = FunctionSet::<()>::new();
565 let function = Rc::new(
566 Function::new("foo", function_body_stub(), Location::dummy("foo"))
567 .make_read_only(Location::dummy("readonly")),
568 );
569 set.define(function.clone()).unwrap();
570
571 let error = set.unset("foo").unwrap_err();
572 assert_eq!(error.existing, function);
573 }
574
575 #[test]
576 fn iteration() {
577 let mut set = FunctionSet::<()>::new();
578 let function1 = Rc::new(Function::new(
579 "foo",
580 function_body_stub(),
581 Location::dummy("foo"),
582 ));
583 let function2 = Rc::new(Function::new(
584 "bar",
585 function_body_stub(),
586 Location::dummy("bar"),
587 ));
588 set.define(function1.clone()).unwrap();
589 set.define(function2.clone()).unwrap();
590
591 let functions = set.iter().collect::<Vec<_>>();
592 assert!(
593 functions[..] == [&function1, &function2] || functions[..] == [&function2, &function1],
594 "{functions:?}"
595 );
596 }
597}