use std::{collections::{HashMap, hash_map::Entry, VecDeque}};
#[derive(Debug)]
pub struct SymTab {
table: HashMap<Vec<u32>, HashMap<String, Symbol>>,
scope_counter: HashMap<u32, u32>,
scope_level: u32,
pub current_scope: Vec<u32>,
}
impl SymTab {
pub fn init() -> Self {
Self {
table: HashMap::from([(vec![1],HashMap::new())]),
scope_counter: HashMap::new(),
scope_level: 1,
current_scope: vec![1],
}
}
pub fn enter_scope(&mut self) {
self.scope_level += 1;
if self.scope_counter.contains_key(&self.scope_level) {
self.scope_counter.entry(self.scope_level).and_modify(|v| {*v +=1});
} else {
self.scope_counter.insert(self.scope_level, 1);
}
self.current_scope.push(*self.scope_counter.get(&self.scope_level).unwrap());
self.table.insert(self.current_scope.to_vec(), HashMap::new());
}
pub fn leave_scope(&mut self) {
self.scope_level -= 1;
self.current_scope.pop();
}
pub fn put(&mut self, name: String, sym: Symbol) {
self.table.get_mut(&self.current_scope).unwrap().insert(name, sym);
}
pub fn extis(&self, s: &Vec<u32>, name: &String) -> (bool, Vec<u32>) {
let mut ss = s.clone();
while !ss.is_empty() {
if self.table.get(&ss).unwrap().contains_key(name) {
return (true,ss);
}
ss.pop();
}
panic!("symbol is not exist")
}
pub fn entry(&mut self, s: &Vec<u32>, name: &String) -> Entry<String, Symbol> {
self.table.get_mut(s).unwrap().entry(name.to_string())
}
pub fn get(&mut self, s: &Vec<u32>, name: &String) -> &Symbol {
self.table.get(s).unwrap().get(name).unwrap()
}
pub fn get_fn(&mut self, name: &String) -> &Symbol {
self.table.get(&vec![1]).unwrap().get(name).unwrap()
}
}
#[derive(Debug)]
pub struct Symbol {
pub name: String,
pub reg: Option<String>,
pub alloc_virtual_reg: bool,
pub alloc_phy_reg: bool,
pub is_func: bool,
pub array_range: VecDeque<i32>,
}
impl Symbol {
pub fn new(name: String, array_range: VecDeque<i32>) -> Self {
Self{
name,
reg: None,
alloc_virtual_reg: false,
alloc_phy_reg: false,
is_func: false,
array_range,
}
}
pub fn new_fn(name: String) -> Self {
Self{
name,
reg: None,
alloc_virtual_reg: false,
alloc_phy_reg: false,
is_func: true,
array_range: VecDeque::new(),
}
}
}
mod tests {
#[test]
fn test_enter() {
let mut s = crate::symbols::SymTab::init();
s.enter_scope();
println!("{:?}", s.current_scope);
println!("{:?}", s.table);
s.leave_scope();
println!("{:?}", s.current_scope);
println!("{:?}", s.table);
}
#[test]
fn test_enter2() {
let mut s = crate::symbols::SymTab::init();
s.enter_scope();
println!("{:?}", s.current_scope);
println!("{:?}", s.table);
s.put("x".to_string(), crate::symbols::Symbol::new("x".to_string(), std::collections::VecDeque::new()));
s.leave_scope();
println!("{:?}", s.current_scope);
println!("{:?}", s.table);
}
#[test]
fn test_enter3() {
let mut s = crate::symbols::SymTab::init();
s.enter_scope();
println!("{:?}", s.current_scope);
println!("{:?}", s.table);
s.put("x".to_string(), crate::symbols::Symbol::new("x".to_string(), std::collections::VecDeque::new()));
s.enter_scope();
println!("current scope is {:?}", s.current_scope);
let r = s.extis(&s.current_scope, &"x".to_string());
println!("x in {:?}", r);
s.leave_scope();
s.leave_scope();
println!("{:?}", s.current_scope);
println!("{:?}", s.table);
}
#[test]
fn test_fn_1() {
let mut s = crate::symbols::SymTab::init();
s.put("fn1".to_string(), crate::symbols::Symbol::new_fn("fn1".to_string()));
println!("c t {:?}", s.table);
s.enter_scope();
s.get_fn(&"fn1".to_string());
println!("c s {:?}", s.current_scope);
println!("c t {:?}", s.table);
s.leave_scope();
println!("c s {:?}", s.current_scope);
println!("c t {:?}", s.table);
}
}