Skip to content

Commit b1faeca

Browse files
authored
Parse Subprogram Instantiation Statement (#208)
* 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
1 parent c84e06b commit b1faeca

File tree

9 files changed

+330
-5
lines changed

9 files changed

+330
-5
lines changed

vhdl_lang/src/analysis/declarative.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ impl<'a> AnalyzeContext<'a> {
531531
}
532532
}
533533
}
534-
534+
Declaration::SubprogramInstantiation(_) => {
535+
// TODO: subprogram instantiation statement
536+
}
535537
Declaration::Use(ref mut use_clause) => {
536538
self.analyze_use_clause(scope, use_clause, diagnostics)?;
537539
}

vhdl_lang/src/analysis/named_entity.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::ast::{
1111
AttributeDeclaration, AttributeSpecification, ComponentDeclaration, Declaration, Designator,
1212
FileDeclaration, HasIdent, Ident, InterfaceFileDeclaration, InterfacePackageDeclaration,
1313
ObjectClass, ObjectDeclaration, PackageInstantiation, SubprogramBody, SubprogramDeclaration,
14-
TypeDeclaration, WithDecl,
14+
SubprogramInstantiation, TypeDeclaration, WithDecl,
1515
};
1616
use crate::ast::{ExternalObjectClass, InterfaceDeclaration, InterfaceObjectDeclaration};
1717
use crate::data::*;
@@ -527,13 +527,20 @@ impl HasEntityId for Declaration {
527527
Declaration::Alias(alias) => alias.ent_id(),
528528
Declaration::SubprogramDeclaration(decl) => decl.ent_id(),
529529
Declaration::SubprogramBody(body) => body.ent_id(),
530+
Declaration::SubprogramInstantiation(decl) => decl.ent_id(),
530531
Declaration::Package(pkg) => pkg.ent_id(),
531532
Declaration::Use(_) => None,
532533
Declaration::Configuration(_) => None,
533534
}
534535
}
535536
}
536537

