Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining a modular type within a generic package

Tags:

ada

In brief, why doesnt this work:

generic
   Max : in Positive;
package Modular_Gen_Issue is
   procedure Foo;
private
   type Mod_Thing is mod Max; -- NOK
   type Int_Thing is new Integer range 0 .. Max; -- OK

end Modular_Gen_Issue;

With compilation:

$ gnatmake modular_gen_issue.ads
gcc-4.4 -c modular_gen_issue.ads
modular_gen_issue.ads:6:26: non-static expression used for modular type bound
modular_gen_issue.ads:6:26: "Max" is not static constant or named number (RM 4.9(5))
gnatmake: "modular_gen_issue.ads" compilation error
$

How can I pass in a single number and use it to define a modular type ?

And yes it has to be a modular type!

like image 543
NWS Avatar asked Jun 12 '13 11:06

NWS


2 Answers

Sorry, you can't. Whenever you declare a modular type, the modulus has to be a static value, i.e. a value the compiler can figure out right then and there. And this doesn't work. This is true of many parts of type declarations, especially parts that the compiler needs in order to figure out how many bits an object needs to be, or other features about an object's representation. On the other hand, in Int_Thing, the upper bound of the range doesn't need to be static (the compiler already knows an Int_Thing will be represented the same as an Integer, and the range is used for bounds checking but isn't used to determine how big an Int_Thing will be).

If this is a real-life situation and you need a generic that can handle varying modular types, you might be able make the modular type itself a generic parameter:

generic
    type Mod_Thing is mod <>;
package Modular_Gen_Issue is ...

(P.S. The range of Mod_Thing in your example would be 0..Max-1, not 0..Max.)

like image 95
ajb Avatar answered Nov 10 '22 11:11

ajb


In addition to what ajb wrote, consider the following usage of your generic package:

procedure Foo (Bar : in Positive) is
   package Instance is new Modular_Gen_Issue (Max => Bar);
begin
   null;
end Foo;

Here, the package Instance is created with a non-static value that may change with every call to Foo. Because Ada allows this, the compiler must expect any parameter of a generic unit to be non-static. That's why you cannot declare your modular type in there, even though you could instantiate your package with a static value.

Extending ajb's suggestion, you can do:

generic
   type Mod_Thing_Base is mod <>;
package Modular_Gen_Issue is
   type Mod_Thing is new Mod_Thing_Base;
end Modular_Gen_Issue;

This way, you can define primitive operations of Mod_Thing (which you couldn't do by taking it as parameter directly).

like image 24
flyx Avatar answered Nov 10 '22 11:11

flyx