* Access to generic formal parameters in an generic package instantiation @ 2012-07-29 18:16 Florian Weimer 2012-07-29 19:36 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Florian Weimer @ 2012-07-29 18:16 UTC (permalink / raw) If G is a generic package and P is one of its formal parameters, it is legal to refer to G.P where G is visible? Does this depend on the kind of entity, or whether the formal part uses <>? Has anybody tried to use generic formal packages to emulate Standard ML signatures? Is it possible to express SML "where" constraints, that is, specify that two types in two formal packages are the same, without break down the formal packages to their components? It seems that generic formal packages are unusual because GNAT shows some strange effects (and the occasional bug box). ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-29 18:16 Access to generic formal parameters in an generic package instantiation Florian Weimer @ 2012-07-29 19:36 ` Dmitry A. Kazakov 2012-07-29 21:31 ` Florian Weimer 2012-07-30 18:33 ` Adam Beneschan 2012-07-31 7:48 ` Georg Bauhaus 2 siblings, 1 reply; 8+ messages in thread From: Dmitry A. Kazakov @ 2012-07-29 19:36 UTC (permalink / raw) On Sun, 29 Jul 2012 20:16:00 +0200, Florian Weimer wrote: > If G is a generic package and P is one of its formal parameters, it is > legal to refer to G.P where G is visible? Does this depend on the > kind of entity, or whether the formal part uses <>? Sometimes it works, sometimes it does not, I am not a language lawyer to tell when GNAT is right or not. Facing this problem quite frequently, I developed a custom to rename formal parameters within the declaration area, e.g. generic type Foo is ...; with package Bar is new Baz (<>); package Boo is subtype My_Foo is Foo; package My_Bar is renames Bar; ... Another method of making formal parameters visible is to have it a generic child. > that is, specify that two types in two formal packages are the same, > without break down the formal packages to their components? Yes. There several techniques to accomplish this. 1. You can to make that type a formal parameter and specify it among the formal parameters of the instances: type T is ... with package P1 (T, <>); with package P2 (T, <>); 2. You can take the type from one package and constrain another with it: with package P1 (<>); with package P2 (P1.T, <>); 3. You can factor out a generic parameter package that defines T and other common types and make it generic parent for the packages of interest. > It seems that generic formal packages are unusual because GNAT shows > some strange effects (and the occasional bug box). There were always problems with generics in GNAT. Though you likely won't believe me anyway, but using generics is a very bad idea unless absolutely nothing else works. Here is an outlook what it becomes in a relatively simple case: http://www.dmitry-kazakov.de/ada/fuzzy_packages.gif Can you figure out a chain of instantiation of this for some given floating-point type? How many instances it does? In a really complex case there are multiple pages of such diagrams. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-29 19:36 ` Dmitry A. Kazakov @ 2012-07-29 21:31 ` Florian Weimer 2012-07-30 18:37 ` Adam Beneschan 0 siblings, 1 reply; 8+ messages in thread From: Florian Weimer @ 2012-07-29 21:31 UTC (permalink / raw) * Dmitry A. Kazakov: > On Sun, 29 Jul 2012 20:16:00 +0200, Florian Weimer wrote: > >> If G is a generic package and P is one of its formal parameters, it is >> legal to refer to G.P where G is visible? Does this depend on the >> kind of entity, or whether the formal part uses <>? > > Sometimes it works, sometimes it does not, I am not a language lawyer to > tell when GNAT is right or not. It seems that the names of the generic formal declarations are lost except if they refer to implicit declaration (those using <>). I'm not sure why implicit declarations are special-cased like this. There is sometimes no way to reference to an implicit declaration because you are not supplying the arguments. But if you want to get the arguments back reliably, you have to add declarations anyway, and those cover the implicit case as well, so I'm not sure this language feature is really necessary. > Facing this problem quite frequently, I developed a custom to rename > formal parameters within the declaration area, e.g. > > generic > type Foo is ...; > with package Bar is new Baz (<>); > package Boo is > subtype My_Foo is Foo; > package My_Bar is renames Bar; > ... The same approach is used in C++ where template arguments are not accessible from outside of the template. Instead, you have to provide typedefs for alias names. > Another method of making formal parameters visible is to have it a > generic child. This smells a bit like a compiler bug. The standard doesn't seem to mention it. >> that is, specify that two types in two formal packages are the same, >> without break down the formal packages to their components? > > Yes. There several techniques to accomplish this. > > 1. You can to make that type a formal parameter and specify it among the > formal parameters of the instances: > > type T is ... > with package P1 (T, <>); > with package P2 (T, <>); I got a bug box when I tried this. > Though you likely won't believe me anyway, but using generics is a very bad > idea unless absolutely nothing else works. Here is an outlook what it > becomes in a relatively simple case: > > http://www.dmitry-kazakov.de/ada/fuzzy_packages.gif It's just the usual curse of the higher order. Functions call graphs aren't always pretty, either. Anyway, I'm trying to find a good way for resource management which does not rely on finalization, and I want to cut down boilerplate code. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-29 21:31 ` Florian Weimer @ 2012-07-30 18:37 ` Adam Beneschan 0 siblings, 0 replies; 8+ messages in thread From: Adam Beneschan @ 2012-07-30 18:37 UTC (permalink / raw) On Sunday, July 29, 2012 2:31:29 PM UTC-7, Florian Weimer wrote: > > 1. You can to make that type a formal parameter and specify it among the > > formal parameters of the instances: > > > type T is ... > > with package P1 (T, <>); > > with package P2 (T, <>); > > I got a bug box when I tried this. The syntax isn't legal. You shouldn't have gotten a bug box, but you should definitely get an error message. Unless <> is all by itself inside parentheses, you need either a parameter name or "others": generic type T is private; with package P1 (T, others => <>); with package P2 (T, others => <>); or, if (say) P1 has only two formal parameters: with package P1 (T, parameter_name => <>); -- Adam ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-29 18:16 Access to generic formal parameters in an generic package instantiation Florian Weimer 2012-07-29 19:36 ` Dmitry A. Kazakov @ 2012-07-30 18:33 ` Adam Beneschan 2012-07-31 7:48 ` Georg Bauhaus 2 siblings, 0 replies; 8+ messages in thread From: Adam Beneschan @ 2012-07-30 18:33 UTC (permalink / raw) On Sunday, July 29, 2012 11:16:00 AM UTC-7, Florian Weimer wrote: > If G is a generic package and P is one of its formal parameters, it is > legal to refer to G.P where G is visible? No, unless you're inside G. Outside of G, you can't refer to any entities inside G. I wonder if you're referring to a generic *instance*, though. It's helpful to keep the terminology straight: generic type T is private; package Gen_Package is ... package Instance is new Gen_Package (Integer); -- for example Gen_Package is a "generic package". Outside of Gen_Package, you can't refer to Gen_Package.T and it wouldn't make any sense. Instance is not a "generic package"; it's a "generic instance", or an "instance of a generic package". However, you still can't refer to Instance.T. I think the theory was probably that the code knows what Instance.T is because it's right there in the parameter list when Gen_Package is instantiated, so it isn't necessary to allow Instance.T. In this case generic with INST is new Gen_Package (<>); package Gen_Package_2 is ... INST is a "generic formal package", not a "generic package". It represents an instance of Gen_Package, but of course we don't know what the instance is until we instantiate Gen_Package_2. Within Gen_Package_2, you can refer to INST.T, because (unlike the previous example) the code in Gen_Package_2 doesn't know what INST.T is, because there's only a <> in the parameter list of the generic formal package declaration. Hope this helps a little, > Does this depend on the > kind of entity, or whether the formal part uses <>? > > > > Has anybody tried to use generic formal packages to emulate Standard > > ML signatures? Is it possible to express SML "where" constraints, > that is, specify that two types in two formal packages are the same, > without break down the formal packages to their components? You can do something like this: generic with package INST is new Gen_Package (<>); with package ANOTHER_INST is new Another_Gen_Package (T => Inst.T); package Gen_Package_3 is ... Now when you instantiation package Some_Inst is new Gen_Package_3 (P1, P2); the instantiation is legal only if P1 and P2 were instantiated with the same type for T. This seems like what you're looking for. (P.S. This sort of thing is also legal starting with Ada 2005: generic with package INST is new Gen_Package (<>); with package ANOTHER_INST is new Another_Gen_Package (T => Inst.T, others => <>); package Gen_Package_3 is ... That puts a constraint on the type T used to instantiate Another_Gen_Package, while not putting any constraints on any other actual parameters.) Hope this helps a little, -- Adam ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-29 18:16 Access to generic formal parameters in an generic package instantiation Florian Weimer 2012-07-29 19:36 ` Dmitry A. Kazakov 2012-07-30 18:33 ` Adam Beneschan @ 2012-07-31 7:48 ` Georg Bauhaus 2012-07-31 15:29 ` Adam Beneschan 2 siblings, 1 reply; 8+ messages in thread From: Georg Bauhaus @ 2012-07-31 7:48 UTC (permalink / raw) On 29.07.12 20:16, Florian Weimer wrote: > It seems that generic formal packages are unusual because GNAT shows > some strange effects (and the occasional bug box). Compilers seem to differ on this one, which should be Ada 95. I am not sure the generics are properly addressing the issue of type comparison (well, of convertibility). With GNAT's bug boxes currently in the way I can't try the Ada 2012 features. (Something about failures when testing entity node kinds.) generic type T is private; Fst, Snd : in T; package Same_Type is end; with Same_Type; generic type Ancestor is private ; type T1 is new Ancestor; type T2 is new Ancestor; X : T1; Y : T2; -- with package Comparison is new Same_Type (T1, T1'(X), T1 (Y)); package Ops is private package Comparison_1 is new Same_Type (T1, T1'(X), T1 (Y)); package Comparison_2 is new Same_Type (T2, T2 (X), T2'(Y)); end; with Same_Type, Ops; procedure Test_G is type Int is new Integer; type Chr is new Character; Two : constant Int := 2; C : constant Chr := 'c'; package Test_1 is new Ops (Int, Int, Int, Two, Two); --!GNAT! package Test_2 is new Ops (Int, Int, Chr, Two, C); package PK is type root is tagged null record; type left is new root with null record; type right is new root with null record; end PK; use pK; L : Left; R : Right; package test_3 is new ops (Root, Left, Right, L, R); begin null; end Test_G; ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-31 7:48 ` Georg Bauhaus @ 2012-07-31 15:29 ` Adam Beneschan 2012-07-31 16:50 ` Georg Bauhaus 0 siblings, 1 reply; 8+ messages in thread From: Adam Beneschan @ 2012-07-31 15:29 UTC (permalink / raw) On Tuesday, July 31, 2012 12:48:04 AM UTC-7, Georg Bauhaus wrote: > Compilers seem to differ on this one, which should be Ada 95. > I am not sure the generics are properly addressing the issue > of type comparison (well, of convertibility). > > > With GNAT's bug boxes currently in the way I can't try the > Ada 2012 features. (Something about failures when testing entity > node kinds.) > > > > generic > type T is private; > Fst, Snd : in T; > package Same_Type is end; > > with Same_Type; > generic > type Ancestor is private; > type T1 is new Ancestor; > type T2 is new Ancestor; > X : T1; > Y : T2; > -- with package Comparison is new Same_Type (T1, T1'(X), T1 (Y)); > > package Ops is > private > package Comparison_1 is new Same_Type (T1, T1'(X), T1 (Y)); > package Comparison_2 is new Same_Type (T2, T2 (X), T2'(Y)); > end; > > with Same_Type, Ops; > procedure Test_G is > type Int is new Integer; > type Chr is new Character; > Two : constant Int := 2; > C : constant Chr := 'c'; > package Test_1 is new Ops (Int, Int, Int, Two, Two); > --!GNAT! package Test_2 is new Ops (Int, Int, Chr, Two, C); GNAT gets a bug box here, but you do realize that the instantiation is illegal, right? T2 is supposed to be derived from T1, but Chr is not derived from Int. I'm sure you probably realize this, but it's not clear from your post what you're trying to show. > package PK is > type root is tagged null record; > type left is new root with null record; > type right is new root with null record; > end PK; > use pK; > > L : Left; > R : Right; > package test_3 is new ops (Root, Left, Right, L, R); I get an "instantiation error" when I try this with GNAT, which is usually a bad sign. In this case, I think it's a hole in the language. The formal types are declared without "tagged", so that while compiling the generic, they're treated as untagged. And for untagged types, any time you have two types with the same ultimate ancestor, you can convert between them. For tagged types, the rules are different, though, since downward conversions (from a type to its descendant) are not generally allowed, since the descendant can have new components that a conversion wouldn't be able to supply. (I'm not sure offhand whether a downward conversion to a null extension is allowed--I'd have to look it up.) The problem is that a generic formal untagged type can have a tagged type as an actual. So in a case like this, where a generic contains a construct that would be legal for untagged types but illegal for tagged types, the language doesn't seem to prevent error cases from coming up. There may be other constructs besides type conversions that cause problems when an untagged formal has a tagged actual. Anyway, I'll look into this further but will probably send something to Ada-Comment unless this has been brought up already. I think it could be fixed fairly simply. (I'm thinking that adding a rule that a generic formal untagged derived type cannot have a tagged type as an actual would work, and would be unlikely to make any existing code illegal.) -- Adam ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Access to generic formal parameters in an generic package instantiation 2012-07-31 15:29 ` Adam Beneschan @ 2012-07-31 16:50 ` Georg Bauhaus 0 siblings, 0 replies; 8+ messages in thread From: Georg Bauhaus @ 2012-07-31 16:50 UTC (permalink / raw) On 31.07.12 17:29, Adam Beneschan wrote: >> package Test_1 is new Ops (Int, Int, Int, Two, Two); >> > --!GNAT! package Test_2 is new Ops (Int, Int, Chr, Two, C); > GNAT gets a bug box here, but you do realize that the instantiation is illegal, right? T2 is supposed to be derived from T1, but Chr is not derived from Int. I'm sure you probably realize this, but it's not clear from your post what you're trying to show. Yes, I had hoped that GNAT, like ObjectAda, would say that at compile time, i.e. whether I can instantiate the generic with the two types, or that they are too different, in a sense. I thought that involving a number of things tested at compile time could remotely resemble testing (type related?) things like is done when using C++ templates. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-08-07 7:16 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-07-29 18:16 Access to generic formal parameters in an generic package instantiation Florian Weimer 2012-07-29 19:36 ` Dmitry A. Kazakov 2012-07-29 21:31 ` Florian Weimer 2012-07-30 18:37 ` Adam Beneschan 2012-07-30 18:33 ` Adam Beneschan 2012-07-31 7:48 ` Georg Bauhaus 2012-07-31 15:29 ` Adam Beneschan 2012-07-31 16:50 ` Georg Bauhaus
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox