lt-core/src/symbols.rs

270 lines
7.1 KiB
Rust
Raw Normal View History

2024-05-05 18:19:28 +02:00
use {
2024-05-12 18:58:39 +02:00
crate::expr::LTExpr,
std::{
collections::HashMap,
sync::{Arc, RwLock},
},
tisc::linker::LinkAddr,
2024-05-05 18:19:28 +02:00
};
#[derive(Clone, Debug)]
pub enum SymbolDef {
FrameRef {
typ: laddertypes::TypeTerm,
stack_ref: tisc::VM_Word,
},
StaticRef {
typ: laddertypes::TypeTerm,
2024-05-12 18:58:39 +02:00
link_addr: Option<tisc::VM_Word>,
},
Procedure {
2024-05-12 18:58:39 +02:00
in_types: Vec<laddertypes::TypeTerm>,
out_types: Vec<laddertypes::TypeTerm>,
link_addr: LinkAddr,
export: bool
2024-05-12 18:58:39 +02:00
},
}
2024-05-05 18:19:28 +02:00
impl SymbolDef {
2024-05-12 18:58:39 +02:00
pub fn get_type(
&self,
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
) -> laddertypes::TypeTerm {
match self {
2024-05-12 18:58:39 +02:00
SymbolDef::FrameRef { typ, stack_ref: _ } => typ.clone(),
SymbolDef::StaticRef { typ, link_addr: _ } => typ.clone(),
SymbolDef::Procedure {
in_types,
out_types,
link_addr: _,
export: _,
2024-05-12 18:58:39 +02:00
} => laddertypes::TypeTerm::App(vec![
typectx
.write()
.unwrap()
.parse("Fn")
.expect("parse typeterm"),
laddertypes::TypeTerm::App(in_types.clone()),
laddertypes::TypeTerm::App(out_types.clone()),
]),
}
}
2024-05-05 18:19:28 +02:00
}
/* Describes a lexical scope of symbols
*/
pub struct Scope {
/* definition of runtime symbols
*/
2024-05-12 18:58:39 +02:00
symbols: HashMap<String, SymbolDef>,
/* type symbols
*/
pub typectx: Arc<RwLock<laddertypes::TypeDict>>,
/* number of words required for
* the stack frame of this scope
*/
frame_size: usize,
/* parent scope whose all
* symbols are inherited
2024-05-12 18:58:39 +02:00
*/
parent: Option<Arc<RwLock<Scope>>>,
2024-05-05 18:19:28 +02:00
}
impl Scope {
pub fn new() -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(Scope {
2024-05-05 18:19:28 +02:00
symbols: HashMap::new(),
2024-05-12 18:58:39 +02:00
typectx: Arc::new(RwLock::new(laddertypes::dict::TypeDict::new())),
frame_size: 0,
2024-05-12 18:58:39 +02:00
parent: None,
}))
}
pub fn with_parent(parent: &Arc<RwLock<Scope>>) -> Arc<RwLock<Self>> {
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))
2024-05-05 18:19:28 +02:00
}
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
2024-05-05 18:19:28 +02:00
}
pub fn get(&self, name: &str) -> Option<SymbolDef> {
2024-05-12 18:58:39 +02:00
match self.symbols.get(name) {
Some(def) => Some(def.clone()),
None => {
if let Some(parent) = self.parent.as_ref() {
2024-05-12 18:58:39 +02:00
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,
}),
2024-05-12 18:58:39 +02:00
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
};
},
_ => {}
2024-05-12 18:58:39 +02:00
}
}
}
}
//<><><><><><>
2024-05-05 18:19:28 +02:00
2024-05-12 18:58:39 +02:00
pub fn declare_proc_parse(
&mut self,
name: &str,
type_vars: Vec<&str>,
2024-05-05 18:19:28 +02:00
in_types: Vec<&str>,
2024-05-12 18:58:39 +02:00
out_types: Vec<&str>,
2024-05-05 18:19:28 +02:00
) {
for v in type_vars {
self.typectx.write().unwrap().add_varname(v.into());
}
self.declare_proc(
String::from(name),
2024-05-12 18:58:39 +02:00
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
);
}
2024-05-12 18:58:39 +02:00
pub fn declare_proc(
&mut self,
name: String,
2024-05-12 18:58:39 +02:00
in_types: Vec<laddertypes::TypeTerm>,
out_types: Vec<laddertypes::TypeTerm>,
export: bool
) {
2024-05-12 18:58:39 +02:00
self.symbols.insert(
name.clone(),
2024-05-12 18:58:39 +02:00
SymbolDef::Procedure {
link_addr: LinkAddr::Relative{ symbol: name, offset: 0 },
2024-05-12 18:58:39 +02:00
in_types,
out_types,
export
2024-05-12 18:58:39 +02:00
},
);
}
//<><><><><>
2024-05-12 18:58:39 +02:00
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);
2024-05-05 18:19:28 +02:00
}
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;
2024-05-12 18:58:39 +02:00
self.symbols
.insert(name, SymbolDef::FrameRef { typ, stack_ref });
stack_ref
}
//<><><><><><>
2024-05-12 18:58:39 +02:00
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);
}
2024-05-12 18:58:39 +02:00
pub fn declare_static(&mut self, name: String, typ: laddertypes::TypeTerm) {
self.symbols.insert(
name,
SymbolDef::StaticRef {
typ,
link_addr: None,
},
);
}
2024-05-05 18:19:28 +02:00
}