using visitor for rendering ast

This commit is contained in:
Janis 2024-12-26 01:02:40 +01:00
parent 4e59e02178
commit f6fc83ce02

View file

@ -2162,7 +2162,60 @@ pub mod ast_visitor {
where where
AstT: AstExt, AstT: AstExt,
{ {
pub fn visit<F: FnMut(&mut AstT, Index, Tag, Data)>( pub fn visit_pre<F: FnMut(&mut AstT, &[Index], Index, Tag, Data)>(
&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<F: FnMut(&mut AstT, &[Index], Index, Tag, Data)>(
&mut self, &mut self,
mut cb: F, mut cb: F,
) { ) {
@ -2186,6 +2239,7 @@ pub mod ast_visitor {
match tag { match tag {
Tag::File Tag::File
| Tag::FunctionDecl | Tag::FunctionDecl
| Tag::GlobalDecl
| Tag::Block | Tag::Block
| Tag::BlockTrailingExpr => { | Tag::BlockTrailingExpr => {
self.scopes.push(i); self.scopes.push(i);
@ -2196,11 +2250,13 @@ pub mod ast_visitor {
A::PopSelf(i) => { A::PopSelf(i) => {
// already popped. // already popped.
let (tag, data) = self.ast.get_node_tag_and_data(i); 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 { match tag {
Tag::File Tag::File
| Tag::FunctionDecl | Tag::FunctionDecl
| Tag::GlobalDecl
| Tag::Block | Tag::Block
| Tag::BlockTrailingExpr => { | Tag::BlockTrailingExpr => {
self.scopes.pop(); self.scopes.pop();
@ -2272,37 +2328,21 @@ impl<'a> AstRenderer<'a> {
} }
} }
fn render_node<W: core::fmt::Write>( fn render<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result {
&mut self, self.ast.visitor().visit_pre(|ast, scopes, node, tag, _| {
w: &mut W, let loc = ast.source_locs[node.index()];
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 children = Children(ast.get_node_children(node));
let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node); let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node);
let is_comptime = self let is_comptime =
.ast ast.is_node_comptime_evaluable(&mut self.comptime_cache, node);
.is_node_comptime_evaluable(&mut self.comptime_cache, node); _ = writeln_indented!(
writeln_indented!( scopes.len() as u32 * 2,
indent * 2,
w, w,
"{node} {}({ty}) = ({loc}) {tag:?} {children}", "{node} {}({ty}) = ({loc}) {tag:?} {children}",
if is_comptime { "CONST " } else { "" } if is_comptime { "CONST " } else { "" }
)?; );
});
for child in children.0 {
self.render_node(w, indent + 1, child)?;
}
Ok(())
}
fn render<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result {
for file in self.ast.get_root_file_indices() {
self.render_node(w, 0, file)?;
}
Ok(()) Ok(())
} }
@ -2490,7 +2530,7 @@ pub mod ast_gen {
} }
pub fn intern_types(&mut self) { 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 { match tag {
Tag::ArrayType => { Tag::ArrayType => {
let (length, pointee) = data.as_two_indices(); let (length, pointee) = data.as_two_indices();
@ -2619,7 +2659,9 @@ pub mod ast_gen {
} }
pub fn resolve_decl_refs(&mut self) { pub fn resolve_decl_refs(&mut self) {
self.ast.visitor_rev_mut().visit(|ast, node, tag, _data| { self.ast
.visitor_rev_mut()
.visit_post(|ast, _, node, tag, _| {
match tag { match tag {
Tag::TypeDeclRefUnresolved => { Tag::TypeDeclRefUnresolved => {
let (scope, name) = let (scope, name) =