@@ -267,7 +267,7 @@ impl<'a> ResolvedName<'a> {
267267 }
268268 }
269269
270- fn as_type_of_attr_prefix (
270+ pub ( crate ) fn as_type_of_attr_prefix (
271271 & self ,
272272 prefix_pos : & SrcPos ,
273273 attr : & AttributeSuffix ,
@@ -656,6 +656,43 @@ impl<'a> AnalyzeContext<'a> {
656656 }
657657 }
658658
659+ // Resolve an index used in an array attribute such as arr_t'left(0) to an index type
660+ pub ( crate ) fn array_index_expression_in_attribute (
661+ & self ,
662+ indexes : & [ Option < BaseType < ' a > > ] ,
663+ mut expr : Option < & mut WithPos < Expression > > ,
664+ diagnostics : & mut dyn DiagnosticHandler ,
665+ ) -> EvalResult < BaseType < ' a > > {
666+ let idx = if let Some ( expr) = expr. as_mut ( ) {
667+ if let Expression :: Literal ( Literal :: AbstractLiteral ( AbstractLiteral :: Integer ( idx) ) ) =
668+ expr. item
669+ {
670+ idx as usize
671+ } else {
672+ diagnostics. error ( & expr. pos , "Expected an integer literal" ) ;
673+ return Err ( EvalError :: Unknown ) ;
674+ }
675+ } else {
676+ 1
677+ } ;
678+
679+ if let Some ( idx_typ) = indexes. get ( idx - 1 ) {
680+ if let Some ( idx_typ) = idx_typ {
681+ Ok ( * idx_typ)
682+ } else {
683+ // Array index was not analyzed
684+ Err ( EvalError :: Unknown )
685+ }
686+ } else {
687+ if let Some ( expr) = expr {
688+ let ndims = indexes. len ( ) ;
689+ let dimensions = plural ( "dimension" , "dimensions" , ndims) ;
690+ diagnostics. error ( & expr. pos , format ! ( "Index {idx} out of range for array with {ndims} {dimensions}, expected 1 to {ndims}" ) ) ;
691+ }
692+ Err ( EvalError :: Unknown )
693+ }
694+ }
695+
659696 pub fn attribute_suffix (
660697 & self ,
661698 name_pos : & SrcPos ,
@@ -673,35 +710,11 @@ impl<'a> AnalyzeContext<'a> {
673710 let typ = prefix. as_type_of_attr_prefix ( prefix_pos, attr, diagnostics) ?;
674711
675712 if let Some ( ( _, indexes) ) = typ. array_type ( ) {
676- let idx = if let Some ( expr) = attr. expr {
677- if let Expression :: Literal ( Literal :: AbstractLiteral (
678- AbstractLiteral :: Integer ( idx) ,
679- ) ) = expr. item
680- {
681- idx as usize
682- } else {
683- diagnostics. error ( & expr. pos , "Expected an integer literal" ) ;
684- return Err ( EvalError :: Unknown ) ;
685- }
686- } else {
687- 1
688- } ;
689-
690- if let Some ( idx_typ) = indexes. get ( idx - 1 ) {
691- if let Some ( idx_typ) = idx_typ {
692- Ok ( * idx_typ)
693- } else {
694- // Array index was not analyzed
695- Err ( EvalError :: Unknown )
696- }
697- } else {
698- if let Some ( expr) = attr. expr {
699- let ndims = indexes. len ( ) ;
700- let dimensions = plural ( "dimension" , "dimensions" , ndims) ;
701- diagnostics. error ( & expr. pos , format ! ( "Index {idx} out of range for array with {ndims} {dimensions}, expected 1 to {ndims}" ) ) ;
702- }
703- Err ( EvalError :: Unknown )
704- }
713+ self . array_index_expression_in_attribute (
714+ indexes,
715+ attr. expr . as_mut ( ) . map ( |expr| expr. as_mut ( ) ) ,
716+ diagnostics,
717+ )
705718 } else if typ. is_scalar ( ) {
706719 check_no_attr_argument ( attr, diagnostics) ;
707720 Ok ( typ. into ( ) )
@@ -1369,96 +1382,6 @@ impl<'a> AnalyzeContext<'a> {
13691382 Ok ( ( ) )
13701383 }
13711384
1372- /// Fallback solution that just lookups names
1373- pub fn resolve_name (
1374- & self ,
1375- scope : & Scope < ' a > ,
1376- name_pos : & SrcPos ,
1377- name : & mut Name ,
1378- diagnostics : & mut dyn DiagnosticHandler ,
1379- ) -> EvalResult < NamedEntities < ' a > > {
1380- match name {
1381- Name :: Selected ( prefix, suffix) => {
1382- match self . resolve_name ( scope, & prefix. pos , & mut prefix. item , diagnostics) ? {
1383- NamedEntities :: Single ( named_entity) => {
1384- match self . lookup_selected ( & prefix. pos , named_entity, suffix) {
1385- Ok ( visible) => {
1386- suffix. set_reference ( & visible) ;
1387- Ok ( visible)
1388- }
1389- Err ( err) => {
1390- err. add_to ( diagnostics) ?;
1391- Err ( EvalError :: Unknown )
1392- }
1393- }
1394- }
1395- NamedEntities :: Overloaded ( ..) => Err ( EvalError :: Unknown ) ,
1396- }
1397- }
1398-
1399- Name :: SelectedAll ( prefix) => {
1400- self . resolve_name ( scope, & prefix. pos , & mut prefix. item , diagnostics) ?;
1401- Err ( EvalError :: Unknown )
1402- }
1403- Name :: Designator ( designator) => match scope. lookup ( name_pos, designator. designator ( ) ) {
1404- Ok ( visible) => {
1405- designator. set_reference ( & visible) ;
1406- Ok ( visible)
1407- }
1408- Err ( diagnostic) => {
1409- diagnostics. push ( diagnostic) ;
1410- Err ( EvalError :: Unknown )
1411- }
1412- } ,
1413- Name :: Slice ( ref mut prefix, ref mut drange) => {
1414- self . resolve_name ( scope, & prefix. pos , & mut prefix. item , diagnostics) ?;
1415- self . drange_unknown_type ( scope, drange. as_mut ( ) , diagnostics) ?;
1416- Err ( EvalError :: Unknown )
1417- }
1418- Name :: Attribute ( ref mut attr) => {
1419- self . analyze_attribute_name ( scope, attr, diagnostics) ?;
1420- Err ( EvalError :: Unknown )
1421- }
1422- Name :: CallOrIndexed ( ref mut call) => {
1423- self . resolve_name ( scope, & call. name . pos , & mut call. name . item , diagnostics) ?;
1424- self . analyze_assoc_elems ( scope, & mut call. parameters , diagnostics) ?;
1425- Err ( EvalError :: Unknown )
1426- }
1427- Name :: External ( ref mut ename) => {
1428- let ExternalName { subtype, .. } = ename. as_mut ( ) ;
1429- self . analyze_subtype_indication ( scope, subtype, diagnostics) ?;
1430- Err ( EvalError :: Unknown )
1431- }
1432- }
1433- }
1434-
1435- pub fn analyze_attribute_name (
1436- & self ,
1437- scope : & Scope < ' a > ,
1438- attr : & mut AttributeName ,
1439- diagnostics : & mut dyn DiagnosticHandler ,
1440- ) -> FatalResult {
1441- // @TODO more, attr must be checked inside the scope of attributes of prefix
1442- let AttributeName {
1443- name,
1444- signature,
1445- expr,
1446- ..
1447- } = attr;
1448-
1449- as_fatal ( self . resolve_name ( scope, & name. pos , & mut name. item , diagnostics) ) ?;
1450-
1451- if let Some ( ref mut signature) = signature {
1452- if let Err ( err) = self . resolve_signature ( scope, signature) {
1453- err. add_to ( diagnostics) ?;
1454- }
1455- }
1456- if let Some ( ref mut expr) = expr {
1457- self . expr_unknown_ttyp ( scope, expr, diagnostics) ?;
1458- }
1459- Ok ( ( ) )
1460- }
1461-
14621385 /// Analyze an indexed name where the prefix entity is already known
14631386 /// Returns the type of the array element
14641387 pub fn analyze_indexed_name (
0 commit comments