use { crate::expr::LTExpr, std::{ collections::HashMap, sync::{Arc, RwLock}, }, }; #[derive(Clone, Debug)] pub enum SymbolDef { FrameRef { typ: laddertypes::TypeTerm, stack_ref: tisc::VM_Word, }, StaticRef { typ: laddertypes::TypeTerm, link_addr: Option, }, Procedure { in_types: Vec, out_types: Vec, link_addr: Option, }, } impl SymbolDef { pub fn get_type( &self, typectx: &Arc>, ) -> laddertypes::TypeTerm { match self { SymbolDef::FrameRef { typ, stack_ref: _ } => typ.clone(), SymbolDef::StaticRef { typ, link_addr: _ } => typ.clone(), SymbolDef::Procedure { in_types, out_types, link_addr: _, } => laddertypes::TypeTerm::App(vec![ typectx .write() .unwrap() .parse("Fn") .expect("parse typeterm"), laddertypes::TypeTerm::App(in_types.clone()), laddertypes::TypeTerm::App(out_types.clone()), ]), } } } /* Describes a lexical scope of symbols */ pub struct Scope { /* definition of runtime symbols */ symbols: HashMap, /* type symbols */ pub typectx: Arc>, /* number of words required for * the stack frame of this scope */ frame_size: usize, /* parent scope whose all * symbols are inherited */ parent: Option>>, } impl Scope { pub fn new() -> Arc> { Arc::new(RwLock::new(Scope { symbols: HashMap::new(), typectx: Arc::new(RwLock::new(laddertypes::dict::TypeDict::new())), frame_size: 0, parent: None, })) } pub fn with_parent(parent: &Arc>) -> Arc> { let s = Scope { symbols: HashMap::new(), // todo: create proper child scope typectx: parent.read().unwrap().typectx.clone(), frame_size: 0, parent: Some(parent.clone()), }; Arc::new(RwLock::new(s)) } pub fn get_frame_size(&self) -> usize { self.frame_size } pub fn get(&self, name: &str) -> Option { match self.symbols.get(name) { Some(def) => Some(def.clone()), None => { if let Some(parent) = self.parent.as_ref() { match parent.read().unwrap().get(name) { Some(SymbolDef::FrameRef { typ, stack_ref }) => Some(SymbolDef::FrameRef { typ: typ.clone(), stack_ref: stack_ref + self.get_frame_size() as i64, }), x => x.clone(), } } else { None } } } } /* pub fn get_link_addr(&self, name: &str) -> Option { match self.get(name) { Some(SymbolDef::Procedure{ in_types:_, out_types:_, link_addr }) => { link_addr } Some(SymbolDef::StaticRef { typ:_, link_addr }) => { link_addr } Some(SymbolDef::FrameRef { typ:_, stack_ref:_ }) => None, None => None } } */ //<><><><><><> pub fn declare_proc_parse( &mut self, name: &str, type_vars: Vec<&str>, in_types: Vec<&str>, out_types: Vec<&str>, ) { for v in type_vars { self.typectx.write().unwrap().add_varname(v.into()); } self.declare_proc( String::from(name), in_types .into_iter() .map(|t| { self.typectx .write() .unwrap() .parse(t) .expect("parse typeterm") }) .collect(), out_types .into_iter() .map(|t| { self.typectx .write() .unwrap() .parse(t) .expect("parse typeterm") }) .collect(), ); } pub fn declare_proc( &mut self, name: String, in_types: Vec, out_types: Vec, ) { self.symbols.insert( name, SymbolDef::Procedure { link_addr: None, //LinkAddr::Relative{ name, offset: 0 }, in_types, out_types, }, ); } //<><><><><> pub fn declare_var_parse(&mut self, name: &str, typ: &str) { let typ = self .typectx .write() .unwrap() .parse(typ) .expect("parse typeterm"); self.declare_var(String::from(name), typ); } pub fn declare_var(&mut self, name: String, typ: laddertypes::TypeTerm) -> tisc::VM_Word { let stack_ref = self.frame_size as tisc::VM_Word; self.frame_size += 1; self.symbols .insert(name, SymbolDef::FrameRef { typ, stack_ref }); stack_ref } //<><><><><><> pub fn declare_static_parse(&mut self, name: &str, typ: &str) { let typ = self .typectx .write() .unwrap() .parse(typ) .expect("parse typeterm"); self.declare_static(String::from(name), typ); } pub fn declare_static(&mut self, name: String, typ: laddertypes::TypeTerm) { self.symbols.insert( name, SymbolDef::StaticRef { typ, link_addr: None, }, ); } }