use { std::{ collections::HashMap, sync::{Arc, RwLock}, }, crate::expr::LTExpr }; #[derive(Clone, Debug)] pub enum SymbolDef { FrameRef { typ: laddertypes::TypeTerm, stack_ref: tisc::VM_Word, }, StaticRef { typ: laddertypes::TypeTerm, link_addr: Option< tisc::VM_Word > }, Procedure { in_types: Vec< laddertypes::TypeTerm >, out_types: Vec< laddertypes::TypeTerm >, link_addr: Option< tisc::VM_Word > } } 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< String, SymbolDef >, /* 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< Arc> > } 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< laddertypes::TypeTerm >, out_types: Vec< laddertypes::TypeTerm > ) { 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 }); } }