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-traits = "0.2.19"
 | 
			
		||||
ordered-float = "4.2.2"
 | 
			
		||||
paste = "1.0.15"
 | 
			
		||||
petgraph = "0.6.5"
 | 
			
		||||
thiserror = "1.0.63"
 | 
			
		||||
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 {
 | 
			
		||||
        let key = Key::PointerType {
 | 
			
		||||
            pointee,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -835,7 +835,7 @@ impl<'a> AstVisitorTrait<&'a mut super::Ast> for IrBuilder {
 | 
			
		|||
        idx: super::Index,
 | 
			
		||||
    ) -> Result<(), Self::Error> {
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -890,19 +890,23 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
 | 
			
		|||
 | 
			
		||||
    fn visit_parameter(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        ast: &'a mut Ast,
 | 
			
		||||
        _ast: &'a mut Ast,
 | 
			
		||||
        idx: Index,
 | 
			
		||||
    ) -> Result<Self::Value, Self::Error> {
 | 
			
		||||
        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))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn visit_global_decl(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        ast: &'a mut Ast,
 | 
			
		||||
        _ast: &'a mut Ast,
 | 
			
		||||
        idx: Index,
 | 
			
		||||
    ) -> Result<Self::Value, Self::Error> {
 | 
			
		||||
        Ok(PlaceOrValue::Place(idx))
 | 
			
		||||
| 
						 | 
				
			
			@ -910,7 +914,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
 | 
			
		|||
 | 
			
		||||
    fn visit_address_of_expr(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        ast: &'a mut Ast,
 | 
			
		||||
        _ast: &'a mut Ast,
 | 
			
		||||
        idx: Index,
 | 
			
		||||
    ) -> Result<Self::Value, Self::Error> {
 | 
			
		||||
        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 (_, 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))
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1015,6 +1019,9 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
 | 
			
		|||
        let bodies = unsafe { Index::from_slice_unchecked(&ast.extra[extra..][..2]) };
 | 
			
		||||
        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 b = self.visit_any(ast, b)?;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1025,6 +1032,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver {
 | 
			
		|||
        }
 | 
			
		||||
        .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);
 | 
			
		||||
 | 
			
		||||
        Ok(a.with_index(idx))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ pub mod debug;
 | 
			
		|||
pub mod intern;
 | 
			
		||||
pub mod ir;
 | 
			
		||||
pub mod parser;
 | 
			
		||||
pub mod tag;
 | 
			
		||||
pub mod visitor;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +64,7 @@ pub enum Tag {
 | 
			
		|||
    StructDeclInterned,
 | 
			
		||||
    /// `data` is an index to a type, and an intern to a name
 | 
			
		||||
    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,
 | 
			
		||||
    /// `data` is an inlined key into the symbol table (scope: index, name: intern)
 | 
			
		||||
    DeclRefUnresolved,
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +181,7 @@ impl Tag {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
 | 
			
		||||
enum ParseError {
 | 
			
		||||
pub enum ParseError {
 | 
			
		||||
    #[error("Unexpected end of token iter.")]
 | 
			
		||||
    UnexpectedEndOfTokens,
 | 
			
		||||
    #[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 {
 | 
			
		||||
    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 Value;
 | 
			
		||||
    const UNIMPL: Self::Error;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,6 @@
 | 
			
		|||
#![feature(
 | 
			
		||||
    extract_if,
 | 
			
		||||
    iter_advance_by,
 | 
			
		||||
    box_into_inner,
 | 
			
		||||
    hash_extract_if,
 | 
			
		||||
    bigint_helper_methods,
 | 
			
		||||
    map_try_insert,
 | 
			
		||||
    iter_intersperse,
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +27,7 @@ pub mod symbol_table;
 | 
			
		|||
pub mod tokens;
 | 
			
		||||
pub mod triples;
 | 
			
		||||
 | 
			
		||||
mod utils;
 | 
			
		||||
pub mod utils;
 | 
			
		||||
use utils::unit;
 | 
			
		||||
 | 
			
		||||
pub fn tokenize<'a>(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue