Skip to content

Commit 41835e9

Browse files
committed
Typecheck multi dimensional array aggregates
1 parent f81dcae commit 41835e9

File tree

2 files changed

+67
-17
lines changed

2 files changed

+67
-17
lines changed

vhdl_lang/src/analysis/expression.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -835,20 +835,15 @@ impl<'a> AnalyzeContext<'a> {
835835
Type::Array {
836836
elem_type, indexes, ..
837837
} => {
838-
if let [index_type] = indexes.as_slice() {
839-
for assoc in assocs.iter_mut() {
840-
as_fatal(self.analyze_1d_array_assoc_elem(
841-
scope,
842-
target_base,
843-
*index_type,
844-
*elem_type,
845-
assoc,
846-
diagnostics,
847-
))?;
848-
}
849-
} else {
850-
// @TODO multi dimensional array
851-
self.analyze_aggregate(scope, assocs, diagnostics)?;
838+
for assoc in assocs.iter_mut() {
839+
as_fatal(self.array_assoc_elem(
840+
scope,
841+
target_base,
842+
indexes,
843+
*elem_type,
844+
assoc,
845+
diagnostics,
846+
))?;
852847
}
853848
}
854849
Type::Record(record_scope) => {
@@ -978,15 +973,16 @@ impl<'a> AnalyzeContext<'a> {
978973
Ok(())
979974
}
980975

981-
pub fn analyze_1d_array_assoc_elem(
976+
pub fn array_assoc_elem(
982977
&self,
983978
scope: &Scope<'a>,
984979
array_type: TypeEnt<'a>,
985-
index_type: Option<BaseType<'a>>,
980+
index_types: &[Option<BaseType<'a>>],
986981
elem_type: TypeEnt<'a>,
987982
assoc: &mut ElementAssociation,
988983
diagnostics: &mut dyn DiagnosticHandler,
989984
) -> EvalResult {
985+
let index_type = index_types.first().and_then(|x| *x);
990986
let mut can_be_array = true;
991987

992988
let expr = match assoc {
@@ -1045,7 +1041,28 @@ impl<'a> AnalyzeContext<'a> {
10451041
ElementAssociation::Positional(ref mut expr) => expr,
10461042
};
10471043

1048-
if can_be_array {
1044+
if index_types.len() > 1 {
1045+
if let Expression::Aggregate(ref mut inner) = expr.item {
1046+
for assoc in inner.iter_mut() {
1047+
as_fatal(self.array_assoc_elem(
1048+
scope,
1049+
array_type,
1050+
&index_types[1..],
1051+
elem_type,
1052+
assoc,
1053+
diagnostics,
1054+
))?;
1055+
}
1056+
} else {
1057+
diagnostics.error(
1058+
&expr.pos,
1059+
format!(
1060+
"Expected sub-aggregate for target {}",
1061+
array_type.describe()
1062+
),
1063+
);
1064+
}
1065+
} else if can_be_array {
10491066
// If the choice is only a range or positional the expression can be an array
10501067
let types = self.expr_type(scope, expr, diagnostics)?;
10511068
let is_array = self.is_possible(&types, array_type.base());

vhdl_lang/src/analysis/tests/typecheck_expression.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,39 @@ constant bad1 : integer := (3, 4, 5);
797797
);
798798
}
799799

800+
#[test]
801+
fn typecheck_multi_dimensional_array_aggregate() {
802+
let mut builder = LibraryBuilder::new();
803+
let code = builder.in_declarative_region(
804+
"
805+
type arr2_t is array (0 to 1, 2 to 3) of integer;
806+
type arr1_t is array (0 to 1) of integer;
807+
constant good1 : arr2_t := (others => (0, 1));
808+
constant good2 : arr2_t := (others => (others => 0));
809+
constant good3 : arr2_t := ((others => 0), (others => 0));
810+
811+
constant a1 : arr1_t := (0, 1);
812+
constant bad1 : arr2_t := (others => 1 & 1);
813+
constant bad2 : arr2_t := (others => a1);
814+
",
815+
);
816+
817+
let diagnostics = builder.analyze();
818+
check_diagnostics(
819+
diagnostics,
820+
vec![
821+
Diagnostic::error(
822+
code.s1("1 & 1"),
823+
"Expected sub-aggregate for target array type 'arr2_t'",
824+
),
825+
Diagnostic::error(
826+
code.s1("=> a1").s1("a1"),
827+
"Expected sub-aggregate for target array type 'arr2_t'",
828+
),
829+
],
830+
);
831+
}
832+
800833
#[test]
801834
fn record_aggregate_must_be_simple_name() {
802835
let mut builder = LibraryBuilder::new();

0 commit comments

Comments
 (0)