Skip to main content

sim_kernel/env/
base.rs

1use std::{collections::BTreeMap, sync::Arc};
2
3use crate::{error::Diagnostic, id::Symbol, value::Value};
4
5/// A lexical environment: a frame of symbol bindings chained to a parent.
6///
7/// Lookups walk from the local frame outward through parent frames. The active
8/// `Env` is held by the [`Cx`](crate::Cx) and swapped during nested scopes.
9#[derive(Clone, Debug, Default)]
10pub struct Env {
11    frame: BTreeMap<Symbol, Value>,
12    parent: Option<Arc<Env>>,
13}
14
15impl Env {
16    /// Builds a child environment with an empty frame over `parent`.
17    pub fn child(parent: Arc<Env>) -> Self {
18        Self {
19            frame: BTreeMap::new(),
20            parent: Some(parent),
21        }
22    }
23
24    /// Binds a name in the local frame, returning any previous binding.
25    pub fn define(&mut self, name: Symbol, value: Value) -> Option<Value> {
26        self.frame.insert(name, value)
27    }
28
29    /// Looks up a name, walking outward to parent frames.
30    pub fn get(&self, name: &Symbol) -> Option<Value> {
31        self.frame
32            .get(name)
33            .cloned()
34            .or_else(|| self.parent.as_ref().and_then(|parent| parent.get(name)))
35    }
36}
37
38/// A collected sink of [`Diagnostic`]s accumulated during a checked call.
39#[derive(Clone, Debug, Default)]
40pub struct Diagnostics {
41    messages: Vec<Diagnostic>,
42}
43
44impl Diagnostics {
45    /// Pushes an error-level diagnostic from a message.
46    pub fn push(&mut self, message: impl Into<String>) {
47        self.messages.push(Diagnostic::error(message));
48    }
49
50    /// Pushes an already-built diagnostic.
51    pub fn push_diagnostic(&mut self, diagnostic: Diagnostic) {
52        self.messages.push(diagnostic);
53    }
54
55    /// Pushes an info-level diagnostic from a message.
56    pub fn push_info(&mut self, message: impl Into<String>) {
57        self.messages.push(Diagnostic::info(message));
58    }
59
60    /// Returns the accumulated diagnostics.
61    pub fn messages(&self) -> &[Diagnostic] {
62        &self.messages
63    }
64
65    /// Drains and returns the accumulated diagnostics.
66    pub fn take(&mut self) -> Vec<Diagnostic> {
67        std::mem::take(&mut self.messages)
68    }
69}