Skip to content

Analyze Subprogram Instantiation Declarations #209

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 44 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
f821c10
Parse subprogram instantiation to declaration
Schottkyc137 Nov 2, 2023
443f074
Fix logic for identifier
Schottkyc137 Nov 2, 2023
d680637
Make item and token public
Schottkyc137 Nov 4, 2023
4a9ca46
Check kind mismatch and resolve declaration
Schottkyc137 Nov 4, 2023
a3352ad
revert accidentally deleted test
Schottkyc137 Nov 4, 2023
c22664d
Error on ambiguously instantiated subprograms
Schottkyc137 Nov 4, 2023
9a5eb04
Resolve overloaded uninstantiated subprograms
Schottkyc137 Nov 4, 2023
25a876a
return Err when the signature of the instantiated subprogram does not…
Schottkyc137 Nov 4, 2023
1081afb
Add comments
Schottkyc137 Nov 4, 2023
b6c935b
Disallow instantiating an instantiable subprogram
Schottkyc137 Nov 4, 2023
bfce17e
Disallow instantiating a non-instantiable subprogram
Schottkyc137 Nov 4, 2023
6a3e6ee
Disallow calling an uninstantiated subprogram
Schottkyc137 Nov 4, 2023
268d7f1
Disambiguate based on uninstantiated subprogram
Schottkyc137 Nov 5, 2023
9354884
Fix: no longer always complain when instantiating a function
Schottkyc137 Nov 5, 2023
7119d2b
Merge branch 'master' into analyze-instantiation-statement
Schottkyc137 Nov 6, 2023
e695f04
Merge remote-tracking branch 'origin/master' into analyze-instantiati…
Schottkyc137 Nov 11, 2023
3540726
Merge remote-tracking branch 'origin/master' into analyze-instantiati…
Schottkyc137 Nov 12, 2023
ef8bd2a
Merge master aftermath
Schottkyc137 Nov 12, 2023
1820398
Revert: Signature no longer contains optional generic map
Schottkyc137 Nov 15, 2023
5619678
Refactor boolean to two-state enum
Schottkyc137 Nov 15, 2023
4a2892b
Refactor: Region to GpkgRegion
Schottkyc137 Nov 15, 2023
f7a05a3
Refactor: subprogram instantiation to own function
Schottkyc137 Nov 15, 2023
ff9257f
Revert: Use region instead of GpkgRegion
Schottkyc137 Nov 15, 2023
3e53448
Instantiate subprograms
Schottkyc137 Nov 18, 2023
31d8b9a
Remove debug print
Schottkyc137 Nov 18, 2023
a34c1ca
Refactor into more generic code
Schottkyc137 Nov 18, 2023
93bc41f
Inline check_ent_is_uninstantiated_subprogram
Schottkyc137 Nov 18, 2023
6c86b46
Fill in todos and false unreachable calls
Schottkyc137 Nov 18, 2023
2bc87bc
Add documentation
Schottkyc137 Nov 18, 2023
0b5be76
Add more checks to subprogram instance testcase
Schottkyc137 Nov 18, 2023
c603aae
Set reference to the uninstantiated subprogram
Schottkyc137 Nov 18, 2023
0ed44d8
Fix: Analyze the return of a function type in the correct scope
Schottkyc137 Nov 18, 2023
6a4711c
Add subprogram instance tests for future improvements
Schottkyc137 Nov 18, 2023
6a95128
Enable subprogram declarations as reference to the overloaded entity
Schottkyc137 Nov 18, 2023
bdc8ff7
Add comment explaining the limitations of the current uninstantiated …
Schottkyc137 Nov 18, 2023
095559c
Rename is_uninst* for less ambiguity
Schottkyc137 Nov 18, 2023
fc149f9
Revert making fields public
Schottkyc137 Nov 18, 2023
6faa616
Revert accidental change
Schottkyc137 Nov 18, 2023
1d558a2
Merge remote-tracking branch 'origin/master' into analyze-instantiati…
Schottkyc137 Nov 18, 2023
4b959c0
Improve test case and add other ognored one
Schottkyc137 Nov 18, 2023
93c2d84
Add copyright header
Schottkyc137 Nov 19, 2023
9414fff
Refactor SignatureKey to SubprogramKey
Schottkyc137 Nov 19, 2023
d9e7070
Merge branch 'master' of https://github.com/VHDL-LS/rust_hdl into ana…
Schottkyc137 Nov 19, 2023
ffcc735
Add uninstantiated subprograms to checked declarations
Schottkyc137 Nov 19, 2023
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
363 changes: 338 additions & 25 deletions vhdl_lang/src/analysis/declarative.rs

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions vhdl_lang/src/analysis/overloaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,21 @@ impl<'a> AnalyzeContext<'a> {
return Err(EvalError::Unknown);
}

