use preserves::value::{Map, IOValue}; use crate::syntax::block::Item; use super::types; pub struct ModuleContext { pub literals: Map, pub typedefs: Vec, pub functiondefs: Vec, } pub struct FunctionContext<'a> { pub m: &'a mut ModuleContext, pub temp_counter: usize, pub temps: Map>, pub captures: Vec, } pub struct Capture { pub field_name: String, pub source_expr: String, } impl ModuleContext { pub fn new() -> Self { ModuleContext { literals: Map::new(), typedefs: Vec::new(), functiondefs: Vec::new(), } } pub fn define_literal(&mut self, v: &IOValue) -> String { let next_id = format!("LIT{}", self.literals.len()); "&*".to_owned() + self.literals.entry(v.clone()).or_insert(next_id) } pub fn define_type(&mut self, i: Item) { self.typedefs.push(i) } pub fn define_function Item>(&mut self, f: F) { let i = f(FunctionContext::new(self)); self.functiondefs.push(i) } } impl<'a> FunctionContext<'a> { pub fn new(m: &'a mut ModuleContext) -> Self { FunctionContext { m: m, temp_counter: 0, temps: Map::new(), captures: Vec::new(), } } pub fn capture(&mut self, field_name: &str, source_expr: &str) { self.captures.push(Capture { field_name: field_name.to_owned(), source_expr: source_expr.to_owned(), }) } pub fn gentempname(&mut self) -> String { let i = self.temp_counter; self.temp_counter += 1; format!("_tmp{}", i) } }