diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index d2440739..d4237e0d 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,10 +1,16 @@ use crate::analysis::DesignRoot; -use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; +use crate::ast::visitor::{Visitor, VisitorResult}; +use crate::ast::{ + AnyDesignUnit, AnyPrimaryUnit, AnySecondaryUnit, ComponentDeclaration, Declaration, + EntityDeclaration, InstantiationStatement, InterfaceDeclaration, MapAspect, PackageDeclaration, + SubprogramDeclaration, UnitKey, +}; use crate::data::{ContentReader, Symbol}; use crate::syntax::Kind::*; -use crate::syntax::{Symbols, Token, Tokenizer, Value}; -use crate::{Position, Source}; +use crate::syntax::{Symbols, Token, TokenAccess, Tokenizer, Value}; +use crate::{EntityId, Position, Source}; use itertools::Itertools; +use std::collections::HashSet; use std::default::Default; macro_rules! kind { @@ -23,6 +29,193 @@ macro_rules! ident { }; } +#[derive(Eq, PartialEq, Debug)] +enum MapAspectKind { + Port, + Generic, +} + +/// Extracts the name of ports or generics from an AST for an entity with a certain ID. +/// The entity can be an `Entity`, `Component` or `Package`. +/// After walking the AST, the ports or generics are written to the `items` vector. +/// The `kind` member chooses whether to select ports or generics. +struct PortsOrGenericsExtractor<'a> { + id: EntityId, + items: &'a mut Vec, + kind: MapAspectKind, +} + +impl DesignRoot { + fn extract_port_or_generic_names( + &self, + id: EntityId, + items: &mut Vec, + kind: MapAspectKind, + ) { + let mut searcher = PortsOrGenericsExtractor { id, items, kind }; + self.walk(&mut searcher); + } +} + +impl<'a> Visitor for PortsOrGenericsExtractor<'a> { + fn visit_component_declaration( + &mut self, + node: &ComponentDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + if node.ident.decl != Some(self.id) { + return VisitorResult::Skip; + } + if self.kind == MapAspectKind::Port { + for port in &node.port_list { + self.items.push(port.completable_name()) + } + } + if self.kind == MapAspectKind::Generic { + for generic in &node.generic_list { + self.items.push(generic.completable_name()) + } + } + VisitorResult::Stop + } + + fn visit_entity_declaration( + &mut self, + node: &EntityDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + if node.ident.decl != Some(self.id) { + return VisitorResult::Skip; + } + if self.kind == MapAspectKind::Port { + if let Some(ports) = &node.port_clause { + for port in ports { + self.items.push(port.completable_name()) + } + } + } + if self.kind == MapAspectKind::Generic { + if let Some(generics) = &node.generic_clause { + for generic in generics { + self.items.push(generic.completable_name()) + } + } + } + VisitorResult::Stop + } + + fn visit_package_declaration( + &mut self, + node: &PackageDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + if node.ident.decl != Some(self.id) { + return VisitorResult::Skip; + } + if self.kind == MapAspectKind::Generic { + if let Some(generics) = &node.generic_clause { + for generic in generics { + self.items.push(generic.completable_name()) + } + } + } + VisitorResult::Stop + } +} + +impl InterfaceDeclaration { + /// Returns completable names for an interface declarations. + /// Example: + /// `signal my_signal : natural := 5` => `my_signal` + fn completable_name(&self) -> String { + match self { + InterfaceDeclaration::Object(obj) => obj.ident.tree.to_string(), + InterfaceDeclaration::File(file) => file.ident.to_string(), + InterfaceDeclaration::Type(typ) => typ.tree.item.name().to_string(), + InterfaceDeclaration::Subprogram(decl, _) => match decl { + SubprogramDeclaration::Procedure(proc) => proc.designator.to_string(), + SubprogramDeclaration::Function(func) => func.designator.to_string(), + }, + InterfaceDeclaration::Package(package) => package.package_name.to_string(), + } + } +} + +/// Visitor responsible for completions in selected AST elements +struct AutocompletionVisitor<'a> { + root: &'a DesignRoot, + cursor: Position, + completions: &'a mut Vec, +} + +impl<'a> AutocompletionVisitor<'a> { + /// Loads completion options for the given map aspect. + /// Returns `true`, when the cursor is inside the map aspect and the search should not continue. + /// Returns `false` otherwise + fn load_completions_for_map_aspect( + &mut self, + node: &InstantiationStatement, + map: &MapAspect, + ctx: &dyn TokenAccess, + kind: MapAspectKind, + ) -> bool { + if !map.span(ctx).contains(self.cursor) { + return false; + } + let formals_in_map: HashSet = + HashSet::from_iter(map.formals().map(|name| name.to_string().to_lowercase())); + if let Some(ent) = node.entity_reference() { + self.root + .extract_port_or_generic_names(ent, self.completions, kind); + self.completions + .retain(|name| !formals_in_map.contains(&name.to_lowercase())); + } + true + } +} + +impl<'a> Visitor for AutocompletionVisitor<'a> { + /// Visit an instantiation statement extracting completions for ports or generics. + fn visit_instantiation_statement( + &mut self, + node: &InstantiationStatement, + ctx: &dyn TokenAccess, + ) -> VisitorResult { + if let Some(map) = &node.generic_map { + if self.load_completions_for_map_aspect(node, map, ctx, MapAspectKind::Generic) { + return VisitorResult::Stop; + } + } + if let Some(map) = &node.port_map { + if self.load_completions_for_map_aspect(node, map, ctx, MapAspectKind::Port) { + return VisitorResult::Stop; + } + } + VisitorResult::Skip + } + + // preliminary optimizations: only visit architecture + fn visit_any_primary_unit( + &mut self, + _node: &AnyPrimaryUnit, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + VisitorResult::Skip + } + + // preliminary optimizations: only visit architecture + fn visit_any_secondary_unit( + &mut self, + node: &AnySecondaryUnit, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + match node { + AnySecondaryUnit::Architecture(_) => VisitorResult::Continue, + AnySecondaryUnit::PackageBody(_) => VisitorResult::Skip, + } + } +} + /// Returns the completable string representation of a declaration /// for example: /// `let alias = parse_vhdl("alias my_alias is ...")` @@ -147,7 +340,16 @@ impl DesignRoot { | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { self.list_available_declarations(library, selected) } - _ => vec![], + _ => { + let mut completions = vec![]; + let mut visitor = AutocompletionVisitor { + completions: &mut completions, + root: self, + cursor, + }; + self.walk(&mut visitor); + completions + } } } } @@ -243,4 +445,47 @@ mod test { let options = root.list_completion_options(code.source(), cursor); assert_eq!(options, vec!["stop", "finish", "resolution_limit", "all"]) } + + #[test] + pub fn completing_instantiation_statement() { + let mut input = LibraryBuilder::new(); + let code = input.code( + "libname", + "\ +entity my_ent is +end entity my_ent; + +architecture arch of my_ent is + component comp is + generic ( + A: natural := 5; + B: integer + ); + port ( + clk : in bit; + rst : in bit; + dout : out bit + ); + end component comp; + signal clk, rst: bit; +begin + comp_inst: comp + generic map ( + A => 2 + ) + port map ( + clk => clk + ); +end arch; + ", + ); + let (root, _) = input.get_analyzed_root(); + let cursor = code.s1("generic map (").pos().end(); + let options = root.list_completion_options(code.source(), cursor); + assert_eq!(options, vec!["B"]); + + let cursor = code.s1("port map (").pos().end(); + let options = root.list_completion_options(code.source(), cursor); + assert_eq!(options, vec!["rst", "dout"]); + } } diff --git a/vhdl_lang/src/analysis/lock.rs b/vhdl_lang/src/analysis/lock.rs index c54afacb..3c470086 100644 --- a/vhdl_lang/src/analysis/lock.rs +++ b/vhdl_lang/src/analysis/lock.rs @@ -111,6 +111,10 @@ impl<'a, T, R> ReadGuard<'a, T, R> { pub fn result(&self) -> &R { self.guard.result.as_ref().unwrap() } + + pub fn data(&self) -> &T { + &self.guard.data + } } impl<'a, T, R> std::ops::Deref for ReadGuard<'a, T, R> { diff --git a/vhdl_lang/src/analysis/root.rs b/vhdl_lang/src/analysis/root.rs index 7bfca3a7..a9e1a39c 100644 --- a/vhdl_lang/src/analysis/root.rs +++ b/vhdl_lang/src/analysis/root.rs @@ -15,6 +15,7 @@ use super::standard::UniversalTypes; use super::visibility::Visibility; use crate::ast::search::*; +use crate::ast::visitor::{walk, Visitor}; use crate::ast::*; use crate::data::*; use crate::syntax::{Symbols, Token, TokenAccess}; @@ -580,6 +581,18 @@ impl DesignRoot { NotFound } + pub fn walk(&self, visitor: &mut impl Visitor) { + for library in self.libraries.values() { + for unit_id in library.sorted_unit_ids() { + let unit = library.units.get(unit_id.key()).unwrap(); + let tokens = &unit.tokens; + if let Some(unit) = unit.unit.get() { + walk(unit.data(), visitor, tokens); + } + } + } + } + pub fn search_library( &self, library_name: &Symbol, @@ -1200,21 +1213,21 @@ package pkg is new gpkg generic map (const => foo); vec![ Diagnostic::error( code.s("pkg", 2), - "A primary unit has already been declared with name 'pkg' in library 'libname'" + "A primary unit has already been declared with name 'pkg' in library 'libname'", ).related(code.s("pkg", 1), "Previously defined here"), Diagnostic::error( code.s("entname", 2), - "A primary unit has already been declared with name 'entname' in library 'libname'" + "A primary unit has already been declared with name 'entname' in library 'libname'", ).related(code.s("entname", 1), "Previously defined here"), Diagnostic::error( code.s("pkg", 3), - "A primary unit has already been declared with name 'pkg' in library 'libname'" + "A primary unit has already been declared with name 'pkg' in library 'libname'", ).related(code.s("pkg", 1), "Previously defined here"), Diagnostic::error( code.s("pkg", 4), - "A primary unit has already been declared with name 'pkg' in library 'libname'" + "A primary unit has already been declared with name 'pkg' in library 'libname'", ).related(code.s("pkg", 1), "Previously defined here"), - ] + ], ); } diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index 5d31b989..cf2aa63a 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -17,6 +17,7 @@ mod any_design_unit; #[macro_use] pub mod search; +pub mod visitor; pub use self::display::*; pub(crate) use self::util::*; @@ -203,6 +204,16 @@ pub enum SelectedName { Selected(Box>, WithPos>), } +impl SelectedName { + /// Returns the reference that this name selects + pub fn reference(&self) -> Reference { + match &self { + SelectedName::Designator(desi) => desi.reference, + SelectedName::Selected(_, desi) => desi.item.reference, + } + } +} + /// LRM 9.3.4 Function calls #[derive(PartialEq, Debug, Clone)] pub struct CallOrIndexed { @@ -1021,6 +1032,17 @@ pub enum InstantiatedUnit { Configuration(WithPos), } +impl InstantiatedUnit { + /// Returns a reference to the unit that this instantiation declares + pub fn entity_reference(&self) -> Reference { + match &self { + InstantiatedUnit::Entity(name, _) => name.item.reference(), + InstantiatedUnit::Configuration(name) => name.item.reference(), + InstantiatedUnit::Component(name) => name.item.reference(), + } + } +} + #[derive(PartialEq, Debug, Clone)] pub struct MapAspect { pub start: TokenId, // `generic` or `map` @@ -1049,6 +1071,13 @@ pub struct InstantiationStatement { pub semicolon: TokenId, } +impl InstantiationStatement { + /// Returns the reference to the entity declaring this instance + pub fn entity_reference(&self) -> Reference { + self.unit.entity_reference() + } +} + /// 11.8 Generate statements #[derive(PartialEq, Debug, Clone)] pub struct GenerateBody { diff --git a/vhdl_lang/src/ast/visitor.rs b/vhdl_lang/src/ast/visitor.rs new file mode 100644 index 00000000..7c00ea85 --- /dev/null +++ b/vhdl_lang/src/ast/visitor.rs @@ -0,0 +1,2434 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// Lic// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// This Source Code Form is subject to the terms of the Mozilla Public +// You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) 2023, Olof Kraigher olof.kraigher@gmail.com + +use crate::ast::visitor::VisitorResult::{Continue, Skip, Stop}; +use crate::ast::*; +use crate::syntax::TokenAccess; +use itertools::Itertools; +use std::ops::Deref; + +#[derive(PartialEq)] +pub enum VisitorResult { + Continue, + Stop, + Skip, +} + +pub trait Visitor { + fn visit_attribute_name( + &mut self, + _node: &AttributeName, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_attribute_designator( + &mut self, + _node: &AttributeDesignator, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_external_path( + &mut self, + _node: &ExternalPath, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_external_name( + &mut self, + _node: &ExternalName, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_name(&mut self, _node: &Name, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_selected_name( + &mut self, + _node: &SelectedName, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_call_or_indexed( + &mut self, + _node: &CallOrIndexed, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_choice(&mut self, _node: &Choice, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_element_association( + &mut self, + _node: &ElementAssociation, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_actual_part(&mut self, _node: &ActualPart, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_association_element( + &mut self, + _node: &AssociationElement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_abstract_literal( + &mut self, + _node: &AbstractLiteral, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_bit_string(&mut self, _node: &BitString, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_physical_literal( + &mut self, + _node: &PhysicalLiteral, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_literal(&mut self, _node: &Literal, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_allocator(&mut self, _node: &Allocator, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_qualified_expression( + &mut self, + _node: &QualifiedExpression, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_expression(&mut self, _node: &Expression, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_ident(&mut self, _node: &Ident, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_discrete_range( + &mut self, + _node: &DiscreteRange, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_range_constraint( + &mut self, + _node: &RangeConstraint, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_range(&mut self, _node: &Range, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_element_constraint( + &mut self, + _node: &ElementConstraint, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_subtype_constraint( + &mut self, + _node: &SubtypeConstraint, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_record_element_resolution( + &mut self, + _node: &RecordElementResolution, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_resolution_indication( + &mut self, + _node: &ResolutionIndication, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_type_mark(&mut self, _node: &TypeMark, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_subtype_indication( + &mut self, + _node: &SubtypeIndication, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_array_index(&mut self, _node: &ArrayIndex, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_element_declaration( + &mut self, + _node: &ElementDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_protected_type_declarative_item( + &mut self, + _node: &ProtectedTypeDeclarativeItem, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_designator(&mut self, _node: &Designator, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_alias_declaration( + &mut self, + _node: &AliasDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_attribute_declaration( + &mut self, + _node: &AttributeDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_entity_tag(&mut self, _node: &EntityTag, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_entity_name(&mut self, _node: &EntityName, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_attribute_specification( + &mut self, + _node: &AttributeSpecification, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_attribute(&mut self, _node: &Attribute, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_protected_type_declaration( + &mut self, + _node: &ProtectedTypeDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_protected_type_body( + &mut self, + _node: &ProtectedTypeBody, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_physical_type_declaration( + &mut self, + _node: &PhysicalTypeDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_enumeration_literal( + &mut self, + _node: &EnumerationLiteral, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_type_definition( + &mut self, + _node: &TypeDefinition, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_type_declaration( + &mut self, + _node: &TypeDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_object_declaration( + &mut self, + _node: &ObjectDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_file_declaration( + &mut self, + _node: &FileDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_subprogram_designator( + &mut self, + _node: &SubprogramDesignator, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_procedure_specification( + &mut self, + _node: &ProcedureSpecification, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_function_specification( + &mut self, + _node: &FunctionSpecification, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_subprogram_body( + &mut self, + _node: &SubprogramBody, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_signature(&mut self, _node: &Signature, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_subprogram_declaration( + &mut self, + _node: &SubprogramDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_interface_file_declaration( + &mut self, + _node: &InterfaceFileDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_interface_object_declaration( + &mut self, + _node: &InterfaceObjectDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_subprogram_default( + &mut self, + _node: &SubprogramDefault, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_interface_package_generic_map_aspect( + &mut self, + _node: &InterfacePackageGenericMapAspect, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_interface_package_declaration( + &mut self, + _node: &InterfacePackageDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_interface_declaration( + &mut self, + _node: &InterfaceDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_port_clause(&mut self, _node: &PortClause, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_component_declaration( + &mut self, + _node: &ComponentDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_declaration(&mut self, _node: &Declaration, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_wait_statement( + &mut self, + _node: &WaitStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_assert_statement( + &mut self, + _node: &AssertStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_report_statement( + &mut self, + _node: &ReportStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_target(&mut self, _node: &Target, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_waveform_element( + &mut self, + _node: &WaveformElement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_waveform(&mut self, _node: &Waveform, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_delay_mechanism( + &mut self, + _node: &DelayMechanism, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_signal_assignment( + &mut self, + _node: &SignalAssignment, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_signal_force_assignment( + &mut self, + _node: &SignalForceAssignment, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_signal_release_assignment( + &mut self, + _node: &SignalReleaseAssignment, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_variable_assignment( + &mut self, + _node: &VariableAssignment, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_if_statement(&mut self, _node: &IfStatement, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_case_statement( + &mut self, + _node: &CaseStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_iteration_scheme( + &mut self, + _node: &IterationScheme, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_loop_statement( + &mut self, + _node: &LoopStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_next_statement( + &mut self, + _node: &NextStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_exit_statement( + &mut self, + _node: &ExitStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_return_statement( + &mut self, + _node: &ReturnStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_sequential_statement( + &mut self, + _node: &SequentialStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_labeled_sequential_statement( + &mut self, + _node: &LabeledSequentialStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_block_statement( + &mut self, + _node: &BlockStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_block_header(&mut self, _node: &BlockHeader, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_sensitivity_list( + &mut self, + _node: &SensitivityList, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_process_statement( + &mut self, + _node: &ProcessStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_concurrent_procedure_call( + &mut self, + _node: &ConcurrentProcedureCall, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_concurrent_assert_statement( + &mut self, + _node: &ConcurrentAssertStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_concurrent_signal_assignment( + &mut self, + _node: &ConcurrentSignalAssignment, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_instantiated_unit( + &mut self, + _node: &InstantiatedUnit, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_instantiation_statement( + &mut self, + _node: &InstantiationStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_generate_body( + &mut self, + _node: &GenerateBody, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_for_generate_statement( + &mut self, + _node: &ForGenerateStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_if_generate_statement( + &mut self, + _node: &IfGenerateStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_case_generate_statement( + &mut self, + _node: &CaseGenerateStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_concurrent_statement( + &mut self, + _node: &ConcurrentStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_labeled_concurrent_statement( + &mut self, + _node: &LabeledConcurrentStatement, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_library_clause( + &mut self, + _node: &LibraryClause, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_use_clause(&mut self, _node: &UseClause, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_context_reference( + &mut self, + _node: &ContextReference, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_context_item(&mut self, _node: &ContextItem, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_context_declaration( + &mut self, + _node: &ContextDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_package_instantiation( + &mut self, + _node: &PackageInstantiation, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_instantiation_list( + &mut self, + _node: &InstantiationList, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_entity_aspect( + &mut self, + _node: &EntityAspect, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_binding_indication( + &mut self, + _node: &BindingIndication, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_component_specification( + &mut self, + _node: &ComponentSpecification, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_v_unit_binding_indication( + &mut self, + _node: &VUnitBindingIndication, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_configuration_specification( + &mut self, + _node: &ConfigurationSpecification, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_configuration_declarative_item( + &mut self, + _node: &ConfigurationDeclarativeItem, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_component_configuration( + &mut self, + _node: &ComponentConfiguration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_configuration_item( + &mut self, + _node: &ConfigurationItem, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_block_configuration( + &mut self, + _node: &BlockConfiguration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_configuration_declaration( + &mut self, + _node: &ConfigurationDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_entity_declaration( + &mut self, + _node: &EntityDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_architecture_body( + &mut self, + _node: &ArchitectureBody, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_package_declaration( + &mut self, + _node: &PackageDeclaration, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_package_body(&mut self, _node: &PackageBody, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_any_primary_unit( + &mut self, + _node: &AnyPrimaryUnit, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_any_secondary_unit( + &mut self, + _node: &AnySecondaryUnit, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_any_design_unit( + &mut self, + _node: &AnyDesignUnit, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_design_file(&mut self, _node: &DesignFile) -> VisitorResult { + Continue + } + fn visit_reference(&mut self, _node: &Reference, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + fn visit_item_with_pos( + &mut self, + _pos: &SrcPos, + _node: &dyn ASTNode, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_item_with_decl( + &mut self, + _decl: &Option, + _node: &dyn ASTNode, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_item_with_reference( + &mut self, + _ref: &Reference, + _node: &dyn ASTNode, + _ctx: &dyn TokenAccess, + ) -> VisitorResult { + Continue + } + fn visit_name_list(&mut self, _node: &NameList, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn visit_map_aspect(&mut self, _node: &MapAspect, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } +} + +/// An AST Node has two methods it needs to declare: +/// - A `visit(Visitor, Context)` method. +/// - A `children()` method. +pub trait ASTNode { + /// Called when traversing the AST. + /// Each node must call the respective method in the `Visitor` class. + /// If the node doesn't have a representation + /// (for example, for utility types such as `Box` or `Vec`), + /// simply return `Continue`. + fn visit(&self, visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult; + + /// Returns the Children of this Node. + /// Must return all children that are considered AST elements. + /// Doesn't return auxiliary information such as the Tokens. + fn children(&self) -> Vec<&dyn ASTNode>; +} + +pub fn walk(node: &dyn ASTNode, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) { + let mut stack: Vec<&dyn ASTNode> = vec![node]; + while let Some(node) = stack.pop() { + match node.visit(visitor, ctx) { + Stop => return, + Skip => continue, + _ => {} + } + for child in node.children().into_iter().rev() { + stack.push(child); + } + } +} + +pub fn walk_design_file(node: &DesignFile, visitor: &mut dyn Visitor) { + visitor.visit_design_file(node); + for (tokens, unit) in &node.design_units { + walk(unit, visitor, tokens); + } +} + +impl ASTNode for Box { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![self.deref()] + } +} + +impl ASTNode for Option { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match &self { + None => vec![], + Some(el) => vec![el], + } + } +} + +impl ASTNode for (T, U) { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.0, &self.1] + } +} + +impl ASTNode for Vec { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + self.iter().map(|f| f as &dyn ASTNode).collect() + } +} + +impl ASTNode for WithPos { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_item_with_pos(&self.pos, &self.item, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.item] + } +} + +impl ASTNode for WithDecl { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_item_with_decl(&self.decl, &self.tree, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.tree] + } +} + +impl ASTNode for WithRef { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_item_with_reference(&self.reference, &self.item, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.reference, &self.item] + } +} + +impl ASTNode for Conditional { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.condition, &self.item] + } +} + +impl ASTNode for Conditionals { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.conditionals, &self.else_item] + } +} + +impl ASTNode for Selection { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.alternatives, &self.expression] + } +} + +impl ASTNode for AssignmentRightHand { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match &self { + AssignmentRightHand::Simple(expr) => vec![expr], + AssignmentRightHand::Conditional(conds) => vec![conds], + AssignmentRightHand::Selected(sel) => vec![sel], + } + } +} + +impl ASTNode for Alternative { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.choices, &self.item] + } +} + +impl ASTNode for DesignFile { + fn visit(&self, visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_design_file(self) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + self.design_units + .iter() + .map(|it| &it.1 as &dyn ASTNode) + .collect_vec() + } +} + +impl ASTNode for AnyDesignUnit { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_any_design_unit(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + AnyDesignUnit::Primary(unit) => vec![unit], + AnyDesignUnit::Secondary(unit) => vec![unit], + } + } +} + +impl ASTNode for AnyPrimaryUnit { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_any_primary_unit(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + AnyPrimaryUnit::Entity(decl) => vec![decl], + AnyPrimaryUnit::Configuration(decl) => vec![decl], + AnyPrimaryUnit::Package(decl) => vec![decl], + AnyPrimaryUnit::PackageInstance(decl) => vec![decl], + AnyPrimaryUnit::Context(decl) => vec![decl], + } + } +} + +impl ASTNode for ContextDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_context_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.items] + } +} + +impl ASTNode for ContextItem { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_context_item(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ContextItem::Use(clause) => vec![clause], + ContextItem::Library(clause) => vec![clause], + ContextItem::Context(clause) => vec![clause], + } + } +} + +impl ASTNode for ContextReference { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_context_reference(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.name_list] + } +} + +impl ASTNode for SeparatedList { + fn visit(&self, _visitor: &mut dyn Visitor, _ctx: &dyn TokenAccess) -> VisitorResult { + Continue + } + + fn children(&self) -> Vec<&dyn ASTNode> { + self.items.iter().map(|it| it as &dyn ASTNode).collect_vec() + } +} + +impl ASTNode for LibraryClause { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_library_clause(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.name_list] + } +} + +impl ASTNode for UseClause { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_use_clause(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.name_list] + } +} + +impl ASTNode for Ident { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_ident(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for PackageInstantiation { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_package_instantiation(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.context_clause, + &self.ident, + &self.package_name, + &self.generic_map, + ] + } +} + +impl ASTNode for AssociationElement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_association_element(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.formal, &self.actual] + } +} + +impl ASTNode for ActualPart { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_actual_part(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ActualPart::Expression(expr) => vec![expr], + ActualPart::Open => vec![], + } + } +} + +impl ASTNode for SelectedName { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_selected_name(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + SelectedName::Designator(desi) => vec![desi], + SelectedName::Selected(name, desi) => vec![name, desi], + } + } +} + +impl ASTNode for Designator { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_designator(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for PackageDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_package_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.context_clause, + &self.ident, + &self.generic_clause, + &self.decl, + ] + } +} + +impl ASTNode for Declaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Declaration::Object(decl) => vec![decl], + Declaration::File(decl) => vec![decl], + Declaration::Type(decl) => vec![decl], + Declaration::Component(decl) => vec![decl], + Declaration::Attribute(decl) => vec![decl], + Declaration::Alias(decl) => vec![decl], + Declaration::SubprogramDeclaration(decl) => vec![decl], + Declaration::SubprogramBody(decl) => vec![decl], + Declaration::Use(decl) => vec![decl], + Declaration::Package(decl) => vec![decl], + Declaration::Configuration(decl) => vec![decl], + } + } +} + +impl ASTNode for ConfigurationSpecification { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_configuration_specification(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.spec, &self.bind_ind, &self.vunit_bind_inds] + } +} + +impl ASTNode for VUnitBindingIndication { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_v_unit_binding_indication(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.vunit_list] + } +} + +impl ASTNode for BindingIndication { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_binding_indication(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.entity_aspect, &self.generic_map, &self.port_map] + } +} + +impl ASTNode for EntityAspect { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_entity_aspect(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + EntityAspect::Entity(name, id) => vec![name, id], + EntityAspect::Configuration(config) => vec![config], + EntityAspect::Open => vec![], + } + } +} + +impl ASTNode for ComponentSpecification { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_component_specification(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.instantiation_list, &self.component_name] + } +} + +impl ASTNode for InstantiationList { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_instantiation_list(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + InstantiationList::Labels(idents) => vec![idents], + InstantiationList::Others => vec![], + InstantiationList::All => vec![], + } + } +} + +impl ASTNode for SubprogramBody { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_subprogram_body(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.specification, &self.declarations, &self.statements] + } +} + +impl ASTNode for LabeledSequentialStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_labeled_sequential_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.label, &self.statement] + } +} + +impl ASTNode for SubprogramDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_subprogram_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + SubprogramDeclaration::Procedure(proc) => vec![proc], + SubprogramDeclaration::Function(func) => vec![func], + } + } +} + +impl ASTNode for SequentialStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_sequential_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + SequentialStatement::Wait(stmt) => vec![stmt], + SequentialStatement::Assert(stmt) => vec![stmt], + SequentialStatement::Report(stmt) => vec![stmt], + SequentialStatement::VariableAssignment(stmt) => vec![stmt], + SequentialStatement::SignalAssignment(stmt) => vec![stmt], + SequentialStatement::SignalForceAssignment(stmt) => vec![stmt], + SequentialStatement::SignalReleaseAssignment(stmt) => vec![stmt], + SequentialStatement::ProcedureCall(stmt) => vec![stmt], + SequentialStatement::If(stmt) => vec![stmt], + SequentialStatement::Case(stmt) => vec![stmt], + SequentialStatement::Loop(stmt) => vec![stmt], + SequentialStatement::Next(stmt) => vec![stmt], + SequentialStatement::Exit(stmt) => vec![stmt], + SequentialStatement::Return(stmt) => vec![stmt], + SequentialStatement::Null => vec![], + } + } +} + +impl ASTNode for CaseStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_case_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.expression, &self.alternatives] + } +} + +impl ASTNode for ReturnStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_return_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match &self.expression { + Some(expr) => vec![expr], + None => vec![], + } + } +} + +impl ASTNode for ExitStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_exit_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.loop_label, &self.condition] + } +} + +impl ASTNode for NextStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_next_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.loop_label, &self.condition] + } +} + +impl ASTNode for LoopStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_loop_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.iteration_scheme, &self.statements] + } +} + +impl ASTNode for IterationScheme { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_iteration_scheme(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + IterationScheme::While(scheme) => vec![scheme], + IterationScheme::For(ident, range) => vec![ident, range], + } + } +} + +impl ASTNode for DiscreteRange { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_discrete_range(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + DiscreteRange::Discrete(type_mark, range) => vec![type_mark, range], + DiscreteRange::Range(range) => vec![range], + } + } +} + +impl ASTNode for TypeMark { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_type_mark(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.name] + } +} + +impl ASTNode for Range { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_range(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Range::Range(constraint) => vec![constraint], + Range::Attribute(attr) => vec![attr.deref()], + } + } +} + +impl ASTNode for RangeConstraint { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_range_constraint(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.left_expr, &self.right_expr] + } +} + +impl ASTNode for IfStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_if_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.conds] + } +} + +impl ASTNode for CallOrIndexed { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_call_or_indexed(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.name, &self.parameters] + } +} + +impl ASTNode for SignalReleaseAssignment { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_signal_release_assignment(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.target] + } +} + +impl ASTNode for Target { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_target(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Target::Name(name) => vec![name], + Target::Aggregate(aggr) => vec![aggr], + } + } +} + +impl ASTNode for ElementAssociation { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_element_association(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ElementAssociation::Positional(expr) => vec![expr], + ElementAssociation::Named(choices, expr) => vec![choices, expr], + } + } +} + +impl ASTNode for SignalForceAssignment { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_signal_force_assignment(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.rhs] + } +} + +impl ASTNode for SignalAssignment { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_signal_assignment(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.target, &self.delay_mechanism, &self.rhs] + } +} + +impl ASTNode for DelayMechanism { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_delay_mechanism(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + DelayMechanism::Transport => vec![], + DelayMechanism::Inertial { reject } => vec![reject], + } + } +} + +impl ASTNode for Waveform { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_waveform(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Waveform::Elements(elements) => vec![elements], + Waveform::Unaffected => vec![], + } + } +} + +impl ASTNode for WaveformElement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_waveform_element(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.value, &self.after] + } +} + +impl ASTNode for VariableAssignment { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_variable_assignment(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.target, &self.rhs] + } +} + +impl ASTNode for ReportStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_report_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.severity, &self.report] + } +} + +impl ASTNode for AssertStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_assert_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.condition, &self.report, &self.severity] + } +} + +impl ASTNode for Choice { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_choice(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Choice::Expression(expr) => vec![expr], + Choice::DiscreteRange(range) => vec![range], + Choice::Others => vec![], + } + } +} + +impl ASTNode for WaitStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_wait_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.sensitivity_clause, + &self.condition_clause, + &self.timeout_clause, + ] + } +} + +impl ASTNode for FunctionSpecification { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_function_specification(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.parameter_list, &self.return_type] + } +} + +impl ASTNode for ProcedureSpecification { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_procedure_specification(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.designator, &self.parameter_list] + } +} + +impl ASTNode for SubprogramDesignator { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_subprogram_designator(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for AliasDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_alias_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.designator, + &self.subtype_indication, + &self.name, + &self.signature, + ] + } +} + +impl ASTNode for Attribute { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_attribute(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Attribute::Specification(spec) => vec![spec], + Attribute::Declaration(decl) => vec![decl], + } + } +} + +impl ASTNode for SubtypeIndication { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_subtype_indication(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.resolution, &self.type_mark, &self.constraint] + } +} + +impl ASTNode for AttributeSpecification { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_attribute_specification(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.entity_name, &self.expr] + } +} + +impl ASTNode for EntityName { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_entity_name(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + EntityName::Name(name) => vec![name], + EntityName::All | EntityName::Others => vec![], + } + } +} + +impl ASTNode for ResolutionIndication { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_resolution_indication(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ResolutionIndication::FunctionName(name) => vec![name], + ResolutionIndication::ArrayElement(name) => vec![name], + ResolutionIndication::Record(record) => vec![record], + ResolutionIndication::Unresolved => vec![], + } + } +} + +impl ASTNode for RecordElementResolution { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_record_element_resolution(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.resolution] + } +} + +impl ASTNode for SubtypeConstraint { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_subtype_constraint(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + SubtypeConstraint::Range(range) => vec![range], + SubtypeConstraint::Array(ranges, constraint) => vec![ranges, constraint], + SubtypeConstraint::Record(constraints) => vec![constraints], + } + } +} + +impl ASTNode for ElementConstraint { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_element_constraint(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.constraint] + } +} + +impl ASTNode for AttributeDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_attribute_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.type_mark] + } +} + +impl ASTNode for ComponentDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_component_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.generic_list, &self.port_list] + } +} + +impl ASTNode for TypeDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_type_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.def] + } +} + +impl ASTNode for TypeDefinition { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_type_definition(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + TypeDefinition::Enumeration(literals) => vec![literals], + TypeDefinition::Numeric(range) => vec![range], + TypeDefinition::Physical(decl) => vec![decl], + TypeDefinition::Array(indices, indication) => vec![indices, indication], + TypeDefinition::Record(record) => vec![record], + TypeDefinition::Access(subtype) => vec![subtype], + TypeDefinition::Incomplete(reference) => vec![reference], + TypeDefinition::File(type_mark) => vec![type_mark], + TypeDefinition::Protected(decl) => vec![decl], + TypeDefinition::ProtectedBody(body) => vec![body], + TypeDefinition::Subtype(subtype) => vec![subtype], + } + } +} + +impl ASTNode for Reference { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_reference(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for ProtectedTypeBody { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_protected_type_body(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.decl] + } +} + +impl ASTNode for ProtectedTypeDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_protected_type_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.items] + } +} + +impl ASTNode for ProtectedTypeDeclarativeItem { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_protected_type_declarative_item(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ProtectedTypeDeclarativeItem::Subprogram(decl) => vec![decl], + } + } +} + +impl ASTNode for ElementDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_element_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.subtype] + } +} + +impl ASTNode for ArrayIndex { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_array_index(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ArrayIndex::IndexSubtypeDefintion(type_mark) => vec![type_mark], + ArrayIndex::Discrete(range) => vec![range], + } + } +} + +impl ASTNode for PhysicalTypeDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_physical_type_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.range, &self.primary_unit, &self.secondary_units] + } +} + +impl ASTNode for PhysicalLiteral { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_physical_literal(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.value, &self.unit] + } +} + +impl ASTNode for EnumerationLiteral { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_enumeration_literal(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for FileDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_file_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.ident, + &self.subtype_indication, + &self.file_name, + &self.open_info, + ] + } +} + +impl ASTNode for ObjectDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_object_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.subtype_indication, &self.expression] + } +} + +impl ASTNode for InterfaceDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_interface_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + InterfaceDeclaration::Object(obj) => vec![obj], + InterfaceDeclaration::File(obj) => vec![obj], + InterfaceDeclaration::Type(obj) => vec![obj], + InterfaceDeclaration::Subprogram(decl, default) => vec![decl, default], + InterfaceDeclaration::Package(pkg) => vec![pkg], + } + } +} + +impl ASTNode for InterfaceObjectDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_interface_object_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.subtype_indication, &self.expression] + } +} + +impl ASTNode for InterfaceFileDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_interface_file_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.subtype_indication] + } +} + +impl ASTNode for SubprogramDefault { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_subprogram_default(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + SubprogramDefault::Name(name) => vec![name], + SubprogramDefault::Box => vec![], + } + } +} + +impl ASTNode for InterfacePackageDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_interface_package_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.ident, &self.package_name, &self.generic_map] + } +} + +impl ASTNode for InterfacePackageGenericMapAspect { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_interface_package_generic_map_aspect(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + InterfacePackageGenericMapAspect::Map(map) => vec![map], + InterfacePackageGenericMapAspect::Box => vec![], + InterfacePackageGenericMapAspect::Default => vec![], + } + } +} + +impl ASTNode for ConfigurationDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_configuration_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.context_clause, + &self.ident, + &self.entity_name, + &self.decl, + &self.vunit_bind_inds, + &self.block_config, + ] + } +} + +impl ASTNode for ConfigurationDeclarativeItem { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_configuration_declarative_item(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ConfigurationDeclarativeItem::Use(clause) => vec![clause], + } + } +} + +impl ASTNode for BlockConfiguration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_block_configuration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.block_spec, &self.use_clauses, &self.items] + } +} + +impl ASTNode for ConfigurationItem { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_configuration_item(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ConfigurationItem::Block(block) => vec![block], + ConfigurationItem::Component(component) => vec![component], + } + } +} + +impl ASTNode for ComponentConfiguration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_component_configuration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.spec, + &self.bind_ind, + &self.vunit_bind_inds, + &self.block_config, + ] + } +} + +impl ASTNode for EntityDeclaration { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_entity_declaration(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.context_clause, + &self.ident, + &self.generic_clause, + &self.port_clause, + &self.decl, + &self.statements, + ] + } +} + +impl ASTNode for AnySecondaryUnit { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_any_secondary_unit(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + AnySecondaryUnit::Architecture(arch) => vec![arch], + AnySecondaryUnit::PackageBody(package) => vec![package], + } + } +} + +impl ASTNode for LabeledConcurrentStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_labeled_concurrent_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.label, &self.statement] + } +} + +impl ASTNode for ConcurrentStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_concurrent_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match &self { + ConcurrentStatement::ProcedureCall(stmt) => vec![stmt], + ConcurrentStatement::Block(stmt) => vec![stmt], + ConcurrentStatement::Process(stmt) => vec![stmt], + ConcurrentStatement::Assert(stmt) => vec![stmt], + ConcurrentStatement::Assignment(stmt) => vec![stmt], + ConcurrentStatement::Instance(stmt) => vec![stmt], + ConcurrentStatement::ForGenerate(stmt) => vec![stmt], + ConcurrentStatement::IfGenerate(stmt) => vec![stmt], + ConcurrentStatement::CaseGenerate(stmt) => vec![stmt], + } + } +} + +impl ASTNode for CaseGenerateStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_case_generate_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.sels] + } +} + +impl ASTNode for IfGenerateStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_if_generate_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.conds] + } +} + +impl ASTNode for ForGenerateStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_for_generate_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.index_name, &self.discrete_range, &self.body] + } +} + +impl ASTNode for InstantiationStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_instantiation_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.unit, &self.generic_map, &self.port_map] + } +} + +impl ASTNode for GenerateBody { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_generate_body(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.alternative_label, &self.decl, &self.statements] + } +} + +impl ASTNode for InstantiatedUnit { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_instantiated_unit(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + InstantiatedUnit::Component(component) => vec![component], + InstantiatedUnit::Entity(name, ident) => vec![name, ident], + InstantiatedUnit::Configuration(config) => vec![config], + } + } +} + +impl ASTNode for ConcurrentSignalAssignment { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_concurrent_signal_assignment(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.target, &self.delay_mechanism, &self.rhs] + } +} + +impl ASTNode for ConcurrentAssertStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_concurrent_assert_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.statement] + } +} + +impl ASTNode for ProcessStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_process_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.sensitivity_list, &self.decl, &self.statements] + } +} + +impl ASTNode for BlockStatement { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_block_statement(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.guard_condition, + &self.header, + &self.decl, + &self.statements, + ] + } +} + +impl ASTNode for BlockHeader { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_block_header(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.generic_map, + &self.generic_map, + &self.port_map, + &self.port_map, + ] + } +} + +impl ASTNode for ConcurrentProcedureCall { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_concurrent_procedure_call(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.call] + } +} + +impl ASTNode for PackageBody { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_package_body(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.context_clause, &self.ident, &self.decl] + } +} + +impl ASTNode for SensitivityList { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_sensitivity_list(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + SensitivityList::Names(names) => vec![names], + SensitivityList::All => vec![], + } + } +} + +impl ASTNode for ArchitectureBody { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_architecture_body(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![ + &self.context_clause, + &self.ident, + &self.entity_name, + &self.decl, + &self.statements, + ] + } +} + +impl ASTNode for Expression { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_expression(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Expression::Binary(_, lhs, rhs) => vec![lhs, rhs], + Expression::Unary(_, expr) => vec![expr], + Expression::Aggregate(elements) => vec![elements], + Expression::Qualified(qual) => vec![qual], + Expression::Name(name) => vec![name], + Expression::Literal(lit) => vec![lit], + Expression::New(allocator) => vec![allocator], + } + } +} + +impl ASTNode for QualifiedExpression { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_qualified_expression(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.type_mark, &self.expr] + } +} + +impl ASTNode for Allocator { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_allocator(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Allocator::Qualified(qual) => vec![qual], + Allocator::Subtype(subtype) => vec![subtype], + } + } +} + +impl ASTNode for AttributeDesignator { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_attribute_designator(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for Signature { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_signature(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Signature::Function(t1, t2) => vec![t1, t2], + Signature::Procedure(proc) => vec![proc], + } + } +} + +impl ASTNode for Name { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_name(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Name::Designator(desi) => vec![desi], + Name::Selected(name, desi) => vec![name, desi], + Name::SelectedAll(name) => vec![name], + Name::Slice(name, range) => vec![name, range], + Name::Attribute(attr) => vec![attr], + Name::CallOrIndexed(coi) => vec![coi], + Name::External(external) => vec![external], + } + } +} + +impl ASTNode for ExternalName { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_external_name(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.path, &self.subtype] + } +} + +impl ASTNode for ExternalPath { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_external_path(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + ExternalPath::Package(name) => vec![name], + ExternalPath::Absolute(name) => vec![name], + ExternalPath::Relative(name, _) => vec![name], + } + } +} + +impl ASTNode for AttributeName { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_attribute_name(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.name, &self.signature, &self.attr, &self.expr] + } +} + +impl ASTNode for AbstractLiteral { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_abstract_literal(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![] + } +} + +impl ASTNode for Literal { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_literal(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + match self { + Literal::String(_) | Literal::BitString(_) | Literal::Character(_) | Literal::Null => { + vec![] + } + Literal::AbstractLiteral(lit) => vec![lit], + Literal::Physical(phy) => vec![phy], + } + } +} + +impl ASTNode for EntityTag { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_entity_tag(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.designator, &self.signature] + } +} + +impl ASTNode for MapAspect { + fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult { + visitor.visit_map_aspect(self, ctx) + } + + fn children(&self) -> Vec<&dyn ASTNode> { + vec![&self.list] + } +} diff --git a/vhdl_lang/src/data/source.rs b/vhdl_lang/src/data/source.rs index f6ba18ef..7ad3db15 100644 --- a/vhdl_lang/src/data/source.rs +++ b/vhdl_lang/src/data/source.rs @@ -541,6 +541,10 @@ impl SrcPos { pub fn combine(&self, other: &dyn AsRef) -> Self { self.clone().combine_into(other) } + + pub fn contains(&self, pos: Position) -> bool { + self.range.contains(pos) + } } /// Denotes an item with an associated source file.