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>(
&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<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result { fn render<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result {
for file in self.ast.get_root_file_indices() { self.ast.visitor().visit_pre(|ast, scopes, node, tag, _| {
self.render_node(w, 0, file)?; 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(()) 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,36 +2659,38 @@ 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
match tag { .visitor_rev_mut()
Tag::TypeDeclRefUnresolved => { .visit_post(|ast, _, node, tag, _| {
let (scope, name) = match tag {
ast.datas[node.index()].as_index_intern(); Tag::TypeDeclRefUnresolved => {
// look in my_scope let (scope, name) =
if let Some(decl) = self.syms.find_type_symbol( ast.datas[node.index()].as_index_intern();
scope, // look in my_scope
name, if let Some(decl) = self.syms.find_type_symbol(
ast.source_locs[node.index()], scope,
) { name,
ast.resolve_type_ref(node, decl) ast.source_locs[node.index()],
}; ) {
} ast.resolve_type_ref(node, decl)
Tag::DeclRefUnresolved => { };
let (scope, name) = }
ast.datas[node.index()].as_index_intern(); Tag::DeclRefUnresolved => {
let (scope, name) =
ast.datas[node.index()].as_index_intern();
// look in my_scope // look in my_scope
if let Some(decl) = self.syms.find_symbol( if let Some(decl) = self.syms.find_symbol(
scope, scope,
name, name,
ast.source_locs[node.index()], ast.source_locs[node.index()],
) { ) {
ast.resolve_decl_ref(node, decl) ast.resolve_decl_ref(node, decl)
}; };
}
_ => {}
} }
_ => {} });
}
});
} }
fn current_scope(&self) -> Index { fn current_scope(&self) -> Index {