use crate::prelude::*;
pub enum ScopeTypes {
Function,
Block,
}
pub struct Environment {
scopes: Vec<FxHashMap<String, ASTValue>>,
scopes_types: Vec<ScopeTypes>,
scoped_returns: Vec<ASTValue>,
}
impl Default for Environment {
fn default() -> Self {
Self::new()
}
}
impl Environment {
pub fn new() -> Self {
Environment {
scopes: vec![FxHashMap::default()],
scopes_types: vec![],
scoped_returns: vec![],
}
}
pub fn define(&mut self, name: String, value: ASTValue) {
if let Some(scope) = self.scopes.last_mut() {
scope.insert(name, value);
}
}
pub fn assign(&mut self, name: &str, value: ASTValue) -> bool {
for scope in self.scopes.iter_mut().rev() {
if scope.contains_key(name) {
scope.insert(name.to_string(), value);
return true;
}
}
false
}
pub fn get(&self, name: &str) -> Option<ASTValue> {
for scope in self.scopes.iter().rev() {
if let Some(value) = scope.get(name) {
return Some(value.clone());
}
}
None
}
pub fn begin_scope(&mut self, returns: ASTValue, func: bool) {
self.scopes.push(FxHashMap::default());
if func {
self.scopes_types.push(ScopeTypes::Function);
} else {
self.scopes_types.push(ScopeTypes::Block);
}
self.scoped_returns.push(returns);
}
pub fn end_scope(&mut self) {
self.scopes.pop();
self.scopes_types.pop();
self.scoped_returns.pop();
}
pub fn get_return(&self) -> Option<ASTValue> {
for (i, scope) in self.scopes_types.iter().enumerate().rev() {
if let ScopeTypes::Function = scope {
return self.scoped_returns.get(i).cloned();
}
}
None
}
pub fn is_global_scope(&self) -> bool {
self.scopes.len() == 1
}
}