Skip to content

Commit

Permalink
Parse Subprogram Instantiation Statement (#208)
Browse files Browse the repository at this point in the history
* Add subprogram instantiation statement in AST

* Parse function instantiation statement

* Parse subprogram instantiation to declaration

* Add visitor

* Fix logic for identifier

* Add tests; refactoring

* Shorten path

* Fix tests
  • Loading branch information
Schottkyc137 committed Nov 4, 2023
1 parent c84e06b commit b1faeca
Show file tree
Hide file tree
Showing 9 changed files with 330 additions and 5 deletions.
4 changes: 3 additions & 1 deletion vhdl_lang/src/analysis/declarative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,9 @@ impl<'a> AnalyzeContext<'a> {
}
}
}

Declaration::SubprogramInstantiation(_) => {
// TODO: subprogram instantiation statement
}
Declaration::Use(ref mut use_clause) => {
self.analyze_use_clause(scope, use_clause, diagnostics)?;
}
Expand Down
9 changes: 8 additions & 1 deletion vhdl_lang/src/analysis/named_entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::ast::{
AttributeDeclaration, AttributeSpecification, ComponentDeclaration, Declaration, Designator,
FileDeclaration, HasIdent, Ident, InterfaceFileDeclaration, InterfacePackageDeclaration,
ObjectClass, ObjectDeclaration, PackageInstantiation, SubprogramBody, SubprogramDeclaration,
TypeDeclaration, WithDecl,
SubprogramInstantiation, TypeDeclaration, WithDecl,
};
use crate::ast::{ExternalObjectClass, InterfaceDeclaration, InterfaceObjectDeclaration};
use crate::data::*;
Expand Down Expand Up @@ -527,13 +527,20 @@ impl HasEntityId for Declaration {
Declaration::Alias(alias) => alias.ent_id(),
Declaration::SubprogramDeclaration(decl) => decl.ent_id(),
Declaration::SubprogramBody(body) => body.ent_id(),
Declaration::SubprogramInstantiation(decl) => decl.ent_id(),
Declaration::Package(pkg) => pkg.ent_id(),
Declaration::Use(_) => None,
Declaration::Configuration(_) => None,
}
}
}

impl HasEntityId for SubprogramInstantiation {
fn ent_id(&self) -> Option<EntityId> {
self.ident.decl
}
}

