From 4e59e02178d3557f6fe6963145dffd63574f3cf4 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 26 Dec 2024 00:40:11 +0100 Subject: [PATCH] visitor pattern for ast --- src/ast2/intern.rs | 2 +- src/ast2/mod.rs | 246 ++++++++++++++++++++++++++++++--------------- 2 files changed, 166 insertions(+), 82 deletions(-) diff --git a/src/ast2/intern.rs b/src/ast2/intern.rs index 884e445..66edcbd 100644 --- a/src/ast2/intern.rs +++ b/src/ast2/intern.rs @@ -379,7 +379,7 @@ pub struct Index(u32); impl Display for Index { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.index()) + write!(f, "${}", self.index()) } } diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index 0801abf..ecf0532 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -2086,6 +2086,139 @@ pub fn interned_type_and_value_to_comptime_number( } } +use ast_visitor::AstVisitor; + +impl Ast { + pub fn visitor_mut(&mut self) -> AstVisitor<&mut Self> { + AstVisitor { + scopes: vec![], + nodes: self + .get_root_file_indices() + .map(|i| ast_visitor::A::PushChildren(i)) + .collect(), + ast: self, + rev: false, + } + } + pub fn visitor_rev_mut(&mut self) -> AstVisitor<&mut Self> { + AstVisitor { + scopes: vec![], + nodes: self + .get_root_file_indices() + .map(|i| ast_visitor::A::PushChildren(i)) + .collect(), + ast: self, + rev: true, + } + } + + pub fn visitor(&self) -> AstVisitor<&Self> { + AstVisitor { + scopes: vec![], + nodes: self + .get_root_file_indices() + .map(|i| ast_visitor::A::PushChildren(i)) + .collect(), + ast: self, + rev: false, + } + } +} + +pub mod ast_visitor { + use super::*; + pub trait AstExt { + fn get_node_children(&self, node: Index) -> Vec; + fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data); + } + + impl AstExt for &Ast { + fn get_node_children(&self, node: Index) -> Vec { + Ast::get_node_children(self, node) + } + + fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data) { + (self.tags[node.index()], self.datas[node.index()]) + } + } + impl AstExt for &mut Ast { + fn get_node_children(&self, node: Index) -> Vec { + Ast::get_node_children(self, node) + } + + fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data) { + (self.tags[node.index()], self.datas[node.index()]) + } + } + + pub struct AstVisitor { + pub(super) ast: AstT, + pub(super) scopes: Vec, + pub(super) nodes: Vec, + pub(super) rev: bool, + } + + impl AstVisitor + where + AstT: AstExt, + { + pub fn visit( + &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)); + 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); + + match tag { + Tag::File + | Tag::FunctionDecl + | Tag::Block + | Tag::BlockTrailingExpr => { + self.scopes.push(i); + } + _ => {} + } + } + A::PopSelf(i) => { + // already popped. + let (tag, data) = self.ast.get_node_tag_and_data(i); + let _ = cb(&mut self.ast, i, tag, data); + + match tag { + Tag::File + | Tag::FunctionDecl + | Tag::Block + | Tag::BlockTrailingExpr => { + self.scopes.pop(); + } + _ => {} + } + } + } + } + } + } + + pub enum A { + PushChildren(Index), + PopSelf(Index), + } +} + pub struct AstRenderer<'a> { ast: &'a Ast, #[allow(dead_code)] @@ -2357,41 +2490,17 @@ pub mod ast_gen { } pub fn intern_types(&mut self) { - let mut nodes = self - .ast - .get_root_file_indices() - .map(|i| A::PushChildren(i)) - .collect::>(); - - enum A { - PushChildren(Index), - PopSelf(Index), - } - - while let Some(node) = nodes.pop() { - match node { - A::PushChildren(i) => { - nodes.push(A::PopSelf(i)); - nodes.extend( - self.ast - .get_node_children(i) - .into_iter() - .map(|i| A::PushChildren(i)), - ); - } - A::PopSelf(i) => { - let tag = self.ast.tags[i.index()]; - let data = self.ast.datas[i.index()]; + self.ast.visitor_mut().visit(|ast, i, tag, data| { match tag { Tag::ArrayType => { let (length, pointee) = data.as_two_indices(); let pointee = - self.ast.datas[pointee.index()].as_intern(); + ast.datas[pointee.index()].as_intern(); variant!( self.intern.get_key(pointee) => intern::Key::PointerType { pointee, flags }); // get interened value from constant node let length = { - let value = self.ast.datas[length.index()] + let value = ast.datas[length.index()] .as_index_intern() .1; @@ -2424,48 +2533,48 @@ pub mod ast_gen { Some(flags), length, ); - self.ast.tags[i.index()] = Tag::InternedType; - self.ast.datas[i.index()] = Data::intern(ty); + ast.tags[i.index()] = Tag::InternedType; + ast.datas[i.index()] = Data::intern(ty); } Tag::PointerType => { let (pointee, flags) = data.as_index_and_extra_offset(); let pointee = - self.ast.datas[pointee.index()].as_intern(); + ast.datas[pointee.index()].as_intern(); let ty = self.intern.get_pointer_type( pointee, Some(PointerFlags::unpack(flags as u8)), ); - self.ast.tags[i.index()] = Tag::InternedType; - self.ast.datas[i.index()] = Data::intern(ty); + ast.tags[i.index()] = Tag::InternedType; + ast.datas[i.index()] = Data::intern(ty); } Tag::TypeDeclRef => { let decl = data.as_index(); - let (name, _) = self.ast.datas[decl.index()] + let (name, _) = ast.datas[decl.index()] .as_intern_and_extra_offset(); let ty = self.intern.get_struct_type(name, decl); - self.ast.tags[i.index()] = Tag::InternedType; - self.ast.datas[i.index()] = Data::intern(ty); + ast.tags[i.index()] = Tag::InternedType; + ast.datas[i.index()] = Data::intern(ty); } Tag::FunctionProto => { let (_, i) = data.as_intern_and_extra_offset(); - let return_type = self.ast.get_type_of_node( + let return_type = ast.get_type_of_node( &self.intern, &mut TypeCache::new(), - Index::new(self.ast.extra[i]), + Index::new(ast.extra[i]), ); let parameters = { - let (a, b) = self.ast.datas - [self.ast.extra[i + 1] as usize] + let (a, b) = ast.datas + [ast.extra[i + 1] as usize] .as_extra_range(); - self.ast.extra[a..b].iter().map(|&i| { + ast.extra[a..b].iter().map(|&i| { // i is index to a parameter, a parameter is (index, intern) - let ty = self.ast.datas[i as usize] + let ty = ast.datas[i as usize] .as_index_intern() .0; - self.ast.datas[ty.index()].as_intern() + ast.datas[ty.index()].as_intern() }) }; @@ -2476,7 +2585,7 @@ pub mod ast_gen { let (name, offset) = data.as_intern_and_extra_offset(); let flags = - StructFlags::unpack(self.ast.extra[offset]); + StructFlags::unpack(ast.extra[offset]); let types = (offset + 1) ..(offset + 1 + flags.num_fields as usize); @@ -2486,13 +2595,13 @@ pub mod ast_gen { + 1 + flags.num_fields as usize * 2); - let types = self.ast.extra[types] + let types = ast.extra[types] .iter() .map(|&i| Index::new(i)) .map(|i| { - self.ast.datas[i.index()].as_intern() + ast.datas[i.index()].as_intern() }); - let names = self.ast.extra[names] + let names = ast.extra[names] .iter() .map(|&i| intern::Index::from_u32(i)); @@ -2506,65 +2615,40 @@ pub mod ast_gen { } _ => {} } - } - } - } + }); } pub fn resolve_decl_refs(&mut self) { - let mut nodes = - self.ast.get_root_file_indices().collect::>(); - let mut scopes = Vec::new(); - - while let Some(node) = nodes.pop() { - match self.ast.tags[node.index()] { - Tag::File - | Tag::FunctionDecl - | Tag::Block - | Tag::BlockTrailingExpr => { - scopes.push(node); - } - _ => {} - } - - let children = self.ast.get_node_children(node); - nodes.extend(children.into_iter().rev()); - - match self.ast.tags[node.index()] { - Tag::File - | Tag::FunctionDecl - | Tag::Block - | Tag::BlockTrailingExpr => { - scopes.pop(); - } + self.ast.visitor_rev_mut().visit(|ast, node, tag, _data| { + match tag { Tag::TypeDeclRefUnresolved => { let (scope, name) = - self.ast.datas[node.index()].as_index_intern(); + ast.datas[node.index()].as_index_intern(); // look in my_scope if let Some(decl) = self.syms.find_type_symbol( scope, name, - self.ast.source_locs[node.index()], + ast.source_locs[node.index()], ) { - self.ast.resolve_type_ref(node, decl) + ast.resolve_type_ref(node, decl) }; } Tag::DeclRefUnresolved => { let (scope, name) = - self.ast.datas[node.index()].as_index_intern(); + ast.datas[node.index()].as_index_intern(); // look in my_scope if let Some(decl) = self.syms.find_symbol( scope, name, - self.ast.source_locs[node.index()], + ast.source_locs[node.index()], ) { - self.ast.resolve_decl_ref(node, decl) + ast.resolve_decl_ref(node, decl) }; } _ => {} } - } + }); } fn current_scope(&self) -> Index {