* Problem with Position of the enumeration Type @ 2019-01-23 10:05 Luis Ladron de Guevara Moreno 2019-01-23 10:33 ` AdaMagica ` (3 more replies) 0 siblings, 4 replies; 25+ messages in thread From: Luis Ladron de Guevara Moreno @ 2019-01-23 10:05 UTC (permalink / raw) Hello, I have an issue with the declaration of the enumeration type, when i try to map the values of an enumeration to a specific position. the code: procedure EnumerationTest is Position : Integer; type E_Test is (Pos10, Pos11, Pos12, Pos13, Pos14); for E_Test use (Pos10 => 10, Pos11 => 11, Pos12 => 12, Pos13 => 13, Pos14 => 14); begin for I in E_Test'Base loop Position := E_Test'pos (I); ada.Text_IO.Put (" Position: " & Position'Img & " Value: " & I'Img); end loop; end EnumerationTest; i thought that the result of the position was 10, 11, 12, 13, 14. But When i run this code, the result is 0, 1, 2, 3. I don't know what it is the exactly meaning of: for E_Test use (Pos10 => 10, Pos11 => 11, Pos12 => 12, Pos13 => 13, Pos14 => 14); and how can i assign a different position for the specific value. Could anyone help me with this problem? Thank you so much =) ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 10:05 Problem with Position of the enumeration Type Luis Ladron de Guevara Moreno @ 2019-01-23 10:33 ` AdaMagica 2019-01-23 10:55 ` AdaMagica 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno 2019-01-23 11:32 ` Mark Lorenzen ` (2 subsequent siblings) 3 siblings, 2 replies; 25+ messages in thread From: AdaMagica @ 2019-01-23 10:33 UTC (permalink / raw) See RM 13.4(11/3)ff: NOTES 14 Unchecked_Conversion may be used to query the internal codes used for an enumeration type. The attributes of the type, such as Succ, Pred, and Pos, are unaffected by the enumeration_representation_clauserepresentation_clause. Some questions on your code: Position : Integer; -- Why is this Integer and not Natural? for I in E_Test'Base loop -- Why do you use 'Base here? ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 10:33 ` AdaMagica @ 2019-01-23 10:55 ` AdaMagica 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno 1 sibling, 0 replies; 25+ messages in thread From: AdaMagica @ 2019-01-23 10:55 UTC (permalink / raw) See RM 3.5.1(7): The position number of the value of the first listed enumeration literal is zero; the position number of the value of each subsequent enumeration literal is one more than that of its predecessor in the list. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 10:33 ` AdaMagica 2019-01-23 10:55 ` AdaMagica @ 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno 2019-01-23 12:15 ` Karl Müller ` (2 more replies) 1 sibling, 3 replies; 25+ messages in thread From: Luis Ladron de Guevara Moreno @ 2019-01-23 12:08 UTC (permalink / raw) El miércoles, 23 de enero de 2019, 11:33:36 (UTC+1), AdaMagica escribió: > See RM 13.4(11/3)ff: > NOTES > 14 Unchecked_Conversion may be used to query the internal codes used for > an enumeration type. The attributes of the type, such as Succ, Pred, and Pos, are unaffected by the enumeration_representation_clauserepresentation_clause. > > Some questions on your code: > > Position : Integer; -- Why is this Integer and not Natural? > > for I in E_Test'Base loop -- Why do you use 'Base here? I wrote a Integer as an example, i could add Natural also, for this example there are not difference. I'm using 'Range to go through all the positions in enumeration. I tried to use Ada.Unchecked_Conversion and i got obtain the values for the position. but as you told me, if i use 'post (), the number of the list start in 0. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno @ 2019-01-23 12:15 ` Karl Müller 2019-01-23 21:50 ` Niklas Holsti 2019-01-24 8:06 ` AdaMagica 2 siblings, 0 replies; 25+ messages in thread From: Karl Müller @ 2019-01-23 12:15 UTC (permalink / raw) For GNAT the Attribute 'Enum_Rep could be helpful: ada.Text_IO.Put (" Position: " & Position'Img & " Value: " & I'Enum_Rep'Img); Result: Position: 0 Value: 10 Position: 1 Value: 11 Position: 2 Value: 12 Position: 3 Value: 13 Position: 4 Value: 14 Regards Karl ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno 2019-01-23 12:15 ` Karl Müller @ 2019-01-23 21:50 ` Niklas Holsti 2019-01-24 8:06 ` AdaMagica 2 siblings, 0 replies; 25+ messages in thread From: Niklas Holsti @ 2019-01-23 21:50 UTC (permalink / raw) On 19-01-23 14:08 , Luis Ladron de Guevara Moreno wrote: > El miércoles, 23 de enero de 2019, 11:33:36 (UTC+1), AdaMagica escribió: >> ... >> Some questions on your code: >> ... >> >> for I in E_Test'Base loop -- Why do you use 'Base here? > ... > I'm using 'Range to go through all the positions in enumeration. You misread AdaMagica's question, which was about 'Base (which you use), not about 'Range (which you did not use). In your code, as E_Test is a not a subtype of some wider enumeration type, E_Test'Base is the same as E_Test. Regarding 'Range, note that for E in E_Test'Range loop ... end loop; can be written simply as for E in E_Test loop ... end loop; with exactly the same effect. Now: did you mean to write 'Base (and not 'Range), and if so, why? -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno 2019-01-23 12:15 ` Karl Müller 2019-01-23 21:50 ` Niklas Holsti @ 2019-01-24 8:06 ` AdaMagica 2 siblings, 0 replies; 25+ messages in thread From: AdaMagica @ 2019-01-24 8:06 UTC (permalink / raw) Am Mittwoch, 23. Januar 2019 13:08:34 UTC+1 schrieb Luis Ladron de Guevara Moreno: > El miércoles, 23 de enero de 2019, 11:33:36 (UTC+1), AdaMagica escribió: > > See RM 13.4(11/3)ff: > > NOTES > > 14 Unchecked_Conversion may be used to query the internal codes used for > > an enumeration type. The attributes of the type, such as Succ, Pred, and Pos, are unaffected by the enumeration_representation_clauserepresentation_clause. > > > > Some questions on your code: > > > > Position : Integer; -- Why is this Integer and not Natural? > > > > for I in E_Test'Base loop -- Why do you use 'Base here? > > I wrote a Integer as an example, i could add Natural also, for this example there are not difference. It does make a difference. Ada has subtypes just for this purpose: If you know that the values of an object of some type belong only to some subtype, you indicate this in the declaration. This is the very idea of stong typing. > I'm using 'Range to go through all the positions in enumeration. No, you used 'Base. For a enum type E, these are always the same: for V in E loop for V in E'Range loop For an enum type that is not derived, E'Base is the same as E. For types derived from E, there might be a difference. > I tried to use Ada.Unchecked_Conversion and i got obtain the values for the position. but as you told me, if i use 'post (), the number of the list start in 0. Yes, this is what the RM prescribes. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 10:05 Problem with Position of the enumeration Type Luis Ladron de Guevara Moreno 2019-01-23 10:33 ` AdaMagica @ 2019-01-23 11:32 ` Mark Lorenzen 2019-01-23 12:30 ` Luis Ladron de Guevara Moreno 2019-01-23 17:06 ` Simon Wright 2019-01-23 21:42 ` Niklas Holsti 3 siblings, 1 reply; 25+ messages in thread From: Mark Lorenzen @ 2019-01-23 11:32 UTC (permalink / raw) On Wednesday, January 23, 2019 at 11:06:01 AM UTC+1, Luis Ladron de Guevara Moreno wrote: > Hello, > > I have an issue with the declaration of the enumeration type, when i try to map the values of an enumeration to a specific position. > > the code: > > procedure EnumerationTest is > > Position : Integer; > > type E_Test is (Pos10, Pos11, Pos12, Pos13, Pos14); > > for E_Test use (Pos10 => 10, > Pos11 => 11, > Pos12 => 12, > Pos13 => 13, > Pos14 => 14); > > begin > > for I in E_Test'Base loop > > Position := E_Test'pos (I); > ada.Text_IO.Put (" Position: " & Position'Img & " Value: " & I'Img); > end loop; > > end EnumerationTest; > > i thought that the result of the position was 10, 11, 12, 13, 14. But When i run this code, the result is 0, 1, 2, 3. I don't know what it is the exactly meaning of: > > for E_Test use (Pos10 => 10, > Pos11 => 11, > Pos12 => 12, > Pos13 => 13, > Pos14 => 14); > > and how can i assign a different position for the specific value. > Could anyone help me with this problem? > > Thank you so much =) What problem are you trying to solve? Defining the representation of enumeration values is normally only useful when doing I/O i.e. when you need to map an integer value to an enumeration value. Regards, Mark L ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 11:32 ` Mark Lorenzen @ 2019-01-23 12:30 ` Luis Ladron de Guevara Moreno 2019-01-23 20:22 ` Shark8 0 siblings, 1 reply; 25+ messages in thread From: Luis Ladron de Guevara Moreno @ 2019-01-23 12:30 UTC (permalink / raw) El miércoles, 23 de enero de 2019, 12:32:49 (UTC+1), Mark Lorenzen escribió: > On Wednesday, January 23, 2019 at 11:06:01 AM UTC+1, Luis Ladron de Guevara Moreno wrote: > > Hello, > > > > I have an issue with the declaration of the enumeration type, when i try to map the values of an enumeration to a specific position. > > > > the code: > > > > procedure EnumerationTest is > > > > Position : Integer; > > > > type E_Test is (Pos10, Pos11, Pos12, Pos13, Pos14); > > > > for E_Test use (Pos10 => 10, > > Pos11 => 11, > > Pos12 => 12, > > Pos13 => 13, > > Pos14 => 14); > > > > begin > > > > for I in E_Test'Base loop > > > > Position := E_Test'pos (I); > > ada.Text_IO.Put (" Position: " & Position'Img & " Value: " & I'Img); > > end loop; > > > > end EnumerationTest; > > > > i thought that the result of the position was 10, 11, 12, 13, 14. But When i run this code, the result is 0, 1, 2, 3. I don't know what it is the exactly meaning of: > > > > for E_Test use (Pos10 => 10, > > Pos11 => 11, > > Pos12 => 12, > > Pos13 => 13, > > Pos14 => 14); > > > > and how can i assign a different position for the specific value. > > Could anyone help me with this problem? > > > > Thank you so much =) > > What problem are you trying to solve? Defining the representation of enumeration values is normally only useful when doing I/O i.e. when you need to map an integer value to an enumeration value. > > Regards, > > Mark L My problem is that i thougth that when i write: for E_Test use (Pos10 => 10, Pos11 => 11, Pos12 => 12, Pos13 => 13, Pos14 => 14); the numbers 10, 11, 12... was the position of the enumeration and when i tried to use ex. 'Pos(Pos12) i obtained a 2. The position of the values cannot be modified. these values are the representation of the enum, i understand. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 12:30 ` Luis Ladron de Guevara Moreno @ 2019-01-23 20:22 ` Shark8 2019-01-24 8:13 ` AdaMagica 0 siblings, 1 reply; 25+ messages in thread From: Shark8 @ 2019-01-23 20:22 UTC (permalink / raw) On Wednesday, January 23, 2019 at 5:30:24 AM UTC-7, Luis Ladron de Guevara Moreno wrote: > > the numbers 10, 11, 12... was the position of the enumeration and when i tried to use ex. 'Pos(Pos12) i obtained a 2. The position of the values cannot be modified. these values are the representation of the enum, i understand. That's correct -- 'Pos gives you the position in the ordered-set of the enumeration, and 'Val does the inverse. What you want is Unchecked_Conversion, to do this well you want to specify the sizes so they match up. Type Enum_Reps is range 10..14 -- You could hide this in the private section, with Size => Natural'Size; -- and have renaming-as-a-body for the actual -- conversion functions. Function Convert is new Unchecked_Conversion( E_Test, Enum_Reps ); Function Convert is new Unchecked_Conversion( Enum_Reps, E_Test ); and then just use Convert. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 20:22 ` Shark8 @ 2019-01-24 8:13 ` AdaMagica 0 siblings, 0 replies; 25+ messages in thread From: AdaMagica @ 2019-01-24 8:13 UTC (permalink / raw) Am Mittwoch, 23. Januar 2019 21:22:09 UTC+1 schrieb Shark8: > What you want is Unchecked_Conversion, to do this well you want to specify the sizes so they match up. Tht's correct, sizes of source and target must be same. > Type Enum_Reps is range 10..14 -- You could hide this in the private section, > with Size => Natural'Size; -- and have renaming-as-a-body for the actual > -- conversion functions. But this is wrong. Enum_Reps'Size (Natural as defined) is very different from E_Test'Size. If you want to know what might happen in this case, see http://www.christ-usch-grein.homepage.t-online.de/AdaMagica/Prokrustes-e.html I was bitten by this when porting Ada code from one architeture and commpiler to a different archit. and comp. > Function Convert is new Unchecked_Conversion( E_Test, Enum_Reps ); > Function Convert is new Unchecked_Conversion( Enum_Reps, E_Test ); > > and then just use Convert. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 10:05 Problem with Position of the enumeration Type Luis Ladron de Guevara Moreno 2019-01-23 10:33 ` AdaMagica 2019-01-23 11:32 ` Mark Lorenzen @ 2019-01-23 17:06 ` Simon Wright 2019-01-23 22:54 ` Randy Brukardt 2019-01-23 21:42 ` Niklas Holsti 3 siblings, 1 reply; 25+ messages in thread From: Simon Wright @ 2019-01-23 17:06 UTC (permalink / raw) Luis Ladron de Guevara Moreno <luis33.lgm@gmail.com> writes: > type E_Test is (Pos10, Pos11, Pos12, Pos13, Pos14); > > for E_Test use (Pos10 => 10, > Pos11 => 11, > Pos12 => 12, > Pos13 => 13, > Pos14 => 14); > i thought that the result of the position was 10, 11, 12, 13, 14. But > When i run this code, the result is 0, 1, 2, 3. As Karl Müller <mtb23@gmx.de> hinted, you can use the non-standard GNAT implementation-defined attribute 'Enum_Rep[1]. The next page describes 'Enum_Val. [1] https://gcc.gnu.org/onlinedocs/gnat_rm/Attribute-Enum_005fRep.html ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 17:06 ` Simon Wright @ 2019-01-23 22:54 ` Randy Brukardt 2019-01-23 23:47 ` Keith Thompson 0 siblings, 1 reply; 25+ messages in thread From: Randy Brukardt @ 2019-01-23 22:54 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 419 bytes --] "Simon Wright" <simon@pushface.org> wrote in message news:lyzhrruww2.fsf@pushface.org... ... > As Karl Müller <mtb23@gmx.de> hinted, you can use the non-standard GNAT > implementation-defined attribute 'Enum_Rep[1]. The next page describes > 'Enum_Val. It's Standard, just not until Ada 2020. See http://www.ada-auth.org/standards/2xrm/html/RM-13-4.html#p10.1. (Yes, borrowed from GNAT.) Randy. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 22:54 ` Randy Brukardt @ 2019-01-23 23:47 ` Keith Thompson 2019-01-24 4:34 ` Keith Thompson 2019-01-24 21:41 ` Randy Brukardt 0 siblings, 2 replies; 25+ messages in thread From: Keith Thompson @ 2019-01-23 23:47 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Simon Wright" <simon@pushface.org> wrote in message > news:lyzhrruww2.fsf@pushface.org... > ... >> As Karl Müller <mtb23@gmx.de> hinted, you can use the non-standard GNAT >> implementation-defined attribute 'Enum_Rep[1]. The next page describes >> 'Enum_Val. > > It's Standard, just not until Ada 2020. See > http://www.ada-auth.org/standards/2xrm/html/RM-13-4.html#p10.1. > > (Yes, borrowed from GNAT.) I'm glad to see this being standardized. Unchecked_Conversion can be a workaround, but it's difficult (perhaps impossible) to portably determine the integer type to which you need to convert. For example, both of these are valid: type Unsigned_Byte is (UMin, UMax); for Unsigned_Byte use (0, 255); for Unsigned_Byte'Size use 8; type Signed_Byte is (SMin, SMax); for Signed_Byte use (-128, 127); for Signed_Byte'Size use 8; Both types will have the same representation for the min and max values. How can you *portably* determine the appropriate target type for an Unchecked_Conversion that yields the correct values? (You can do it manually on a case by case basis.) -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */ ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 23:47 ` Keith Thompson @ 2019-01-24 4:34 ` Keith Thompson 2019-01-24 9:11 ` Simon Wright 2019-01-24 21:41 ` Randy Brukardt 1 sibling, 1 reply; 25+ messages in thread From: Keith Thompson @ 2019-01-24 4:34 UTC (permalink / raw) Keith Thompson <kst-u@mib.org> writes: > "Randy Brukardt" <randy@rrsoftware.com> writes: >> "Simon Wright" <simon@pushface.org> wrote in message >> news:lyzhrruww2.fsf@pushface.org... >> ... >>> As Karl Müller <mtb23@gmx.de> hinted, you can use the non-standard GNAT >>> implementation-defined attribute 'Enum_Rep[1]. The next page describes >>> 'Enum_Val. >> >> It's Standard, just not until Ada 2020. See >> http://www.ada-auth.org/standards/2xrm/html/RM-13-4.html#p10.1. >> >> (Yes, borrowed from GNAT.) > > I'm glad to see this being standardized. GNAT 7.30 has a bug in its implementation of the 'Enum_Val attribute. In some cases, it appears to examine only the low-order bits of the argument, causing it to yield a valid value when it should raise Constraint_Error. A demo: with Ada.Text_IO; use Ada.Text_IO; procedure Enum_Bug is type Enum is (Two, Four); for Enum use (2, 4); begin for I in 10 .. 11 loop begin Put(Integer'Image(I) & ": "); Put_Line(Enum'Image(Enum'Enum_Val(I))); exception when Constraint_Error => Put_Line("Constraint_Error"); end; end loop; end Enum_Bug; Expected output: 10: Constraint_Error 11: Constraint_Error Actual output: 10: TWO 11: Constraint_Error I'll also report this via https://www.adacore.com/community/contact -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */ ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-24 4:34 ` Keith Thompson @ 2019-01-24 9:11 ` Simon Wright 0 siblings, 0 replies; 25+ messages in thread From: Simon Wright @ 2019-01-24 9:11 UTC (permalink / raw) Keith Thompson <kst-u@mib.org> writes: > GNAT 7.30 has a bug in its implementation of the 'Enum_Val attribute. > In some cases, it appears to examine only the low-order bits of the > argument, causing it to yield a valid value when it should raise > Constraint_Error. Same error in FSF GCC 8.1.0, 9.0.0. > I'll also report this via https://www.adacore.com/community/contact Better to <report@adacore.com>, I think ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 23:47 ` Keith Thompson 2019-01-24 4:34 ` Keith Thompson @ 2019-01-24 21:41 ` Randy Brukardt 1 sibling, 0 replies; 25+ messages in thread From: Randy Brukardt @ 2019-01-24 21:41 UTC (permalink / raw) "Keith Thompson" <kst-u@mib.org> wrote in message news:lnimyf0wee.fsf@kst-u.example.com... > "Randy Brukardt" <randy@rrsoftware.com> writes: ... > Both types will have the same representation for the min and max values. > How can you *portably* determine the appropriate target type for an > Unchecked_Conversion that yields the correct values? > > (You can do it manually on a case by case basis.) But that's impossible in a generic unit. Which was the main reason for finally deciding to include these attributes. Randy. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 10:05 Problem with Position of the enumeration Type Luis Ladron de Guevara Moreno ` (2 preceding siblings ...) 2019-01-23 17:06 ` Simon Wright @ 2019-01-23 21:42 ` Niklas Holsti 2019-01-23 22:35 ` Simon Wright 2019-01-26 9:44 ` G.B. 3 siblings, 2 replies; 25+ messages in thread From: Niklas Holsti @ 2019-01-23 21:42 UTC (permalink / raw) On 19-01-23 12:05 , Luis Ladron de Guevara Moreno wrote: > Hello, > > I have an issue with the declaration of the enumeration type, > when i try to map the values of an enumeration to a specific position. > > the code: > > procedure EnumerationTest is > > Position : Integer; > > type E_Test is (Pos10, Pos11, Pos12, Pos13, Pos14); > > for E_Test use (Pos10 => 10, > Pos11 => 11, > Pos12 => 12, > Pos13 => 13, > Pos14 => 14); > > begin > > for I in E_Test'Base loop > > Position := E_Test'pos (I); > ada.Text_IO.Put (" Position: " & Position'Img & " Value: " & I'Img); > end loop; > > end EnumerationTest; > > i thought that the result of the position was 10, > 11, 12, 13, 14. But When i run this code, the result > is 0, 1, 2, 3. I don't know what it is the exactly meaning of: > > for E_Test use (Pos10 => 10, > Pos11 => 11, > Pos12 => 12, > Pos13 => 13, > Pos14 => 14); > > and how can i assign a different position for the specific value. The point is that Ada enumeration literals are not merely synonyms for integer values, unlike C enums. The list of names (enumeration literals) in the declaration of the enumerated type defines the position numbers, which always start from 0 and increase by 1 for each literal. These position numbers, which can be queried with the 'Pos attribute, are independent of the possible "for .. use" representation clause for the enumeration. On the next level -- physical representation -- if you have code like E : E_Test; ... E := Pos12; you can ask as follows: The compiler allocates a memory location for the object E. Let's say that an octet of 8 bits is allocated. What are the values of these 8 bits after the assignment of Pos12 to E? In other words, which bit pattern in memory represents the logical value Pos12? This question is answered by the presence (or absence) of a "for E_Test use" representation clause: - if there is no such clause, the value of the bits is given by the position number, which for Pos12 is 2 (2#0000_0010# in binary) - if there is such a clause, the value of the bits is given by the representation value in that clause, which for Pos12 is 12 (binary 2#0000_1100#) using the values in your example. As others have remarked, you can discover the representation value by an Unchecked_Conversion from E_Test to some integer type (with the same number of bits), or by the GNAT-specific attribute 'Enum_Rep. In your example, the representation values are contiguous, but there can also be gaps, for example: for E_Test use (Pos10 => 10, Pos11 => 21, Pos12 => 34, Pos13 => 100, Pos14 => 255); (However, the representation values must be in ascending order, so that their order is the same as the position-number order.) The important points to note are that the 'Pos values still run from 0 to 4, and most importantly that the 'Succ and 'Pred attribute functions "skip" the gaps, so that, for example, E := E_Test'Succ (Pos11); makes E = Pos12, represented in memory as 34. Thus, 'Succ is not just "add one to the value", but "take the next representation value". As an aside, this means that 'Succ and 'Pred on enumeration types with "gappy" representations can be much more expensive (in processor time) than for enumeration types with gap-less representations or default representations. For this reason, Ada design and coding rules for embedded/critical systems often place restrictions on enumeration types with representation clauses, for example that 'Succ, 'Pred and the like should not be used for such types. Such rules also commonly say that such types should not be used as array index types, because of the possible introduction of gaps in the array representations. Furthermore, if you loop over an enumeration with a gappy representations, such as for E in E_Test loop ... end loop; the loop will use _only_ the valid representations. So the bits holding the value of the loop-counter E will successively take on the values 10, 21, 34, 100, 255, but will skip the values in between. This is quite different from what would happen in C. As others have also noted, enumeration representation clauses are used mostly when the enumeration value is an input (say, from some memory-mapped control register, or from a binary input file) or an output. Communication protocols and HW interfaces often define fields that encode some finite set of possible logical values/meanings, but where the encoding has gaps. A final note: if you use an enumerated type for an input value, it is wise to check if the input is valid before using it. Use the 'Valid attribute for this. However, this attribute can also have a non-trivial cost. For example, the compiler may implement the function call E_Test'Valid(E) by code that compares the (representation of) E against each of the valid values 10, 21, 34, 100, 255 in turn (although a better compiler would use a binary search). An alternative I often use is to define the enumerated type with default representation (= position numbers), define the input as an integer (in this case 0 .. 255), and translate from input to enumeration with an array, like this: type Input_Value is range 0 .. 255; E_For_Input : constant array (Input_Value) of E_Test is := ( 10 => Pos10, 21 => Pos11, 34 => Pos12, 100 => Pos13, 255 => Pos14, others => Pos_Invalid); where I assume that E_Test is extended with the literal Pos_Invalid. Given an input value In, the corresponding enumeration value E is obtained by E := E_For_Input(I), and validity can be checked by "if E /= Pos_Invalid then ..." instead of using E_Test'Valid. A similar translation can be used to map an internal enumeration (with default representation) to an external, gappy, output encoding. These alternatives (array-based translations) have the advantage, compared to enumeration representation clauses, that the representation values (external input/output values) can use a different order than the enumerated type. This can make it easier to define logical subtypes (sub-ranges) of the enumerated type. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 21:42 ` Niklas Holsti @ 2019-01-23 22:35 ` Simon Wright 2019-01-23 23:20 ` Niklas Holsti 2019-01-24 16:43 ` Jeffrey R. Carter 2019-01-26 9:44 ` G.B. 1 sibling, 2 replies; 25+ messages in thread From: Simon Wright @ 2019-01-23 22:35 UTC (permalink / raw) Niklas Holsti <niklas.holsti@tidorum.invalid> writes: > Such rules also commonly say that such types should not be used as > array index types, because of the possible introduction of gaps in the > array representations. Not, it seems, with GNAT: $ cat gappy.adb with Ada.Text_IO; use Ada.Text_IO; procedure Gappy is type E_Test is (Pos10, Pos11, Pos12, Pos13, Pos14); for E_Test use (Pos10 => 100, Pos11 => 110, Pos12 => 120, Pos13 => 130, Pos14 => 255); type Arr is array (E_Test) of Integer; begin Put_Line ("Arr's size is" & Arr'Max_Size_In_Storage_Elements'Img & " bytes."); end Gappy; $ gnatmake -f gappy gcc -c gappy.adb gnatbind -x gappy.ali gnatlink gappy.ali $ ./gappy Arr's size is 20 bytes. I'd think any other behaviour would be unreasonable (though I can't see any statement about it in the ARM). ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 22:35 ` Simon Wright @ 2019-01-23 23:20 ` Niklas Holsti 2019-01-24 16:43 ` Jeffrey R. Carter 1 sibling, 0 replies; 25+ messages in thread From: Niklas Holsti @ 2019-01-23 23:20 UTC (permalink / raw) On 19-01-24 00:35 , Simon Wright wrote: > Niklas Holsti <niklas.holsti@tidorum.invalid> writes: > >> Such rules also commonly say that such types should not be used as >> array index types, because of the possible introduction of gaps in the >> array representations. > > Not, it seems, with GNAT: [skip example] Nice to know. > I'd think any other behaviour would be unreasonable (though I can't see > any statement about it in the ARM). Avoiding gaps in such arrays means that GNAT is effectively using the position number as the (machine-level) index, which means that indexing with an arbitrary enumeration value (not a loop induction variable) requires the use of the 'Pos function, with its possible longish execution time for a gappy enumeration. So it's a space vs time trade-off, and GNAT chooses to reduce space at the cost of time. I too think that this is the choice less likely to surprise users. While enumeration representation clauses are a logical and sometimes useful feature, they are not very often the best design approach -- or not as often as one first thinks, when learning about them. I tend to use them only for outputs on the HW level, not so much for inputs (because of the need for validity checking that I commented on). -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 22:35 ` Simon Wright 2019-01-23 23:20 ` Niklas Holsti @ 2019-01-24 16:43 ` Jeffrey R. Carter 2019-01-24 19:39 ` Niklas Holsti 1 sibling, 1 reply; 25+ messages in thread From: Jeffrey R. Carter @ 2019-01-24 16:43 UTC (permalink / raw) On 1/23/19 11:35 PM, Simon Wright wrote: > Niklas Holsti <niklas.holsti@tidorum.invalid> writes: > >> Such rules also commonly say that such types should not be used as >> array index types, because of the possible introduction of gaps in the >> array representations. > > Not, it seems, with GNAT: This is not a language rule. I can find nothing in the ARM about disallowing such types as array indices. So naturally GNAT and all other compilers must support it. -- Jeff Carter "When and now is this guitar piece from Stottlemeyer? Yes, it's with Mr. Dog in Gertrude's pinball forest." The World's Funniest Joke 133 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-24 16:43 ` Jeffrey R. Carter @ 2019-01-24 19:39 ` Niklas Holsti 2019-01-24 20:29 ` Jeffrey R. Carter 2019-01-24 21:43 ` Randy Brukardt 0 siblings, 2 replies; 25+ messages in thread From: Niklas Holsti @ 2019-01-24 19:39 UTC (permalink / raw) On 19-01-24 18:43 , Jeffrey R. Carter wrote: > On 1/23/19 11:35 PM, Simon Wright wrote: >> Niklas Holsti <niklas.holsti@tidorum.invalid> writes: >> >>> Such rules also commonly say that such types should not be used as >>> array index types, because of the possible introduction of gaps in the >>> array representations. >> >> Not, it seems, with GNAT: > > This is not a language rule. I can find nothing in the ARM about > disallowing such types as array indices. So naturally GNAT and all other > compilers must support it. All compliant compilers, yes. But the question was: if the enumerated index type has gaps in its representation, can there be corresponding gaps (unused intervals of storage units) between the elements of the array, as represented in memory? Or must the elements still be contiguous, except for alignment padding? In other words, can the compiled code compute the offset of an array element directly from the representation of the enumerated index value (causing gaps in the array), or must it always first compute the position number of that value, and then compute the offset from the position number (suppressing gaps)? This discussion has not yet pointed to an ARM rule that forbids gaps in the array's representation. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-24 19:39 ` Niklas Holsti @ 2019-01-24 20:29 ` Jeffrey R. Carter 2019-01-24 21:43 ` Randy Brukardt 1 sibling, 0 replies; 25+ messages in thread From: Jeffrey R. Carter @ 2019-01-24 20:29 UTC (permalink / raw) On 1/24/19 8:39 PM, Niklas Holsti wrote: > > All compliant compilers, yes. But the question was: if the enumerated index type > has gaps in its representation, can there be corresponding gaps (unused > intervals of storage units) between the elements of the array, as represented in > memory? Or must the elements still be contiguous, except for alignment padding? > > In other words, can the compiled code compute the offset of an array element > directly from the representation of the enumerated index value (causing gaps in > the array), or must it always first compute the position number of that value, > and then compute the offset from the position number (suppressing gaps)? > > This discussion has not yet pointed to an ARM rule that forbids gaps in the > array's representation. In the absence of representation specifications (Component_Size, Pack, Convention), AFAIK the only thing that the ARM says about the implementation of arrays is that multidimensional arrays must be in row-major order. Other than that, it's up to the compiler, so any array could have "gaps", regardless of the index subtypes. -- Jeff Carter "When and now is this guitar piece from Stottlemeyer? Yes, it's with Mr. Dog in Gertrude's pinball forest." The World's Funniest Joke 133 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-24 19:39 ` Niklas Holsti 2019-01-24 20:29 ` Jeffrey R. Carter @ 2019-01-24 21:43 ` Randy Brukardt 1 sibling, 0 replies; 25+ messages in thread From: Randy Brukardt @ 2019-01-24 21:43 UTC (permalink / raw) "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message news:gauihgF9eu2U1@mid.individual.net... > On 19-01-24 18:43 , Jeffrey R. Carter wrote: >> On 1/23/19 11:35 PM, Simon Wright wrote: >>> Niklas Holsti <niklas.holsti@tidorum.invalid> writes: >>> >>>> Such rules also commonly say that such types should not be used as >>>> array index types, because of the possible introduction of gaps in the >>>> array representations. >>> >>> Not, it seems, with GNAT: >> >> This is not a language rule. I can find nothing in the ARM about >> disallowing such types as array indices. So naturally GNAT and all other >> compilers must support it. > > All compliant compilers, yes. But the question was: if the enumerated > index type has gaps in its representation, can there be corresponding gaps > (unused intervals of storage units) between the elements of the array, as > represented in memory? Or must the elements still be contiguous, except > for alignment padding? > > In other words, can the compiled code compute the offset of an array > element directly from the representation of the enumerated index value > (causing gaps in the array), or must it always first compute the position > number of that value, and then compute the offset from the position number > (suppressing gaps)? > > This discussion has not yet pointed to an ARM rule that forbids gaps in > the array's representation. There's no language rule of course, but more a practical one: operations like slicing and sliding become challenging if the array has gaps. And you don't get to ignore those just 'cause they're hard. Randy. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Problem with Position of the enumeration Type 2019-01-23 21:42 ` Niklas Holsti 2019-01-23 22:35 ` Simon Wright @ 2019-01-26 9:44 ` G.B. 1 sibling, 0 replies; 25+ messages in thread From: G.B. @ 2019-01-26 9:44 UTC (permalink / raw) On 23.01.19 22:42, Niklas Holsti wrote: > > As others have also noted, enumeration representation clauses are used mostly when the enumeration value is an input (say, from some memory-mapped control register, or from a binary input file) or an output. Communication protocols and HW interfaces often define fields that encode some finite set of possible logical values/meanings, but where the encoding has gaps. > > A final note: if you use an enumerated type for an input value, it is wise to check if the input is valid before using it. Use the 'Valid attribute for this. However, this attribute can also have a non-trivial cost. For example, the compiler may implement the function call E_Test'Valid(E) by code that compares the (representation of) E against each of the valid values 10, 21, 34, 100, 255 in turn (although a better compiler would use a binary search). Has it been pointed out that one can use two enum types together, one for I/O and the other for internal purposes and then simply convert? type E_Test is (A, B, C); type E_for_IO is new E_Test; for E_for_IO use (A => 2#0000_1010# B => 2#0001_0101# C => 2#0010_0010#); ... some_E_Test := E_Test (some_E_for_IO); -- "HOTDOGS ARE NOT BOOKMARKS" Springfield Elementary teaching staff ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2019-01-26 9:44 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-01-23 10:05 Problem with Position of the enumeration Type Luis Ladron de Guevara Moreno 2019-01-23 10:33 ` AdaMagica 2019-01-23 10:55 ` AdaMagica 2019-01-23 12:08 ` Luis Ladron de Guevara Moreno 2019-01-23 12:15 ` Karl Müller 2019-01-23 21:50 ` Niklas Holsti 2019-01-24 8:06 ` AdaMagica 2019-01-23 11:32 ` Mark Lorenzen 2019-01-23 12:30 ` Luis Ladron de Guevara Moreno 2019-01-23 20:22 ` Shark8 2019-01-24 8:13 ` AdaMagica 2019-01-23 17:06 ` Simon Wright 2019-01-23 22:54 ` Randy Brukardt 2019-01-23 23:47 ` Keith Thompson 2019-01-24 4:34 ` Keith Thompson 2019-01-24 9:11 ` Simon Wright 2019-01-24 21:41 ` Randy Brukardt 2019-01-23 21:42 ` Niklas Holsti 2019-01-23 22:35 ` Simon Wright 2019-01-23 23:20 ` Niklas Holsti 2019-01-24 16:43 ` Jeffrey R. Carter 2019-01-24 19:39 ` Niklas Holsti 2019-01-24 20:29 ` Jeffrey R. Carter 2019-01-24 21:43 ` Randy Brukardt 2019-01-26 9:44 ` G.B.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox