* Representation Clauses And Freezing @ 2000-07-17 0:00 Marin D. Condic 2000-07-17 0:00 ` Stephen Leake ` (2 more replies) 0 siblings, 3 replies; 15+ messages in thread From: Marin D. Condic @ 2000-07-17 0:00 UTC (permalink / raw) I am trying to find a reasonable workaround to a problem involving representation clauses and tagged records. I believe I am running into problems with freezing rules. Below are two compiler listings which are very similar. When the record type is visible, the compiler is happy. When the record type is private, it complains. The question in my mind is *WHY* is there some sort of restriction on this? What compiler mission cannot be achieved unless the record is visible? Is there some sort of workaround that would enable representation clauses on private tagged records? (Inheritance from a rep-claused-tagged-record is its own problem!) GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, Inc. Compiling: rep_clause_01.ads (source file time stamp: 2000-07-17 14:20:14) 1. with System ; 2. 3. package Rep_Clause_01 is 4. 5. type UInteger_16 is mod 2**16 ; 6. for UInteger_16'Size use 16 ; 7. 8. type Rec_Type is tagged record 9. Field_01 : Uinteger_16 := 0 ; 10. Field_02 : Uinteger_16 := 0 ; 11. Field_03 : Uinteger_16 := 0 ; 12. end record ; 13. 14. private 15. 16. for Rec_Type use record 17. Field_01 at 4 range 0..15 ; 18. Field_02 at 6 range 0..15 ; 19. Field_03 at 8 range 0..15 ; 20. end record ; 21. 22. for Rec_Type'Size use 10 * System.Storage_Unit ; 23. for Rec_Type'Alignment use 2 ; 24. 25. end Rep_Clause_01 ; 25 lines: No errors GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, Inc. Compiling: rep_clause_02.ads (source file time stamp: 2000-07-17 14:20:14) 1. 2. with System ; 3. 4. package Rep_Clause_02 is 5. 6. type UInteger_16 is mod 2**16 ; 7. for UInteger_16'Size use 16 ; 8. 9. type Rec_Type is tagged private ; 10. 11. private 12. 13. type Rec_Type is tagged record 14. Field_01 : Uinteger_16 := 0 ; 15. Field_02 : Uinteger_16 := 0 ; 16. Field_03 : Uinteger_16 := 0 ; 17. end record ; 18. 19. for Rec_Type use record 20. Field_01 at 4 range 0..15 ; 21. Field_02 at 6 range 0..15 ; 22. Field_03 at 8 range 0..15 ; 23. end record ; 24. 25. for Rec_Type'Size use 10 * System.Storage_Unit ; | >>> size for "Rec_Type" too small, minimum allowed is 128 26. for Rec_Type'Alignment use 2 ; | >>> alignment for "Rec_Type" must be at least 4 27. 28. end Rep_Clause_02 ; MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Nothing in the world is more dangerous than sincere ignorance and conscientious stupidity." -- Martin Luther King, Jr ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-17 0:00 Representation Clauses And Freezing Marin D. Condic @ 2000-07-17 0:00 ` Stephen Leake 2000-07-20 0:00 ` Marin D. Condic 2000-07-18 0:00 ` Tucker Taft 2000-07-18 0:00 ` Nicolas Brunot 2 siblings, 1 reply; 15+ messages in thread From: Stephen Leake @ 2000-07-17 0:00 UTC (permalink / raw) If you follow the compiler's advice, and change the size and alignment clauses to: for Rec_Type'Size use 16 * System.Storage_Unit; for Rec_Type'Alignment use 4; then it is "happy" again (well, except for all the spaces before the semicolons, but not around elipses :). I have no explanation for why the record size and alignment changes when it is a private type. But why do you care? We've been around on this topic before; the general consensus has been that it is better to define a non-tagged record type that has a rep clause, and include that as a component in a tagged type. -- Stephe "Marin D. Condic" <mcondic-nospam@acm.com> writes: > I am trying to find a reasonable workaround to a problem involving > representation clauses and tagged records. I believe I am running into > problems with freezing rules. Below are two compiler listings which are > very similar. When the record type is visible, the compiler is happy. > When the record type is private, it complains. The question in my mind > is *WHY* is there some sort of restriction on this? What compiler > mission cannot be achieved unless the record is visible? Is there some > sort of workaround that would enable representation clauses on private > tagged records? (Inheritance from a rep-claused-tagged-record is its own > problem!) > > GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, > Inc. > > Compiling: rep_clause_01.ads (source file time stamp: 2000-07-17 > 14:20:14) > > 1. with System ; > 2. > 3. package Rep_Clause_01 is > 4. > 5. type UInteger_16 is mod 2**16 ; > 6. for UInteger_16'Size use 16 ; > 7. > 8. type Rec_Type is tagged record > 9. Field_01 : Uinteger_16 := 0 ; > 10. Field_02 : Uinteger_16 := 0 ; > 11. Field_03 : Uinteger_16 := 0 ; > 12. end record ; > 13. > 14. private > 15. > 16. for Rec_Type use record > 17. Field_01 at 4 range 0..15 ; > 18. Field_02 at 6 range 0..15 ; > 19. Field_03 at 8 range 0..15 ; > 20. end record ; > 21. > 22. for Rec_Type'Size use 10 * System.Storage_Unit ; > 23. for Rec_Type'Alignment use 2 ; > 24. > 25. end Rep_Clause_01 ; > > 25 lines: No errors > > > GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, > Inc. > > Compiling: rep_clause_02.ads (source file time stamp: 2000-07-17 > 14:20:14) > > 1. > 2. with System ; > 3. > 4. package Rep_Clause_02 is > 5. > 6. type UInteger_16 is mod 2**16 ; > 7. for UInteger_16'Size use 16 ; > 8. > 9. type Rec_Type is tagged private ; > 10. > 11. private > 12. > 13. type Rec_Type is tagged record > 14. Field_01 : Uinteger_16 := 0 ; > 15. Field_02 : Uinteger_16 := 0 ; > 16. Field_03 : Uinteger_16 := 0 ; > 17. end record ; > 18. > 19. for Rec_Type use record > 20. Field_01 at 4 range 0..15 ; > 21. Field_02 at 6 range 0..15 ; > 22. Field_03 at 8 range 0..15 ; > 23. end record ; > 24. > 25. for Rec_Type'Size use 10 * System.Storage_Unit ; > | > >>> size for "Rec_Type" too small, minimum allowed is 128 > > 26. for Rec_Type'Alignment use 2 ; > | > >>> alignment for "Rec_Type" must be at least 4 > > 27. > 28. end Rep_Clause_02 ; > > > > MDC > -- > ====================================================================== > Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ > Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m > Visit my web site at: http://www.mcondic.com/ > > "Nothing in the world is more dangerous than sincere ignorance and > conscientious stupidity." > > -- Martin Luther King, Jr > ====================================================================== -- -- Stephe ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-17 0:00 ` Stephen Leake @ 2000-07-20 0:00 ` Marin D. Condic 2000-07-20 0:00 ` Stephen Leake 2000-07-21 0:00 ` tmoran 0 siblings, 2 replies; 15+ messages in thread From: Marin D. Condic @ 2000-07-20 0:00 UTC (permalink / raw) Stephen Leake wrote: > > If you follow the compiler's advice, and change the size and alignment > clauses to: > > for Rec_Type'Size use 16 * System.Storage_Unit; > for Rec_Type'Alignment use 4; > > then it is "happy" again (well, except for all the spaces before the > semicolons, but not around elipses :). > Making the compiler happy isn't really the issue. If I could accept whatever the compiler insisted on giving me, then I wouldn't need a representation clause, right? My question is, if in fact this is some sort of required behavior because of freezing rules or other language issues, then *why* is it required? If it is *not* required behavior, then that just means I've got a compiler weakness and another compiler might actually make this work. > I have no explanation for why the record size and alignment changes > when it is a private type. But why do you care? > If it is legal to slam a representation clause on a tagged type and if tagged types exist to enable object oriented design (hence the "private" aspects), then one ought to be able to slam a representation clause on the tagged record in the private part of the spec and not have to put the record elements in the visible part of the spec. Otherwise, what's the point? Why do I care? I'm often confronted with problems that require control of representation and I'd like to be in a position to say "Ada can do that!" In the case where tagged records and control of representation intersect, it appears that this is not the case - unless as suggested by Tucker Taft elsewhere in the thread, this is just a compiler weakness. > We've been around on this topic before; the general consensus has been > that it is better to define a non-tagged record type that has a rep > clause, and include that as a component in a tagged type. > I find that answer to be unacceptable for a variety of reasons. Mostly because you have a hard time building class-wide operations that depend on representation and other attributes to get the job done that you want done. It also has efficiency concerns and other problems that may not be an issue for many systems, but they are for some of mine. At this stage, I'm more interested in establishing some reason for why such a restriction would exist - if it is not just a compiler bug. It is possible that what I want to do is perfectly legitimate and its just an obstinate implementation that won't give me what I want. Or its possible it is a language restriction - in which case maybe there needs to be a revision somewhere along the line to remove that restriction. MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Nothing in the world is more dangerous than sincere ignorance and conscientious stupidity." -- Martin Luther King, Jr ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-20 0:00 ` Marin D. Condic @ 2000-07-20 0:00 ` Stephen Leake 2000-07-21 0:00 ` Marin D. Condic 2000-07-21 0:00 ` tmoran 1 sibling, 1 reply; 15+ messages in thread From: Stephen Leake @ 2000-07-20 0:00 UTC (permalink / raw) "Marin D. Condic" <mcondic-nospam@acm.com> writes: > Stephen Leake wrote: > > > > If you follow the compiler's advice, and change the size and alignment > > clauses to: > > > > for Rec_Type'Size use 16 * System.Storage_Unit; > > for Rec_Type'Alignment use 4; > > > > then it is "happy" again (well, except for all the spaces before the > > semicolons, but not around elipses :). > > > Making the compiler happy isn't really the issue. If I could accept > whatever the compiler insisted on giving me, then I wouldn't need a > representation clause, right? But you can give a rep clause. It's just not the same one as you could give if the type were public. So I don't understand what the problem is. > My question is, if in fact this is some sort of required behavior > because of freezing rules or other language issues, then *why* is it > required? If it is *not* required behavior, then that just means I've > got a compiler weakness and another compiler might actually make this > work. Compilers are free to choose the implementation for tagged types. This compiler apparently has a representation for private tagged types that is slightly different then for public tagged types. Your rep clause does not completely specify the full tagged type. So again, what is the problem? > If it is legal to slam a representation clause on a tagged type and if > tagged types exist to enable object oriented design (hence the "private" > aspects), then one ought to be able to slam a representation clause on > the tagged record in the private part of the spec and not have to put > the record elements in the visible part of the spec. Otherwise, what's > the point? See above; it is legal to put a rep clause on a private tagged type. GNAT says so. > Why do I care? I'm often confronted with problems that require control > of representation and I'd like to be in a position to say "Ada can do > that!" In the case where tagged records and control of representation > intersect, it appears that this is not the case - unless as suggested by > Tucker Taft elsewhere in the thread, this is just a compiler weakness. You have two very different issues. First, the rep clause you gave was rejected by the compiler, so you need to find out why and/or fix the rep clause so it will be accepted. Second, you want to know if rep clauses are legal on private tagged types. The answer to the first issue is given above; that rep clause is accepted by GNAT. The answer to the second issue is "yes". > > We've been around on this topic before; the general consensus has been > > that it is better to define a non-tagged record type that has a rep > > clause, and include that as a component in a tagged type. > > > I find that answer to be unacceptable for a variety of reasons. Mostly > because you have a hard time building class-wide operations that depend > on representation and other attributes to get the job done that you want > done. It also has efficiency concerns and other problems that may not be > an issue for many systems, but they are for some of mine. You'll have to be more specific. I don't see a significant difference: Method 1: type Specific_Rep_Type is record something : integer_32; something_else : integer_32; end record; for Specific_Rep_Type use record something at 0 range 0 .. 31; something_else at 4 range 0 .. 31; end record; for Specific_Rep_Type'size use 64; type Object_Type is tagged record specific_stuff : Specific_rep_Type; end record; Method 2: type Object_Type is tagged record something : integer_32; something_else : integer_32; end record; for Specific_Rep_Type use record something at <implementation_specific> range 0 .. 31; something_else at <implementation_specific> range 0 .. 31; end record; for Object_Type'size use 64 + <implementation_specific>; Method 1 is guaranteed portable across compilers, and clearly specifies the size and location of everything that is critical. The rep clauses are the same whether the type is public or private. Method 2 is not guaranteed portable, and is certainly less clear about what is critically placed and what is not. As you have seen, the rep clauses may have to change depending on whether the type is public or private; that's included in the meaning of <implementation_specific>. What advantage of Method 2 am I missing? > At this stage, I'm more interested in establishing some reason for why > such a restriction would exist - if it is not just a compiler bug. It is > possible that what I want to do is perfectly legitimate and its just an > obstinate implementation that won't give me what I want. Or its possible > it is a language restriction - in which case maybe there needs to be a > revision somewhere along the line to remove that restriction. You don't have a "restriction", you have a "difference in implementation specifics between public and private tagged types". Perfectly legitimate according to the Ada 95 standard. -- -- Stephe ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-20 0:00 ` Stephen Leake @ 2000-07-21 0:00 ` Marin D. Condic 2000-07-21 0:00 ` Stephen Leake 2000-07-21 0:00 ` Simon Wright 0 siblings, 2 replies; 15+ messages in thread From: Marin D. Condic @ 2000-07-21 0:00 UTC (permalink / raw) Stephen Leake wrote: > > Making the compiler happy isn't really the issue. If I could accept > > whatever the compiler insisted on giving me, then I wouldn't need a > > representation clause, right? > > But you can give a rep clause. It's just not the same one as you could > give if the type were public. So I don't understand what the problem is. > Are you serious? What good is a rep clause unless it is the rep clause that *I* want? If any old rep clause would do, then why bother putting one on there at all? Decoration? Try to imagine that you want to line up a data type to match a hardware register or a message coming into a system from the outside world. You have to put a rep clause on the data type so that specific bits, bytes and words fall into specific positions. Having the compiler reject your rep clause and suggest another does absolutely no good and is totally pointless. > Compilers are free to choose the implementation for tagged types. This > compiler apparently has a representation for private tagged types that > is slightly different then for public tagged types. Your rep clause > does not completely specify the full tagged type. So again, what is > the problem? > Thats just another way of saying "it is legal behavior for a compiler to reject all representation clauses" - which is another way of saying that it is totally useless. I understand that a compiler needs to be in a position to pick the representation of the tag, but I ought to be able to own the entire rest of the record - including any derivations thereof. If the compiler wants to own bits 0..31, that's fine with me, but I want to own bits 32..N and get exactly what I specify. No longword alignments I didn't ask for. No extra spare space between fields. Nothing but precisely what I specify - otherwise it does me no good. You might just as well have said "representation clauses on tagged records are illegal in Ada" because it amounts to the same thing. > > First, the rep clause you gave was rejected by the compiler, so you > need to find out why and/or fix the rep clause so it will be accepted. > Bzzzzzzzt. Wrong answer. :-) My rep clause expresses a legitimate representation of the data in legal syntax. A compiler is free to reject it and claim to be validated. Fair enough. But if it rejects it and claims to be useful - "just change your representation to my representation" then I must regretfully reject the compiler for this application. Now if there is another way of *expressing* the same representation that the compiler will like better, I'll accept that as a workaround - but that's like saying "if it won't accept it on a tagged record, then just don't use tagged records - use a regular record or an array of raw bytes or something else." Sure, you can do that, but then you lose the use of the language feature and you're back to asking what good is it to have a rep clause for a tagged record? Why not just program the whole thing in assembly language? > > You'll have to be more specific. I don't see a significant difference: > > Method 1: > > type Specific_Rep_Type is record > something : integer_32; > something_else : integer_32; > end record; > for Specific_Rep_Type use record > something at 0 range 0 .. 31; > something_else at 4 range 0 .. 31; > end record; > for Specific_Rep_Type'size use 64; > > type Object_Type is tagged record > specific_stuff : Specific_rep_Type; > end record; > Is the following statement guaranteed to be true? Object_Type'Size = Specific_Rep_Type'Size Well of course not. We've got to account for the tag so I'll accept subtraction of a constant to remove the tag. Is the following statement true in all cases (assuming the tag is a 32 bit word) (Object_Type'Size - 32) = Specific_Rep_Type'Size Now go extend that Object_Type with Another_Specific_Rep_Type and are you guaranteed that (New_Object_Type'Size - 32) = (Specific_Rep_Type'Size + Another_Specific_Rep_Type'Size) The answer, BTW, is "no". The first one *may* hold by accident, but is not guaranteed because Object_Type may extend its size to do word alignment, etc. The second one doesn't hold, again because the compiler may choose to start the additional fields at any offset from the beginning of the record. Why do I want to do this? I suppose its not going to be sufficient to say "because I just do!" :-) Try putting an overlay of a byte array on top of the record. Why? It's a really fast way of translating the record into something you can run down the wire to someone else. You get your structured data for 99% of the computing and you get your raw data for the 1% of the computing that needs to treat it as such. Isolating that in the non-visible part of the base class and making it work for all derived classes is a *really slick* way of building a message passing system. You probably also want to put a word array or longword array overlay on top of it so you can compute checksums. You also want 'Size to give you what you expect so you can compute the size of the message. Yada Yada Yada. Trust me on this - I've done a lot of message passing stuff and I've always found Ada to be a real nasty bitch (especially 83) when trying to use it for this kind of application. It is a *lot* easier to get this out of C or other languages that pretty much let you toss type safety out the window. (Don't take this as an endorsement of C - just an illustration.) And please don't offer me 'Read and 'Write. Not only is it data motion, but it degenerates to too many procedure calls and still leaves you with no good way of computing the message size or checksums as you go along. I could eat the efficiency issues on many apps, but many others can't ignore it. > You don't have a "restriction", you have a "difference in > implementation specifics between public and private tagged types". > Perfectly legitimate according to the Ada 95 standard. > And as I said before, totally useless. Just because it is "legal" doesn't make it "useful". I think the reason this problem annoys me so much is that over the years, Ada has taken a lot of heat from real time programmers because it was viewed as too restrictive. I've defended the language in most cases because I knew it well enough to know that there was usually some way of getting what you needed out of it. In the arena of message passing systems, I've always had to conceed that Ada made you do so many butt-ugly things to get what you needed done that it almost wasn't worth it. Ada95 fixed a lot of sore spots for the real time and embedded world, but I still can't build the message passing stuff in an elegant and efficient way - not unless I find a compiler that will let me get absolute control over the representation of the tagged types. Either that or give me a "union" and pointers I can translate into arrays. :-) MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Nothing in the world is more dangerous than sincere ignorance and conscientious stupidity." -- Martin Luther King, Jr ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-21 0:00 ` Marin D. Condic @ 2000-07-21 0:00 ` Stephen Leake 2000-07-21 0:00 ` Marin D. Condic 2000-07-21 0:00 ` Simon Wright 1 sibling, 1 reply; 15+ messages in thread From: Stephen Leake @ 2000-07-21 0:00 UTC (permalink / raw) "Marin D. Condic" <mcondic-nospam@acm.com> writes: > Stephen Leake wrote: > > > Making the compiler happy isn't really the issue. If I could accept > > > whatever the compiler insisted on giving me, then I wouldn't need a > > > representation clause, right? > > > > But you can give a rep clause. It's just not the same one as you could > > give if the type were public. So I don't understand what the problem is. > > > Are you serious? What good is a rep clause unless it is the rep clause > that *I* want? If any old rep clause would do, then why bother putting > one on there at all? Decoration? The difference was in the size and alignment representation clauses: You wanted: for Rec_Type use record Field_01 at 4 range 0..15 ; Field_02 at 6 range 0..15 ; Field_03 at 8 range 0..15 ; end record ; for Rec_Type'Size use 10 * System.Storage_Unit; for Rec_Type'Alignment use 4; The compiler will accept: for Rec_Type use record Field_01 at 4 range 0..15 ; Field_02 at 6 range 0..15 ; Field_03 at 8 range 0..15 ; end record ; for Rec_Type'Size use 16 * System.Storage_Unit; for Rec_Type'Alignment use 4; The fields you explicitly located are in the same places. I'm not clear why you can't live with this size and alignment for the record. > Try to imagine that you want to line up a data type to match a hardware > register or a message coming into a system from the outside world. You > have to put a rep clause on the data type so that specific bits, bytes > and words fall into specific positions. Having the compiler reject your > rep clause and suggest another does absolutely no good and is totally > pointless. Clearly the size can't matter, since the only compiler knows the tag size. I can see that alignment might matter, but it should be simple to get the message into the right alignment in the first place. Is that the problem? You also indicate below that you want to specify the locations of additional components in derived types, and that there seems to be padding at the end of Rec_Type above. Instead, assume the extra space is actually additional tag information, and move your fields down: for Rec_Type use record -- tag seems to be 10 bytes Field_01 at 10 range 0..15 ; Field_02 at 12 range 0..15 ; Field_03 at 14 range 0..15 ; end record ; for Rec_Type'Size use 16 * System.Storage_Unit; for Rec_Type'Alignment use 4; Oops, the compiler doesn't like this either; it wants more space. So I don't know what's going on, and I can see that this will not work for derived types; you can't live with "gaps" in the representation. So I am reduced to suggesting that you call ACT, and ask them how to make it work (you are a paying customer?). They may know a work-around, or they may be able to change the compiler to do what you want. > <snip> > Yada Yada Yada. Trust me on this - I've done a lot of message passing > stuff and I've always found Ada to be a real nasty bitch (especially 83) > when trying to use it for this kind of application. It is a *lot* easier > to get this out of C or other languages that pretty much let you toss > type safety out the window. (Don't take this as an endorsement of C - > just an illustration.) Perhaps you see it as "easier" in C because C doesn't have tagged types, so none of the issues you are raising here occur. You can always convert a tagged record into an equivalent variant record. Perhaps you cannot afford the run-time overhead to do this, so you are trying to map the tagged record directly onto the byte stream. I agree that is a neat way to do things. > <snip> > I think the reason this problem annoys me so much is that over the > years, Ada has taken a lot of heat from real time programmers because it > was viewed as too restrictive. I've defended the language in most cases > because I knew it well enough to know that there was usually some way of > getting what you needed out of it. In the arena of message passing > systems, I've always had to conceed that Ada made you do so many > butt-ugly things to get what you needed done that it almost wasn't worth > it. But you are comparing apples and oranges. C has no tagged types. If you want to say "message passing is easier in C than in Ada", please be sure you are comparing variant records in each, not variant records in C to tagged records in Ada! > Ada95 fixed a lot of sore spots for the real time and embedded > world, but I still can't build the message passing stuff in an > elegant and efficient way - not unless I find a compiler that will > let me get absolute control over the representation of the tagged > types. Either that or give me a "union" and pointers I can translate > into arrays. :-) You have "union" and pointers. Either via Unchecked_Conversion, or via pragma Unchecked_Union. Take the C solution you like, and translate into Ada. Then you'll have the best of both worlds! -- -- Stephe ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-21 0:00 ` Stephen Leake @ 2000-07-21 0:00 ` Marin D. Condic 0 siblings, 0 replies; 15+ messages in thread From: Marin D. Condic @ 2000-07-21 0:00 UTC (permalink / raw) Stephen Leake wrote: > The fields you explicitly located are in the same places. I'm not > clear why you can't live with this size and alignment for the record. > Size does matter. :-) In one sense, it ought to be sufficient for me to say "Because I just may feel like it one day!" A rep clause should give me what I ask for (assuming it is logically possibly to do so) or it is useless. You might as well not have it if it is going to constantly try to out-guess you or insist that it knows what's best for you. Give me what I ask for or tell me that you don't support rep clauses because not giving me what I ask for is, in my mind, not supporting rep clauses. If I'm trying to make something line up with physical hardware, then I may very well need to control the size and having the compiler tack extra space on the end is not going to help. It also impacts math involving 'Size. Alignment might also be an issue if I have to physically locate some structure at specific hardware addresses. Memory mapped I/O devices may require all sorts of specifics that the compiler isn't smart enough to know about - so it ought to trust me to know whats best. As for the space and position occupied by the tag - I think it is a weakness of Ada that there are no attributes for at least discovering where they live and how big they are. Given that in all probability, the tag is going to be some contiguous chunk of bits at the start of the record (anybody ever seen an implementation that was not?) all I really need to know is the size so I can make my rep clauses relative to that size. (Ada could probably have specified that it *must* appear at the start of the record and that the first usable bit would be offset from the front of the record by Rectype'Tag'Size or some such construct.) In any event, I'm macho enough to figure out for the implementation what it is and take my chances on lack of portability by defining whatever constants I need and doing my own adjustments to get around the tag. > Perhaps you see it as "easier" in C because C doesn't have tagged > types, so none of the issues you are raising here occur. > > You can always convert a tagged record into an equivalent variant > record. Perhaps you cannot afford the run-time overhead to do this, so > you are trying to map the tagged record directly onto the byte stream. > I agree that is a neat way to do things. > You might want to go to my web page (http://www.mcondic.com/) and look on the Ada page (http://www.mcondic.com/Ada_Programming.html) for the paper I put there describing some of the issues involved in message passing systems and where there are issues with how Ada does things. I don't want to try to describe how all of the message passing issues can be handled in C (or Jovial - which did a very nice job of giving me what I asked for :-) but basically you'd be doing it by (in effect) creating your own "tagged records" and doing your own dispatching. You still kind of have to do this even with Ada tagged records on the input side, because you have no clue what you have until you start decoding the raw data. Because C barely has any typing enforcement in comparison to Ada, you can dummy this up fairly readily - if dangerously. Variant records don't cut it and there's generally too many restrictions on them to make them do what you need to do here in an easy way. (You may be able to get there, but it just gets *hard* to constantly be trying to overcome the strong typing all the time. Remember, you're fundamentally dealing with raw data onto which you want to sometimes impose order - at least at the low level of the communication interface. The strong typing can go back to being an asset once you get the data a sufficient distance from the hose.) See my paper and you may get a handle on what it is I want and why I want it. MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Nothing in the world is more dangerous than sincere ignorance and conscientious stupidity." -- Martin Luther King, Jr ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-21 0:00 ` Marin D. Condic 2000-07-21 0:00 ` Stephen Leake @ 2000-07-21 0:00 ` Simon Wright 2000-07-22 0:00 ` Marin D. Condic 1 sibling, 1 reply; 15+ messages in thread From: Simon Wright @ 2000-07-21 0:00 UTC (permalink / raw) "Marin D. Condic" <mcondic-nospam@acm.com> writes: > Try to imagine that you want to line up a data type to match a > hardware register or a message coming into a system from the outside > world. You have to put a rep clause on the data type so that > specific bits, bytes and words fall into specific positions. Having > the compiler reject your rep clause and suggest another does > absolutely no good and is totally pointless. I do agree. But, you are trying to do this with tagged types, and the tag part is not specified by the standard. If you have the same release of the same compiler on the same hardware at both ends, why use rep clauses? (I'm assuming that the tag isn't a pointer to a type-specific dope structure -- if it was you would be completely wrong to try to send such data over the wire or even inter-process). If you have any difference at all, you *can not* sensibly send tags over the wire. -Simon ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-21 0:00 ` Simon Wright @ 2000-07-22 0:00 ` Marin D. Condic 2000-07-22 0:00 ` tmoran 0 siblings, 1 reply; 15+ messages in thread From: Marin D. Condic @ 2000-07-22 0:00 UTC (permalink / raw) Simon Wright wrote: > I do agree. But, you are trying to do this with tagged types, and the > tag part is not specified by the standard. > I understand this. See my other post where I whine and snivel about the standard not specifying some attribute(s) to enable you to do this. :-) At least you can get there with some system dependencies, but they'll be isolated at the lowest level and I generally consider that "fair". > If you have the same release of the same compiler on the same hardware > at both ends, why use rep clauses? (I'm assuming that the tag isn't a > pointer to a type-specific dope structure -- if it was you would be > completely wrong to try to send such data over the wire or even > inter-process). > I understand and agree that this is one possibility. However, if you're building a system that is going to be around for a while and is not for some very narrow application, you can bet money that you won't have the same compiler/version/hardware at both ends. You send a message to the outside world and you don't know what will be at the other end over time. If your device is useful, someone may want to hook some completely as yet unknown device to the same wire and want to utilize your message catalog for as yet unknown purposes. It happens all the time. Either that, or you're connecting to someone else's message catalog that is already defined & can't be changed. Hence, you want your message catalog to be very explicit and detailed because this represents your "contract" (dare I use that word here? :-) with the outside world. > If you have any difference at all, you *can not* sensibly send tags > over the wire. > I don't want to send the tag. I want to strip it out and just send the data and let the other end figure out what it wants to do with it from there. The basic idea here is that if I could build a base class that defined a message header and all of the low-level services needed to transmit/receive the messages, I could then very easily extend the base class for whatever message passing system I have to build and not worry about the low level details. Key to this is that the low-level operations are class-wide. No matter how you extend the message, the base class needs to be able to determine where the "real" data is in the record, how big it is, how to checksum it, how to interpret it as raw bytes, etc, etc. In a weakly typed language, you could do this by basically passing the address of any structure and its size in some TBD manner and the low level stuff would just send/receive it as bytes. You can get there with Ada, but you'd prefer to work with what would be the more "natural" method of tagged records. (I've seen it done in Ada with addresses, but the code begins to get ugly and doesn't seem to provide the kind of abstraction that would make it very clean.) I don't want the derived classes to have to provide similar operations - just the stuff needed for the content of the extended message. I don't want the derived class to have to provide conversions to a stream or anything like that because it shouldn't have to and it only creates extra programming work (chances for errors, etc) and inefficient message passing. (Remember, I'm "real-time" here and this is often a critical issue.) If the base class can deal with the offset of the tag and can reliably get the size of the record, then you can handle this fairly well. You just define an array of bytes and overlay it on the tagged record. You can then compute the message size and a checksum if needed, fill in whatever header information you want and blip the stuff down the wire. It's harder on the way back in, because you are going to have to recreate the tagged record from a message ID (some version of a case statement to do your own dispatching, so you'll need knowledge of the other derived types at that juncture) but there's no way around that one no matter what you do. Still, the base class can tell you what kind of message you have from the header and put the bytes into the derived class once you've determined the record type. Obviously, this is all dependent on being able to control the representation of all the messages and not having anything spurious in the record beyond the tag. If you're curious about it, I've got a paper on my web page that describes it (originally aimed at being a kind of "training" thing for the uninitiate - so its kind of basic.) http://www.mcondic.com/Ada_Programming.html (towards the bottom) There's also some code to try to illustrate where I'm trying to go. If you look it over and have suggestions, I'm all ears. MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Nothing in the world is more dangerous than sincere ignorance and conscientious stupidity." -- Martin Luther King, Jr ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-22 0:00 ` Marin D. Condic @ 2000-07-22 0:00 ` tmoran 2000-07-22 0:00 ` Marin D. Condic 2000-07-24 0:00 ` Ted Dennison 0 siblings, 2 replies; 15+ messages in thread From: tmoran @ 2000-07-22 0:00 UTC (permalink / raw) >operations are class-wide. No matter how you extend the message, the >base class needs to be able to determine where the "real" data is in the >record, how big it is, how to checksum it, how to interpret it as raw >bytes, etc, etc. In a weakly typed language, you could do this by You can really do a lot with Streams. You can of course define a 'Write to one child of Root_Stream_Type that puts the bytes of the data object into a Stream_Element_Array. But a different child of Root_Stream_Type could instead put a kind_of_record_indicator, or a checksum, or a length, or even an address into its resulting Stream_Element_Array. So your Output_To_Device procedure could take a Stream_Element_Array that consisted of one (or more) triples of (count, checksum, start_address), should you want to do that. For bitmaps In Claw we use record rep clauses (with TAG_SIZE offsets included) to lay things out for Windows system calls, but we define Mono_Bitmap'Class'Read, VGA_Bitmap'Class'Read, etc, for use in embedding bitmaps in files or sending them over networks. That's also used internally for the function Read(Filename:String) return Claw.Root_Bitmap'Class; kind of thing for simple read/write of .bmp files. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-22 0:00 ` tmoran @ 2000-07-22 0:00 ` Marin D. Condic 2000-07-24 0:00 ` Ted Dennison 1 sibling, 0 replies; 15+ messages in thread From: Marin D. Condic @ 2000-07-22 0:00 UTC (permalink / raw) tmoran@bix.com wrote: > You can really do a lot with Streams. You can of course define a > 'Write to one child of Root_Stream_Type that puts the bytes of the > data object into a Stream_Element_Array. But a different child of <snip> I've played with streams and the 'Read/'Write stuff and I like it a lot. I believe my posted examples on my webpage utilize this - or I have one around here somewhere.... (where did I put it??? :-) For stuff on a PC or workstation using TCP/IP as the transport, I'd agree that this is the way to go. Either using the defaults or rolling your own, you could pretty much handle the representation issues in that manner. The problem is if you have this sort of thing on a hard real time system with possibly limited memory and not much spare CPU. You really need to minimize the data motion and whatever overhead is associated with the 'Read and 'Write. When I've tinkered with this, it seems to degenerate into some kind of procedure call for each field of the record. That can translate into significant time. Also, you are moving the data out of the record and into a temporary stream, then out of the stream and into some hardware buffer (maybe) and that translates into more overhead. Using an overlay of a Stream_Element_Array, you can avoid this. Please don't get me wrong - I wouldn't avoid Ada.Streams in most applications because the overhead for data motion, etc., would likely be unimportant. It's a clever way of getting there and would work quite well. I just want to build a subsystem that doesn't depend on this as a necessity so that it could be usable in tough situations. MDC -- ====================================================================== Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m Visit my web site at: http://www.mcondic.com/ "Nothing in the world is more dangerous than sincere ignorance and conscientious stupidity." -- Martin Luther King, Jr ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-22 0:00 ` tmoran 2000-07-22 0:00 ` Marin D. Condic @ 2000-07-24 0:00 ` Ted Dennison 1 sibling, 0 replies; 15+ messages in thread From: Ted Dennison @ 2000-07-24 0:00 UTC (permalink / raw) In article <ujme5.27$Al5.45903@news.pacbell.net>, tmoran@bix.com wrote: > >operations are class-wide. No matter how you extend the message, the > >base class needs to be able to determine where the "real" data is in the > >record, how big it is, how to checksum it, how to interpret it as raw > >bytes, etc, etc. In a weakly typed language, you could do this by > > You can really do a lot with Streams. You can of course define a > 'Write to one child of Root_Stream_Type that puts the bytes of the > data object into a Stream_Element_Array. But a different child of > Root_Stream_Type could instead put a kind_of_record_indicator, or a > checksum, or a length, or even an address into its resulting To do anything with streams in an enviroment like this (one where you care what the exact representation of the output is) you need to make your own 'Write for each and every type you or anyone else will ever want to write to the stream. But if its only the one tagged type, then that's not much of a problem. -- T.E.D. http://www.telepath.com/~dennison/Ted/TED.html Sent via Deja.com http://www.deja.com/ Before you buy. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-20 0:00 ` Marin D. Condic 2000-07-20 0:00 ` Stephen Leake @ 2000-07-21 0:00 ` tmoran 1 sibling, 0 replies; 15+ messages in thread From: tmoran @ 2000-07-21 0:00 UTC (permalink / raw) In Claw, we've successfully used TAG_SIZE : constant := 4; and, for instance, for DIBitmap_Info_Type use record Bitmap_Info_Header at 0+Claw.TAG_SIZE range 0 .. 40*8-1; Color_Table at 40+Claw.TAG_SIZE range 0 .. 256*32-1; end record; with Gnat, Janus, ObjectAda, and Rational Windows targetted compilers. I certainly hope none of those compilers changes its tag storage layout in a future version, and it sure would be nice if there would be some official Ada ruling or implementation advice, but this has worked for several years and I'd be surprised, and complain, if it stopped. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-17 0:00 Representation Clauses And Freezing Marin D. Condic 2000-07-17 0:00 ` Stephen Leake @ 2000-07-18 0:00 ` Tucker Taft 2000-07-18 0:00 ` Nicolas Brunot 2 siblings, 0 replies; 15+ messages in thread From: Tucker Taft @ 2000-07-18 0:00 UTC (permalink / raw) "Marin D. Condic" wrote: > > I am trying to find a reasonable workaround to a problem involving > representation clauses and tagged records. I believe I am running into > problems with freezing rules. Below are two compiler listings which are > very similar. When the record type is visible, the compiler is happy. > When the record type is private, it complains. The question in my mind > is *WHY* is there some sort of restriction on this? What compiler > mission cannot be achieved unless the record is visible? Is there some > sort of workaround that would enable representation clauses on private > tagged records? (Inheritance from a rep-claused-tagged-record is its own > problem!) The behavior is mysterious, and probably just a bug. I would report it to the compiler vendor, and see what they say. -Tuck > > GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, > Inc. > > Compiling: rep_clause_01.ads (source file time stamp: 2000-07-17 > 14:20:14) > > 1. with System ; > 2. > 3. package Rep_Clause_01 is > 4. > 5. type UInteger_16 is mod 2**16 ; > 6. for UInteger_16'Size use 16 ; > 7. > 8. type Rec_Type is tagged record > 9. Field_01 : Uinteger_16 := 0 ; > 10. Field_02 : Uinteger_16 := 0 ; > 11. Field_03 : Uinteger_16 := 0 ; > 12. end record ; > 13. > 14. private > 15. > 16. for Rec_Type use record > 17. Field_01 at 4 range 0..15 ; > 18. Field_02 at 6 range 0..15 ; > 19. Field_03 at 8 range 0..15 ; > 20. end record ; > 21. > 22. for Rec_Type'Size use 10 * System.Storage_Unit ; > 23. for Rec_Type'Alignment use 2 ; > 24. > 25. end Rep_Clause_01 ; > > 25 lines: No errors > > GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, > Inc. > > Compiling: rep_clause_02.ads (source file time stamp: 2000-07-17 > 14:20:14) > > 1. > 2. with System ; > 3. > 4. package Rep_Clause_02 is > 5. > 6. type UInteger_16 is mod 2**16 ; > 7. for UInteger_16'Size use 16 ; > 8. > 9. type Rec_Type is tagged private ; > 10. > 11. private > 12. > 13. type Rec_Type is tagged record > 14. Field_01 : Uinteger_16 := 0 ; > 15. Field_02 : Uinteger_16 := 0 ; > 16. Field_03 : Uinteger_16 := 0 ; > 17. end record ; > 18. > 19. for Rec_Type use record > 20. Field_01 at 4 range 0..15 ; > 21. Field_02 at 6 range 0..15 ; > 22. Field_03 at 8 range 0..15 ; > 23. end record ; > 24. > 25. for Rec_Type'Size use 10 * System.Storage_Unit ; > | > >>> size for "Rec_Type" too small, minimum allowed is 128 > > 26. for Rec_Type'Alignment use 2 ; > | > >>> alignment for "Rec_Type" must be at least 4 > > 27. > 28. end Rep_Clause_02 ; > > MDC > -- > ====================================================================== > Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ > Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m > Visit my web site at: http://www.mcondic.com/ > > "Nothing in the world is more dangerous than sincere ignorance and > conscientious stupidity." > > -- Martin Luther King, Jr > ====================================================================== -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Commercial Division, AverStar (formerly Intermetrics) (http://www.averstar.com/services/IT_consulting.html) Burlington, MA USA ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Representation Clauses And Freezing 2000-07-17 0:00 Representation Clauses And Freezing Marin D. Condic 2000-07-17 0:00 ` Stephen Leake 2000-07-18 0:00 ` Tucker Taft @ 2000-07-18 0:00 ` Nicolas Brunot 2 siblings, 0 replies; 15+ messages in thread From: Nicolas Brunot @ 2000-07-18 0:00 UTC (permalink / raw) I think this has something to do with the compiler implementation hidden tag field of the tagged record. (the compiler refuses to put 'for field_01 use at 2 range 0..15' and says : component overlap tag field of "rec_type") may be the compiler implementation changes if rec_type is private may be (worse) than compilation is ok without warning, but execution crashes when rec_type is not private. Have you tested ? Anyway it's an illogic behavior (even if compatibble with RM) of the compiler to be more restrictive on a private type than on a the same visible one. Nicolas BRUNOT "Marin D. Condic" a ?crit : > I am trying to find a reasonable workaround to a problem involving > representation clauses and tagged records. I believe I am running into > problems with freezing rules. Below are two compiler listings which are > very similar. When the record type is visible, the compiler is happy. > When the record type is private, it complains. The question in my mind > is *WHY* is there some sort of restriction on this? What compiler > mission cannot be achieved unless the record is visible? Is there some > sort of workaround that would enable representation clauses on private > tagged records? (Inheritance from a rep-claused-tagged-record is its own > problem!) > > GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, > Inc. > > Compiling: rep_clause_01.ads (source file time stamp: 2000-07-17 > 14:20:14) > > 1. with System ; > 2. > 3. package Rep_Clause_01 is > 4. > 5. type UInteger_16 is mod 2**16 ; > 6. for UInteger_16'Size use 16 ; > 7. > 8. type Rec_Type is tagged record > 9. Field_01 : Uinteger_16 := 0 ; > 10. Field_02 : Uinteger_16 := 0 ; > 11. Field_03 : Uinteger_16 := 0 ; > 12. end record ; > 13. > 14. private > 15. > 16. for Rec_Type use record > 17. Field_01 at 4 range 0..15 ; > 18. Field_02 at 6 range 0..15 ; > 19. Field_03 at 8 range 0..15 ; > 20. end record ; > 21. > 22. for Rec_Type'Size use 10 * System.Storage_Unit ; > 23. for Rec_Type'Alignment use 2 ; > 24. > 25. end Rep_Clause_01 ; > > 25 lines: No errors > > GNAT 3.12p (19990629) Copyright 1992-1999 Free Software Foundation, > Inc. > > Compiling: rep_clause_02.ads (source file time stamp: 2000-07-17 > 14:20:14) > > 1. > 2. with System ; > 3. > 4. package Rep_Clause_02 is > 5. > 6. type UInteger_16 is mod 2**16 ; > 7. for UInteger_16'Size use 16 ; > 8. > 9. type Rec_Type is tagged private ; > 10. > 11. private > 12. > 13. type Rec_Type is tagged record > 14. Field_01 : Uinteger_16 := 0 ; > 15. Field_02 : Uinteger_16 := 0 ; > 16. Field_03 : Uinteger_16 := 0 ; > 17. end record ; > 18. > 19. for Rec_Type use record > 20. Field_01 at 4 range 0..15 ; > 21. Field_02 at 6 range 0..15 ; > 22. Field_03 at 8 range 0..15 ; > 23. end record ; > 24. > 25. for Rec_Type'Size use 10 * System.Storage_Unit ; > | > ??? size for "Rec_Type" too small, minimum allowed is 128 > > 26. for Rec_Type'Alignment use 2 ; > | > ??? alignment for "Rec_Type" must be at least 4 > > 27. > 28. end Rep_Clause_02 ; > > MDC > -- > ====================================================================== > Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/ > Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m > Visit my web site at: http://www.mcondic.com/ > > "Nothing in the world is more dangerous than sincere ignorance and > conscientious stupidity." > > -- Martin Luther King, Jr > ====================================================================== ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2000-07-24 0:00 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2000-07-17 0:00 Representation Clauses And Freezing Marin D. Condic 2000-07-17 0:00 ` Stephen Leake 2000-07-20 0:00 ` Marin D. Condic 2000-07-20 0:00 ` Stephen Leake 2000-07-21 0:00 ` Marin D. Condic 2000-07-21 0:00 ` Stephen Leake 2000-07-21 0:00 ` Marin D. Condic 2000-07-21 0:00 ` Simon Wright 2000-07-22 0:00 ` Marin D. Condic 2000-07-22 0:00 ` tmoran 2000-07-22 0:00 ` Marin D. Condic 2000-07-24 0:00 ` Ted Dennison 2000-07-21 0:00 ` tmoran 2000-07-18 0:00 ` Tucker Taft 2000-07-18 0:00 ` Nicolas Brunot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox