@@ -157,7 +157,7 @@ impl<'a> ResolvedName<'a> {
157157 | AnyEntKind :: Attribute ( _)
158158 | AnyEntKind :: ElementDeclaration ( _)
159159 | AnyEntKind :: Label
160- | AnyEntKind :: LoopParameter => {
160+ | AnyEntKind :: LoopParameter ( _ ) => {
161161 return Err ( format ! (
162162 "{} cannot be selected from design unit" ,
163163 ent. kind( ) . describe( )
@@ -207,7 +207,7 @@ impl<'a> ResolvedName<'a> {
207207 | AnyEntKind :: InterfaceFile ( _)
208208 | AnyEntKind :: Component ( _)
209209 | AnyEntKind :: Label
210- | AnyEntKind :: LoopParameter
210+ | AnyEntKind :: LoopParameter ( _ )
211211 | AnyEntKind :: PhysicalLiteral ( _) => ResolvedName :: Final ( ent) ,
212212 AnyEntKind :: Attribute ( _) | AnyEntKind :: ElementDeclaration ( _) => {
213213 return Err ( format ! (
@@ -329,9 +329,8 @@ impl<'a> AnalyzeContext<'a> {
329329 ) )
330330 }
331331 ResolvedName :: Final ( ent) => match ent. actual_kind ( ) {
332- AnyEntKind :: LoopParameter => {
333- // TODO cannot handle yet
334- Ok ( None )
332+ AnyEntKind :: LoopParameter ( typ) => {
333+ Ok ( typ. map ( |typ| DisambiguatedType :: Unambiguous ( typ. into ( ) ) ) )
335334 }
336335 AnyEntKind :: PhysicalLiteral ( typ) => Ok ( Some ( DisambiguatedType :: Unambiguous ( * typ) ) ) ,
337336 AnyEntKind :: File ( subtype) => {
@@ -373,10 +372,7 @@ impl<'a> AnalyzeContext<'a> {
373372 ) )
374373 }
375374 ResolvedName :: Final ( ent) => match ent. actual_kind ( ) {
376- AnyEntKind :: LoopParameter => {
377- // TODO cannot handle yet
378- Ok ( None )
379- }
375+ AnyEntKind :: LoopParameter ( typ) => Ok ( typ. map ( |typ| typ. into ( ) ) ) ,
380376 AnyEntKind :: PhysicalLiteral ( typ) => Ok ( Some ( * typ) ) ,
381377 AnyEntKind :: File ( subtype) => Ok ( Some ( subtype. type_mark ( ) ) ) ,
382378 AnyEntKind :: InterfaceFile ( typ) => Ok ( Some ( * typ) ) ,
@@ -502,7 +498,7 @@ impl<'a> AnalyzeContext<'a> {
502498 } else {
503499 None
504500 } ) ,
505- // @TODO attribute not handled
501+ // @TODO attribute is handled elesewhere
506502 Suffix :: Attribute ( _) => Ok ( None ) ,
507503 // @TODO Prefix must non-overloaded
508504 Suffix :: CallOrIndexed ( assocs) => {
@@ -518,7 +514,8 @@ impl<'a> AnalyzeContext<'a> {
518514 if could_be_indexed_name ( assocs) {
519515 // @TODO check types of indexes
520516 self . analyze_assoc_elems ( scope, assocs, diagnostics) ?;
521- if let Some ( ( elem_type, num_indexes) ) = prefix_typ. array_type ( ) {
517+ if let Some ( ( elem_type, indexes) ) = prefix_typ. array_type ( ) {
518+ let num_indexes = indexes. len ( ) ;
522519 if assocs. len ( ) != num_indexes {
523520 Err ( Diagnostic :: dimension_mismatch (
524521 name_pos,
@@ -540,6 +537,46 @@ impl<'a> AnalyzeContext<'a> {
540537 }
541538 }
542539
540+ pub fn attribute_suffix (
541+ & self ,
542+ typ : TypeEnt < ' a > ,
543+ attr : & mut AttributeSuffix ,
544+ ) -> EvalResult < Option < BaseType < ' a > > > {
545+ match attr. attr . item {
546+ // @TODO check that it is a scalar type
547+ AttributeDesignator :: Left
548+ | AttributeDesignator :: Right
549+ | AttributeDesignator :: High
550+ | AttributeDesignator :: Low => {
551+ if let Some ( ( _, indexes) ) = typ. array_type ( ) {
552+ if attr. expr . is_none ( ) {
553+ // @TODO could also be 'left(2) for different dimensions
554+ Ok ( Some ( indexes. first ( ) . unwrap ( ) . unwrap ( ) ) )
555+ } else {
556+ Err ( EvalError :: Unknown )
557+ }
558+ } else {
559+ match typ. base ( ) . kind ( ) {
560+ Type :: Enum ( _)
561+ | Type :: Integer
562+ | Type :: Real
563+ | Type :: Physical
564+ | Type :: Universal ( _) => Ok ( Some ( typ. into ( ) ) ) ,
565+ _ => Ok ( None ) ,
566+ }
567+ }
568+ }
569+ AttributeDesignator :: Length => {
570+ if typ. array_type ( ) . is_some ( ) {
571+ Ok ( Some ( self . universal_integer ( ) ) )
572+ } else {
573+ Ok ( None )
574+ }
575+ }
576+ _ => Err ( EvalError :: Unknown ) ,
577+ }
578+ }
579+
543580 pub fn name_resolve (
544581 & self ,
545582 scope : & Scope < ' a > ,
@@ -645,18 +682,54 @@ impl<'a> AnalyzeContext<'a> {
645682 }
646683 }
647684
648- if let Suffix :: Attribute ( attr) = suffix {
649- if let Some ( signature) = attr. signature {
650- if let Err ( e) = self . resolve_signature ( scope, signature) {
651- diagnostics. push ( e. into_non_fatal ( ) ?) ;
685+ // Attributes for non-types not handled yet
686+ if let Suffix :: Attribute ( ref mut attr) = suffix {
687+ let typ = match resolved {
688+ ResolvedName :: Type ( typ) => typ,
689+ ResolvedName :: ObjectName ( oname) => oname. type_mark ( ) ,
690+ ResolvedName :: Expression ( DisambiguatedType :: Unambiguous ( typ) ) => typ,
691+ _ => {
692+ // @TODO ignore for now
693+ if let Some ( signature) = attr. signature {
694+ if let Err ( e) = self . resolve_signature ( scope, signature) {
695+ diagnostics. push ( e. into_non_fatal ( ) ?) ;
696+ }
697+ }
698+ if let Some ( expr) = attr. expr {
699+ self . analyze_expression ( scope, expr, diagnostics) ?;
700+ }
701+
702+ // @TODO not handled yet
703+ return Err ( EvalError :: Unknown ) ;
652704 }
653- }
654- if let Some ( expr) = attr. expr {
655- self . analyze_expression ( scope, expr, diagnostics) ?;
656- }
705+ } ;
706+
707+ return match self . attribute_suffix ( typ, attr) {
708+ Ok ( Some ( typ) ) => Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
709+ typ. into ( ) ,
710+ ) ) ) ,
711+ Ok ( None ) => {
712+ diagnostics. push ( Diagnostic :: cannot_be_prefix ( name_pos, resolved, suffix) ) ;
713+ Err ( EvalError :: Unknown )
714+ }
715+ Err ( EvalError :: Unknown ) => {
716+ // @TODO ignore for now
717+ if let Some ( signature) = attr. signature {
718+ if let Err ( e) = self . resolve_signature ( scope, signature) {
719+ diagnostics. push ( e. into_non_fatal ( ) ?) ;
720+ }
721+ }
722+ if let Some ( expr) = attr. expr {
723+ self . analyze_expression ( scope, expr, diagnostics) ?;
724+ }
657725
658- // @TODO not handled yet
659- return Err ( EvalError :: Unknown ) ;
726+ // @TODO not handled yet
727+ return Err ( EvalError :: Unknown ) ;
728+ }
729+ Err ( err) => {
730+ return Err ( err) ;
731+ }
732+ } ;
660733 }
661734
662735 match resolved {
@@ -830,6 +903,7 @@ impl<'a> AnalyzeContext<'a> {
830903 ) ) ) ;
831904 }
832905 }
906+
833907 diagnostics. push ( Diagnostic :: cannot_be_prefix ( name_pos, resolved, suffix) ) ;
834908 return Err ( EvalError :: Unknown ) ;
835909 }
@@ -1636,4 +1710,93 @@ variable c0 : integer_vector(0 to 6);
16361710 ) ] ,
16371711 )
16381712 }
1713+
1714+ #[ test]
1715+ fn scalar_type_attribute ( ) {
1716+ let test = TestSetup :: new ( ) ;
1717+ let code = test. snippet ( "integer'left" ) ;
1718+ assert_eq ! (
1719+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1720+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1721+ test. lookup_type( "integer" )
1722+ ) ) )
1723+ ) ;
1724+ let code = test. snippet ( "integer'right" ) ;
1725+ assert_eq ! (
1726+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1727+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1728+ test. lookup_type( "integer" )
1729+ ) ) )
1730+ ) ;
1731+ let code = test. snippet ( "integer'high" ) ;
1732+ assert_eq ! (
1733+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1734+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1735+ test. lookup_type( "integer" )
1736+ ) ) )
1737+ ) ;
1738+ let code = test. snippet ( "integer'low" ) ;
1739+ assert_eq ! (
1740+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1741+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1742+ test. lookup_type( "integer" )
1743+ ) ) )
1744+ ) ;
1745+ }
1746+
1747+ #[ test]
1748+ fn array_type_attribute ( ) {
1749+ let test = TestSetup :: new ( ) ;
1750+ test. declarative_part (
1751+ "
1752+ type arr_t is array (integer range 0 to 3) of integer;
1753+ " ,
1754+ ) ;
1755+ let code = test. snippet ( "arr_t'left" ) ;
1756+ assert_eq ! (
1757+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1758+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1759+ test. lookup_type( "integer" )
1760+ ) ) )
1761+ ) ;
1762+ }
1763+
1764+ #[ test]
1765+ fn length_attribute_of_array_type ( ) {
1766+ let test = TestSetup :: new ( ) ;
1767+
1768+ test. declarative_part (
1769+ "
1770+ type arr_t is array (integer range 0 to 3) of integer;
1771+ " ,
1772+ ) ;
1773+
1774+ let code = test. snippet ( "arr_t'length" ) ;
1775+ assert_eq ! (
1776+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1777+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1778+ test. ctx( ) . universal_integer( ) . into( )
1779+ ) ) )
1780+ ) ;
1781+ }
1782+
1783+ #[ test]
1784+ fn length_attribute_of_array_object ( ) {
1785+ let test = TestSetup :: new ( ) ;
1786+
1787+ test. declarative_part (
1788+ "
1789+ type arr_t is array (integer range 0 to 3) of integer;
1790+ constant c0 : arr_t := (others => 0);
1791+ " ,
1792+ ) ;
1793+
1794+ let code = test. snippet ( "c0'length" ) ;
1795+ assert_eq ! (
1796+ test. name_resolve( & code, None , & mut NoDiagnostics ) ,
1797+ Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1798+ test. ctx( ) . universal_integer( ) . into( )
1799+ ) ) )
1800+ ) ;
1801+ }
16391802}
0 commit comments