From f6fc83ce0265deb0b34a87eb2bb021ada32f60c9 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 26 Dec 2024 01:02:40 +0100 Subject: [PATCH] using visitor for rendering ast --- src/ast2/mod.rs | 164 ++++++++++++++++++++++++++++++------------------ 1 file changed, 103 insertions(+), 61 deletions(-) diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index ecf0532..35b57c4 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -2162,7 +2162,60 @@ pub mod ast_visitor { where AstT: AstExt, { - pub fn visit( + pub fn visit_pre( + &mut self, + mut cb: F, + ) { + while let Some(node) = self.nodes.pop() { + match node { + A::PushChildren(i) => { + self.nodes.push(A::PopSelf(i)); + let children_iter = self + .ast + .get_node_children(i) + .into_iter() + .map(|i| A::PushChildren(i)); + // inverse because we are popping from the end + if !self.rev { + self.nodes.extend(children_iter.rev()) + } else { + self.nodes.extend(children_iter) + }; + + let (tag, data) = self.ast.get_node_tag_and_data(i); + + let _ = cb(&mut self.ast, &self.scopes, i, tag, data); + + match tag { + Tag::File + | Tag::FunctionDecl + | Tag::GlobalDecl + | Tag::Block + | Tag::BlockTrailingExpr => { + self.scopes.push(i); + } + _ => {} + } + } + A::PopSelf(i) => { + // already popped. + let (tag, _data) = self.ast.get_node_tag_and_data(i); + + match tag { + Tag::File + | Tag::FunctionDecl + | Tag::GlobalDecl + | Tag::Block + | Tag::BlockTrailingExpr => { + self.scopes.pop(); + } + _ => {} + } + } + } + } + } + pub fn visit_post( &mut self, mut cb: F, ) { @@ -2186,6 +2239,7 @@ pub mod ast_visitor { match tag { Tag::File | Tag::FunctionDecl + | Tag::GlobalDecl | Tag::Block | Tag::BlockTrailingExpr => { self.scopes.push(i); @@ -2196,11 +2250,13 @@ pub mod ast_visitor { A::PopSelf(i) => { // already popped. let (tag, data) = self.ast.get_node_tag_and_data(i); - let _ = cb(&mut self.ast, i, tag, data); + + let _ = cb(&mut self.ast, &self.scopes, i, tag, data); match tag { Tag::File | Tag::FunctionDecl + | Tag::GlobalDecl | Tag::Block | Tag::BlockTrailingExpr => { self.scopes.pop(); @@ -2272,37 +2328,21 @@ impl<'a> AstRenderer<'a> { } } - fn render_node( - &mut self, - w: &mut W, - indent: u32, - node: Index, - ) -> core::fmt::Result { - let tag = self.ast.tags[node.index()]; - let loc = self.ast.source_locs[node.index()]; - - let children = Children(self.ast.get_node_children(node)); - let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node); - let is_comptime = self - .ast - .is_node_comptime_evaluable(&mut self.comptime_cache, node); - writeln_indented!( - indent * 2, - w, - "{node} {}({ty}) = ({loc}) {tag:?} {children}", - if is_comptime { "CONST " } else { "" } - )?; - - for child in children.0 { - self.render_node(w, indent + 1, child)?; - } - - Ok(()) - } fn render(&mut self, w: &mut W) -> core::fmt::Result { - for file in self.ast.get_root_file_indices() { - self.render_node(w, 0, file)?; - } + self.ast.visitor().visit_pre(|ast, scopes, node, tag, _| { + let loc = ast.source_locs[node.index()]; + + let children = Children(ast.get_node_children(node)); + let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node); + let is_comptime = + ast.is_node_comptime_evaluable(&mut self.comptime_cache, node); + _ = writeln_indented!( + scopes.len() as u32 * 2, + w, + "{node} {}({ty}) = ({loc}) {tag:?} {children}", + if is_comptime { "CONST " } else { "" } + ); + }); Ok(()) } @@ -2490,7 +2530,7 @@ pub mod ast_gen { } pub fn intern_types(&mut self) { - self.ast.visitor_mut().visit(|ast, i, tag, data| { + self.ast.visitor_mut().visit_post(|ast, _, i, tag, data| { match tag { Tag::ArrayType => { let (length, pointee) = data.as_two_indices(); @@ -2619,36 +2659,38 @@ pub mod ast_gen { } pub fn resolve_decl_refs(&mut self) { - self.ast.visitor_rev_mut().visit(|ast, node, tag, _data| { - match tag { - Tag::TypeDeclRefUnresolved => { - let (scope, name) = - ast.datas[node.index()].as_index_intern(); - // look in my_scope - if let Some(decl) = self.syms.find_type_symbol( - scope, - name, - ast.source_locs[node.index()], - ) { - ast.resolve_type_ref(node, decl) - }; - } - Tag::DeclRefUnresolved => { - let (scope, name) = - ast.datas[node.index()].as_index_intern(); + self.ast + .visitor_rev_mut() + .visit_post(|ast, _, node, tag, _| { + match tag { + Tag::TypeDeclRefUnresolved => { + let (scope, name) = + ast.datas[node.index()].as_index_intern(); + // look in my_scope + if let Some(decl) = self.syms.find_type_symbol( + scope, + name, + ast.source_locs[node.index()], + ) { + ast.resolve_type_ref(node, decl) + }; + } + Tag::DeclRefUnresolved => { + let (scope, name) = + ast.datas[node.index()].as_index_intern(); - // look in my_scope - if let Some(decl) = self.syms.find_symbol( - scope, - name, - ast.source_locs[node.index()], - ) { - ast.resolve_decl_ref(node, decl) - }; + // look in my_scope + if let Some(decl) = self.syms.find_symbol( + scope, + name, + ast.source_locs[node.index()], + ) { + ast.resolve_decl_ref(node, decl) + }; + } + _ => {} } - _ => {} - } - }); + }); } fn current_scope(&self) -> Index {