impl HasEntityId for PackageInstantiation {
fn ent_id(&self) -> Option<EntityId> {
self.ident.decl
Expand Down
4 changes: 2 additions & 2 deletions vhdl_lang/src/analysis/overloaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,8 @@ impl Diagnostic {

#[cfg(test)]
mod tests {

use super::*;
use crate::analysis::overloaded;
use crate::analysis::tests::TestSetup;
use crate::data::DiagnosticHandler;
use crate::syntax::test::check_diagnostics;
Expand Down Expand Up @@ -449,7 +449,7 @@ mod tests {
&fcall.pos,
&des,
&mut fcall.item.parameters,
SubprogramKind::Function(ttyp),
overloaded::SubprogramKind::Function(ttyp),
overloaded.entities().collect(),
diagnostics,
))
Expand Down
30 changes: 30 additions & 0 deletions vhdl_lang/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,18 @@ impl<T: AsRef<SrcPos>> AsRef<SrcPos> for WithDecl<T> {
}
}

#[derive(PartialEq, Debug, Clone)]
pub struct WithToken<T> {
item: T,
token: TokenId,
}

impl<T> WithToken<T> {
pub fn new(item: T, token: TokenId) -> WithToken<T> {
WithToken { item, token }
}
}

/// LRM 6.6 Alias declarations
#[derive(PartialEq, Debug, Clone)]
pub struct AliasDeclaration {
Expand Down Expand Up @@ -686,6 +698,23 @@ pub struct SubprogramHeader {
pub map_aspect: Option<MapAspect>,
}

#[derive(PartialEq, Debug, Clone)]
pub enum SubprogramKind {
Function,
Procedure,
}

/// LRM 4.4 Subprogram Instantiation Statement
#[derive(PartialEq, Debug, Clone)]
pub struct SubprogramInstantiation {
pub kind: WithToken<SubprogramKind>,
pub ident: WithDecl<Ident>,
pub subprogram_name: WithPos<Name>,
pub signature: Option<WithPos<Signature>>,
pub generic_map: Option<MapAspect>,
pub semi: TokenId,
}

/// LRM 4.5.3 Signatures
#[derive(PartialEq, Debug, Clone)]
pub enum Signature {
Expand Down Expand Up @@ -780,6 +809,7 @@ pub enum Declaration {
Attribute(Attribute),
Alias(AliasDeclaration),
SubprogramDeclaration(SubprogramDeclaration),
SubprogramInstantiation(SubprogramInstantiation),
SubprogramBody(SubprogramBody),
Use(UseClause),
Package(PackageInstantiation),
Expand Down
84 changes: 84 additions & 0 deletions vhdl_lang/src/ast/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,43 @@ impl Display for SubprogramDeclaration {
}
}

impl Display for SubprogramInstantiation {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self.kind.item {
SubprogramKind::Function => write!(f, "function ")?,
SubprogramKind::Procedure => write!(f, "procedure ")?,
};
write!(f, "{}", self.ident)?;
write!(f, " is new ")?;
write!(f, "{}", self.subprogram_name)?;
if let Some(signature) = &self.signature {
write!(f, " {}", signature)?;
}
if let Some(generic_map) = &self.generic_map {
writeln!(f, " generic map (")?;
write_separated_list(&generic_map.list, f, ",")?;
write!(f, "\n)")?;
}
Ok(())
}
}

fn write_separated_list<T: Display>(
list: &SeparatedList<T>,
f: &mut Formatter<'_>,
separator: &str,
) -> Result {
let mut first = true;
for assoc in &list.items {
if !first {
writeln!(f, "{separator}")?;
}
write!(f, " {assoc}")?;
first = false;
}
Ok(())
}

impl Display for InterfaceFileDeclaration {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "file {} : {}", self.ident, self.subtype_indication)
Expand Down Expand Up @@ -2147,4 +2184,51 @@ end package;",
},
);
}

#[test]
fn write_subprogram_instantiation() {
assert_format_eq(
"function my_func is new func;",
"function my_func is new func",
Code::subprogram_instantiation,
);
}

#[test]
fn write_subprogram_instantiation_signature() {
assert_format_eq(
"function my_func is new func [bit return bit_vector];",
"function my_func is new func [bit return bit_vector]",
Code::subprogram_instantiation,
);
}

#[test]
fn write_subprogram_instantiation_signature_generic_map() {
assert_format_eq(
"procedure proc is new proc generic map (x => x, y => a.b);",
"procedure proc is new proc generic map (
x => x,
y => a.b
)",
Code::subprogram_instantiation,
);
}