// Disambiguate based on uninstantiated subprogram
ok_kind.retain(|ent| !ent.is_uninst_subprogram());

if ok_kind.len() == 1 {
let ent = ok_kind[0];
self.check_call(scope, call_pos, ent, assocs, diagnostics)?;
return Ok(Disambiguated::Unambiguous(ent));
} else if ok_kind.is_empty() {
diagnostics.push(Diagnostic::error(
call_name,
format!("uninstantiated subprogram {} cannot be called", call_name),
));
return Err(EvalError::Unknown);
}

let ok_formals = self.disambiguate_by_assoc_formals(scope, call_pos, &ok_kind, assocs)?;

// Only one candidate matched actual/formal profile
Expand Down
132 changes: 81 additions & 51 deletions vhdl_lang/src/analysis/package_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,56 @@
//! Copyright (c) 2023, Olof Kraigher [email protected]

use fnv::FnvHashMap;
use vhdl_lang::SrcPos;

use super::analyze::*;
use super::names::ResolvedName;
use super::scope::*;
use crate::ast::ActualPart;
use crate::ast::AssociationElement;
use crate::ast::Expression;
use crate::ast::Literal;
use crate::ast::Name;
use crate::ast::Operator;
use crate::ast::PackageInstantiation;
use crate::ast::{ActualPart, MapAspect};
use crate::data::DiagnosticHandler;
use crate::named_entity::*;
use crate::Diagnostic;
use crate::NullDiagnostics;

