use { crate::expr::LTExpr, std::{ collections::HashMap, sync::{Arc, RwLock}, }, tisc::linker::LinkAddr, }; #[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: LinkAddr, export: bool }, } 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: _, export: _, } => 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 export(self) -> Vec<(String, SymbolDef)> { self.symbols .into_iter() .filter(|(name, def)| match def { SymbolDef::Procedure { in_types:_, out_types:_, link_addr:_, export } => *export, _ => false } ) .collect() } pub fn import(&mut self, symbol_imports: Vec<(String, SymbolDef)>) { for (name, def) in symbol_imports { self.symbols.insert( name, def ); } } 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 } } } } /// takes the link-addresses from a Linker /// and updates the symbol table to relative addresses /// based on the next super-label pub fn update_link_addresses( &mut self, base_symbol: &String, linker: &tisc::Linker ) { for (name, def) in self.symbols.iter_mut() { if let Some(offset) = linker.get_link_addr( name ) { match def { SymbolDef::Procedure { in_types:_,out_types:_, link_addr, export:_ } => { *link_addr = LinkAddr::Relative{ symbol: base_symbol.clone(), offset }; }, _ => {} } } } } //<><><><><><> 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(), false ); } pub fn declare_proc( &mut self, name: String, in_types: Vec, out_types: Vec, export: bool ) { self.symbols.insert( name.clone(), SymbolDef::Procedure { link_addr: LinkAddr::Relative{ symbol: name, offset: 0 }, in_types, out_types, export }, ); } //<><><><><> 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, }, ); } }