gent/interpreter/
environment.rs

1//! Environment for scoped variable storage
2
3use crate::interpreter::types::EnumDef;
4use crate::interpreter::Value;
5use std::collections::HashMap;
6
7/// Scoped environment for storing variables
8#[derive(Debug, Clone)]
9pub struct Environment {
10    /// Stack of scopes (innermost scope is last)
11    scopes: Vec<HashMap<String, Value>>,
12    /// Enum type definitions
13    enums: HashMap<String, EnumDef>,
14}
15
16impl Environment {
17    /// Create a new environment with a global scope
18    pub fn new() -> Self {
19        Self {
20            scopes: vec![HashMap::new()],
21            enums: HashMap::new(),
22        }
23    }
24
25    /// Define a variable in the current scope
26    pub fn define(&mut self, name: impl Into<String>, value: Value) {
27        if let Some(scope) = self.scopes.last_mut() {
28            scope.insert(name.into(), value);
29        }
30    }
31
32    /// Get a variable from any scope (innermost first)
33    pub fn get(&self, name: &str) -> Option<&Value> {
34        for scope in self.scopes.iter().rev() {
35            if let Some(value) = scope.get(name) {
36                return Some(value);
37            }
38        }
39        None
40    }
41
42    /// Set an existing variable in the nearest scope where it exists
43    pub fn set(&mut self, name: &str, value: Value) -> bool {
44        for scope in self.scopes.iter_mut().rev() {
45            if scope.contains_key(name) {
46                scope.insert(name.to_string(), value);
47                return true;
48            }
49        }
50        false
51    }
52
53    /// Push a new scope onto the stack
54    pub fn push_scope(&mut self) {
55        self.scopes.push(HashMap::new());
56    }
57
58    /// Pop the current scope from the stack
59    pub fn pop_scope(&mut self) {
60        if self.scopes.len() > 1 {
61            self.scopes.pop();
62        }
63    }
64
65    /// Check if a variable exists in any scope
66    pub fn contains(&self, name: &str) -> bool {
67        self.get(name).is_some()
68    }
69
70    /// Get the current scope depth
71    pub fn depth(&self) -> usize {
72        self.scopes.len()
73    }
74
75    /// Define an enum type
76    pub fn define_enum(&mut self, def: EnumDef) {
77        self.enums.insert(def.name.clone(), def);
78    }
79
80    /// Get an enum definition
81    pub fn get_enum(&self, name: &str) -> Option<&EnumDef> {
82        self.enums.get(name)
83    }
84}
85
86impl Default for Environment {
87    fn default() -> Self {
88        Self::new()
89    }
90}