Skip to content

Commit d117beb

Browse files
committed
Analyze formals when instantiating, provides references to ports/generics
1 parent d2fe287 commit d117beb

File tree

8 files changed

+641
-29
lines changed

8 files changed

+641
-29
lines changed

vhdl_lang/src/analysis/concurrent.rs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,38 +191,70 @@ impl<'a> AnalyzeContext<'a> {
191191
match instance.unit {
192192
// @TODO architecture
193193
InstantiatedUnit::Entity(ref mut entity_name, ..) => {
194-
fn is_entity(kind: &NamedEntityKind) -> bool {
195-
matches!(kind, NamedEntityKind::Entity(..))
196-
}
197-
198194
if let Err(err) =
199195
self.resolve_selected_name(parent, entity_name)
200196
.and_then(|entities| {
201-
self.resolve_non_overloaded_with_kind(
197+
let expected = "entity";
198+
let ent = self.resolve_non_overloaded(
202199
entities,
203200
entity_name.suffix_pos(),
204-
&is_entity,
205-
"entity",
206-
)
201+
expected,
202+
)?;
203+
204+
if let NamedEntityKind::Entity(ent_region) = ent.kind() {
205+
self.analyze_assoc_elems_with_formal_region(
206+
ent_region,
207+
parent,
208+
&mut instance.generic_map,
209+
diagnostics,
210+
)?;
211+
self.analyze_assoc_elems_with_formal_region(
212+
ent_region,
213+
parent,
214+
&mut instance.port_map,
215+
diagnostics,
216+
)?;
217+
Ok(())
218+
} else {
219+
Err(AnalysisError::NotFatal(
220+
ent.kind_error(entity_name.suffix_pos(), expected),
221+
))
222+
}
207223
})
208224
{
209225
err.add_to(diagnostics)?;
210226
}
211227
}
212228
InstantiatedUnit::Component(ref mut component_name) => {
213-
fn is_component(kind: &NamedEntityKind) -> bool {
214-
matches!(kind, NamedEntityKind::Component)
215-
}
216-
217229
if let Err(err) =
218230
self.resolve_selected_name(parent, component_name)
219231
.and_then(|entities| {
220-
self.resolve_non_overloaded_with_kind(
232+
let expected = "component";
233+
let ent = self.resolve_non_overloaded(
221234
entities,
222235
component_name.suffix_pos(),
223-
&is_component,
224-
"component",
225-
)
236+
expected,
237+
)?;
238+
239+
if let NamedEntityKind::Component(ent_region) = ent.kind() {
240+
self.analyze_assoc_elems_with_formal_region(
241+
ent_region,
242+
parent,
243+
&mut instance.generic_map,
244+
diagnostics,
245+
)?;
246+
self.analyze_assoc_elems_with_formal_region(
247+
ent_region,
248+
parent,
249+
&mut instance.port_map,
250+
diagnostics,
251+
)?;
252+
Ok(())
253+
} else {
254+
Err(AnalysisError::NotFatal(
255+
ent.kind_error(component_name.suffix_pos(), expected),
256+
))
257+
}
226258
})
227259
{
228260
err.add_to(diagnostics)?;
@@ -246,12 +278,12 @@ impl<'a> AnalyzeContext<'a> {
246278
{
247279
err.add_to(diagnostics)?;
248280
}
281+
282+
self.analyze_assoc_elems(parent, &mut instance.generic_map, diagnostics)?;
283+
self.analyze_assoc_elems(parent, &mut instance.port_map, diagnostics)?;
249284
}
250285
};
251286

252-
self.analyze_assoc_elems(parent, &mut instance.generic_map, diagnostics)?;
253-
self.analyze_assoc_elems(parent, &mut instance.port_map, diagnostics)?;
254-
255287
Ok(())
256288
}
257289
}

vhdl_lang/src/analysis/declarative.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,23 @@ impl<'a> AnalyzeContext<'a> {
303303
region.add(ident.clone(), NamedEntityKind::File, diagnostics);
304304
}
305305
Declaration::Component(ref mut component) => {
306-
region.add(&component.ident, NamedEntityKind::Component, diagnostics);
307-
let mut region = region.nested();
308-
self.analyze_interface_list(&mut region, &mut component.generic_list, diagnostics)?;
309-
self.analyze_interface_list(&mut region, &mut component.port_list, diagnostics)?;
310-
region.close(diagnostics);
306+
let mut component_region = region.nested();
307+
self.analyze_interface_list(
308+
&mut component_region,
309+
&mut component.generic_list,
310+
diagnostics,
311+
)?;
312+
self.analyze_interface_list(
313+
&mut component_region,
314+
&mut component.port_list,
315+
diagnostics,
316+
)?;
317+
component_region.close(diagnostics);
318+
region.add(
319+
&component.ident,
320+
NamedEntityKind::Component(component_region.without_parent()),
321+
diagnostics,
322+
);
311323
}
312324
Declaration::Attribute(ref mut attr) => match attr {
313325
Attribute::Declaration(ref mut attr_decl) => {

vhdl_lang/src/analysis/named_entity.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub enum NamedEntityKind {
9999
},
100100
File,
101101
InterfaceFile(TypeEnt),
102-
Component,
102+
Component(Region<'static>),
103103
Attribute,
104104
SubprogramDecl(Signature),
105105
Subprogram(Signature),
@@ -163,7 +163,7 @@ impl NamedEntityKind {
163163
File => "file",
164164
InterfaceFile(..) => "file",
165165
ElementDeclaration(..) => "element declaration",
166-
Component => "component",
166+
Component(..) => "component",
167167
Attribute => "attribute",
168168
SubprogramDecl(signature) | Subprogram(signature) => {
169169
if signature.return_type.is_some() {

vhdl_lang/src/analysis/semantic.rs

Lines changed: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,228 @@ impl<'a> AnalyzeContext<'a> {
416416
Ok(())
417417
}
418418

419+
pub fn resolve_formal_name(
420+
&self,
421+
formal_region: &Region<'_>,
422+
region: &Region<'_>,
423+
name_pos: &SrcPos,
424+
name: &mut Name,
425+
diagnostics: &mut dyn DiagnosticHandler,
426+
) -> FatalResult<Option<NamedEntities>> {
427+
match name {
428+
Name::Selected(prefix, suffix) => {
429+
suffix.clear_reference();
430+
431+
match self.resolve_formal_name(
432+
formal_region,
433+
region,
434+
&prefix.pos,
435+
&mut prefix.item,
436+
diagnostics,
437+
)? {
438+
Some(NamedEntities::Single(ref named_entity)) => {
439+
match self.lookup_selected(&prefix.pos, named_entity, suffix) {
440+
Ok(visible) => {
441+
suffix.set_reference(&visible);
442+
Ok(Some(visible))
443+
}
444+
Err(err) => {
445+
err.add_to(diagnostics)?;
446+
Ok(None)
447+
}
448+
}
449+
}
450+
Some(NamedEntities::Overloaded(..)) => Ok(None),
451+
None => Ok(None),
452+
}
453+
}
454+
455+
Name::SelectedAll(_) => {
456+
diagnostics.error(name_pos, "Invalid formal");
457+
Ok(None)
458+
}
459+
Name::Designator(designator) => {
460+
designator.clear_reference();
461+
match formal_region.lookup_within(name_pos, designator.designator()) {
462+
Ok(visible) => {
463+
designator.set_reference(&visible);
464+
Ok(Some(visible))
465+
}
466+
Err(diagnostic) => {
467+
diagnostics.push(diagnostic);
468+
Ok(None)
469+
}
470+
}
471+
}
472+
Name::Indexed(ref mut prefix, ref mut exprs) => {
473+
self.resolve_formal_name(
474+
formal_region,
475+
region,
476+
&prefix.pos,
477+
&mut prefix.item,
478+
diagnostics,
479+
)?;
480+
for expr in exprs.iter_mut() {
481+
self.analyze_expression(region, expr, diagnostics)?;
482+
}
483+
Ok(None)
484+
}
485+
486+
Name::Slice(ref mut prefix, ref mut drange) => {
487+
self.resolve_formal_name(
488+
formal_region,
489+
region,
490+
&prefix.pos,
491+
&mut prefix.item,
492+
diagnostics,
493+
)?;
494+
self.analyze_discrete_range(region, drange.as_mut(), diagnostics)?;
495+
Ok(None)
496+
}
497+
Name::Attribute(..) => {
498+
diagnostics.error(name_pos, "Invalid formal");
499+
Ok(None)
500+
}
501+
Name::FunctionCall(ref mut fcall) => {
502+
let prefix = if let Some(prefix) = fcall.name.item.prefix() {
503+
prefix
504+
} else {
505+
diagnostics.error(name_pos, "Invalid formal");
506+
return Ok(None);
507+
};
508+
509+
if formal_region
510+
.lookup_within(name_pos, prefix.designator())
511+
.is_err()
512+
{
513+
// The prefix of the name was not found in the formal region
514+
// it must be a type conversion or a single parameter function call
515+
self.resolve_name(region, &fcall.name.pos, &mut fcall.name.item, diagnostics)?;
516+
// @TODO check is type cast or function call
517+
518+
if let &mut [AssociationElement {
519+
ref formal,
520+
ref mut actual,
521+
}] = &mut fcall.parameters[..]
522+
{
523+
if formal.is_some() {
524+
diagnostics.error(name_pos, "Invalid formal conversion");
525+
} else if let ActualPart::Expression(Expression::Name(
526+
ref mut actual_name,
527+
)) = actual.item
528+
{
529+
self.resolve_formal_name(
530+
formal_region,
531+
region,
532+
&actual.pos,
533+
actual_name.as_mut(),
534+
diagnostics,
535+
)?;
536+
}
537+
} else {
538+
diagnostics.error(name_pos, "Invalid formal conversion");
539+
}
540+
} else {
541+
match self.resolve_formal_name(
542+
formal_region,
543+
region,
544+
&fcall.name.pos,
545+
&mut fcall.name.item,
546+
diagnostics,
547+
)? {
548+
Some(NamedEntities::Single(ent)) => {
549+
if ent.actual_kind().is_type() {
550+
// A type conversion
551+
// @TODO Ignore for now
552+
self.analyze_assoc_elems(
553+
region,
554+
&mut fcall.parameters,
555+
diagnostics,
556+
)?;
557+
} else if let Some(indexed_name) = fcall.to_indexed() {
558+
*name = indexed_name;
559+
560+
if let Name::Indexed(ref mut prefix, ref mut indexes) = name {
561+
if let Some(type_mark) = type_mark_of_sliced_or_indexed(&ent) {
562+
if let Err(err) = self.analyze_indexed_name(
563+
region,
564+
name_pos,
565+
prefix.suffix_pos(),
566+
type_mark,
567+
indexes,
568+
diagnostics,
569+
) {
570+
err.add_to(diagnostics)?;
571+
}
572+
} else {
573+
diagnostics.error(
574+
prefix.suffix_pos(),
575+
format!("{} cannot be indexed", ent.describe()),
576+
)
577+
}
578+
}
579+
} else {
580+
diagnostics.push(Diagnostic::error(
581+
&fcall.name.pos,
582+
format!(
583+
"{} cannot be the prefix of a function call",
584+
ent.describe()
585+
),
586+
));
587+
588+
self.analyze_assoc_elems(
589+
region,
590+
&mut fcall.parameters,
591+
diagnostics,
592+
)?;
593+
}
594+
}
595+
Some(NamedEntities::Overloaded(..)) => {
596+
// @TODO check function arguments
597+
self.analyze_assoc_elems(region, &mut fcall.parameters, diagnostics)?;
598+
}
599+
None => {
600+
self.analyze_assoc_elems(region, &mut fcall.parameters, diagnostics)?;
601+
}
602+
};
603+
}
604+
605+
Ok(None)
606+
}
607+
Name::External(..) => {
608+
diagnostics.error(name_pos, "Invalid formal");
609+
Ok(None)
610+
}
611+
}
612+
}
613+
614+
pub fn analyze_assoc_elems_with_formal_region(
615+
&self,
616+
formal_region: &Region<'_>,
617+
region: &Region<'_>,
618+
elems: &mut [AssociationElement],
619+
diagnostics: &mut dyn DiagnosticHandler,
620+
) -> FatalNullResult {
621+
for AssociationElement { formal, actual } in elems.iter_mut() {
622+
if let Some(ref mut formal) = formal {
623+
self.resolve_formal_name(
624+
formal_region,
625+
region,
626+
&formal.pos,
627+
&mut formal.item,
628+
diagnostics,
629+
)?;
630+
}
631+
match actual.item {
632+
ActualPart::Expression(ref mut expr) => {
633+
self.analyze_expression_pos(region, &actual.pos, expr, diagnostics)?;
634+
}
635+
ActualPart::Open => {}
636+
}
637+
}
638+
Ok(())
639+
}
640+
419641
pub fn analyze_function_call(
420642
&self,
421643
region: &Region<'_>,
@@ -1103,7 +1325,7 @@ impl Diagnostic {
11031325
}
11041326

11051327
impl NamedEntity {
1106-
fn kind_error(&self, pos: &SrcPos, expected: &str) -> Diagnostic {
1328+
pub fn kind_error(&self, pos: &SrcPos, expected: &str) -> Diagnostic {
11071329
let mut error = Diagnostic::error(
11081330
pos,
11091331
format!("Expected {}, got {}", expected, self.describe()),

0 commit comments

Comments
 (0)