diff --git a/crates/saft-ast-to-ir/src/lib.rs b/crates/saft-ast-to-ir/src/lib.rs index 0e08ebc..e692f7c 100644 --- a/crates/saft-ast-to-ir/src/lib.rs +++ b/crates/saft-ast-to-ir/src/lib.rs @@ -51,8 +51,13 @@ impl Error { } } +enum LowererItem { + Ir_(Spanned), + Unlowered, +} + pub struct Lowerer { - items: Vec>, + items: Vec, scopes: Vec>, scope_base: usize, var_counter: usize, @@ -81,22 +86,39 @@ impl Lowerer { &mut self, stmts: &Vec>, ) -> Result<(), Error> { - for stmt in stmts { - let s = &stmt.s; - if let ast::Statement::Item(item) = &stmt.v { - self.resolve_item(&s.spanned(item))?; - } + let items = stmts + .iter() + .filter_map(|stmt| match &stmt.v { + ast::Statement::Item(item) => Some(stmt.s.spanned(item)), + _ => None, + }) + .collect::>(); + + let item_refs = items + .iter() + .map(|item| self.new_item(self.item_name(item))) + .collect::>(); + + for (item, ref_) in items.iter().zip(item_refs) { + let resolved = self.resolve_item(item)?; + self.replace_item(ref_, resolved); } + Ok(()) } - fn resolve_item(&mut self, item: &Spanned<&ast::Item>) -> Result, Error> { + fn item_name(&self, item: &Spanned<&ast::Item>) -> Spanned { + match &item.v { + ast::Item::Function(ast::Function { ident, .. }) => ident.clone(), + } + } + + fn resolve_item(&mut self, item: &Spanned<&ast::Item>) -> Result, Error> { let Spanned { s, v: item } = item; Ok(s.spanned(match item { ast::Item::Function(fun @ ast::Function { ident, .. }) => { - let item = s.spanned(ir::Item::Function(self.lower_item_fn(fun)?)); - self.new_item(ident, item) + ir::Item::Function(self.lower_item_fn(fun)?) } })) } @@ -129,7 +151,14 @@ impl Lowerer { .try_collect::>()?; Ok(ir::Module { - items: self.items, + items: self + .items + .into_iter() + .map(|li| match li { + LowererItem::Ir_(itm) => itm, + LowererItem::Unlowered => panic!("Should be no unlowered items left now"), + }) + .collect::>(), stmts, }) } @@ -384,9 +413,9 @@ impl Lowerer { ) } - fn new_item(&mut self, ident: &Spanned, item: Spanned) -> ir::ItemRef { + fn new_item(&mut self, ident: Spanned) -> ir::ItemRef { let ref_ = ir::ItemRef(self.items.len()); - self.items.push(item); + self.items.push(LowererItem::Unlowered); self.scopes .last_mut() .unwrap() @@ -394,6 +423,10 @@ impl Lowerer { ref_ } + fn replace_item(&mut self, ref_: ir::ItemRef, item: Spanned) { + self.items[ref_.0] = LowererItem::Ir_(item); + } + fn new_varref(&mut self) -> ir::VarRef { let ref_ = ir::VarRef(self.var_counter); self.var_counter += 1;