@@ -316,7 +316,31 @@ impl<'a> ResolvedName<'a> {
316316 ) ;
317317 Err ( EvalError :: Unknown )
318318 }
319+
320+ /// Convenience function that returns `Some(name)` when self is an object name, else `None`
321+ fn as_object_name ( & self ) -> Option < ObjectName < ' a > > {
322+ match self {
323+ ResolvedName :: ObjectName ( oname) => Some ( * oname) ,
324+ _ => None ,
325+ }
326+ }
327+ }
328+
329+ /// Represents the result when resolving an attribute.
330+ /// This can either be a value or a type.
331+ ///
332+ /// in the future, the value case might also hold the value
333+ /// of the static expression of the attribute.
334+ ///
335+ /// Values are returned for attributes such as `'low`, `'high`, `'val(..)`, e.t.c.
336+ /// Types are returned for attributes such as `'base`, `'subtype`, `'element`
337+ pub enum AttrResolveResult < ' a > {
338+ /// The result type is a type. E.g. `a'base`, `a'subtype`, `a'element`
339+ Type ( BaseType < ' a > ) ,
340+ /// The result type is a value with type, e.g. `a'low`, `b'high`, `c'image(x)`
341+ Value ( BaseType < ' a > ) ,
319342}
343+
320344#[ derive( Debug ) ]
321345pub struct AttributeSuffix < ' a > {
322346 pub signature : & ' a mut Option < WithPos < crate :: ast:: Signature > > ,
@@ -712,7 +736,7 @@ impl<'a> AnalyzeContext<'a> {
712736 prefix : & ResolvedName < ' a > ,
713737 attr : & mut AttributeSuffix ,
714738 diagnostics : & mut dyn DiagnosticHandler ,
715- ) -> EvalResult < BaseType < ' a > > {
739+ ) -> EvalResult < AttrResolveResult < ' a > > {
716740 match attr. attr . item {
717741 AttributeDesignator :: Left
718742 | AttributeDesignator :: Right
@@ -726,9 +750,10 @@ impl<'a> AnalyzeContext<'a> {
726750 attr. expr . as_mut ( ) . map ( |expr| expr. as_mut ( ) ) ,
727751 diagnostics,
728752 )
753+ . map ( AttrResolveResult :: Value )
729754 } else if typ. is_scalar ( ) {
730755 check_no_attr_argument ( attr, diagnostics) ;
731- Ok ( typ. into ( ) )
756+ Ok ( AttrResolveResult :: Value ( typ. into ( ) ) )
732757 } else {
733758 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
734759 name_pos, prefix, attr,
@@ -740,10 +765,10 @@ impl<'a> AnalyzeContext<'a> {
740765 let typ = prefix. as_type_of_attr_prefix ( prefix_pos, attr, diagnostics) ?;
741766
742767 if typ. array_type ( ) . is_some ( ) {
743- Ok ( self . boolean ( ) . base ( ) )
768+ Ok ( AttrResolveResult :: Value ( self . boolean ( ) . base ( ) ) )
744769 } else if typ. is_scalar ( ) {
745770 check_no_attr_argument ( attr, diagnostics) ;
746- Ok ( self . boolean ( ) . base ( ) )
771+ Ok ( AttrResolveResult :: Value ( self . boolean ( ) . base ( ) ) )
747772 } else {
748773 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
749774 name_pos, prefix, attr,
@@ -759,7 +784,7 @@ impl<'a> AnalyzeContext<'a> {
759784 }
760785
761786 if typ. is_scalar ( ) {
762- Ok ( self . string ( ) . base ( ) )
787+ Ok ( AttrResolveResult :: Value ( self . string ( ) . base ( ) ) )
763788 } else {
764789 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
765790 name_pos, prefix, attr,
@@ -775,7 +800,7 @@ impl<'a> AnalyzeContext<'a> {
775800 }
776801
777802 if typ. is_scalar ( ) {
778- Ok ( typ. base ( ) )
803+ Ok ( AttrResolveResult :: Value ( typ. base ( ) ) )
779804 } else {
780805 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
781806 name_pos, prefix, attr,
@@ -790,7 +815,7 @@ impl<'a> AnalyzeContext<'a> {
790815 if let Some ( ref mut expr) = check_single_argument ( name_pos, attr, diagnostics) {
791816 self . expr_with_ttyp ( scope, typ, expr, diagnostics) ?;
792817 }
793- Ok ( self . universal_integer ( ) )
818+ Ok ( AttrResolveResult :: Value ( self . universal_integer ( ) ) )
794819 } else {
795820 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
796821 name_pos, prefix, attr,
@@ -805,7 +830,7 @@ impl<'a> AnalyzeContext<'a> {
805830 if let Some ( ref mut expr) = check_single_argument ( name_pos, attr, diagnostics) {
806831 self . integer_expr ( scope, expr, diagnostics) ?;
807832 }
808- Ok ( typ. base ( ) )
833+ Ok ( AttrResolveResult :: Value ( typ. base ( ) ) )
809834 } else {
810835 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
811836 name_pos, prefix, attr,
@@ -823,7 +848,7 @@ impl<'a> AnalyzeContext<'a> {
823848 if let Some ( ref mut expr) = check_single_argument ( name_pos, attr, diagnostics) {
824849 self . expr_with_ttyp ( scope, typ, expr, diagnostics) ?;
825850 }
826- Ok ( typ. base ( ) )
851+ Ok ( AttrResolveResult :: Value ( typ. base ( ) ) )
827852 } else {
828853 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
829854 name_pos, prefix, attr,
@@ -835,7 +860,7 @@ impl<'a> AnalyzeContext<'a> {
835860 let typ = prefix. as_type_of_attr_prefix ( prefix_pos, attr, diagnostics) ?;
836861
837862 if typ. array_type ( ) . is_some ( ) {
838- Ok ( self . universal_integer ( ) )
863+ Ok ( AttrResolveResult :: Value ( self . universal_integer ( ) ) )
839864 } else {
840865 diagnostics. push ( Diagnostic :: cannot_be_prefix_of_attribute (
841866 name_pos, prefix, attr,
@@ -847,7 +872,7 @@ impl<'a> AnalyzeContext<'a> {
847872 | AttributeDesignator :: InstanceName
848873 | AttributeDesignator :: PathName => {
849874 check_no_attr_argument ( attr, diagnostics) ;
850- Ok ( self . string ( ) . base ( ) )
875+ Ok ( AttrResolveResult :: Value ( self . string ( ) . base ( ) ) )
851876 }
852877
853878 AttributeDesignator :: Signal ( sattr) => {
@@ -858,45 +883,45 @@ impl<'a> AnalyzeContext<'a> {
858883 if let Some ( expr) = attr. expr {
859884 self . expr_with_ttyp ( scope, self . time ( ) , expr, diagnostics) ?;
860885 }
861- Ok ( typ. base ( ) )
886+ Ok ( AttrResolveResult :: Value ( typ. base ( ) ) )
862887 }
863888 SignalAttribute :: Stable | SignalAttribute :: Quiet => {
864889 if let Some ( expr) = expr {
865890 self . expr_with_ttyp ( scope, self . time ( ) , expr, diagnostics) ?;
866891 }
867- Ok ( self . boolean ( ) . base ( ) )
892+ Ok ( AttrResolveResult :: Value ( self . boolean ( ) . base ( ) ) )
868893 }
869894 SignalAttribute :: Transaction => {
870895 check_no_sattr_argument ( sattr, expr, diagnostics) ;
871- Ok ( self . bit ( ) . base ( ) )
896+ Ok ( AttrResolveResult :: Value ( self . bit ( ) . base ( ) ) )
872897 }
873898 SignalAttribute :: Event => {
874899 check_no_sattr_argument ( sattr, expr, diagnostics) ;
875- Ok ( self . boolean ( ) . base ( ) )
900+ Ok ( AttrResolveResult :: Value ( self . boolean ( ) . base ( ) ) )
876901 }
877902 SignalAttribute :: Active => {
878903 check_no_sattr_argument ( sattr, expr, diagnostics) ;
879- Ok ( self . boolean ( ) . base ( ) )
904+ Ok ( AttrResolveResult :: Value ( self . boolean ( ) . base ( ) ) )
880905 }
881906 SignalAttribute :: LastEvent => {
882907 check_no_sattr_argument ( sattr, expr, diagnostics) ;
883- Ok ( self . time ( ) . base ( ) )
908+ Ok ( AttrResolveResult :: Value ( self . time ( ) . base ( ) ) )
884909 }
885910 SignalAttribute :: LastActive => {
886911 check_no_sattr_argument ( sattr, expr, diagnostics) ;
887- Ok ( self . time ( ) . base ( ) )
912+ Ok ( AttrResolveResult :: Value ( self . time ( ) . base ( ) ) )
888913 }
889914 SignalAttribute :: LastValue => {
890915 check_no_sattr_argument ( sattr, expr, diagnostics) ;
891- Ok ( typ. base ( ) )
916+ Ok ( AttrResolveResult :: Value ( typ. base ( ) ) )
892917 }
893918 SignalAttribute :: Driving => {
894919 check_no_sattr_argument ( sattr, expr, diagnostics) ;
895- Ok ( self . boolean ( ) . base ( ) )
920+ Ok ( AttrResolveResult :: Value ( self . boolean ( ) . base ( ) ) )
896921 }
897922 SignalAttribute :: DrivingValue => {
898923 check_no_sattr_argument ( sattr, expr, diagnostics) ;
899- Ok ( typ. base ( ) )
924+ Ok ( AttrResolveResult :: Value ( typ. base ( ) ) )
900925 }
901926 }
902927 }
@@ -912,9 +937,44 @@ impl<'a> AnalyzeContext<'a> {
912937 diagnostics. error ( name_pos, "Range cannot be used as an expression" ) ;
913938 Err ( EvalError :: Unknown )
914939 }
915- AttributeDesignator :: Type ( _) => {
916- diagnostics. error ( name_pos, "Type cannot be used as an expression" ) ;
917- Err ( EvalError :: Unknown )
940+ AttributeDesignator :: Type ( attr) => self
941+ . resolve_type_attribute_suffix ( prefix, & attr, name_pos, diagnostics)
942+ . map ( |typ| AttrResolveResult :: Type ( typ. base ( ) ) ) ,
943+ }
944+ }
945+
946+ /// Resolves any type attribute suffixes
947+ ///
948+ /// # Example
949+ /// ```vhdl
950+ /// variable x: std_logic_vector(2 downto 0);
951+ /// x'subtype -> std_logic_vector(2 downto 0)
952+ /// x'element -> std_logic
953+ /// ```
954+ fn resolve_type_attribute_suffix (
955+ & self ,
956+ prefix : & ResolvedName < ' a > ,
957+ suffix : & TypeAttribute ,
958+ pos : & SrcPos ,
959+ diagnostics : & mut dyn DiagnosticHandler ,
960+ ) -> EvalResult < TypeEnt < ' a > > {
961+ // all type attribute suffixes require that the prefix be an object type
962+ let Some ( obj) = prefix. as_object_name ( ) else {
963+ diagnostics. error ( pos, format ! ( "The {} attribute can only be used on objects, not {}" , suffix, prefix. describe( ) ) ) ;
964+ return Err ( EvalError :: Unknown )
965+ } ;
966+ match suffix {
967+ TypeAttribute :: Subtype => Ok ( obj. type_mark ( ) ) ,
968+ TypeAttribute :: Element => {
969+ if let Some ( ( elem_type, _) ) = obj. type_mark ( ) . array_type ( ) {
970+ Ok ( elem_type)
971+ } else {
972+ diagnostics. error (
973+ pos,
974+ "The element attribute can only be used for array types" ,
975+ ) ;
976+ Err ( EvalError :: Unknown )
977+ }
918978 }
919979 }
920980 }
@@ -1035,13 +1095,15 @@ impl<'a> AnalyzeContext<'a> {
10351095 }
10361096 }
10371097
1038- // Attributes for non-types not handled yet
10391098 if let Suffix :: Attribute ( ref mut attr) = suffix {
10401099 let typ =
10411100 self . attribute_suffix ( name_pos, & prefix. pos , scope, & resolved, attr, diagnostics) ?;
1042- return Ok ( ResolvedName :: Expression ( DisambiguatedType :: Unambiguous (
1043- typ. into ( ) ,
1044- ) ) ) ;
1101+ return match typ {
1102+ AttrResolveResult :: Type ( base) => Ok ( ResolvedName :: Type ( base. into ( ) ) ) ,
1103+ AttrResolveResult :: Value ( base) => Ok ( ResolvedName :: Expression (
1104+ DisambiguatedType :: Unambiguous ( base. into ( ) ) ,
1105+ ) ) ,
1106+ } ;
10451107 }
10461108
10471109 match resolved {
@@ -1737,6 +1799,90 @@ mod test {
17371799 }
17381800 }
17391801
1802+ #[ test]
1803+ fn consecutive_name_attributes ( ) {
1804+ let test = TestSetup :: new ( ) ;
1805+ test. declarative_part (
1806+ "\
1807+ variable a: natural range 0 to 9 := 9;
1808+ variable b: natural range 0 to a'subtype'high;
1809+ " ,
1810+ ) ;
1811+ assert_matches ! (
1812+ test. name_resolve( & test. snippet( "b" ) , None , & mut NoDiagnostics ) ,
1813+ Ok ( ResolvedName :: ObjectName ( _) )
1814+ ) ;
1815+ }
1816+
1817+ #[ test]
1818+ fn element_subtype_for_non_arrays ( ) {
1819+ let test = TestSetup :: new ( ) ;
1820+ test. declarative_part (
1821+ "
1822+ variable thevar : integer;
1823+ " ,
1824+ ) ;
1825+ let code = test. snippet ( "thevar'element" ) ;
1826+ let mut diagnostics = Vec :: new ( ) ;
1827+ assert_eq ! (
1828+ test. name_resolve( & code, None , & mut diagnostics) ,
1829+ Err ( EvalError :: Unknown )
1830+ ) ;
1831+ check_diagnostics (
1832+ diagnostics,
1833+ vec ! [ Diagnostic :: error(
1834+ code. s1( "thevar'element" ) ,
1835+ "The element attribute can only be used for array types" ,
1836+ ) ] ,
1837+ )
1838+ }
1839+
1840+ #[ test]
1841+ fn element_type_attributes_on_non_object_types ( ) {
1842+ let test = TestSetup :: new ( ) ;
1843+ test. declarative_part (
1844+ "
1845+ type my_type is array(natural range<>) of integer;
1846+ " ,
1847+ ) ;
1848+ let code = test. snippet ( "my_type'subtype" ) ;
1849+ let mut diagnostics = Vec :: new ( ) ;
1850+ assert_eq ! (
1851+ test. name_resolve( & code, None , & mut diagnostics) ,
1852+ Err ( EvalError :: Unknown )
1853+ ) ;
1854+ check_diagnostics (
1855+ diagnostics,
1856+ vec ! [ Diagnostic :: error(
1857+ code. s1( "my_type'subtype" ) ,
1858+ "The subtype attribute can only be used on objects, not array type 'my_type'" ,
1859+ ) ] ,
1860+ )
1861+ }
1862+
1863+ #[ test]
1864+ fn consecutive_type_attributes ( ) {
1865+ let test = TestSetup :: new ( ) ;
1866+ test. declarative_part (
1867+ "
1868+ variable x: integer;
1869+ " ,
1870+ ) ;
1871+ let code = test. snippet ( "x'subtype'subtype'high" ) ;
1872+ let mut diagnostics = Vec :: new ( ) ;
1873+ assert_eq ! (
1874+ test. name_resolve( & code, None , & mut diagnostics) ,
1875+ Err ( EvalError :: Unknown )
1876+ ) ;
1877+ check_diagnostics (
1878+ diagnostics,
1879+ vec ! [ Diagnostic :: error(
1880+ code. s1( "x'subtype'subtype" ) ,
1881+ "The subtype attribute can only be used on objects, not integer type 'INTEGER'" ,
1882+ ) ] ,
1883+ )
1884+ }
1885+
17401886 #[ test]
17411887 fn object_name ( ) {
17421888 let test = TestSetup :: new ( ) ;
@@ -2579,29 +2725,6 @@ variable thevar : integer_vector(0 to 1);
25792725 )
25802726 }
25812727
2582- #[ test]
2583- fn subtype_attribute ( ) {
2584- let test = TestSetup :: new ( ) ;
2585- test. declarative_part (
2586- "
2587- variable thevar : integer_vector(0 to 1);
2588- " ,
2589- ) ;
2590- let code = test. snippet ( "thevar'subtype" ) ;
2591- let mut diagnostics = Vec :: new ( ) ;
2592- assert_eq ! (
2593- test. name_resolve( & code, None , & mut diagnostics) ,
2594- Err ( EvalError :: Unknown )
2595- ) ;
2596- check_diagnostics (
2597- diagnostics,
2598- vec ! [ Diagnostic :: error(
2599- code,
2600- "Type cannot be used as an expression" ,
2601- ) ] ,
2602- )
2603- }
2604-
26052728 #[ test]
26062729 fn name_attributes ( ) {
26072730 let test = TestSetup :: new ( ) ;
0 commit comments