@@ -267,7 +267,7 @@ impl<'a> ResolvedName<'a> {
267
267
}
268
268
}
269
269
270
- fn as_type_of_attr_prefix (
270
+ pub ( crate ) fn as_type_of_attr_prefix (
271
271
& self ,
272
272
prefix_pos : & SrcPos ,
273
273
attr : & AttributeSuffix ,
@@ -656,6 +656,43 @@ impl<'a> AnalyzeContext<'a> {
656
656
}
657
657
}
658
658
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
+
659
696
pub fn attribute_suffix (
660
697
& self ,
661
698
name_pos : & SrcPos ,
@@ -673,35 +710,11 @@ impl<'a> AnalyzeContext<'a> {
673
710
let typ = prefix. as_type_of_attr_prefix ( prefix_pos, attr, diagnostics) ?;
674
711
675
712
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
+ )
705
718
} else if typ. is_scalar ( ) {
706
719
check_no_attr_argument ( attr, diagnostics) ;
707
720
Ok ( typ. into ( ) )
@@ -1369,96 +1382,6 @@ impl<'a> AnalyzeContext<'a> {
1369
1382
Ok ( ( ) )
1370
1383
}
1371
1384
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
-
1462
1385
/// Analyze an indexed name where the prefix entity is already known
1463
1386
/// Returns the type of the array element
1464
1387
pub fn analyze_indexed_name (
0 commit comments