use std::{
any::Any, borrow::Borrow, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc,
};
use crate::data::Data;
use super::{function::Function, Scope, ScopeRef};
#[derive(Debug, Clone, Copy)]
pub enum IfState {
Started,
Captured,
Finished,
}
pub struct BlockScope {
local_functions: HashMap<String, Function>,
parent: Option<ScopeRef>,
did_break: bool,
pub return_value: Data,
pub if_state: IfState,
}
impl BlockScope {
pub fn new(parent: Option<ScopeRef>) -> Self {
Self {
local_functions: HashMap::new(),
parent,
return_value: Data::None,
did_break: false,
if_state: IfState::Finished,
}
}
pub fn break_self(&mut self) {
self.did_break = true;
}
pub fn did_break(&self) -> bool {
self.did_break
}
}
impl Debug for BlockScope {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BlockScope")
.field("local_functions", &self.local_functions)
.field("parent", &self.parent)
.field("did_break", &self.did_break)
.field("return_value", &self.return_value)
.field("if_state", &self.if_state)
.finish()
}
}
impl Scope for BlockScope {
fn has_function(&self, name: &str) -> bool {
if self.local_functions.contains_key(name) {
true
} else if let Some(parent) = &self.parent {
let borrow: &RefCell<dyn Scope> = parent.borrow();
borrow.borrow().has_function(name)
} else {
false
}
}
fn get_function(&self, name: &str) -> Option<Function> {
let function = self.local_functions.get(name);
if function.is_some() {
function.map(|x| x.clone())
} else if let Some(parent) = &self.parent {
let borrow: &RefCell<dyn Scope> = parent.borrow();
borrow.borrow().get_function(name).map(|x| x.clone())
} else {
None
}
}
fn set_function(&mut self, name: &str, function: Function) {
if self.local_functions.contains_key(name) {
*self.local_functions.get_mut(name).unwrap() = function;
} else {
self.local_functions.insert(String::from(name), function);
}
}
fn delete_function(&mut self, name: &str) {
self.local_functions.remove(name);
}
fn parent(&self) -> Option<ScopeRef> {
self.parent.as_ref().map(|x| Rc::clone(x))
}
fn set_return_value(&mut self, value: Data) {
self.return_value = value;
}
fn get_function_list(&self) -> HashMap<String, Function> {
self.local_functions.clone()
}
fn get_if_state(&self) -> Option<IfState> {
Some(self.if_state)
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_mut(&mut self) -> &mut dyn Any {
self
}
fn set_if_state(&mut self, state: IfState) {
self.if_state = state;
}
}