538+
impl HasEntityId for SubprogramInstantiation {
539+
fn ent_id(&self) -> Option<EntityId> {
540+
self.ident.decl
541+
}
542+
}
543+
537544
impl HasEntityId for PackageInstantiation {
538545
fn ent_id(&self) -> Option<EntityId> {
539546
self.ident.decl

vhdl_lang/src/analysis/overloaded.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,8 @@ impl Diagnostic {
414414

415415
#[cfg(test)]
416416
mod tests {
417-
418417
use super::*;
418+
use crate::analysis::overloaded;
419419
use crate::analysis::tests::TestSetup;
420420
use crate::data::DiagnosticHandler;
421421
use crate::syntax::test::check_diagnostics;
@@ -449,7 +449,7 @@ mod tests {
449449
&fcall.pos,
450450
&des,
451451
&mut fcall.item.parameters,
452-
SubprogramKind::Function(ttyp),
452+
overloaded::SubprogramKind::Function(ttyp),
453453
overloaded.entities().collect(),
454454
diagnostics,
455455
))

vhdl_lang/src/ast.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,18 @@ impl<T: AsRef<SrcPos>> AsRef<SrcPos> for WithDecl<T> {
476476
}
477477
}
478478

479+
#[derive(PartialEq, Debug, Clone)]
480+
pub struct WithToken<T> {
481+
item: T,
482+
token: TokenId,
483+
}
484+
485+
impl<T> WithToken<T> {
486+
pub fn new(item: T, token: TokenId) -> WithToken<T> {
487+
WithToken { item, token }
488+
}
489+
}
490+
479491
/// LRM 6.6 Alias declarations
480492
#[derive(PartialEq, Debug, Clone)]
481493
pub struct AliasDeclaration {
@@ -686,6 +698,23 @@ pub struct SubprogramHeader {
686698
pub map_aspect: Option<MapAspect>,
687699
}
688700

701+
#[derive(PartialEq, Debug, Clone)]
702+
pub enum SubprogramKind {
703+
Function,
704+
Procedure,
705+
}
706+
707+
/// LRM 4.4 Subprogram Instantiation Statement
708+
#[derive(PartialEq, Debug, Clone)]
709+
pub struct SubprogramInstantiation {
710+
pub kind: WithToken<SubprogramKind>,
711+
pub ident: WithDecl<Ident>,
712+
pub subprogram_name: WithPos<Name>,
713+
pub signature: Option<WithPos<Signature>>,
714+
pub generic_map: Option<MapAspect>,
715+
pub semi: TokenId,
716+
}
717+
689718
/// LRM 4.5.3 Signatures
690719
#[derive(PartialEq, Debug, Clone)]
691720
pub enum Signature {
@@ -780,6 +809,7 @@ pub enum Declaration {
780809
Attribute(Attribute),
781810
Alias(AliasDeclaration),
782811
SubprogramDeclaration(SubprogramDeclaration),
812+
SubprogramInstantiation(SubprogramInstantiation),
783813
SubprogramBody(SubprogramBody),
784814
Use(UseClause),
785815
Package(PackageInstantiation),

vhdl_lang/src/ast/display.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,43 @@ impl Display for SubprogramDeclaration {
863863
}
864864
}
865865

866+
impl Display for SubprogramInstantiation {
867+
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
868+
match self.kind.item {
869+
SubprogramKind::Function => write!(f, "function ")?,
870+
SubprogramKind::Procedure => write!(f, "procedure ")?,
871+
};
872+
write!(f, "{}", self.ident)?;
873+
write!(f, " is new ")?;
874+
write!(f, "{}", self.subprogram_name)?;
875+
if let Some(signature) = &self.signature {
876+
write!(f, " {}", signature)?;
877+
}
878+
if let Some(generic_map) = &self.generic_map {
879+
writeln!(f, " generic map (")?;
880+
write_separated_list(&generic_map.list, f, ",")?;
881+
write!(f, "\n)")?;
882+
}
883+
Ok(())
884+
}
885+
}
886+
887+
fn write_separated_list<T: Display>(
888+
list: &SeparatedList<T>,
889+
f: &mut Formatter<'_>,
890+
separator: &str,
891+
) -> Result {
892+
let mut first = true;
893+
for assoc in &list.items {
894+
if !first {
895+
writeln!(f, "{separator}")?;
896+
}
897+
write!(f, " {assoc}")?;
898+
first = false;
899+
}
900+
Ok(())
901+
}
902+
866903
impl Display for InterfaceFileDeclaration {
867904
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
868905
write!(f, "file {} : {}", self.ident, self.subtype_indication)
@@ -2147,4 +2184,51 @@ end package;",
21472184
},
21482185
);
21492186
}
2187+
2188+
#[test]
2189+
fn write_subprogram_instantiation() {
2190+
assert_format_eq(
2191+
"function my_func is new func;",
2192+
"function my_func is new func",
2193+
Code::subprogram_instantiation,
2194+
);
2195+
}
2196+
2197+
#[test]
2198+
fn write_subprogram_instantiation_signature() {
2199+
assert_format_eq(
2200+
"function my_func is new func [bit return bit_vector];",
2201+
"function my_func is new func [bit return bit_vector]",
2202+
Code::subprogram_instantiation,
2203+
);
2204+
}
2205+
2206+
#[test]
2207+
fn write_subprogram_instantiation_signature_generic_map() {
2208+
assert_format_eq(
2209+
"procedure proc is new proc generic map (x => x, y => a.b);",
2210+
"procedure proc is new proc generic map (
2211+
x => x,
2212+
y => a.b
2213+
)",
2214+
Code::subprogram_instantiation,
2215+
);
2216+
}
2217+
2218+
#[test]
2219+
fn subprogram_instantiation_declaration() {
2220+
assert_format_eq(
2221+
"procedure proc is new proc generic map (x => x, y => a.b);",
2222+
"procedure proc is new proc generic map (
2223+
x => x,
2224+
y => a.b
2225+
)",
2226+
|code| {
2227+
assert_matches!(
2228+
code.declarative_part().remove(0),
2229+
Declaration::SubprogramInstantiation(inst) => inst
2230+
)
2231+
},
2232+
);
2233+
}
21502234
}

