Skip to content

Add baseline analysis and completions for simple external names #383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions vhdl_lang/src/analysis/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<'a> AnalyzeContext<'a, '_> {
let ent = self.arena.explicit(
label.name(),
parent,
AnyEntKind::Concurrent(statement.statement.item.label_typ()),
AnyEntKind::Concurrent(statement.statement.item.label_typ(), Region::default()),
Some(label.pos(self.ctx)),
span,
Some(self.source()),
Expand All @@ -61,7 +61,7 @@ impl<'a> AnalyzeContext<'a, '_> {
scope.anonymous_designator(),
Some(parent),
Related::None,
AnyEntKind::Concurrent(statement.statement.item.label_typ()),
AnyEntKind::Concurrent(statement.statement.item.label_typ(), Region::default()),
None,
span,
Some(self.source()),
Expand Down Expand Up @@ -108,6 +108,13 @@ impl<'a> AnalyzeContext<'a, '_> {
)?;
self.analyze_declarative_part(&nested, parent, &mut block.decl, diagnostics)?;
self.analyze_concurrent_part(&nested, parent, &mut block.statements, diagnostics)?;
let ent = self.arena.get(statement.label.decl.get().unwrap());
unsafe {
ent.set_kind(AnyEntKind::Concurrent(
Some(Concurrent::Block),
nested.into_region(),
));
}
}
ConcurrentStatement::Process(ref mut process) => {
let ProcessStatement {
Expand All @@ -130,6 +137,13 @@ impl<'a> AnalyzeContext<'a, '_> {
self.define_labels_for_sequential_part(&nested, parent, statements, diagnostics)?;
self.analyze_declarative_part(&nested, parent, decl, diagnostics)?;
self.analyze_sequential_part(&nested, parent, statements, diagnostics)?;
let ent = self.arena.get(statement.label.decl.get().unwrap());
unsafe {
ent.set_kind(AnyEntKind::Concurrent(
Some(Concurrent::Process),
nested.into_region(),
));
}
}
ConcurrentStatement::ForGenerate(ref mut gen) => {
let ForGenerateStatement {
Expand All @@ -153,6 +167,13 @@ impl<'a> AnalyzeContext<'a, '_> {
diagnostics,
);
self.analyze_generate_body(&nested, parent, body, src_span, diagnostics)?;
let ent = self.arena.get(statement.label.decl.get().unwrap());
unsafe {
ent.set_kind(AnyEntKind::Concurrent(
Some(Concurrent::Generate),
nested.into_region(),
));
}
}
ConcurrentStatement::IfGenerate(ref mut gen) => {
let Conditionals {
Expand Down Expand Up @@ -248,7 +269,7 @@ impl<'a> AnalyzeContext<'a, '_> {
self.ctx,
self.arena,
parent,
AnyEntKind::Concurrent(Some(Concurrent::Generate)),
AnyEntKind::Concurrent(Some(Concurrent::Generate), Region::default()),
span,
Some(self.source()),
);
Expand Down
42 changes: 22 additions & 20 deletions vhdl_lang/src/analysis/declarative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,26 @@ impl Declaration {
match parent {
// LRM: block_declarative_item
AnyEntKind::Design(Design::Architecture(..))
| AnyEntKind::Concurrent(Some(Concurrent::Block | Concurrent::Generate)) => matches!(
self,
Object(ObjectDeclaration {
class: Constant | Signal | SharedVariable,
..
}) | File(_)
| Type(_)
| Component(_)
| Attribute(_)
| Alias(_)
| SubprogramDeclaration(_)
| SubprogramInstantiation(_)
| SubprogramBody(_)
| Use(_)
| Package(_)
| Configuration(_)
| View(_)
),
| AnyEntKind::Concurrent(Some(Concurrent::Block | Concurrent::Generate), _) => {
matches!(
self,
Object(ObjectDeclaration {
class: Constant | Signal | SharedVariable,
..
}) | File(_)
| Type(_)
| Component(_)
| Attribute(_)
| Alias(_)
| SubprogramDeclaration(_)
| SubprogramInstantiation(_)
| SubprogramBody(_)
| Use(_)
| Package(_)
| Configuration(_)
| View(_)
)
}
// LRM: configuration_declarative_item
AnyEntKind::Design(Design::Configuration) => {
matches!(self, Use(_) | Attribute(ast::Attribute::Specification(_)))
Expand Down Expand Up @@ -92,7 +94,7 @@ impl Declaration {
| Overloaded::UninstSubprogramDecl(..)
| Overloaded::UninstSubprogram(..),
)
| AnyEntKind::Concurrent(Some(Concurrent::Process))
| AnyEntKind::Concurrent(Some(Concurrent::Process), _)
| AnyEntKind::Type(named_entity::Type::Protected(..)) => matches!(
self,
Object(ObjectDeclaration {
Expand Down Expand Up @@ -1261,7 +1263,7 @@ fn get_entity_class(ent: EntRef<'_>) -> Option<EntityClass> {
AnyEntKind::Type(Type::Subtype(_)) => Some(EntityClass::Subtype),
AnyEntKind::Type(_) => Some(EntityClass::Type),
AnyEntKind::ElementDeclaration(_) => None,
AnyEntKind::Concurrent(_) => Some(EntityClass::Label),
AnyEntKind::Concurrent(..) => Some(EntityClass::Label),
AnyEntKind::Sequential(_) => Some(EntityClass::Label),
AnyEntKind::Object(obj) => match obj.class {
ObjectClass::Signal => Some(EntityClass::Signal),
Expand Down
76 changes: 63 additions & 13 deletions vhdl_lang/src/analysis/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl<'a> ResolvedName<'a> {
AnyEntKind::Library
| AnyEntKind::Attribute(_)
| AnyEntKind::ElementDeclaration(_)
| AnyEntKind::Concurrent(_)
| AnyEntKind::Concurrent(..)
| AnyEntKind::Sequential(_)
| AnyEntKind::LoopParameter(_) => {
return Err((
Expand Down Expand Up @@ -258,7 +258,7 @@ impl<'a> ResolvedName<'a> {
| AnyEntKind::View(_)
| AnyEntKind::InterfaceFile(_)
| AnyEntKind::Component(_)
| AnyEntKind::Concurrent(_)
| AnyEntKind::Concurrent(..)
| AnyEntKind::Sequential(_)
| AnyEntKind::LoopParameter(_)
| AnyEntKind::PhysicalLiteral(_) => ResolvedName::Final(ent),
Expand Down Expand Up @@ -1273,8 +1273,40 @@ impl<'a> AnalyzeContext<'a, '_> {
});
}
SplitName::External(ename) => {
let ExternalName { subtype, class, .. } = ename;
let ExternalName {
subtype,
class,
path,
..
} = ename;
let subtype = self.resolve_subtype_indication(scope, subtype, diagnostics)?;
match self.resolve_external_path(scope, path, diagnostics)? {
Some(ResolvedName::ObjectName(obj)) => {
if !self.can_be_target_type(obj.type_mark(), subtype.base()) {
diagnostics.push(Diagnostic::type_mismatch(
&path.pos(self.ctx),
&obj.describe_type(),
subtype.type_mark(),
))
}
if *class != obj.base.class().into() {
diagnostics.push(Diagnostic::new(
path.pos(self.ctx),
format!("class {} does not match {}", *class, obj.base.class()),
ErrorCode::MismatchedObjectClass,
))
}
}
None => {
// ignore; we do not analyze this yet
}
_ => {
diagnostics.push(Diagnostic::mismatched_kinds(
path.pos(self.ctx),
"External path must point to a constant, variable or signal",
));
}
}
return Ok(ResolvedName::ObjectName(ObjectName {
base: ObjectBase::ExternalName(*class),
type_mark: Some(subtype.type_mark().to_owned()),
Expand Down Expand Up @@ -1583,6 +1615,24 @@ impl<'a> AnalyzeContext<'a, '_> {
Ok(resolved)
}

// Currently, only resolves Package name
fn resolve_external_path(
&self,
scope: &Scope<'a>,
path: &mut WithTokenSpan<ExternalPath>,
diagnostics: &mut dyn DiagnosticHandler,
) -> EvalResult<Option<ResolvedName<'a>>> {
match &mut path.item {
ExternalPath::Package(pkg) => Ok(Some(self.name_resolve(
scope,
pkg.span,
&mut pkg.item,
diagnostics,
)?)),
_ => Ok(None),
}
}

// Helper function:
// Resolve a name that must be some kind of object selection, index or slice
// Such names occur as assignment targets and aliases
Expand Down Expand Up @@ -2251,7 +2301,7 @@ constant c0 : rec_t := (others => 0);
",
);

assert_matches!(test.name_resolve(&test.snippet("c0.field"), None, &mut NoDiagnostics),
assert_matches!(test.name_resolve(&test.snippet("c0.field"), None, &mut NoDiagnostics),
Ok(ResolvedName::ObjectName(oname)) if oname.type_mark() == test.lookup_type("natural"));
}

Expand Down Expand Up @@ -2493,7 +2543,7 @@ type enum2_t is (alpha, beta);
test.declarative_part(
"
type ptr_t is access integer_vector;
variable vptr : ptr_t;
variable vptr : ptr_t;
",
);
let code = test.snippet("vptr(0 to 1)");
Expand All @@ -2509,7 +2559,7 @@ variable vptr : ptr_t;
test.declarative_part(
"
type ptr_t is access integer_vector;
variable vptr : ptr_t;
variable vptr : ptr_t;
",
);
let code = test.snippet("vptr(0)");
Expand Down Expand Up @@ -2637,7 +2687,7 @@ variable c0 : arr_t;
let test = TestSetup::new();
test.declarative_part(
"
type arr_t is array (integer range 0 to 3) of integer;
type arr_t is array (integer range 0 to 3) of integer;
",
);
let code = test.snippet("arr_t'left");
Expand All @@ -2654,7 +2704,7 @@ type arr_t is array (integer range 0 to 3) of integer;
let test = TestSetup::new();
test.declarative_part(
"
type arr_t is array (integer range 0 to 3, character range 'a' to 'c') of integer;
type arr_t is array (integer range 0 to 3, character range 'a' to 'c') of integer;
",
);
let code = test.snippet("arr_t'left(1)");
Expand Down Expand Up @@ -2710,7 +2760,7 @@ type arr_t is array (integer range 0 to 3, character range 'a' to 'c') of intege

test.declarative_part(
"
type arr_t is array (integer range 0 to 3) of integer;
type arr_t is array (integer range 0 to 3) of integer;
",
);

Expand All @@ -2729,7 +2779,7 @@ type arr_t is array (integer range 0 to 3) of integer;

test.declarative_part(
"
type arr_t is array (integer range 0 to 3) of integer;
type arr_t is array (integer range 0 to 3) of integer;
constant c0 : arr_t := (others => 0);
",
);
Expand All @@ -2749,7 +2799,7 @@ constant c0 : arr_t := (others => 0);

test.declarative_part(
"
type arr_t is array (integer range 0 to 3) of integer;
type arr_t is array (integer range 0 to 3) of integer;
constant c0 : arr_t := (others => 0);
",
);
Expand Down Expand Up @@ -2954,7 +3004,7 @@ variable thevar : integer;
let test = TestSetup::new();
test.declarative_part(
"
signal thesig : integer;
signal thesig : integer;
",
);

Expand Down Expand Up @@ -3100,7 +3150,7 @@ variable thevar : integer;
let test = TestSetup::new();
test.declarative_part(
"
signal thesig : integer;
signal thesig : integer;
",
);

Expand Down
4 changes: 3 additions & 1 deletion vhdl_lang/src/analysis/package_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ impl<'a> AnalyzeContext<'a, '_> {
AnyEntKind::ElementDeclaration(self.map_subtype(mapping, *subtype, scope))
}
AnyEntKind::Sequential(s) => AnyEntKind::Sequential(*s),
AnyEntKind::Concurrent(c) => AnyEntKind::Concurrent(*c),
AnyEntKind::Concurrent(c, region) => {
AnyEntKind::Concurrent(*c, self.map_region(parent, mapping, region, scope)?)
}
AnyEntKind::Object(obj) => AnyEntKind::Object(self.map_object(mapping, obj, scope)),
AnyEntKind::LoopParameter(typ) => AnyEntKind::LoopParameter(
typ.map(|typ| self.map_type_ent(mapping, typ.into(), scope).base()),
Expand Down
2 changes: 1 addition & 1 deletion vhdl_lang/src/analysis/sequential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ impl<'a> From<EntRef<'a>> for SequentialRoot<'a> {
SequentialRoot::Process
}
}
AnyEntKind::Concurrent(Some(Concurrent::Process)) => SequentialRoot::Process,
AnyEntKind::Concurrent(Some(Concurrent::Process), _) => SequentialRoot::Process,
_ => SequentialRoot::Process,
}
}
Expand Down
Loading