Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ada: Re-exporting enum type values

Tags:

ada

I have an ada package in the form of

package C is
   type Test is (Test_1, Test_2, Test_3);   
end C;

and another package in the form of

with C;
package B is
   subtype Test is C.Test;
end B;

and yet another in the form of

with B;
package A is
   subtype Test is B.Test;   
   Item: Test := Test_1;
end A;

Naively, I would expect that a subtype defined in B, which is later subtyped by A, would be able to access members of the original type. However, upon inspection, the members of C are not even visible in the scope of B. This can be fixed by adding use c;, this seems like a find solution to a degree, however to use it in A, you would have to add with c; use c; to every package that transitively depends on C. This could lead to confusion as it wouldn't be implicitly obvious that you should be using C.

I would like to be able to "rexport" these types, so that I can abstract layers of my program better.

like image 380
Siech0 Avatar asked Dec 11 '25 07:12

Siech0


2 Answers

If you change package A to

with B;
package A is
   subtype Test is B.Test;
   use all type Test;
   Item: Test := Test_1;
end A;

the code compiles. Not sure whether this will help.

This is an Ada 2012 feature; see ARM 8.4(8) and (8.1). use all type makes the primitive operations of the type visible (which includes enumeration literals).

like image 116
Simon Wright Avatar answered Dec 13 '25 02:12

Simon Wright


If you really want to re-export the values, you can do this:

with C;
package B is
   subtype Test is C.Test;
   function Test_1 return Test is (C.Test_1);
   function Test_2 return Test is (C.Test_2);
   function Test_3 return Test is (C.Test_3); 
end B;

Unfortunately, you can't use named numbers since enumerations are not numeric types. You can make these functions normal constants instead, but conceptually, this would execute code at elaboration time (the compiler will probably optimize it away, but you can't use pragma Preelaborate anymore).

This allows you to access the literals in A using B.Test_1 etc. This is also a proper abstraction as A will not depend on the literals defined in C anymore (you can rename the literals in C without affecting A, you do need to update B though to map the new names to the original ones).

Simply importing the literal names into the namespace of A is not an abstraction.

like image 24
flyx Avatar answered Dec 13 '25 02:12

flyx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!