virtual_rust/interpreter/
environment.rs1use std::collections::HashMap;
8
9use crate::interpreter::error::RuntimeError;
10use crate::interpreter::value::Value;
11
12#[derive(Debug, Clone)]
14struct Variable {
15 value: Value,
16 mutable: bool,
17}
18
19#[derive(Debug, Clone)]
25pub struct Environment {
26 scopes: Vec<HashMap<String, Variable>>,
27}
28
29impl Default for Environment {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35impl Environment {
36 pub fn new() -> Self {
38 Environment {
39 scopes: vec![HashMap::new()],
40 }
41 }
42
43 pub fn push_scope(&mut self) {
45 self.scopes.push(HashMap::new());
46 }
47
48 pub fn pop_scope(&mut self) {
50 self.scopes.pop();
51 }
52
53 pub fn define(&mut self, name: String, value: Value, mutable: bool) {
55 if let Some(scope) = self.scopes.last_mut() {
56 scope.insert(name, Variable { value, mutable });
57 }
58 }
59
60 pub fn get(&self, name: &str) -> Option<&Value> {
62 self.scopes
63 .iter()
64 .rev()
65 .find_map(|scope| scope.get(name).map(|var| &var.value))
66 }
67
68 pub fn set(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
71 for scope in self.scopes.iter_mut().rev() {
72 if let Some(var) = scope.get_mut(name) {
73 if !var.mutable {
74 return Err(RuntimeError::new(format!(
75 "Cannot assign to immutable variable '{name}'"
76 )));
77 }
78 var.value = value;
79 return Ok(());
80 }
81 }
82 Err(RuntimeError::new(format!(
83 "Undefined variable: '{name}'"
84 )))
85 }
86}