#[test]
fn subprogram_instantiation_declaration() {
assert_format_eq(
"procedure proc is new proc generic map (x => x, y => a.b);",
"procedure proc is new proc generic map (
x => x,
y => a.b
)",
|code| {
assert_matches!(
code.declarative_part().remove(0),
Declaration::SubprogramInstantiation(inst) => inst
)
},
);
}
}
23 changes: 23 additions & 0 deletions vhdl_lang/src/ast/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub enum FoundDeclaration<'a> {
Alias(&'a mut AliasDeclaration),
Function(&'a mut FunctionSpecification),
Procedure(&'a mut ProcedureSpecification),
SubprogramInstantiation(&'a mut SubprogramInstantiation),
Package(&'a mut PackageDeclaration),
PackageBody(&'a mut PackageBody),
PackageInstance(&'a mut PackageInstantiation),
Expand Down Expand Up @@ -1012,6 +1013,9 @@ impl Search for Declaration {
Declaration::SubprogramDeclaration(decl) => {
return_if_found!(decl.search(ctx, searcher));
}
Declaration::SubprogramInstantiation(decl) => {
return_if_found!(decl.search(ctx, searcher));
}
Declaration::Attribute(Attribute::Declaration(decl)) => {
return_if_found!(searcher
.search_decl(ctx, FoundDeclaration::Attribute(decl))
Expand Down Expand Up @@ -1358,6 +1362,19 @@ impl Search for MapAspect {
}
}

impl Search for SubprogramInstantiation {
fn search(&mut self, ctx: &dyn TokenAccess, searcher: &mut impl Searcher) -> SearchResult {
return_if_found!(searcher
.search_decl(ctx, FoundDeclaration::SubprogramInstantiation(self))
.or_not_found());
return_if_found!(self.subprogram_name.search(ctx, searcher));
if let Some(signature) = &mut self.signature {
return_if_found!(signature.item.search(ctx, searcher));
}
self.generic_map.search(ctx, searcher)
}
}

// Search for reference to declaration/definition at cursor
pub struct ItemAtCursor {
source: Source,
Expand Down Expand Up @@ -1670,6 +1687,7 @@ impl<'a> FoundDeclaration<'a> {
FoundDeclaration::GenerateBody(..) => None,
FoundDeclaration::ConcurrentStatement(..) => None,
FoundDeclaration::SequentialStatement(..) => None,
FoundDeclaration::SubprogramInstantiation(_) => None,
}
}
}
Expand All @@ -1682,6 +1700,7 @@ impl<'a> HasEntityId for FoundDeclaration<'a> {
FoundDeclaration::ForGenerateIndex(_, value) => value.index_name.decl,
FoundDeclaration::Function(value) => value.designator.decl,
FoundDeclaration::Procedure(value) => value.designator.decl,
FoundDeclaration::SubprogramInstantiation(value) => value.ident.decl,
FoundDeclaration::Object(value) => value.ident.decl,
FoundDeclaration::ElementDeclaration(elem) => elem.ident.decl,
FoundDeclaration::EnumerationLiteral(_, elem) => elem.decl,
Expand Down Expand Up @@ -1716,6 +1735,7 @@ impl<'a> HasSrcPos for FoundDeclaration<'a> {
FoundDeclaration::ForIndex(ident, _) => ident.pos(),
FoundDeclaration::ForGenerateIndex(_, value) => value.index_name.pos(),
FoundDeclaration::Function(value) => &value.designator.tree.pos,
FoundDeclaration::SubprogramInstantiation(value) => &value.ident.tree.pos,
FoundDeclaration::Procedure(value) => &value.designator.tree.pos,
FoundDeclaration::Object(value) => value.ident.pos(),
FoundDeclaration::ElementDeclaration(elem) => elem.ident.pos(),
Expand Down Expand Up @@ -1762,6 +1782,9 @@ impl std::fmt::Display for FoundDeclaration<'_> {
FoundDeclaration::Function(ref value) => {
write!(f, "{value};")
}
FoundDeclaration::SubprogramInstantiation(ref value) => {
write!(f, "{value};")
}
FoundDeclaration::Procedure(ref value) => {
write!(f, "{value};")
}
Expand Down
24 changes: 24 additions & 0 deletions vhdl_lang/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,14 @@ pub trait Visitor {
fn visit_map_aspect(&mut self, _node: &MapAspect, _ctx: &dyn TokenAccess) -> VisitorResult {
Continue
}

fn visit_subprogram_instantiation(
&mut self,
_node: &SubprogramInstantiation,
_ctx: &dyn TokenAccess,
) -> VisitorResult {
Continue
}
}

/// An AST Node has two methods it needs to declare:
Expand Down Expand Up @@ -1181,10 +1189,26 @@ impl ASTNode for Declaration {
Declaration::Use(decl) => vec![decl],
Declaration::Package(decl) => vec![decl],
Declaration::Configuration(decl) => vec![decl],
Declaration::SubprogramInstantiation(decl) => vec![decl],
}
}
}

impl ASTNode for SubprogramInstantiation {
fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult {
visitor.visit_subprogram_instantiation(self, ctx)
}

fn children(&self) -> Vec<&dyn ASTNode> {
vec![
&self.ident,
&self.subprogram_name,
&self.signature,
&self.generic_map,
]
}
}

impl ASTNode for ConfigurationSpecification {
fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult {
visitor.visit_configuration_specification(self, ctx)
Expand Down
Loading

0 comments on commit b1faeca

Please sign in to comment.