* Generic body @ 2008-05-14 18:26 Sébastien 2008-05-14 21:49 ` Randy Brukardt ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Sébastien @ 2008-05-14 18:26 UTC (permalink / raw) Hi, I'm trying to create a generic procedure with some instance in the same package. package MyPack is generic type Toto is limited private; procedure MyProc; procedure MyProcInt is new MyProc(Toto => Integer); procedure MyProcStr is new MyProc(Toto => String); end MyPack; package body MyPack is procedure MyProc is begin -- Some stuff end MyProc; end MyPack; I don't how to do this because: 1) The compiler refuse the instance of MyProc because it doesn't have the MyProc body 2) If I put the body of MyProc in the package spec, the compiler refuses it because it's not the right place. Thanks by advance for any help Sebastien ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-14 18:26 Generic body Sébastien @ 2008-05-14 21:49 ` Randy Brukardt 2008-05-14 21:51 ` Samuel Tardieu ` (2 subsequent siblings) 3 siblings, 0 replies; 9+ messages in thread From: Randy Brukardt @ 2008-05-14 21:49 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1661 bytes --] "S�bastien" <seb.morand@gmail.com> wrote in message news:g0fash$73v$1@registered.motzarella.org... > Hi, > > I'm trying to create a generic procedure with some instance in the same > package. > > package MyPack is > > generic > type Toto is limited private; > procedure MyProc; > > procedure MyProcInt is new MyProc(Toto => Integer); > procedure MyProcStr is new MyProc(Toto => String); > > end MyPack; > > package body MyPack is > > procedure MyProc is > begin > -- Some stuff > end MyProc; > > end MyPack; > > I don't how to do this because: > 1) The compiler refuse the instance of MyProc because it doesn't have the > MyProc body > 2) If I put the body of MyProc in the package spec, the compiler refuses > it because it's not the right place. > > Thanks by advance for any help You can't do this. The language doesn't allow it because the body of the instances would have to be elaborated before the body of the generic unit. That wouldn't be a major problem for a subprogram, but for a generic package, that could lead to all kinds of havoc (specifically, accessing objects that don't yet exist). To be consistent, it raises Program_Error in all cases. (GNAT rejects some of these cases at compile-time by default, which is not standard Ada behavior. But it still wouldn't work.) And, as you've found out, the only way to put a body into a specification is via an instance. You'll have to put the instances in a separate unit from the generic unit. That's usually preferable anyway (especially in larger projects), but you don't have any choice in this case. Randy. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-14 18:26 Generic body Sébastien 2008-05-14 21:49 ` Randy Brukardt @ 2008-05-14 21:51 ` Samuel Tardieu 2008-05-14 22:03 ` Adam Beneschan 2008-05-15 8:43 ` gautier_niouzes 3 siblings, 0 replies; 9+ messages in thread From: Samuel Tardieu @ 2008-05-14 21:51 UTC (permalink / raw) >>>>> "S�bastien" == S�bastien <seb.morand@gmail.com> writes: S�bastien> I don't how to do this because: 1) The compiler refuse the S�bastien> instance of MyProc because it doesn't have the MyProc body S�bastien> 2) If I put the body of MyProc in the package spec, the S�bastien> compiler refuses it because it's not the right place. What compiler are you using? (name and version) With a recent GNAT, I get: 7. procedure MyProcInt is new MyProc(Toto => Integer); | >>> warning: cannot instantiate "MyProc" before body seen >>> warning: Program_Error will be raised at run time 8. procedure MyProcStr is new MyProc(Toto => String); | >>> actual for "Toto" must be a definite subtype which I think explains things well. Sam -- Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-14 18:26 Generic body Sébastien 2008-05-14 21:49 ` Randy Brukardt 2008-05-14 21:51 ` Samuel Tardieu @ 2008-05-14 22:03 ` Adam Beneschan 2008-05-15 9:25 ` Sébastien 2008-05-15 8:43 ` gautier_niouzes 3 siblings, 1 reply; 9+ messages in thread From: Adam Beneschan @ 2008-05-14 22:03 UTC (permalink / raw) On May 14, 11:26 am, Sébastien <seb.mor...@gmail.com> wrote: > Hi, > > I'm trying to create a generic procedure with some instance in the same > package. > > package MyPack is > > generic > type Toto is limited private; > procedure MyProc; > > procedure MyProcInt is new MyProc(Toto => Integer); > procedure MyProcStr is new MyProc(Toto => String); This one can't be right in any case, because String is an unconstrained type. You can't declare a *variable* X : String; so therefore you can't use String as the actual type for Toto, because MyProc could declare a variable X : Toto; somewhere in it. But if you really need the ability to use "String" here, do this in your generic: type Toto(<>) is limited private; I realize this has nothing to do with your question. > > end MyPack; > > package body MyPack is > > procedure MyProc is > begin > -- Some stuff > end MyProc; > > end MyPack; Regarding your question: you really can't do this in Ada, because of 3.11(13-14): "For the instantiation of a generic unit that has a body, a check is made that this body is already elaborated....The exception Program_Error is raised if any of these checks fails." The compiler *should* accept your program with no errors, but it should fail at runtime because the program will have to "elaborate" the generic instantiation before it elaborates the generic body, and the program will fail on Program_Error before it even gets started. If your compiler is rejecting your program, then either it is doing so because it "knows" that the program can't possibly work when it runs, or it has a bug. Although there may be ways to suppress the elaboration check, depending on your compiler, I wouldn't take that approach, because the check is there for a reason. If you suppress the check, there's a possibility that your program may not work as expected, depending on what the body of your generic looks like, especially if it refers to any global variables in the body of MyPack. I'd recommend putting the generic in its own library unit, or in a different package: package MyProcPack is -- I hate this name generic type Toto(<>) is limited private; procedure MyProc; end MyProcPack; package body MyProcPack is procedure MyProc is ... end MyProc; end MyProcPack; with MyProcPack; pragma Elaborate_All (MyProcPack); package MyPack is procedure MyProcInt is new MyProcPack.MyProc(Toto => Integer); procedure MyProcStr is new MyProcPack.MyProc(Toto => String); end MyPack; The Elaborate_All pragma is necessary to ensure that the body of MyProcPack (including the body of the generic MyProc) is elaborated before MyProc is instantiated. If you don't understand what elaboration is all about, it's too difficult to explain here---sorry. But just trust me that you'll need to do something like what I'm recommending. > I don't how to do this because: > 1) The compiler refuse the instance of MyProc because it doesn't have > the MyProc body As I've mentioned, the compiler really shouldn't refuse this, because it's a legal Ada program although it cannot work right. Some compilers have modes that cause them to reject programs that are certain to raise predefined exceptions, even when the programs are legal, and your compiler could be running in a mode like this. > 2) If I put the body of MyProc in the package spec, the compiler refuses > it because it's not the right place. Right---you can't put any sort of body in a package spec. -- Adam ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-14 22:03 ` Adam Beneschan @ 2008-05-15 9:25 ` Sébastien 2008-05-15 14:59 ` Adam Beneschan 0 siblings, 1 reply; 9+ messages in thread From: Sébastien @ 2008-05-15 9:25 UTC (permalink / raw) > somewhere in it. But if you really need the ability to use "String" > here, do this in your generic: > > type Toto(<>) is limited private; > > I realize this has nothing to do with your question. Not but it's an interesting issue. I remembered this syntax I saw some places and then read that: http://en.wikibooks.org/wiki/Ada_Programming/Generics#Generic_formal_types Now I understand well the matter. Thanks. > Regarding your question: you really can't do this in Ada, because of > 3.11(13-14): "For the instantiation of a generic unit that has a body, > a check is made that this body is already elaborated....The exception > Program_Error is raised if any of these checks fails." The compiler > *should* accept your program with no errors, but it should fail at > runtime because the program will have to "elaborate" the generic > instantiation before it elaborates the generic body, and the program > will fail on Program_Error before it even gets started. If your > compiler is rejecting your program, then either it is doing so because > it "knows" that the program can't possibly work when it runs, or it > has a bug. > Although there may be ways to suppress the elaboration check, > depending on your compiler, I wouldn't take that approach, because the > check is there for a reason. If you suppress the check, there's a > possibility that your program may not work as expected, depending on > what the body of your generic looks like, especially if it refers to > any global variables in the body of MyPack. Yes I understand that warning are now a good things in Ada :-) Espcially when it says some exceptions will be raised at runtime. So I take time to undestand and correct any warning. > I'd recommend putting the generic in its own library unit, or in a > different package: > > package MyProcPack is -- I hate this name > generic > type Toto(<>) is limited private; > procedure MyProc; > end MyProcPack; > > package body MyProcPack is > procedure MyProc is ... end MyProc; > end MyProcPack; > > with MyProcPack; > pragma Elaborate_All (MyProcPack); > package MyPack is > procedure MyProcInt is new MyProcPack.MyProc(Toto => Integer); > procedure MyProcStr is new MyProcPack.MyProc(Toto => String); > end MyPack; > > The Elaborate_All pragma is necessary to ensure that the body of > MyProcPack (including the body of the generic MyProc) is elaborated > before MyProc is instantiated. > > If you don't understand what elaboration is all about, it's too > difficult to explain here---sorry. But just trust me that you'll need > to do something like what I'm recommending. I read a lot of stuff about elaboration, I'm not a master of the subject yet, but I understand a bit about it. I thought that Elaborate_All was about dynamic check vs static check? (flat -gnatE for circular dependancy) >> I don't how to do this because: >> 1) The compiler refuse the instance of MyProc because it doesn't have >> the MyProc body > > As I've mentioned, the compiler really shouldn't refuse this, because > it's a legal Ada program although it cannot work right. Some > compilers have modes that cause them to reject programs that are > certain to raise predefined exceptions, even when the programs are > legal, and your compiler could be running in a mode like this. > >> 2) If I put the body of MyProc in the package spec, the compiler refuses >> it because it's not the right place. > > Right---you can't put any sort of body in a package spec. Ok thanks to all of you for your help. Sebastien ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-15 9:25 ` Sébastien @ 2008-05-15 14:59 ` Adam Beneschan 2008-05-15 15:40 ` Sébastien 0 siblings, 1 reply; 9+ messages in thread From: Adam Beneschan @ 2008-05-15 14:59 UTC (permalink / raw) On May 15, 2:25 am, Sébastien <seb.mor...@gmail.com> wrote: > I read a lot of stuff about elaboration, I'm not a master of the subject > yet, but I understand a bit about it. I thought that Elaborate_All was > about dynamic check vs static check? (flat -gnatE for circular dependancy) I don't think so. It's about elaboration order, and making sure that variables have a chance to get initialized before they're used. If you have a package body: package body Pak2 is Counter : Integer := 0; function Next_Counter return Integer is begin Counter := Counter + 1; return Counter; end Next_Counter; end Pak2; In Ada semantics, the elaboration of Pak2's body is what initializes Counter to 0. But if the elaboration of some other package (say Pak3) used Next_Counter before Pak2's body had a chance to be elaborated, Counter would be uninitialized and Next_Counter would return garbage. So it's necessary to ensure that Pak2's body is elaborated before Pak3 is elaborated, and that's what the Elaborate pragmas are for. (Without the Elaborate pragmas, Pak2's body might be elaborated first anyway, but you can't be sure.) That's how it works in Ada. I know that GNAT has a big long chapter in the manual describing how it determines the elaboration order, but I'm not really familiar with the details. But I'd use the pragmas anyway; even if GNAT would get things right without them, you may want to port to a different compiler at a later time. In any case, I like Gautier's solution and I wish I'd thought of it; that avoids the Elaboration issues completely. -- Adam ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-15 14:59 ` Adam Beneschan @ 2008-05-15 15:40 ` Sébastien 0 siblings, 0 replies; 9+ messages in thread From: Sébastien @ 2008-05-15 15:40 UTC (permalink / raw) > I don't think so. It's about elaboration order, and making sure that > variables have a chance to get initialized before they're used. If > you have a package body: > > package body Pak2 is > Counter : Integer := 0; > function Next_Counter return Integer is > begin > Counter := Counter + 1; > return Counter; > end Next_Counter; > end Pak2; > > In Ada semantics, the elaboration of Pak2's body is what initializes > Counter to 0. But if the elaboration of some other package (say Pak3) > used Next_Counter before Pak2's body had a chance to be elaborated, > Counter would be uninitialized and Next_Counter would return garbage. > So it's necessary to ensure that Pak2's body is elaborated before Pak3 > is elaborated, and that's what the Elaborate pragmas are for. > (Without the Elaborate pragmas, Pak2's body might be elaborated first > anyway, but you can't be sure.) > > That's how it works in Ada. I know that GNAT has a big long chapter > in the manual describing how it determines the elaboration order, but > I'm not really familiar with the details. But I'd use the pragmas > anyway; even if GNAT would get things right without them, you may want > to port to a different compiler at a later time. > > In any case, I like Gautier's solution and I wish I'd thought of it; > that avoids the Elaboration issues completely. > > -- Adam Ok thanks for precision, it's clearer for me about elaboration issue now. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-14 18:26 Generic body Sébastien ` (2 preceding siblings ...) 2008-05-14 22:03 ` Adam Beneschan @ 2008-05-15 8:43 ` gautier_niouzes 2008-05-15 13:11 ` Sébastien 3 siblings, 1 reply; 9+ messages in thread From: gautier_niouzes @ 2008-05-15 8:43 UTC (permalink / raw) Here is how to do it... -- package MyPack is generic type Toto is limited private; procedure MyProc; procedure MyProcInt; procedure MyProcChr; end MyPack; package body MyPack is procedure MyProc is begin null; -- Some stuff end MyProc; procedure MyProcInt_internal is new MyProc(Toto => Integer); procedure MyProcChr_internal is new MyProc(Toto => Character); procedure MyProcInt renames MyProcInt_internal; procedure MyProcChr renames MyProcChr_internal; end MyPack; __________________________________________________________________ Gautier's Ada programming -- http://sourceforge.net/users/gdemont/ NB: For a direct answer, e-mail address on the Web site! ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Generic body 2008-05-15 8:43 ` gautier_niouzes @ 2008-05-15 13:11 ` Sébastien 0 siblings, 0 replies; 9+ messages in thread From: Sébastien @ 2008-05-15 13:11 UTC (permalink / raw) > package MyPack is > > generic > type Toto is limited private; > procedure MyProc; > > procedure MyProcInt; > procedure MyProcChr; > > end MyPack; > > package body MyPack is > > procedure MyProc is > begin > null; -- Some stuff > end MyProc; > > procedure MyProcInt_internal is new MyProc(Toto => Integer); > procedure MyProcChr_internal is new MyProc(Toto => Character); > > procedure MyProcInt renames MyProcInt_internal; > procedure MyProcChr renames MyProcChr_internal; > > end MyPack; Really nice solutions, thanks very much. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-05-15 15:40 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-05-14 18:26 Generic body Sébastien 2008-05-14 21:49 ` Randy Brukardt 2008-05-14 21:51 ` Samuel Tardieu 2008-05-14 22:03 ` Adam Beneschan 2008-05-15 9:25 ` Sébastien 2008-05-15 14:59 ` Adam Beneschan 2008-05-15 15:40 ` Sébastien 2008-05-15 8:43 ` gautier_niouzes 2008-05-15 13:11 ` Sébastien
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox