Skip to content

Commit e0041fe

Browse files
committed
Pre-defined labels in previuos declarative part
1 parent 24be97c commit e0041fe

File tree

7 files changed

+156
-9
lines changed

7 files changed

+156
-9
lines changed

vhdl_lang/src/analysis/concurrent.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,27 @@ impl<'a> AnalyzeContext<'a> {
3030
Ok(())
3131
}
3232

33-
fn analyze_concurrent_statement(
33+
pub fn define_labels_for_concurrent_part(
3434
&self,
3535
scope: &Scope<'a>,
36-
statement: &mut LabeledConcurrentStatement,
36+
statements: &mut [LabeledConcurrentStatement],
3737
diagnostics: &mut dyn DiagnosticHandler,
3838
) -> FatalResult {
39-
if let Some(ref mut label) = statement.label {
40-
scope.add(label.define(self.arena, AnyEntKind::Label), diagnostics);
39+
for statement in statements.iter_mut() {
40+
if let Some(ref mut label) = statement.label {
41+
scope.add(label.define(self.arena, AnyEntKind::Label), diagnostics);
42+
}
4143
}
4244

45+
Ok(())
46+
}
47+
48+
fn analyze_concurrent_statement(
49+
&self,
50+
scope: &Scope<'a>,
51+
statement: &mut LabeledConcurrentStatement,
52+
diagnostics: &mut dyn DiagnosticHandler,
53+
) -> FatalResult {
4354
match statement.statement {
4455
ConcurrentStatement::Block(ref mut block) => {
4556
if let Some(ref mut guard_condition) = block.guard_condition {
@@ -58,6 +69,8 @@ impl<'a> AnalyzeContext<'a> {
5869
if let Some(ref mut list) = block.header.port_map {
5970
self.analyze_assoc_elems(scope, list, diagnostics)?;
6071
}
72+
73+
self.define_labels_for_concurrent_part(scope, &mut block.statements, diagnostics)?;
6174
self.analyze_declarative_part(&nested, &mut block.decl, diagnostics)?;
6275
self.analyze_concurrent_part(&nested, &mut block.statements, diagnostics)?;
6376
}
@@ -77,6 +90,7 @@ impl<'a> AnalyzeContext<'a> {
7790
}
7891
}
7992
let nested = scope.nested();
93+
self.define_labels_for_sequential_part(scope, statements, diagnostics)?;
8094
self.analyze_declarative_part(&nested, decl, diagnostics)?;
8195
self.analyze_sequential_part(
8296
&nested,
@@ -175,6 +189,10 @@ impl<'a> AnalyzeContext<'a> {
175189
if let Some(label) = alternative_label {
176190
scope.add(label.define(self.arena, AnyEntKind::Label), diagnostics);
177191
}
192+
193+
// Pre-declare labels
194+
self.define_labels_for_concurrent_part(scope, statements, diagnostics)?;
195+
178196
if let Some(ref mut decl) = decl {
179197
self.analyze_declarative_part(scope, decl, diagnostics)?;
180198
}

vhdl_lang/src/analysis/declarative.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,11 @@ impl<'a> AnalyzeContext<'a> {
493493
};
494494
let subpgm_region = subpgm_region.with_parent(scope);
495495

496+
self.define_labels_for_sequential_part(
497+
&subpgm_region,
498+
&mut body.statements,
499+
diagnostics,
500+
)?;
496501
self.analyze_declarative_part(&subpgm_region, &mut body.declarations, diagnostics)?;
497502

498503
self.analyze_sequential_part(

vhdl_lang/src/analysis/design_unit.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ impl<'a> AnalyzeContext<'a> {
6161
if let Some(ref mut list) = unit.port_clause {
6262
self.analyze_interface_list(&primary_scope, list, diagnostics)?;
6363
}
64+
self.define_labels_for_concurrent_part(&primary_scope, &mut unit.statements, diagnostics)?;
6465
self.analyze_declarative_part(&primary_scope, &mut unit.decl, diagnostics)?;
6566
self.analyze_concurrent_part(&primary_scope, &mut unit.statements, diagnostics)?;
6667

@@ -239,6 +240,7 @@ impl<'a> AnalyzeContext<'a> {
239240
.explicit(unit.name().clone(), AnyEntKind::Label, Some(unit.pos())),
240241
);
241242

243+
self.define_labels_for_concurrent_part(&scope, &mut unit.statements, diagnostics)?;
242244
self.analyze_declarative_part(&scope, &mut unit.decl, diagnostics)?;
243245
self.analyze_concurrent_part(&scope, &mut unit.statements, diagnostics)?;
244246
scope.close(diagnostics);

vhdl_lang/src/analysis/sequential.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,68 @@ use region::*;
1616
use target::AssignmentType;
1717

1818
impl<'a> AnalyzeContext<'a> {
19+
pub fn define_labels_for_sequential_part(
20+
&self,
21+
scope: &Scope<'a>,
22+
statements: &mut [LabeledSequentialStatement],
23+
diagnostics: &mut dyn DiagnosticHandler,
24+
) -> FatalResult {
25+
for statement in statements.iter_mut() {
26+
if let Some(ref mut label) = statement.label {
27+
scope.add(label.define(self.arena, AnyEntKind::Label), diagnostics);
28+
}
29+
30+
match statement.statement {
31+
SequentialStatement::If(ref mut ifstmt) => {
32+
let IfStatement {
33+
conditionals,
34+
else_item,
35+
} = ifstmt;
36+
37+
for conditional in conditionals {
38+
self.define_labels_for_sequential_part(
39+
scope,
40+
&mut conditional.item,
41+
diagnostics,
42+
)?;
43+
}
44+
if let Some(else_item) = else_item {
45+
self.define_labels_for_sequential_part(scope, else_item, diagnostics)?;
46+
}
47+
}
48+
49+
SequentialStatement::Case(ref mut case_stmt) => {
50+
for alternative in case_stmt.alternatives.iter_mut() {
51+
self.define_labels_for_sequential_part(
52+
scope,
53+
&mut alternative.item,
54+
diagnostics,
55+
)?;
56+
}
57+
}
58+
SequentialStatement::Loop(ref mut loop_stmt) => {
59+
self.define_labels_for_sequential_part(
60+
scope,
61+
&mut loop_stmt.statements,
62+
diagnostics,
63+
)?;
64+
}
65+
_ => {
66+
// Does not have sequential part
67+
}
68+
}
69+
}
70+
71+
Ok(())
72+
}
73+
1974
fn analyze_sequential_statement(
2075
&self,
2176
scope: &Scope<'a>,
2277
sroot: &SequentialRoot<'a>,
2378
statement: &mut LabeledSequentialStatement,
2479
diagnostics: &mut dyn DiagnosticHandler,
2580
) -> FatalResult {
26-
if let Some(ref mut label) = statement.label {
27-
scope.add(self.arena.define(label, AnyEntKind::Label), diagnostics);
28-
}
29-
3081
match statement.statement {
3182
SequentialStatement::Return(ref mut ret) => {
3283
let ReturnStatement { ref mut expression } = ret.item;

vhdl_lang/src/analysis/tests/homographs.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,13 @@ end architecture;
850850
);
851851

852852
let diagnostics = builder.analyze();
853-
check_diagnostics(diagnostics, duplicates(&code, &["lab1", "lab2"]));
853+
check_diagnostics(
854+
diagnostics,
855+
vec![
856+
duplicate(&code, "lab1", 2, 1),
857+
duplicate(&code, "lab2", 2, 1),
858+
],
859+
);
854860
}
855861

856862
#[test]

vhdl_lang/src/analysis/tests/visibility.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,3 +698,62 @@ end function;
698698
Some(code.s("theproc", 2).pos())
699699
);
700700
}
701+
702+
#[test]
703+
fn labels_are_visible_in_declarative_region() {
704+
let mut builder = LibraryBuilder::new();
705+
let code = builder.code(
706+
"libname",
707+
"
708+
entity ent is
709+
end entity;
710+
711+
architecture a of ent is
712+
attribute debug : boolean;
713+
attribute debug of main : label is true;
714+
begin
715+
main: process
716+
begin
717+
wait;
718+
end process;
719+
end architecture;
720+
721+
",
722+
);
723+
let (root, diagnostics) = builder.get_analyzed_root();
724+
check_no_diagnostics(&diagnostics);
725+
let label = root
726+
.search_reference(code.source(), code.sa("debug of ", "main").start())
727+
.unwrap();
728+
assert_eq!(label.decl_pos(), Some(&code.sb("main", ": process").pos()));
729+
}
730+
731+
#[test]
732+
fn sequential_labels_are_visible_in_declarative_region() {
733+
let mut builder = LibraryBuilder::new();
734+
let code = builder.code(
735+
"libname",
736+
"
737+
entity ent is
738+
end entity;
739+
740+
architecture a of ent is
741+
begin
742+
process
743+
attribute debug : boolean;
744+
attribute debug of main : label is true;
745+
begin
746+
main: for i in 0 to 1 loop
747+
end loop;
748+
wait;
749+
end process;
750+
end architecture;
751+
",
752+
);
753+
let (root, diagnostics) = builder.get_analyzed_root();
754+
check_no_diagnostics(&diagnostics);
755+
let label = root
756+
.search_reference(code.source(), code.sa("debug of ", "main").start())
757+
.unwrap();
758+
assert_eq!(label.decl_pos(), Some(&code.sb("main", ": for i ").pos()));
759+
}

vhdl_lang/src/syntax/test.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ impl Code {
125125
self.in_range(range)
126126
}
127127

128+
// Creates a code from the first occurence for before + substr at the
129+
// position of substr
130+
pub fn sb(&self, substr: &str, after: &str) -> Code {
131+
self.s1(&format!("{substr}{after}")).s1(substr)
132+
}
133+
128134
pub fn pos(&self) -> SrcPos {
129135
self.pos.clone()
130136
}

0 commit comments

Comments
 (0)