impl<'a> AnalyzeContext<'a> {
fn package_generic_map(
pub fn generic_package_instance(
&self,
scope: &Scope<'a>,
package_ent: EntRef<'a>,
unit: &mut PackageInstantiation,
diagnostics: &mut dyn DiagnosticHandler,
) -> EvalResult<Region<'a>> {
let PackageInstantiation {
package_name,
generic_map,
..
} = unit;

match self.analyze_package_instance_name(scope, package_name) {
Ok(package_region) => self
.generic_instance(
package_ent,
scope,
&unit.ident.tree.pos,
package_region,
generic_map,
diagnostics,
)
.map(|(region, _)| region),
Err(err) => {
diagnostics.push(err.into_non_fatal()?);
Err(EvalError::Unknown)
}
}
}

pub fn generic_map(
&self,
scope: &Scope<'a>,
generics: GpkgRegion<'a>,
Expand Down Expand Up @@ -124,7 +156,7 @@ impl<'a> AnalyzeContext<'a> {
let resolved =
self.name_resolve(scope, &assoc.actual.pos, name, diagnostics)?;
if let ResolvedName::Overloaded(des, overloaded) = resolved {
let signature = target.signature().key().map(|base_type| {
let signature = target.subprogram_key().map(|base_type| {
mapping
.get(&base_type.id())
.map(|ent| ent.base())
Expand All @@ -139,7 +171,7 @@ impl<'a> AnalyzeContext<'a> {
"Cannot map '{}' to subprogram generic {}{}",
des,
target.designator(),
signature.describe()
signature.key().describe()
),
);

Expand Down Expand Up @@ -188,62 +220,50 @@ impl<'a> AnalyzeContext<'a> {
Ok(mapping)
}

pub fn generic_package_instance(
pub fn generic_instance(
&self,
ent: EntRef<'a>,
scope: &Scope<'a>,
package_ent: EntRef<'a>,
unit: &mut PackageInstantiation,
decl_pos: &SrcPos,
uninst_region: &Region<'a>,
generic_map: &mut Option<MapAspect>,
diagnostics: &mut dyn DiagnosticHandler,
) -> EvalResult<Region<'a>> {
let PackageInstantiation {
package_name,
generic_map,
..
} = unit;
) -> EvalResult<(Region<'a>, FnvHashMap<EntityId, TypeEnt>)> {
let nested = scope.nested().in_package_declaration();
let (generics, other) = uninst_region.to_package_generic();

let mapping = if let Some(generic_map) = generic_map {
self.generic_map(
&nested,
generics,
generic_map.list.items.as_mut_slice(),
diagnostics,
)?
} else {
FnvHashMap::default()
};

match self.analyze_package_instance_name(scope, package_name) {
Ok(package_region) => {
let nested = scope.nested().in_package_declaration();
let (generics, other) = package_region.to_package_generic();

let mapping = if let Some(generic_map) = generic_map {
self.package_generic_map(
&nested,
generics,
generic_map.list.items.as_mut_slice(),
diagnostics,
)?
} else {
FnvHashMap::default()
};

for uninst in other {
match self.instantiate(Some(package_ent), &mapping, uninst) {
Ok(inst) => {
// We ignore diagnostics here, for example when adding implicit operators EQ and NE for interface types
// They can collide if there are more than one interface type that map to the same actual type
nested.add(inst, &mut NullDiagnostics);
}
Err(err) => {
let mut diag = Diagnostic::error(&unit.ident.tree.pos, err);
if let Some(pos) = uninst.decl_pos() {
diag.add_related(pos, "When instantiating this declaration");
}
diagnostics.push(diag);
}
for uninst in other {
match self.instantiate(Some(ent), &mapping, uninst) {
Ok(inst) => {
// We ignore diagnostics here, for example when adding implicit operators EQ and NE for interface types
// They can collide if there are more than one interface type that map to the same actual type
nested.add(inst, &mut NullDiagnostics);
}
Err(err) => {
let mut diag = Diagnostic::error(decl_pos, err);
if let Some(pos) = uninst.decl_pos() {
diag.add_related(pos, "When instantiating this declaration");
}
diagnostics.push(diag);
}

Ok(nested.into_region())
}
Err(err) => {
diagnostics.push(err.into_non_fatal()?);
Err(EvalError::Unknown)
}
}

Ok((nested.into_region(), mapping))
}

fn instantiate(
pub(crate) fn instantiate(
&self,
parent: Option<EntRef<'a>>,
mapping: &FnvHashMap<EntityId, TypeEnt<'a>>,
Expand Down Expand Up @@ -358,6 +378,16 @@ impl<'a> AnalyzeContext<'a> {
Overloaded::Subprogram(signature) => {
Overloaded::Subprogram(self.map_signature(parent, mapping, signature)?)
}
Overloaded::UninstSubprogramDecl(signature, generic_map) => {
Overloaded::UninstSubprogramDecl(
self.map_signature(parent, mapping, signature)?,
generic_map.clone(),
)
}
Overloaded::UninstSubprogram(signature, generic_map) => Overloaded::UninstSubprogram(
self.map_signature(parent, mapping, signature)?,
generic_map.clone(),
),
Overloaded::InterfaceSubprogram(signature) => {
Overloaded::InterfaceSubprogram(self.map_signature(parent, mapping, signature)?)
}
Expand All @@ -379,7 +409,7 @@ impl<'a> AnalyzeContext<'a> {
})
}

fn map_signature(
pub(crate) fn map_signature(
&self,
parent: Option<EntRef<'a>>,
mapping: &FnvHashMap<EntityId, TypeEnt<'a>>,
Expand Down
5 changes: 5 additions & 0 deletions vhdl_lang/src/analysis/semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ impl<'a> AnalyzeContext<'a> {
}
}
diagnostics.push(diagnostic);
} else if ent.is_uninst_subprogram_body() {
diagnostics.error(
&name.pos,
format!("uninstantiated {} cannot be called", ent.describe()),
)
}
}
None => {}
Expand Down
1 change: 0 additions & 1 deletion vhdl_lang/src/analysis/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,6 @@ impl<'a> AnalyzeContext<'a> {

fn binary(
&self,

op: Operator,
implicit_of: TypeEnt<'a>,
left: TypeEnt<'a>,
Expand Down
1 change: 1 addition & 0 deletions vhdl_lang/src/analysis/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod resolves_names;
mod resolves_type_mark;
mod sensitivity_list;
mod subprogram_arguments;
mod subprogram_instance;
mod tool_directive;
mod typecheck_expression;
mod util;
Expand Down
Loading