use indexmap::IndexMap;
use std::cell::RefCell;
use leo_ast::Expression;
use leo_errors::Result;
use leo_span::Symbol;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ConstantPropagationTable {
pub(crate) parent: Option<Box<ConstantPropagationTable>>,
pub(crate) constants: IndexMap<Symbol, Expression>,
pub(crate) scope_index: usize,
pub(crate) scopes: Vec<RefCell<ConstantPropagationTable>>,
}
impl ConstantPropagationTable {
pub fn scope_index(&mut self) -> usize {
let index = self.scope_index;
self.scope_index += 1;
index
}
pub fn insert_constant(&mut self, symbol: Symbol, expr: Expression) -> Result<()> {
self.constants.insert(symbol, expr);
Ok(())
}
pub fn insert_block(&mut self) -> usize {
self.scopes.push(RefCell::new(Default::default()));
self.scope_index()
}
pub fn insert_fn_scope(&mut self) -> Result<()> {
self.scope_index();
self.scopes.push(Default::default());
Ok(())
}
pub fn lookup_constant(&self, symbol: Symbol) -> Option<&Expression> {
if let Some(constant) = self.constants.get(&symbol) {
Some(constant)
} else if let Some(parent) = self.parent.as_ref() {
parent.lookup_constant(symbol)
} else {
None
}
}
pub fn constant_in_local_scope(&self, symbol: Symbol) -> bool {
self.constants.contains_key(&symbol)
}
pub fn constant_in_parent_scope(&self, symbol: Symbol) -> bool {
if let Some(parent) = self.parent.as_ref() {
if parent.constants.contains_key(&symbol) { true } else { parent.constant_in_parent_scope(symbol) }
} else {
false
}
}
pub fn lookup_scope_by_index(&self, index: usize) -> Option<&RefCell<Self>> {
self.scopes.get(index)
}
}