diff --git a/src/ast.rs b/src/ast.rs index 5c6aab5f5..0b46b15d4 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -98,9 +98,6 @@ fn accept_mut(&mut self, visitor: &mut dyn NodeVisitorMut, reversed: bool) { /// Node is the base trait of all AST nodes. pub trait Node: Acceptor + ConcreteNode + std::fmt::Debug { - /// The parent node, or None if this is root. - fn parent(&self) -> Option<&dyn Node>; - /// The type of this node. fn typ(&self) -> Type; @@ -509,9 +506,6 @@ impl Node for $name { fn typ(&self) -> Type { Type::$type } - fn parent(&self) -> Option<&dyn Node> { - self.parent.map(|p| unsafe { &*p }) - } fn category(&self) -> Category { Category::$category } @@ -557,10 +551,6 @@ fn accept_mut(&mut self, visitor: &mut dyn NodeVisitorMut, reversed: bool) { visitor.did_visit_fields_of(self, VisitResult::Continue(())); } } - impl $name { - /// Set the parent fields of all nodes in the tree rooted at `self`. - fn set_parents(&mut self) {} - } }; } @@ -569,7 +559,6 @@ macro_rules! define_keyword_node { ( $name:ident, $($allowed:ident),* $(,)? ) => { #[derive(Default, Debug)] pub struct $name { - parent: Option<*const dyn Node>, range: Option, keyword: ParseKeyword, } @@ -610,7 +599,6 @@ macro_rules! define_token_node { ( $name:ident, $($allowed:ident),* $(,)? ) => { #[derive(Default, Debug)] pub struct $name { - parent: Option<*const dyn Node>, range: Option, parse_token_type: ParseTokenType, } @@ -664,7 +652,6 @@ macro_rules! define_list_node { ) => { #[derive(Default, Debug)] pub struct $name { - parent: Option<*const dyn Node>, list_contents: Box<[$contents]>, } implement_node!($name, list, $type); @@ -712,15 +699,6 @@ fn accept_mut(&mut self, visitor: &mut dyn NodeVisitorMut, reversed: bool) { visitor.did_visit_fields_of(self, flow); } } - impl $name { - /// Set the parent fields of all nodes in the tree rooted at `self`. - fn set_parents(&mut self) { - for i in 0..self.count() { - self[i].parent = Some(self); - self[i].set_parents(); - } - } - } }; } @@ -811,14 +789,6 @@ fn accept_mut(&mut self, visitor: &mut dyn NodeVisitorMut, reversed: bool) { visitor.did_visit_fields_of(self, flow); } } - impl $name { - /// Set the parent fields of all nodes in the tree rooted at `self`. - fn set_parents(&mut self) { - $( - set_parent_of_field!(self, $field_name, $field_type); - )* - } - } } } @@ -1017,108 +987,10 @@ macro_rules! visit_result { }; } -macro_rules! set_parent_of_field { - ( - $self:ident, - $field_name:ident, - (variant<$field_type:ident>) - ) => { - set_parent_of_union_field!($self, $field_name, $field_type); - }; - ( - $self:ident, - $field_name:ident, - (Option<$field_type:ident>) - ) => { - if $self.$field_name.is_some() { - $self.$field_name.as_mut().unwrap().parent = Some($self); - $self.$field_name.as_mut().unwrap().set_parents(); - } - }; - ( - $self:ident, - $field_name:ident, - $field_type:tt - ) => { - $self.$field_name.parent = Some($self); - $self.$field_name.set_parents(); - }; -} - -macro_rules! set_parent_of_union_field { - ( - $self:ident, - $field_name:ident, - ArgumentOrRedirectionVariant - ) => { - if matches!($self.$field_name, ArgumentOrRedirectionVariant::Argument(_)) { - $self.$field_name.as_mut_argument().parent = Some($self); - $self.$field_name.as_mut_argument().set_parents(); - } else { - $self.$field_name.as_mut_redirection().parent = Some($self); - $self.$field_name.as_mut_redirection().set_parents(); - } - }; - ( - $self:ident, - $field_name:ident, - StatementVariant - ) => { - if matches!($self.$field_name, StatementVariant::NotStatement(_)) { - $self.$field_name.as_mut_not_statement().parent = Some($self); - $self.$field_name.as_mut_not_statement().set_parents(); - } else if matches!($self.$field_name, StatementVariant::BlockStatement(_)) { - $self.$field_name.as_mut_block_statement().parent = Some($self); - $self.$field_name.as_mut_block_statement().set_parents(); - } else if matches!($self.$field_name, StatementVariant::BraceStatement(_)) { - $self.$field_name.as_mut_brace_statement().parent = Some($self); - $self.$field_name.as_mut_brace_statement().set_parents(); - } else if matches!($self.$field_name, StatementVariant::IfStatement(_)) { - $self.$field_name.as_mut_if_statement().parent = Some($self); - $self.$field_name.as_mut_if_statement().set_parents(); - } else if matches!($self.$field_name, StatementVariant::SwitchStatement(_)) { - $self.$field_name.as_mut_switch_statement().parent = Some($self); - $self.$field_name.as_mut_switch_statement().set_parents(); - } else if matches!($self.$field_name, StatementVariant::DecoratedStatement(_)) { - $self.$field_name.as_mut_decorated_statement().parent = Some($self); - $self.$field_name.as_mut_decorated_statement().set_parents(); - } - }; - ( - $self:ident, - $field_name:ident, - BlockStatementHeaderVariant - ) => { - if matches!($self.$field_name, BlockStatementHeaderVariant::ForHeader(_)) { - $self.$field_name.as_mut_for_header().parent = Some($self); - $self.$field_name.as_mut_for_header().set_parents(); - } else if matches!( - $self.$field_name, - BlockStatementHeaderVariant::WhileHeader(_) - ) { - $self.$field_name.as_mut_while_header().parent = Some($self); - $self.$field_name.as_mut_while_header().set_parents(); - } else if matches!( - $self.$field_name, - BlockStatementHeaderVariant::FunctionHeader(_) - ) { - $self.$field_name.as_mut_function_header().parent = Some($self); - $self.$field_name.as_mut_function_header().set_parents(); - } else if matches!( - $self.$field_name, - BlockStatementHeaderVariant::BeginHeader(_) - ) { - $self.$field_name.as_mut_begin_header().parent = Some($self); - $self.$field_name.as_mut_begin_header().set_parents(); - } - }; -} - /// A redirection has an operator like > or 2>, and a target like /dev/null or &1. /// Note that pipes are not redirections. #[derive(Default, Debug)] pub struct Redirection { - parent: Option<*const dyn Node>, pub oper: TokenRedirection, pub target: String_, } @@ -1159,7 +1031,6 @@ fn as_mut_variable_assignment_list(&mut self) -> Option<&mut VariableAssignmentL /// An argument or redirection holds either an argument or redirection. #[derive(Default, Debug)] pub struct ArgumentOrRedirection { - parent: Option<*const dyn Node>, pub contents: ArgumentOrRedirectionVariant, } implement_node!(ArgumentOrRedirection, branch, argument_or_redirection); @@ -1203,7 +1074,6 @@ fn as_mut_argument_or_redirection_list(&mut self) -> Option<&mut ArgumentOrRedir /// A statement is a normal command, or an if / while / etc #[derive(Default, Debug)] pub struct Statement { - parent: Option<*const dyn Node>, pub contents: StatementVariant, } implement_node!(Statement, branch, statement); @@ -1223,7 +1093,6 @@ fn as_mut_statement(&mut self) -> Option<&mut Statement> { /// like if statements, where we require a command). #[derive(Default, Debug)] pub struct JobPipeline { - parent: Option<*const dyn Node>, /// Maybe the time keyword. pub time: Option, /// A (possibly empty) list of variable assignments. @@ -1258,7 +1127,6 @@ fn as_mut_job_pipeline(&mut self) -> Option<&mut JobPipeline> { /// A job_conjunction is a job followed by a && or || continuations. #[derive(Default, Debug)] pub struct JobConjunction { - parent: Option<*const dyn Node>, /// The job conjunction decorator. pub decorator: Option, /// The job itself. @@ -1303,7 +1171,6 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { #[derive(Default, Debug)] pub struct ForHeader { - parent: Option<*const dyn Node>, /// 'for' pub kw_for: KeywordFor, /// var_name @@ -1337,7 +1204,6 @@ fn as_mut_for_header(&mut self) -> Option<&mut ForHeader> { #[derive(Default, Debug)] pub struct WhileHeader { - parent: Option<*const dyn Node>, /// 'while' pub kw_while: KeywordWhile, pub condition: JobConjunction, @@ -1363,7 +1229,6 @@ fn as_mut_while_header(&mut self) -> Option<&mut WhileHeader> { #[derive(Default, Debug)] pub struct FunctionHeader { - parent: Option<*const dyn Node>, pub kw_function: KeywordFunction, /// functions require at least one argument. pub first_arg: Argument, @@ -1391,7 +1256,6 @@ fn as_mut_function_header(&mut self) -> Option<&mut FunctionHeader> { #[derive(Default, Debug)] pub struct BeginHeader { - parent: Option<*const dyn Node>, pub kw_begin: KeywordBegin, /// Note that 'begin' does NOT require a semi or nl afterwards. /// This is valid: begin echo hi; end @@ -1416,7 +1280,6 @@ fn as_mut_begin_header(&mut self) -> Option<&mut BeginHeader> { #[derive(Default, Debug)] pub struct BlockStatement { - parent: Option<*const dyn Node>, /// A header like for, while, etc. pub header: BlockStatementHeaderVariant, /// List of jobs in this block. @@ -1447,7 +1310,6 @@ fn as_mut_block_statement(&mut self) -> Option<&mut BlockStatement> { #[derive(Default, Debug)] pub struct BraceStatement { - parent: Option<*const dyn Node>, /// The opening brace, in command position. pub left_brace: TokenLeftBrace, /// List of jobs in this block. @@ -1478,7 +1340,6 @@ fn as_mut_brace_statement(&mut self) -> Option<&mut BraceStatement> { #[derive(Default, Debug)] pub struct IfClause { - parent: Option<*const dyn Node>, /// The 'if' keyword. pub kw_if: KeywordIf, /// The 'if' condition. @@ -1509,7 +1370,6 @@ fn as_mut_if_clause(&mut self) -> Option<&mut IfClause> { #[derive(Default, Debug)] pub struct ElseifClause { - parent: Option<*const dyn Node>, /// The 'else' keyword. pub kw_else: KeywordElse, /// The 'if' clause following it. @@ -1552,7 +1412,6 @@ fn as_mut_elseif_clause_list(&mut self) -> Option<&mut ElseifClauseList> { #[derive(Default, Debug)] pub struct ElseClause { - parent: Option<*const dyn Node>, /// else ; body pub kw_else: KeywordElse, pub semi_nl: Option, @@ -1583,7 +1442,6 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { #[derive(Default, Debug)] pub struct IfStatement { - parent: Option<*const dyn Node>, /// if part pub if_clause: IfClause, /// else if list @@ -1617,7 +1475,6 @@ fn as_mut_if_statement(&mut self) -> Option<&mut IfStatement> { #[derive(Default, Debug)] pub struct CaseItem { - parent: Option<*const dyn Node>, /// case \ ; body pub kw_case: KeywordCase, pub arguments: ArgumentList, @@ -1650,7 +1507,6 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { #[derive(Default, Debug)] pub struct SwitchStatement { - parent: Option<*const dyn Node>, /// switch \ ; body ; end args_redirs pub kw_switch: KeywordSwitch, pub argument: Argument, @@ -1684,7 +1540,6 @@ fn as_mut_switch_statement(&mut self) -> Option<&mut SwitchStatement> { /// "builtin" or "command" or "exec" #[derive(Default, Debug)] pub struct DecoratedStatement { - parent: Option<*const dyn Node>, /// An optional decoration (command, builtin, exec, etc). pub opt_decoration: Option, /// Command to run. @@ -1713,7 +1568,6 @@ fn as_mut_decorated_statement(&mut self) -> Option<&mut DecoratedStatement> { /// A not statement like `not true` or `! true` #[derive(Default, Debug)] pub struct NotStatement { - parent: Option<*const dyn Node>, /// Keyword, either not or exclam. pub kw: KeywordNot, pub time: Option, @@ -1741,7 +1595,6 @@ fn as_mut_not_statement(&mut self) -> Option<&mut NotStatement> { #[derive(Default, Debug)] pub struct JobContinuation { - parent: Option<*const dyn Node>, pub pipe: TokenPipe, pub newlines: MaybeNewlines, pub variables: VariableAssignmentList, @@ -1785,7 +1638,6 @@ fn as_mut_job_continuation_list(&mut self) -> Option<&mut JobContinuationList> { #[derive(Default, Debug)] pub struct JobConjunctionContinuation { - parent: Option<*const dyn Node>, /// The && or || token. pub conjunction: TokenConjunction, pub newlines: MaybeNewlines, @@ -1825,7 +1677,6 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { /// instances of this. #[derive(Default, Debug)] pub struct AndorJob { - parent: Option<*const dyn Node>, pub job: JobConjunction, } implement_node!(AndorJob, branch, andor_job); @@ -1873,7 +1724,6 @@ fn as_mut_andor_job_list(&mut self) -> Option<&mut AndorJobList> { /// In practice the tok_ends are ignored by fish code so we do not bother to store them. #[derive(Default, Debug)] pub struct FreestandingArgumentList { - parent: Option<*const dyn Node>, pub arguments: ArgumentList, } implement_node!(FreestandingArgumentList, branch, freestanding_argument_list); @@ -1947,7 +1797,6 @@ fn as_mut_case_item_list(&mut self) -> Option<&mut CaseItemList> { /// A variable_assignment contains a source range like FOO=bar. #[derive(Default, Debug)] pub struct VariableAssignment { - parent: Option<*const dyn Node>, range: Option, } implement_node!(VariableAssignment, leaf, variable_assignment); @@ -1988,7 +1837,6 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool { /// Zero or more newlines. #[derive(Default, Debug)] pub struct MaybeNewlines { - parent: Option<*const dyn Node>, range: Option, } implement_node!(MaybeNewlines, leaf, maybe_newlines); @@ -2014,7 +1862,6 @@ fn as_mut_maybe_newlines(&mut self) -> Option<&mut MaybeNewlines> { /// This is a separate type because it is sometimes useful to find all arguments. #[derive(Default, Debug)] pub struct Argument { - parent: Option<*const dyn Node>, range: Option, } implement_node!(Argument, leaf, argument); @@ -2659,9 +2506,6 @@ pub fn walk(&'_ self) -> Traversal<'_> { pub fn top(&self) -> &dyn Node { self.top.as_node() } - fn top_mut(&mut self) -> &mut dyn NodeMut { - &mut *self.top - } /// Return whether any errors were encountered during parsing. pub fn errored(&self) -> bool { self.any_error @@ -4104,25 +3948,6 @@ fn parse_from_top( semis: pops.semis, errors: pops.errors, }; - - if top_type == Type::job_list { - // Set all parent nodes. - // It turns out to be more convenient to do this after the parse phase. - // Note: parent nodes are implemented as raw pointers! This means that the contents Ast must not - // change or move after construction. - ast.top_mut() - .as_mut_job_list() - .as_mut() - .unwrap() - .set_parents(); - } else { - ast.top_mut() - .as_mut_freestanding_argument_list() - .as_mut() - .unwrap() - .set_parents(); - } - ast }