pulled out modules into separate files
This commit is contained in:
parent
6cc1822ec6
commit
f30b7827b8
842
src/ast2/ir.rs
Normal file
842
src/ast2/ir.rs
Normal file
|
@ -0,0 +1,842 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast2::{
|
||||||
|
intern::{self, AMD64_POINTER_TYPE_INFO},
|
||||||
|
Index,
|
||||||
|
},
|
||||||
|
triples::{self, Inst, IR},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
enum Error {
|
||||||
|
#[error("This visitor does not implement visiting this tag.")]
|
||||||
|
Unimplemented,
|
||||||
|
}
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
intern::InternPoolWrapper as InternPool,
|
||||||
|
visitor::{AstExt, AstVisitorTrait},
|
||||||
|
TypeCache,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IrBuilder {
|
||||||
|
functions: Vec<Function>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Function {
|
||||||
|
ir: IR,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IrFunctionBuilder<'a> {
|
||||||
|
ir: &'a mut IR,
|
||||||
|
type_cache: &'a mut TypeCache,
|
||||||
|
ref_lookup: &'a mut HashMap<Index, u32>,
|
||||||
|
ip: &'a InternPool,
|
||||||
|
function: Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AstVisitorTrait for IrFunctionBuilder<'a> {
|
||||||
|
type Error = Error;
|
||||||
|
type Value = Option<u32>;
|
||||||
|
const UNIMPL: Self::Error = Error::Unimplemented;
|
||||||
|
|
||||||
|
fn visit_block(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: super::Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Block);
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
|
||||||
|
ast.extra[a..b]
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| Index::from_u32(i).unwrap())
|
||||||
|
.map(|i| self.visit_any(ast, i))
|
||||||
|
.try_fold((), |_, e| e.map(crate::unit))?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_place_to_value_conversion(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::PlaceToValueConversion);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
// idx's (this) type is the pointee type
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
|
||||||
|
let ir = self.ir.push(Inst::Load(ty), Some(triples::Data::lhs(expr)));
|
||||||
|
Ok(Some(ir))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_value_to_place_conversion(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::ValueToPlaceConversion);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
// expr's type is the pointee type
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
|
||||||
|
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
|
||||||
|
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
|
||||||
|
|
||||||
|
let alloca = self.ir.push(
|
||||||
|
Inst::Alloca,
|
||||||
|
Some(triples::Data::new(info.size(), info.align())),
|
||||||
|
);
|
||||||
|
|
||||||
|
_ = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Store(ty), Some(triples::Data::new(expr, alloca)));
|
||||||
|
|
||||||
|
Ok(Some(alloca))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_decl_ref(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::DeclRef);
|
||||||
|
let decl = data.as_index();
|
||||||
|
|
||||||
|
let alloca = self.ref_lookup.get(&decl).cloned().expect("declref");
|
||||||
|
|
||||||
|
Ok(Some(alloca))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_var_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_var_decl_common(ast, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_var_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_var_decl_common(ast, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_var_assign_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_var_decl_common(ast, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_var_assign_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_var_decl_common(ast, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_return(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
|
||||||
|
let ir = self.ir.push(Inst::Return, None);
|
||||||
|
Ok(Some(ir))
|
||||||
|
}
|
||||||
|
fn visit_return_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::ReturnExprStmt);
|
||||||
|
let expr = data.as_index();
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
|
||||||
|
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
|
||||||
|
let ir = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::ReturnValue(ty), Some(triples::Data::lhs(expr)));
|
||||||
|
Ok(Some(ir))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_constant(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Constant);
|
||||||
|
let (ty, value) = data.as_index_intern();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
|
||||||
|
let ir = self.ir.push(Inst::Constant, Some((ty, value).into()));
|
||||||
|
|
||||||
|
Ok(Some(ir))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_subscript_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::SubscriptExpr);
|
||||||
|
let (lhs, index) = data.as_two_indices();
|
||||||
|
|
||||||
|
// pointer type
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
|
||||||
|
let lhs = self.visit_any(ast, lhs)?.unwrap();
|
||||||
|
let index = self.visit_any(ast, index)?.unwrap();
|
||||||
|
|
||||||
|
// TODO: make getelementptr take a variable instead of a constant index.
|
||||||
|
let ir = self.ir.push(
|
||||||
|
Inst::GetElementPtr(ty),
|
||||||
|
Some(triples::Data::new(lhs, index)),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Some(ir))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_call_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::CallExpr);
|
||||||
|
let (func, arguments) = data.as_two_indices();
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
|
||||||
|
let len = self.visit_parameter_list(ast, arguments)?.unwrap();
|
||||||
|
_ = self.ir.push(Inst::InlineType(ty), None);
|
||||||
|
let end = self.ir.nodes.len() as u32;
|
||||||
|
|
||||||
|
let func = self.visit_any(ast, func)?.unwrap();
|
||||||
|
|
||||||
|
let result = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Call(func), Some(triples::Data::new(end - len, end)));
|
||||||
|
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_argument(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Argument);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
let arg = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
|
||||||
|
// let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
|
||||||
|
// self.ir.push(Inst::Argument(ty), Some(triples::Data::lhs(arg)));
|
||||||
|
|
||||||
|
Ok(Some(arg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn visit_named_argument(
|
||||||
|
// &mut self,
|
||||||
|
// ast: &mut super::Ast,
|
||||||
|
// idx: Index,
|
||||||
|
// ) -> Result<Self::Value, Self::Error> {
|
||||||
|
// todo!()
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn visit_argument_list(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::ArgumentList);
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
|
||||||
|
let args = ast.extra[a..b]
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| Index::from_u32(i).unwrap())
|
||||||
|
.map(|i| {
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, i);
|
||||||
|
let arg = self.visit_any_argument(ast, i)?.unwrap();
|
||||||
|
Ok((ty, arg))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
let count = args.len();
|
||||||
|
for (ty, arg) in args {
|
||||||
|
_ = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Argument(ty), Some(triples::Data::lhs(arg)));
|
||||||
|
}
|
||||||
|
// .try_fold((), |_, e| e.map(crate::unit))?;
|
||||||
|
|
||||||
|
Ok(Some(count as u32))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_block_trailing_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::BlockTrailingExpr);
|
||||||
|
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
|
||||||
|
let expr = ast.extra[a..b]
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| Index::from_u32(i).unwrap())
|
||||||
|
.map(|i| self.visit_any(ast, i))
|
||||||
|
// the last node is the trailing
|
||||||
|
.try_fold(None, |_, e| e)?;
|
||||||
|
|
||||||
|
Ok(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_function_proto(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: super::Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::FunctionProto);
|
||||||
|
|
||||||
|
let (_, extra) = data.as_intern_and_extra_offset();
|
||||||
|
let (_return_type, parameter_list) = (
|
||||||
|
Index::from_u32(ast.extra[extra]).unwrap(),
|
||||||
|
Index::from_u32(ast.extra[extra + 1]).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.visit_parameter_list(ast, parameter_list)?;
|
||||||
|
// push parameters to ir
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_parameter_list(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::ParameterList);
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
|
||||||
|
ast.extra[a..b]
|
||||||
|
.to_vec()
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| Index::from_u32(i).unwrap())
|
||||||
|
.map(|i| self.visit_parameter(ast, i))
|
||||||
|
.try_fold((), |_, e| e.map(crate::unit))?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_parameter(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Parameter);
|
||||||
|
let (ty, _name) = data.as_index_intern();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
|
||||||
|
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
|
||||||
|
let ir = self.ir.push(
|
||||||
|
Inst::Parameter(ty),
|
||||||
|
Some(triples::Data::new(info.size(), info.align())),
|
||||||
|
);
|
||||||
|
self.ref_lookup.insert(idx, ir);
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_address_of_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::AddressOf);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
let r = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::GetElementPtr(ty), Some(triples::Data::new(expr, 0)));
|
||||||
|
|
||||||
|
Ok(Some(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_assign(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Assign);
|
||||||
|
let (dst, src) = data.as_two_indices();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
let dst = self.visit_any(ast, dst)?.unwrap();
|
||||||
|
let src = self.visit_any(ast, src)?.unwrap();
|
||||||
|
|
||||||
|
let ir = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Store(ty.into()), Some(triples::Data::new(src, dst)));
|
||||||
|
|
||||||
|
Ok(Some(ir))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_explicit_cast_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::ExplicitCast);
|
||||||
|
let (lhs, ty) = data.as_two_indices();
|
||||||
|
|
||||||
|
let lty = ast.get_type_of_node(&self.ip, &mut self.type_cache, lhs);
|
||||||
|
let rty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty);
|
||||||
|
|
||||||
|
let lhs = self.visit_any(ast, lhs)?.unwrap();
|
||||||
|
|
||||||
|
// TODO: if bitwidth is the same, then this is a noop?
|
||||||
|
let cast = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::ExplicitCast(lty, rty), Some(triples::Data::lhs(lhs)));
|
||||||
|
|
||||||
|
Ok(Some(cast))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_if_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::IfExpr);
|
||||||
|
let (cond, body) = data.as_two_indices();
|
||||||
|
|
||||||
|
let cond = self.visit_any(ast, cond)?.unwrap();
|
||||||
|
let br = self.ir.push(Inst::Branch(cond), None);
|
||||||
|
|
||||||
|
let lbody = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
_ = self.visit_any(ast, body);
|
||||||
|
let jmp = self.ir.push(Inst::Jump, None);
|
||||||
|
let skip = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
|
||||||
|
self.ir.data[br as usize] = Some(triples::Data::new(lbody, skip));
|
||||||
|
self.ir.data[jmp as usize] = Some(triples::Data::lhs(skip));
|
||||||
|
|
||||||
|
Ok(Some(br))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_if_else_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::IfElseExpr);
|
||||||
|
let (cond, extra) = data.as_index_and_extra_offset();
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
|
||||||
|
let [a, b] = ast.extra[extra..][..2] else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let cond = self.visit_any(ast, cond)?.unwrap();
|
||||||
|
let br = self.ir.push(Inst::Branch(cond), None);
|
||||||
|
|
||||||
|
let la = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
let a = self.visit_any(ast, Index::from_u32(a).unwrap())?.unwrap();
|
||||||
|
let jmpa = self.ir.push(Inst::Jump, None);
|
||||||
|
|
||||||
|
let lb = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
let b = self.visit_any(ast, Index::from_u32(b).unwrap())?.unwrap();
|
||||||
|
let jmpb = self.ir.push(Inst::Jump, None);
|
||||||
|
|
||||||
|
let lphi = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
|
||||||
|
let phi = if ty == intern::Index::VOID {
|
||||||
|
br
|
||||||
|
} else {
|
||||||
|
self.ir.push(Inst::Phi2(ty), Some(triples::Data::new(a, b)))
|
||||||
|
};
|
||||||
|
|
||||||
|
self.ir.data[br as usize] = Some(triples::Data::new(la, lb));
|
||||||
|
self.ir.data[jmpa as usize] = Some(triples::Data::lhs(lphi));
|
||||||
|
self.ir.data[jmpb as usize] = Some(triples::Data::lhs(lphi));
|
||||||
|
|
||||||
|
Ok(Some(phi))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_deref_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Not);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
let not = self.ir.push(Inst::Load(ty), Some(triples::Data::lhs(expr)));
|
||||||
|
|
||||||
|
Ok(Some(not))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_not_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Not);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
let not = self.ir.push(Inst::Not(ty), Some(triples::Data::lhs(expr)));
|
||||||
|
|
||||||
|
Ok(Some(not))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_negate_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Negate);
|
||||||
|
let expr = data.as_index();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr);
|
||||||
|
let expr = self.visit_any(ast, expr)?.unwrap();
|
||||||
|
let not = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Negate(ty), Some(triples::Data::lhs(expr)));
|
||||||
|
|
||||||
|
Ok(Some(not))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_or_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Or);
|
||||||
|
let (a, b) = data.as_two_indices();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
|
||||||
|
// TODO: make this an error instead of a panic
|
||||||
|
let a = self.visit_any(ast, a)?.unwrap();
|
||||||
|
let not_a = self.ir.push(Inst::Not(ty), Some(triples::Data::lhs(a)));
|
||||||
|
|
||||||
|
// branch taken if a
|
||||||
|
let br = self.ir.push(Inst::Branch(not_a), None);
|
||||||
|
let lb = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
|
||||||
|
let b = self.visit_any(ast, b)?.unwrap();
|
||||||
|
let jmp = self.ir.push(Inst::Jump, None);
|
||||||
|
|
||||||
|
let la = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
|
||||||
|
self.ir.data[br as usize] = Some(triples::Data::new(lb, la));
|
||||||
|
self.ir.data[jmp as usize] = Some(triples::Data::lhs(la));
|
||||||
|
|
||||||
|
let or = self.ir.push(
|
||||||
|
Inst::Phi2(intern::Index::BOOL),
|
||||||
|
Some(triples::Data::new(a, b)),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Some(or))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_and_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::Or);
|
||||||
|
let (a, b) = data.as_two_indices();
|
||||||
|
|
||||||
|
// TODO: make this an error instead of a panic
|
||||||
|
let a = self.visit_any(ast, a)?.unwrap();
|
||||||
|
|
||||||
|
// branch taken if a
|
||||||
|
let br = self.ir.push(Inst::Branch(a), None);
|
||||||
|
|
||||||
|
let lb = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
let b = self.visit_any(ast, b)?.unwrap();
|
||||||
|
|
||||||
|
let skip = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Label, Some(intern::Index::EMPTY_STRING.into()));
|
||||||
|
|
||||||
|
self.ir.data[br as usize] = Some(triples::Data::new(lb, skip));
|
||||||
|
let and = self.ir.push(
|
||||||
|
Inst::Phi2(intern::Index::BOOL),
|
||||||
|
Some(triples::Data::new(a, b)),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Some(and))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_add_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_sub_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_div_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_rem_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_mul_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_bitand_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_bitor_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_bitxor_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_eq_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_neq_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_lt_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_gt_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_le_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_ge_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_shl_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_shr_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
self.visit_binop_expr(ast, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrFunctionBuilder<'_> {
|
||||||
|
fn visit_var_decl_common(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Option<u32>, Error> {
|
||||||
|
let (tag, data) = ast.get_node_tag_and_data(idx);
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
|
||||||
|
let range = &ast.extra[a..b];
|
||||||
|
let _name = range.get(0).unwrap();
|
||||||
|
|
||||||
|
let (expr, typed_index) = match tag {
|
||||||
|
super::Tag::VarDecl | super::Tag::MutVarDecl => {
|
||||||
|
let typed_index = range
|
||||||
|
.get(1)
|
||||||
|
.cloned()
|
||||||
|
.map(Index::from_u32)
|
||||||
|
.flatten()
|
||||||
|
.unwrap();
|
||||||
|
(None, typed_index)
|
||||||
|
}
|
||||||
|
super::Tag::VarDeclAssignment | super::Tag::MutVarDeclAssignment => {
|
||||||
|
let expr = range
|
||||||
|
.get(1)
|
||||||
|
.cloned()
|
||||||
|
.map(Index::from_u32)
|
||||||
|
.flatten()
|
||||||
|
.unwrap();
|
||||||
|
let typed_index = range
|
||||||
|
.get(2)
|
||||||
|
.cloned()
|
||||||
|
.map(Index::from_u32)
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or(expr);
|
||||||
|
(Some(expr), typed_index)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, typed_index);
|
||||||
|
let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO);
|
||||||
|
|
||||||
|
let alloca = self.ir.push(
|
||||||
|
Inst::Alloca,
|
||||||
|
Some(triples::Data::new(info.size(), info.align())),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(idx) = expr {
|
||||||
|
let expr = self.visit_any(ast, idx)?.unwrap();
|
||||||
|
_ = self
|
||||||
|
.ir
|
||||||
|
.push(Inst::Store(ty), Some(triples::Data::new(expr, alloca)));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ref_lookup.insert(idx, alloca);
|
||||||
|
|
||||||
|
Ok(Some(alloca))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// handles all binary operations that don't short circuit and visit
|
||||||
|
/// both lhs and rhs.
|
||||||
|
fn visit_binop_expr(&mut self, ast: &mut super::Ast, idx: Index) -> Result<Option<u32>, Error> {
|
||||||
|
use triples::Data;
|
||||||
|
let (tag, data) = ast.get_node_tag_and_data(idx);
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
|
||||||
|
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx);
|
||||||
|
|
||||||
|
// TODO: make this an error instead of a panic
|
||||||
|
let lhs = self.visit_any(ast, lhs)?.unwrap();
|
||||||
|
let rhs = self.visit_any(ast, rhs)?.unwrap();
|
||||||
|
|
||||||
|
let (inst, data) = match tag {
|
||||||
|
super::Tag::BitOr => (Inst::BitOr(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::BitXOr => (Inst::BitOr(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::BitAnd => (Inst::BitOr(ty), Data::new(lhs, rhs)),
|
||||||
|
|
||||||
|
super::Tag::Eq => (Inst::Eq(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::NEq => (Inst::Neq(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Lt => (Inst::Lt(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Gt => (Inst::Gt(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Le => (Inst::Le(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Ge => (Inst::Ge(ty), Data::new(lhs, rhs)),
|
||||||
|
|
||||||
|
super::Tag::Shl => (Inst::ShiftLeft(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Shr => (Inst::ShiftRight(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Add => (Inst::Add(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Sub => (Inst::Sub(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Div => (Inst::Div(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Rem => (Inst::Rem(ty), Data::new(lhs, rhs)),
|
||||||
|
super::Tag::Mul => (Inst::Mul(ty), Data::new(lhs, rhs)),
|
||||||
|
_ => panic!("not a binop"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(self.ir.push(inst, Some(data))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstVisitorTrait for IrBuilder {
|
||||||
|
type Value = ();
|
||||||
|
type Error = Error;
|
||||||
|
const UNIMPL: Self::Error = Error::Unimplemented;
|
||||||
|
|
||||||
|
fn visit_function_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut super::Ast,
|
||||||
|
idx: super::Index,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
let data = ast.expect_node_data_for_tag(idx, super::Tag::FunctionDecl);
|
||||||
|
let (proto, block) = data.as_two_indices();
|
||||||
|
|
||||||
|
// visit proto
|
||||||
|
|
||||||
|
// visit block
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
3579
src/ast2/mod.rs
3579
src/ast2/mod.rs
File diff suppressed because it is too large
Load diff
1915
src/ast2/parser.rs
Normal file
1915
src/ast2/parser.rs
Normal file
File diff suppressed because it is too large
Load diff
628
src/ast2/visitor.rs
Normal file
628
src/ast2/visitor.rs
Normal file
|
@ -0,0 +1,628 @@
|
||||||
|
use super::*;
|
||||||
|
pub trait AstExt {
|
||||||
|
fn get_node_children(&self, node: Index) -> Vec<Index>;
|
||||||
|
fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstExt for &Ast {
|
||||||
|
fn get_node_children(&self, node: Index) -> Vec<Index> {
|
||||||
|
Ast::get_node_children(self, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data) {
|
||||||
|
(self.tags[node], self.datas[node])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AstExt for &mut Ast {
|
||||||
|
fn get_node_children(&self, node: Index) -> Vec<Index> {
|
||||||
|
Ast::get_node_children(self, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data) {
|
||||||
|
(self.tags[node], self.datas[node])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AstVisitor<AstT> {
|
||||||
|
pub(super) ast: AstT,
|
||||||
|
pub(super) scopes: Vec<Index>,
|
||||||
|
pub(super) nodes: Vec<A>,
|
||||||
|
pub(super) rev: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AstT> AstVisitor<AstT>
|
||||||
|
where
|
||||||
|
AstT: AstExt,
|
||||||
|
{
|
||||||
|
pub fn visit<
|
||||||
|
F: FnMut(&mut AstT, &[Index], Index, Tag, Data),
|
||||||
|
G: FnMut(&mut AstT, &[Index], Index, Tag, Data),
|
||||||
|
>(
|
||||||
|
&mut self,
|
||||||
|
mut pre: F,
|
||||||
|
mut post: G,
|
||||||
|
) {
|
||||||
|
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 _ = pre(&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);
|
||||||
|
|
||||||
|
let _ = post(&mut self.ast, &self.scopes, i, tag, data);
|
||||||
|
|
||||||
|
match tag {
|
||||||
|
Tag::File
|
||||||
|
| Tag::FunctionDecl
|
||||||
|
| Tag::GlobalDecl
|
||||||
|
| Tag::Block
|
||||||
|
| Tag::BlockTrailingExpr => {
|
||||||
|
self.scopes.pop();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 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::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);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum A {
|
||||||
|
PushChildren(Index),
|
||||||
|
PopSelf(Index),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ast {
|
||||||
|
pub fn visitor_mut(&mut self) -> AstVisitor<&mut Self> {
|
||||||
|
AstVisitor {
|
||||||
|
scopes: vec![],
|
||||||
|
nodes: self
|
||||||
|
.get_root_file_indices()
|
||||||
|
.map(|i| 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| 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| visitor::A::PushChildren(i))
|
||||||
|
.collect(),
|
||||||
|
ast: self,
|
||||||
|
rev: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ast {
|
||||||
|
pub fn visit_all_functions_mut<V>(&mut self, visitor: &mut impl AstVisitorTrait) {
|
||||||
|
for i in
|
||||||
|
(0..self.tags.functions.len()).map(|i| Index::new(Kind::Function, i as u32).unwrap())
|
||||||
|
{
|
||||||
|
visitor.visit_function_decl(self, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_function_mut<F: FnMut(&mut Self)>(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AstVisitorTrait {
|
||||||
|
type Error;
|
||||||
|
type Value;
|
||||||
|
const UNIMPL: Self::Error;
|
||||||
|
|
||||||
|
fn visit_function_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_parameter(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_parameter_list(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_block(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_block_trailing_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_block_maybe_trailing(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
use visitor::AstExt;
|
||||||
|
match ast.get_node_tag_and_data(idx).0 {
|
||||||
|
Tag::BlockTrailingExpr => self.visit_block(ast, idx),
|
||||||
|
Tag::Block => self.visit_block_trailing_expr(ast, idx),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn visit_function_proto(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_call_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_add_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_sub_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_mul_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_div_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_rem_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_eq_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_neq_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_lt_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_gt_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_le_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_ge_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_shl_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_shr_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_bitor_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_bitxor_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_bitand_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_or_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_and_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_not_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_negate_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_deref_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_address_of_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_explicit_cast_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_assign(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_subscript_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_if_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_if_else_expr(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_argument(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_any_argument(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
use visitor::AstExt;
|
||||||
|
match ast.get_node_tag_and_data(idx).0 {
|
||||||
|
Tag::Argument => self.visit_argument(ast, idx),
|
||||||
|
Tag::NamedArgument => self.visit_named_argument(ast, idx),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_named_argument(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_argument_list(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_constant(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_return(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_return_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_global_decl(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_var_decl(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_mut_var_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_var_assign_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_mut_var_assign_decl(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_decl_ref(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
fn visit_value_to_place_conversion(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let idx = ast
|
||||||
|
.get_node_data_for_tag(idx, Tag::ValueToPlaceConversion)
|
||||||
|
.unwrap()
|
||||||
|
.as_index();
|
||||||
|
self.visit_any(ast, idx)
|
||||||
|
}
|
||||||
|
fn visit_place_to_value_conversion(
|
||||||
|
&mut self,
|
||||||
|
ast: &mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let idx = ast
|
||||||
|
.get_node_data_for_tag(idx, Tag::PlaceToValueConversion)
|
||||||
|
.unwrap()
|
||||||
|
.as_index();
|
||||||
|
self.visit_any(ast, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_any(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
use visitor::AstExt;
|
||||||
|
match ast.get_node_tag_and_data(idx).0 {
|
||||||
|
Tag::FunctionProto => self.visit_function_proto(ast, idx),
|
||||||
|
Tag::FunctionDecl => self.visit_function_decl(ast, idx),
|
||||||
|
Tag::ParameterList => self.visit_parameter_list(ast, idx),
|
||||||
|
Tag::Parameter => self.visit_parameter(ast, idx),
|
||||||
|
Tag::Block => self.visit_block(ast, idx),
|
||||||
|
Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx),
|
||||||
|
Tag::Constant => self.visit_constant(ast, idx),
|
||||||
|
Tag::ExprStmt => todo!(),
|
||||||
|
Tag::ReturnStmt => self.visit_return(ast, idx),
|
||||||
|
Tag::ReturnExprStmt => self.visit_return_expr(ast, idx),
|
||||||
|
Tag::VarDecl => self.visit_var_decl(ast, idx),
|
||||||
|
Tag::MutVarDecl => self.visit_mut_var_decl(ast, idx),
|
||||||
|
Tag::VarDeclAssignment => self.visit_var_assign_decl(ast, idx),
|
||||||
|
Tag::MutVarDeclAssignment => self.visit_mut_var_assign_decl(ast, idx),
|
||||||
|
Tag::GlobalDecl => self.visit_global_decl(ast, idx),
|
||||||
|
Tag::StructDecl => todo!(),
|
||||||
|
Tag::FieldDecl => todo!(),
|
||||||
|
Tag::DeclRef => self.visit_decl_ref(ast, idx),
|
||||||
|
Tag::DeclRefUnresolved => todo!(),
|
||||||
|
Tag::InternedType => todo!(),
|
||||||
|
Tag::TypeDeclRef => todo!(),
|
||||||
|
Tag::TypeDeclRefUnresolved => todo!(),
|
||||||
|
Tag::PointerType => todo!(),
|
||||||
|
Tag::ArrayType => todo!(),
|
||||||
|
Tag::CallExpr => self.visit_call_expr(ast, idx),
|
||||||
|
Tag::FieldAccess => todo!(),
|
||||||
|
Tag::ArgumentList => self.visit_argument_list(ast, idx),
|
||||||
|
Tag::Argument => self.visit_argument(ast, idx),
|
||||||
|
Tag::NamedArgument => self.visit_named_argument(ast, idx),
|
||||||
|
Tag::ExplicitCast => self.visit_explicit_cast_expr(ast, idx),
|
||||||
|
Tag::Deref => self.visit_deref_expr(ast, idx),
|
||||||
|
Tag::AddressOf => self.visit_add_expr(ast, idx),
|
||||||
|
Tag::Not => self.visit_not_expr(ast, idx),
|
||||||
|
Tag::Negate => self.visit_negate_expr(ast, idx),
|
||||||
|
Tag::Or => self.visit_or_expr(ast, idx),
|
||||||
|
Tag::And => self.visit_and_expr(ast, idx),
|
||||||
|
Tag::BitOr => self.visit_bitor_expr(ast, idx),
|
||||||
|
Tag::BitXOr => self.visit_bitxor_expr(ast, idx),
|
||||||
|
Tag::BitAnd => self.visit_bitand_expr(ast, idx),
|
||||||
|
Tag::Eq => self.visit_eq_expr(ast, idx),
|
||||||
|
Tag::NEq => self.visit_neq_expr(ast, idx),
|
||||||
|
Tag::Lt => self.visit_lt_expr(ast, idx),
|
||||||
|
Tag::Gt => self.visit_gt_expr(ast, idx),
|
||||||
|
Tag::Le => self.visit_le_expr(ast, idx),
|
||||||
|
Tag::Ge => self.visit_ge_expr(ast, idx),
|
||||||
|
Tag::Shl => self.visit_shl_expr(ast, idx),
|
||||||
|
Tag::Shr => self.visit_shr_expr(ast, idx),
|
||||||
|
Tag::Add => self.visit_add_expr(ast, idx),
|
||||||
|
Tag::Sub => self.visit_sub_expr(ast, idx),
|
||||||
|
Tag::Mul => self.visit_mul_expr(ast, idx),
|
||||||
|
Tag::Div => self.visit_div_expr(ast, idx),
|
||||||
|
Tag::Rem => self.visit_rem_expr(ast, idx),
|
||||||
|
Tag::Assign => self.visit_assign(ast, idx),
|
||||||
|
Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx),
|
||||||
|
Tag::IfExpr => self.visit_if_expr(ast, idx),
|
||||||
|
Tag::IfElseExpr => self.visit_if_else_expr(ast, idx),
|
||||||
|
Tag::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx),
|
||||||
|
Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx),
|
||||||
|
Tag::Error => todo!(),
|
||||||
|
Tag::Undefined => todo!(),
|
||||||
|
Tag::Root => todo!(),
|
||||||
|
Tag::File => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ast {
|
||||||
|
pub fn get_node_data_for_tag(&self, idx: Index, tag: Tag) -> Option<Data> {
|
||||||
|
use visitor::AstExt;
|
||||||
|
let (t, data) = self.get_node_tag_and_data(idx);
|
||||||
|
if t == tag {
|
||||||
|
Some(data)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_node_data_for_tag(&self, idx: Index, tag: Tag) -> Data {
|
||||||
|
self.get_node_data_for_tag(idx, tag)
|
||||||
|
.expect(&format!("node {idx} is not a {tag:?}"))
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ fn main() {
|
||||||
println!("AST:\n{buf}");
|
println!("AST:\n{buf}");
|
||||||
}
|
}
|
||||||
"ast2" => {
|
"ast2" => {
|
||||||
let mut tree2 = compiler::ast2::ast_gen::Parser::new();
|
let mut tree2 = compiler::ast2::parser::Parser::new();
|
||||||
tree2.parse(tokens.iter());
|
tree2.parse(tokens.iter());
|
||||||
eprintln!("{tree2:#?}");
|
eprintln!("{tree2:#?}");
|
||||||
println!("AST (new):\n{tree2}");
|
println!("AST (new):\n{tree2}");
|
||||||
|
|
Loading…
Reference in a new issue