new trait for ast for getting nice nodes
This commit is contained in:
parent
486a634ea1
commit
1bde8f3ccd
|
@ -12,6 +12,7 @@ log = "0.4.22"
|
||||||
num-bigint = "0.4.6"
|
num-bigint = "0.4.6"
|
||||||
num-traits = "0.2.19"
|
num-traits = "0.2.19"
|
||||||
ordered-float = "4.2.2"
|
ordered-float = "4.2.2"
|
||||||
|
paste = "1.0.15"
|
||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
thiserror = "1.0.63"
|
thiserror = "1.0.63"
|
||||||
unicode-xid = "0.2.4"
|
unicode-xid = "0.2.4"
|
||||||
|
|
|
@ -1382,6 +1382,13 @@ impl InternPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_get_return_type(&self, func: Index) -> Option<Index> {
|
||||||
|
match self.get_key(func) {
|
||||||
|
Key::FunctionType { return_type, .. } => Some(return_type),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_pointer_type(&mut self, pointee: Index, flags: Option<PointerFlags>) -> Index {
|
pub fn get_pointer_type(&mut self, pointee: Index, flags: Option<PointerFlags>) -> Index {
|
||||||
let key = Key::PointerType {
|
let key = Key::PointerType {
|
||||||
pointee,
|
pointee,
|
||||||
|
|
|
@ -835,7 +835,7 @@ impl<'a> AstVisitorTrait<&'a mut super::Ast> for IrBuilder {
|
||||||
idx: super::Index,
|
idx: super::Index,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
let data = ast.expect_node_data_for_tag(idx, Tag::FunctionDecl);
|
let data = ast.expect_node_data_for_tag(idx, Tag::FunctionDecl);
|
||||||
let (proto, block) = data.as_two_indices();
|
let (_proto, _block) = data.as_two_indices();
|
||||||
|
|
||||||
// visit proto
|
// visit proto
|
||||||
|
|
||||||
|
@ -890,19 +890,23 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
|
||||||
|
|
||||||
fn visit_parameter(
|
fn visit_parameter(
|
||||||
&mut self,
|
&mut self,
|
||||||
ast: &'a mut Ast,
|
_ast: &'a mut Ast,
|
||||||
idx: Index,
|
idx: Index,
|
||||||
) -> Result<Self::Value, Self::Error> {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
Ok(PlaceOrValue::Value(idx))
|
Ok(PlaceOrValue::Value(idx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_var_decl(&mut self, ast: &'a mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
fn visit_var_decl(
|
||||||
|
&mut self,
|
||||||
|
_ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
Ok(PlaceOrValue::Place(idx))
|
Ok(PlaceOrValue::Place(idx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_global_decl(
|
fn visit_global_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
ast: &'a mut Ast,
|
_ast: &'a mut Ast,
|
||||||
idx: Index,
|
idx: Index,
|
||||||
) -> Result<Self::Value, Self::Error> {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
Ok(PlaceOrValue::Place(idx))
|
Ok(PlaceOrValue::Place(idx))
|
||||||
|
@ -910,7 +914,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
|
||||||
|
|
||||||
fn visit_address_of_expr(
|
fn visit_address_of_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
ast: &'a mut Ast,
|
_ast: &'a mut Ast,
|
||||||
idx: Index,
|
idx: Index,
|
||||||
) -> Result<Self::Value, Self::Error> {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
Ok(PlaceOrValue::Value(idx))
|
Ok(PlaceOrValue::Value(idx))
|
||||||
|
@ -933,7 +937,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
|
||||||
let data = ast.expect_node_data_for_tag(idx, Tag::FunctionDecl);
|
let data = ast.expect_node_data_for_tag(idx, Tag::FunctionDecl);
|
||||||
let (_, body) = data.as_two_indices();
|
let (_, body) = data.as_two_indices();
|
||||||
|
|
||||||
let body = self.visit_block_maybe_trailing_as_value(ast, body)?;
|
let _body = self.visit_block_maybe_trailing_as_value(ast, body)?;
|
||||||
|
|
||||||
Ok(PlaceOrValue::Value(idx))
|
Ok(PlaceOrValue::Value(idx))
|
||||||
}
|
}
|
||||||
|
@ -1015,6 +1019,9 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
|
||||||
let bodies = unsafe { Index::from_slice_unchecked(&ast.extra[extra..][..2]) };
|
let bodies = unsafe { Index::from_slice_unchecked(&ast.extra[extra..][..2]) };
|
||||||
let &[a, b] = bodies else { unreachable!() };
|
let &[a, b] = bodies else { unreachable!() };
|
||||||
|
|
||||||
|
let cond = self.visit_any(ast, cond)?;
|
||||||
|
let cond = ast.convert_to_value_expr(cond);
|
||||||
|
|
||||||
let a = self.visit_any(ast, a)?;
|
let a = self.visit_any(ast, a)?;
|
||||||
let b = self.visit_any(ast, b)?;
|
let b = self.visit_any(ast, b)?;
|
||||||
|
|
||||||
|
@ -1025,6 +1032,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
|
||||||
}
|
}
|
||||||
.map(|a| a.as_u32());
|
.map(|a| a.as_u32());
|
||||||
|
|
||||||
|
ast.datas[idx] = Data::index_and_extra_offset(cond, extra as u32);
|
||||||
ast.extra[extra..][..2].copy_from_slice(&bodies);
|
ast.extra[extra..][..2].copy_from_slice(&bodies);
|
||||||
|
|
||||||
Ok(a.with_index(idx))
|
Ok(a.with_index(idx))
|
||||||
|
|
|
@ -17,6 +17,7 @@ pub mod debug;
|
||||||
pub mod intern;
|
pub mod intern;
|
||||||
pub mod ir;
|
pub mod ir;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
pub mod tag;
|
||||||
pub mod visitor;
|
pub mod visitor;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -63,7 +64,7 @@ pub enum Tag {
|
||||||
StructDeclInterned,
|
StructDeclInterned,
|
||||||
/// `data` is an index to a type, and an intern to a name
|
/// `data` is an index to a type, and an intern to a name
|
||||||
FieldDecl,
|
FieldDecl,
|
||||||
/// `data` is an index to a VarDecl, GlobalDecl or FunctionDecl, and an opaque DeclKind
|
/// `data` is an index to a Parameter, VarDecl, GlobalDecl or FunctionDecl, and an opaque DeclKind
|
||||||
DeclRef,
|
DeclRef,
|
||||||
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
||||||
DeclRefUnresolved,
|
DeclRefUnresolved,
|
||||||
|
@ -180,7 +181,7 @@ impl Tag {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
|
||||||
enum ParseError {
|
pub enum ParseError {
|
||||||
#[error("Unexpected end of token iter.")]
|
#[error("Unexpected end of token iter.")]
|
||||||
UnexpectedEndOfTokens,
|
UnexpectedEndOfTokens,
|
||||||
#[error("Expected Token {0}.")]
|
#[error("Expected Token {0}.")]
|
||||||
|
|
631
src/ast2/tag.rs
Normal file
631
src/ast2/tag.rs
Normal file
|
@ -0,0 +1,631 @@
|
||||||
|
use super::{
|
||||||
|
intern::{Index as Interned, PointerFlags, StructFlags},
|
||||||
|
visitor::AstExt,
|
||||||
|
Ast, Index, ParseError, Tag,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait AstNodeExt {
|
||||||
|
fn get_ast_node(&self, idx: Index) -> AstNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstNodeExt for &mut Ast {
|
||||||
|
fn get_ast_node(&self, idx: Index) -> AstNode {
|
||||||
|
<Ast as AstNodeExt>::get_ast_node(self, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstNodeExt for &Ast {
|
||||||
|
fn get_ast_node(&self, idx: Index) -> AstNode {
|
||||||
|
<Ast as AstNodeExt>::get_ast_node(self, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstNodeExt for Ast {
|
||||||
|
fn get_ast_node(&self, idx: Index) -> AstNode {
|
||||||
|
let (tag, data) = self.get_node_tag_and_data(idx);
|
||||||
|
|
||||||
|
match tag {
|
||||||
|
Tag::Root => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
Tag::File => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let decls = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
||||||
|
|
||||||
|
AstNode::File { decls }
|
||||||
|
}
|
||||||
|
Tag::FunctionProto => {
|
||||||
|
let (name, extra) = data.as_intern_and_extra_offset();
|
||||||
|
|
||||||
|
let (return_type, parameter_list) = (
|
||||||
|
Index::from_u32(self.extra[extra]).unwrap(),
|
||||||
|
Index::from_u32(self.extra[extra + 1]).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
AstNode::FunctionProto {
|
||||||
|
name,
|
||||||
|
return_type,
|
||||||
|
parameter_list,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::FunctionProtoInterned => {
|
||||||
|
let (name, ty) = data.as_two_interns();
|
||||||
|
AstNode::FunctionProtoInterned { name, ty }
|
||||||
|
}
|
||||||
|
Tag::FunctionDecl => {
|
||||||
|
let (proto, body) = data.as_two_indices();
|
||||||
|
|
||||||
|
AstNode::FunctionDecl { proto, body }
|
||||||
|
}
|
||||||
|
Tag::ParameterList => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let params = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
||||||
|
|
||||||
|
AstNode::ParameterList { params }
|
||||||
|
}
|
||||||
|
Tag::Parameter => {
|
||||||
|
let (ty, name) = data.as_index_intern();
|
||||||
|
|
||||||
|
AstNode::Parameter { ty, name }
|
||||||
|
}
|
||||||
|
Tag::Block => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let statements = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
||||||
|
|
||||||
|
AstNode::Block {
|
||||||
|
statements,
|
||||||
|
expr: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::BlockTrailingExpr => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let (expr, statements) = unsafe {
|
||||||
|
Index::from_slice_unchecked(&self.extra[a..b])
|
||||||
|
.split_last()
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
AstNode::Block {
|
||||||
|
statements: statements.to_vec(),
|
||||||
|
expr: Some(*expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::Constant => {
|
||||||
|
let (ty, value) = data.as_index_intern();
|
||||||
|
AstNode::Constant { ty, value }
|
||||||
|
}
|
||||||
|
Tag::ExprStmt => AstNode::ExprStmt {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::ReturnStmt => AstNode::ReturnStmt,
|
||||||
|
Tag::ReturnExprStmt => AstNode::ReturnExprStmt {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::VarDecl => {
|
||||||
|
let (a, _) = data.as_extra_range();
|
||||||
|
let name = Interned::from_u32(self.extra[a]);
|
||||||
|
let ty = Index::from_u32(self.extra[a + 1]).unwrap();
|
||||||
|
|
||||||
|
AstNode::VarDecl { name, ty }
|
||||||
|
}
|
||||||
|
Tag::MutVarDecl => {
|
||||||
|
let (a, _) = data.as_extra_range();
|
||||||
|
let name = Interned::from_u32(self.extra[a]);
|
||||||
|
let ty = Index::from_u32(self.extra[a + 1]).unwrap();
|
||||||
|
|
||||||
|
AstNode::MutVarDecl { name, ty }
|
||||||
|
}
|
||||||
|
Tag::VarDeclAssignment => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let extra = &self.extra[a..b];
|
||||||
|
let name = Interned::from_u32(*extra.get(0).unwrap());
|
||||||
|
let expr = Index::from_u32(*extra.get(1).unwrap()).unwrap();
|
||||||
|
let ty = extra.get(2).map(|&inner| Index::from_u32(inner).unwrap());
|
||||||
|
|
||||||
|
AstNode::MutVarDeclAssignment { name, expr, ty }
|
||||||
|
}
|
||||||
|
Tag::MutVarDeclAssignment => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let extra = &self.extra[a..b];
|
||||||
|
let name = Interned::from_u32(*extra.get(0).unwrap());
|
||||||
|
let expr = Index::from_u32(*extra.get(1).unwrap()).unwrap();
|
||||||
|
let ty = extra.get(2).map(|&inner| Index::from_u32(inner).unwrap());
|
||||||
|
|
||||||
|
AstNode::MutVarDeclAssignment { name, expr, ty }
|
||||||
|
}
|
||||||
|
Tag::GlobalDecl => {
|
||||||
|
let (name, offset) = data.as_intern_and_extra_offset();
|
||||||
|
let ty = Index::from_u32(self.extra[offset]).unwrap();
|
||||||
|
let expr = Index::from_u32(self.extra[offset + 1]).unwrap();
|
||||||
|
|
||||||
|
AstNode::GlobalDecl { name, expr, ty }
|
||||||
|
}
|
||||||
|
Tag::StructDecl => {
|
||||||
|
let (name, offset) = data.as_intern_and_extra_offset();
|
||||||
|
let flags = StructFlags::unpack(self.extra[offset]);
|
||||||
|
|
||||||
|
let types = (offset + 1)..(offset + 1 + flags.num_fields as usize);
|
||||||
|
let names = (offset + 1 + flags.num_fields as usize)
|
||||||
|
..(offset + 1 + flags.num_fields as usize * 2);
|
||||||
|
|
||||||
|
let field_types =
|
||||||
|
unsafe { Index::from_slice_unchecked(&self.extra[types]).to_vec() };
|
||||||
|
|
||||||
|
let field_names = self.extra[names]
|
||||||
|
.iter()
|
||||||
|
.map(|&i| Interned::from_u32(i))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
AstNode::StructDecl {
|
||||||
|
name,
|
||||||
|
flags,
|
||||||
|
field_names,
|
||||||
|
field_types,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::StructDeclInterned => {
|
||||||
|
let (name, ty) = data.as_two_interns();
|
||||||
|
|
||||||
|
AstNode::StructDeclInterned { name, ty }
|
||||||
|
}
|
||||||
|
Tag::FieldDecl => {
|
||||||
|
let (ty, name) = data.as_index_intern();
|
||||||
|
|
||||||
|
AstNode::FieldDecl { name, ty }
|
||||||
|
}
|
||||||
|
Tag::DeclRef => AstNode::DeclRef {
|
||||||
|
decl: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::DeclRefUnresolved => {
|
||||||
|
let (scope, name) = data.as_index_intern();
|
||||||
|
AstNode::DeclRefUnresolved { scope, name }
|
||||||
|
}
|
||||||
|
Tag::InternedType => AstNode::InternedType {
|
||||||
|
intern: data.as_intern(),
|
||||||
|
},
|
||||||
|
Tag::TypeDeclRef => AstNode::TypeDeclRef {
|
||||||
|
decl: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::TypeDeclRefUnresolved => {
|
||||||
|
let (scope, name) = data.as_index_intern();
|
||||||
|
AstNode::TypeDeclRefUnresolved { scope, name }
|
||||||
|
}
|
||||||
|
Tag::PointerType => {
|
||||||
|
let (ty, flags) = data.as_index_and_opaque();
|
||||||
|
let flags = PointerFlags::unpack(flags as u8);
|
||||||
|
AstNode::PointerType { ty, flags }
|
||||||
|
}
|
||||||
|
Tag::ArrayType => {
|
||||||
|
let (length, pointer) = data.as_two_indices();
|
||||||
|
|
||||||
|
AstNode::ArrayType { length, pointer }
|
||||||
|
}
|
||||||
|
Tag::CallExpr => {
|
||||||
|
let (func, argument_list) = data.as_two_indices();
|
||||||
|
AstNode::CallExpr {
|
||||||
|
func,
|
||||||
|
argument_list,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::FieldAccess => {
|
||||||
|
let (expr, field_name) = data.as_index_intern();
|
||||||
|
AstNode::FieldAccess { field_name, expr }
|
||||||
|
}
|
||||||
|
Tag::ArgumentList => {
|
||||||
|
let (a, b) = data.as_extra_range();
|
||||||
|
let arguments = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
||||||
|
|
||||||
|
AstNode::ArgumentList { arguments }
|
||||||
|
}
|
||||||
|
Tag::Argument => AstNode::Argument {
|
||||||
|
expr: data.as_index(),
|
||||||
|
name: None,
|
||||||
|
},
|
||||||
|
Tag::NamedArgument => {
|
||||||
|
let (expr, name) = data.as_index_intern();
|
||||||
|
AstNode::Argument {
|
||||||
|
expr,
|
||||||
|
name: Some(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::ExplicitCast => {
|
||||||
|
let (expr, ty) = data.as_two_indices();
|
||||||
|
|
||||||
|
AstNode::ExplicitCast { expr, ty }
|
||||||
|
}
|
||||||
|
Tag::Deref => AstNode::Deref {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::AddressOf => AstNode::AddressOf {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::Not => AstNode::Not {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::Negate => AstNode::Negate {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::PlaceToValueConversion => AstNode::PlaceToValueConversion {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::ValueToPlaceConversion => AstNode::ValueToPlaceConversion {
|
||||||
|
expr: data.as_index(),
|
||||||
|
},
|
||||||
|
Tag::Or => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Or { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::And => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::And { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::BitOr => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::BitOr { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::BitXOr => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::BitXOr { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::BitAnd => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::BitAnd { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Eq => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Eq { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::NEq => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::NEq { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Lt => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Lt { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Gt => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Gt { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Le => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Le { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Ge => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Ge { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Shl => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Shl { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Shr => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Shr { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Add => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Add { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Sub => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Sub { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Mul => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Mul { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Div => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Div { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Rem => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Rem { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::Assign => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::Assign { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::SubscriptExpr => {
|
||||||
|
let (lhs, rhs) = data.as_two_indices();
|
||||||
|
AstNode::SubscriptExpr { lhs, rhs }
|
||||||
|
}
|
||||||
|
Tag::IfExpr => {
|
||||||
|
let (cond, body) = data.as_two_indices();
|
||||||
|
AstNode::IfExpr { cond, body }
|
||||||
|
}
|
||||||
|
Tag::IfElseExpr => {
|
||||||
|
let (cond, extra) = data.as_index_and_extra_offset();
|
||||||
|
let [a, b] = self.extra[extra..][..2] else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
AstNode::IfElseExpr {
|
||||||
|
cond,
|
||||||
|
a: Index::from_u32(a).unwrap(),
|
||||||
|
b: Index::from_u32(b).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::Error => AstNode::Error {
|
||||||
|
err: data.as_error(),
|
||||||
|
},
|
||||||
|
Tag::Undefined => AstNode::Undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum AstNode {
|
||||||
|
/// pseudo tag, contains a range from a..b into extra of all files.
|
||||||
|
Root {
|
||||||
|
files: Vec<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into extra of all global nodes.
|
||||||
|
File {
|
||||||
|
decls: Vec<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is an intern to a name, and an index into extra of [index: return_type, index: ParameterList]
|
||||||
|
FunctionProto {
|
||||||
|
name: Interned,
|
||||||
|
return_type: Index,
|
||||||
|
parameter_list: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an intern to a name, and an intern to the function type
|
||||||
|
FunctionProtoInterned {
|
||||||
|
name: Interned,
|
||||||
|
ty: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a FunctionProto and an index to a Block
|
||||||
|
FunctionDecl {
|
||||||
|
proto: Index,
|
||||||
|
body: Index,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into extra of indices to parameters
|
||||||
|
ParameterList {
|
||||||
|
params: Vec<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a type, and an intern to a name
|
||||||
|
Parameter {
|
||||||
|
ty: Index,
|
||||||
|
name: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is range from a..b into `extra` of indices to statements
|
||||||
|
Block {
|
||||||
|
statements: Vec<Index>,
|
||||||
|
expr: Option<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a type, and an intern to a value
|
||||||
|
Constant {
|
||||||
|
ty: Index,
|
||||||
|
value: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is an index to an expression
|
||||||
|
ExprStmt {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
/// `data` is none
|
||||||
|
ReturnStmt,
|
||||||
|
/// `data` is an index to an expr
|
||||||
|
ReturnExprStmt {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into `extra` of `[name: intern, type: index]`
|
||||||
|
VarDecl {
|
||||||
|
name: Interned,
|
||||||
|
ty: Index,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into `extra` of `[name: intern, type: index]`
|
||||||
|
MutVarDecl {
|
||||||
|
name: Interned,
|
||||||
|
ty: Index,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into `extra` of `[name: intern, expr: index, type?: index]`
|
||||||
|
VarDeclAssignment {
|
||||||
|
name: Interned,
|
||||||
|
expr: Index,
|
||||||
|
ty: Option<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into `extra` of `[name: intern, expr: index, type?: index]`
|
||||||
|
MutVarDeclAssignment {
|
||||||
|
name: Interned,
|
||||||
|
expr: Index,
|
||||||
|
ty: Option<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is an intern to a name, and an offset into `extra` of `[type: index, expr: index]`
|
||||||
|
GlobalDecl {
|
||||||
|
name: Interned,
|
||||||
|
expr: Index,
|
||||||
|
ty: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an intern to a name, and an offset into extra of `[flags, type0 ,..., typeN ,name0 ,..., nameN]`
|
||||||
|
StructDecl {
|
||||||
|
name: Interned,
|
||||||
|
flags: StructFlags,
|
||||||
|
field_names: Vec<Interned>,
|
||||||
|
field_types: Vec<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is an intern to a name, and an intern to the type of the struct
|
||||||
|
StructDeclInterned {
|
||||||
|
name: Interned,
|
||||||
|
ty: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a type, and an intern to a name
|
||||||
|
FieldDecl {
|
||||||
|
name: Interned,
|
||||||
|
ty: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a Parameter, VarDecl, GlobalDecl or FunctionDecl, and an opaque DeclKind
|
||||||
|
DeclRef {
|
||||||
|
decl: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
||||||
|
DeclRefUnresolved {
|
||||||
|
scope: Index,
|
||||||
|
name: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is an intern of a type
|
||||||
|
InternedType {
|
||||||
|
intern: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a StructDecl
|
||||||
|
TypeDeclRef {
|
||||||
|
decl: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
||||||
|
TypeDeclRefUnresolved {
|
||||||
|
scope: Index,
|
||||||
|
name: Interned,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a Type and u32 PointerFlags (extra offset)
|
||||||
|
PointerType {
|
||||||
|
ty: Index,
|
||||||
|
flags: PointerFlags,
|
||||||
|
},
|
||||||
|
/// `data` is an index to a length expression, and an underlying pointer type
|
||||||
|
ArrayType {
|
||||||
|
length: Index,
|
||||||
|
pointer: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an index to an expr and an index to an ArgumentList
|
||||||
|
CallExpr {
|
||||||
|
func: Index,
|
||||||
|
argument_list: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an index to an expr and an intern to a field name
|
||||||
|
FieldAccess {
|
||||||
|
field_name: Interned,
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
/// `data` is a range from a..b into extra of indices to arguments
|
||||||
|
ArgumentList {
|
||||||
|
arguments: Vec<Index>,
|
||||||
|
},
|
||||||
|
/// `data` is an index to an expression
|
||||||
|
Argument {
|
||||||
|
expr: Index,
|
||||||
|
name: Option<Interned>,
|
||||||
|
},
|
||||||
|
/// `data` is an index to lhs, and an index to the type
|
||||||
|
ExplicitCast {
|
||||||
|
expr: Index,
|
||||||
|
ty: Index,
|
||||||
|
},
|
||||||
|
/// `data` is a single index to an expr
|
||||||
|
Deref {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
AddressOf {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
Not {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
Negate {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
PlaceToValueConversion {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
ValueToPlaceConversion {
|
||||||
|
expr: Index,
|
||||||
|
},
|
||||||
|
/// data is two indices for `lhs` and `rhs`
|
||||||
|
Or {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
And {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
BitOr {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
BitXOr {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
BitAnd {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Eq {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
NEq {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Lt {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Gt {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Le {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Ge {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Shl {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Shr {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Add {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Sub {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Mul {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Div {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Rem {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
Assign {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
SubscriptExpr {
|
||||||
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
|
},
|
||||||
|
IfExpr {
|
||||||
|
cond: Index,
|
||||||
|
body: Index,
|
||||||
|
},
|
||||||
|
/// `data` is an index to an expression and an index into extra for [if, else]
|
||||||
|
IfElseExpr {
|
||||||
|
cond: Index,
|
||||||
|
a: Index,
|
||||||
|
b: Index,
|
||||||
|
},
|
||||||
|
// TODO:
|
||||||
|
/// `data` is a ParseError
|
||||||
|
Error {
|
||||||
|
err: ParseError,
|
||||||
|
},
|
||||||
|
/// placeholder tag for reserved indices/nodes, `data` is none
|
||||||
|
Undefined,
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
use super::*;
|
use crate::{ast2::tag::AstNode, variant};
|
||||||
|
|
||||||
|
use super::{tag::AstNodeExt, *};
|
||||||
|
|
||||||
pub trait AstExt {
|
pub trait AstExt {
|
||||||
fn get_node_children(&self, node: Index) -> Vec<Index>;
|
fn get_node_children(&self, node: Index) -> Vec<Index>;
|
||||||
|
@ -252,7 +254,27 @@ impl Ast {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AstVisitorTrait<Ast: AstExt> {
|
macro_rules! tag_visit_fn {
|
||||||
|
($($tag:tt {$($field_name:ident : $field_ty:ty),* $(,)?}),* $(,)?) => {
|
||||||
|
$(
|
||||||
|
paste::paste! {
|
||||||
|
|
||||||
|
fn [<visit_ $tag:snake>](&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
|
variant!(ast.get_ast_node(idx) => AstNode::$tag { $($field_name),* });
|
||||||
|
self.[<visit_ $tag:snake _impl>](ast, idx, $($field_name),*)
|
||||||
|
}
|
||||||
|
fn [<visit_ $tag:snake _impl>](&mut self, ast: Ast, idx: Index, $($field_name: $field_ty),*) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (ast, idx, $($field_name),*);
|
||||||
|
Err(Self::UNIMPL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
use intern::Index as Interned;
|
||||||
|
|
||||||
|
pub trait AstVisitorTrait<Ast: AstExt + AstNodeExt> {
|
||||||
type Error;
|
type Error;
|
||||||
type Value;
|
type Value;
|
||||||
const UNIMPL: Self::Error;
|
const UNIMPL: Self::Error;
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#![feature(
|
#![feature(
|
||||||
extract_if,
|
|
||||||
iter_advance_by,
|
iter_advance_by,
|
||||||
box_into_inner,
|
box_into_inner,
|
||||||
hash_extract_if,
|
|
||||||
bigint_helper_methods,
|
bigint_helper_methods,
|
||||||
map_try_insert,
|
map_try_insert,
|
||||||
iter_intersperse,
|
iter_intersperse,
|
||||||
|
@ -29,7 +27,7 @@ pub mod symbol_table;
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
pub mod triples;
|
pub mod triples;
|
||||||
|
|
||||||
mod utils;
|
pub mod utils;
|
||||||
use utils::unit;
|
use utils::unit;
|
||||||
|
|
||||||
pub fn tokenize<'a>(
|
pub fn tokenize<'a>(
|
||||||
|
|
Loading…
Reference in a new issue