vhdl_lang/src/ast/search.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub enum FoundDeclaration<'a> {
5757
Alias(&'a mut AliasDeclaration),
5858
Function(&'a mut FunctionSpecification),
5959
Procedure(&'a mut ProcedureSpecification),
60+
SubprogramInstantiation(&'a mut SubprogramInstantiation),
6061
Package(&'a mut PackageDeclaration),
6162
PackageBody(&'a mut PackageBody),
6263
PackageInstance(&'a mut PackageInstantiation),
@@ -1012,6 +1013,9 @@ impl Search for Declaration {
10121013
Declaration::SubprogramDeclaration(decl) => {
10131014
return_if_found!(decl.search(ctx, searcher));
10141015
}
1016+
Declaration::SubprogramInstantiation(decl) => {
1017+
return_if_found!(decl.search(ctx, searcher));
1018+
}
10151019
Declaration::Attribute(Attribute::Declaration(decl)) => {
10161020
return_if_found!(searcher
10171021
.search_decl(ctx, FoundDeclaration::Attribute(decl))
@@ -1358,6 +1362,19 @@ impl Search for MapAspect {
13581362
}
13591363
}
13601364

1365+
impl Search for SubprogramInstantiation {
1366+
fn search(&mut self, ctx: &dyn TokenAccess, searcher: &mut impl Searcher) -> SearchResult {
1367+
return_if_found!(searcher
1368+
.search_decl(ctx, FoundDeclaration::SubprogramInstantiation(self))
1369+
.or_not_found());
1370+
return_if_found!(self.subprogram_name.search(ctx, searcher));
1371+
if let Some(signature) = &mut self.signature {
1372+
return_if_found!(signature.item.search(ctx, searcher));
1373+
}
1374+
self.generic_map.search(ctx, searcher)
1375+
}
1376+
}
1377+
13611378
// Search for reference to declaration/definition at cursor
13621379
pub struct ItemAtCursor {
13631380
source: Source,
@@ -1670,6 +1687,7 @@ impl<'a> FoundDeclaration<'a> {
16701687
FoundDeclaration::GenerateBody(..) => None,
16711688
FoundDeclaration::ConcurrentStatement(..) => None,
16721689
FoundDeclaration::SequentialStatement(..) => None,
1690+
FoundDeclaration::SubprogramInstantiation(_) => None,
16731691
}
16741692
}
16751693
}
@@ -1682,6 +1700,7 @@ impl<'a> HasEntityId for FoundDeclaration<'a> {
16821700
FoundDeclaration::ForGenerateIndex(_, value) => value.index_name.decl,
16831701
FoundDeclaration::Function(value) => value.designator.decl,
16841702
FoundDeclaration::Procedure(value) => value.designator.decl,
1703+
FoundDeclaration::SubprogramInstantiation(value) => value.ident.decl,
16851704
FoundDeclaration::Object(value) => value.ident.decl,
16861705
FoundDeclaration::ElementDeclaration(elem) => elem.ident.decl,
16871706
FoundDeclaration::EnumerationLiteral(_, elem) => elem.decl,
@@ -1716,6 +1735,7 @@ impl<'a> HasSrcPos for FoundDeclaration<'a> {
17161735
FoundDeclaration::ForIndex(ident, _) => ident.pos(),
17171736
FoundDeclaration::ForGenerateIndex(_, value) => value.index_name.pos(),
17181737
FoundDeclaration::Function(value) => &value.designator.tree.pos,
1738+
FoundDeclaration::SubprogramInstantiation(value) => &value.ident.tree.pos,
17191739
FoundDeclaration::Procedure(value) => &value.designator.tree.pos,
17201740
FoundDeclaration::Object(value) => value.ident.pos(),
17211741
FoundDeclaration::ElementDeclaration(elem) => elem.ident.pos(),
@@ -1762,6 +1782,9 @@ impl std::fmt::Display for FoundDeclaration<'_> {
17621782
FoundDeclaration::Function(ref value) => {
17631783
write!(f, "{value};")
17641784
}
1785+
FoundDeclaration::SubprogramInstantiation(ref value) => {
1786+
write!(f, "{value};")
1787+
}
17651788
FoundDeclaration::Procedure(ref value) => {
17661789
write!(f, "{value};")
17671790
}

vhdl_lang/src/ast/visitor.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,14 @@ pub trait Visitor {
804804
fn visit_map_aspect(&mut self, _node: &MapAspect, _ctx: &dyn TokenAccess) -> VisitorResult {
805805
Continue
806806
}
807+
808+
fn visit_subprogram_instantiation(
809+
&mut self,
810+
_node: &SubprogramInstantiation,
811+
_ctx: &dyn TokenAccess,
812+
) -> VisitorResult {
813+
Continue
814+
}
807815
}
808816

809817
/// An AST Node has two methods it needs to declare:
@@ -1181,10 +1189,26 @@ impl ASTNode for Declaration {
11811189
Declaration::Use(decl) => vec![decl],
11821190
Declaration::Package(decl) => vec![decl],
11831191
Declaration::Configuration(decl) => vec![decl],
1192+
Declaration::SubprogramInstantiation(decl) => vec![decl],
11841193
}
11851194
}
11861195
}
11871196

1197+
impl ASTNode for SubprogramInstantiation {
1198+
fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult {
1199+
visitor.visit_subprogram_instantiation(self, ctx)
1200+
}
1201+
1202+
fn children(&self) -> Vec<&dyn ASTNode> {
1203+
vec![
1204+
&self.ident,
1205+
&self.subprogram_name,
1206+
&self.signature,
1207+
&self.generic_map,
1208+
]
1209+
}
1210+
}
1211+
11881212
impl ASTNode for ConfigurationSpecification {
11891213
fn visit(&self, visitor: &mut dyn Visitor, ctx: &dyn TokenAccess) -> VisitorResult {
11901214
visitor.visit_configuration_specification(self, ctx)

0 commit comments

Comments
 (0)