Trying to make a function generic, but getting hung up - ada

I have a variable in a package (rec in this case) that needs to be set when called from package 3, but it's private. Previously the function set_true only set rec to true, so it wasn't a big deal. But I have another package that does the same processing (I'm giving a simple example, but my literal case is more complex), so I thought, well I could pass in the variable I want modified, and let it get changed. Is the only way to set rec in the below layout, to create a second function in package one, that calls set_true with rec as the parameter? I would like to avoid having to keep creating additional functions to handle the local variables. I can't move the variable to public (spec) as I am trying to follow convention and this "type" of variable isn't public anywhere else, and I don't want anyone to be able to just set it on their own (I want functions to have to set). I don't want to have to create a second function named for example set_local_true, and creating an overloaded function set_true, with no parameters, that calls set_true(value => rec) just seems deceptive, does anyone have any better suggestions with the limitations I have?
My two requirements:
Can't make the local variable public.
Be able to use the function to calculate something both externally and internally.
package one is
procedure set_true(value : out Boolean);
end one;
package body one is
rec : Boolean;
begin
procedure set_true(value : out Boolean)
begin
value := true;
end set_true;
end one;
package body two is
local_rec : Boolean;
begin
procedure call_function is
begin
one.set_true(value => local_rec);
end call_function;
end two;
package body three is
begin
procedure call_function is
begin
one.set_true(value => <PACKAGE ONE'S REC))
end call_function;
end three;
EDIT: Or perhaps, what would be a better naming convention for the functions to specify that they are modifying the variable that is local to that package? Set_Local_True again is deceptive cause if you call it from package 3, you're not setting your local true, you're setting package one's local to true....

First off, this is very silly code. I'll assume it is shorthand for something else. But as presented, I can assure you that your clients can set their own booleans themselves without you writing a routine to do it for them. In fact, they can do it better. For the remainder of this answer, I'll assume you aren't acutally writing variables to set booleans for people, but rather doing something of actual use. If not, ignore the rest of this answer and just delete your silly routines.
Secondly, if you are creating a routine with a single out parameter, then unless the object happens to be very large, you should probably make it a function instead. That will allow your clients to use functional programming if they chose. The way you have it, the poor coder has to stop and create a special variable just to call your routine, even if they only want to do it once.
Thirdly, rather than using a unique set routine for each state, I generally prefer to pass in the requested state.
function Set_Frobnost (New_State : boolean := true) return boolean;
If the state is really and truly boolean (no possible third state in the future), then it is debateable. However, it can be a big advantage to your client if they might already have to store the state in a variable (or loop through it).
Your edit about naming shows me you are on the right track.
You should do one of two things here.
Find the higher-level concept controlled by that variable, and name the "setter" routine after that.
Get the hell out of the way and put the flag variable in the pacakge spec.

If you have to access private variables, you might to do it in a child package.
package One is
procedure Foo (X : Boolean);
private
One_Private : Boolean;
end One;
and then
package body One.Two is
procedure Bar is
One.Foo (One.One_Private);
end Bar;
end One.Two;
Elements in the "private" part of a package are like "protected" entities in C++/Java. Truly private variables (only in package body) are not accessible from anywhere else.

Related

Extending a Variable's Lifetime

To be fair, I cannot be entirely sure the title correctly describes the problem I am having, as it merely mirrors my current understanding of Ada as it is.
The Problem
I have a function:
function Make_Option (Title : String) return Access_Option is
O : aliased Option := (
Title_Len => Title'Length,
Title => Title);
begin -- Make_Option
return O'Unrestricted_Access;
end Make_Option;
This function is supposed to create a new menu option for the user, that may in turn be inserted into a menu (one that you might see in a terminal-based environment). You are all probably sighing, as quite evidently, the O variable would be deallocated at the end of this function (from my current understanding). As such, using the Unrestricted_Access here is just plain stupidity, but it mirrors the result of what it is I am trying to accomplish (as this code indeed does compile successfully).
The Access_Option is defined as following:
type Access_Option is access all Option;
The idea is that with an access to the option, which in turn is a discriminated record, is that we can store it within an array-like structure (as the object itself varies in size).
Beyond doubt, it would be nice if we could instead use the Access attribute for this, as the compiler would then make sure the lifetime is long enough of the O variable we are referencing, but as the lifetime as a matter of fact only exists til the end of the Make_Option function, we are presented with the following:
non-local pointer cannot point to local object
What I am then asking, is: how would I go about having a function to create Access_Options for me? Is such a thing even possible, or am I doing it all wrong? To clarify, what I am trying to do is create a neat way for filling an array with references to discriminated records, that I can then dereference and use.
Thought Process
I personally have not tried too many things, more than think about solutions that may be plausible for the problem. And, frankly, rather than going crazy of working makeshift solutions, it would be nice to have a solution that works for large-scale applications too, without messing up the code base to bad.
Would you perhaps have some sort of object queue to handle it? Does Ada even deallocate resources automatically in the first place? Gah. I am confused.
Would it, in fact, be possible to somehow place the O variable outside of the scope for deallocation to then manually deallocate it later?
Given the example you show above a much simpler approach is to simply make an array of Unbounded_String:
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_Io;
procedure Str_Arrays is
type Arr is array(1..10) of Unbounded_String;
A : Arr;
begin
for S of A loop
S := To_Unbounded_String("Hello World!");
end loop;
for S of A loop
Put_Line(To_String(S));
end loop;
end Str_arrays;
Don't try that.
There are two alternative options:
1) Use Ada.Containers.Indefinite_Vectors instead of a plain array.
2) Give your record discriminant a default value. Then you can store it in a plain array.
You seem to be reinventing the bounded string. Alternatives include
Using an instantiation of Ada.Strings.Bounded.Generic_Bounded_Length
Using Ada.Strings.Unbounded
Using an indefinite container (Ada.Containers.Indefinite_*) to hold type String

Ada deferred constant finalized using complicated calculation; where to put the code?

I needed the result of a rather complex calculation to define a private type, something like this:
generic
top_m : Positive;
package Mystic is
type T is private;
private
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
mytable : constant Table := reallyComplicatedFunction(top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Mystic;
I needed the type T to depend on generic parameter top_m in a really complicated way, embodied by reallyComplicatedFunction(.). The function is defined in the body of package Mystic, but it does not use anything else declared by the package.
To my surprise this setup works just fine. Maybe I'm just lucky, because as far as I can tell from decyphering the ARM, this kind of invocation of the function is merely 'legal' but it is not guaranteed not to throw a Program_Error. I interpret this as "it would be too restrictive to forbid this sort of stuff entirely, but the compiler can't be expected to determine its feasibility in all cases either, so we'll just allow you to experiment with it". And then there's the rather significant possibility that I'm completely misreading the reference manual. Anyway, books on Ada give rather stern warnings about this sort of thing, typically around the discussion of pragma Elaborate et al., such that I almost didn't try this solution.
I've also tried to put the function in a private child package of Mystic, but I could not resolve circularities between the child implicitly depending on the parent and the parent specification depending on the child. Anyway, this function is not an extension of Mystic but a necessary code to initialize it.
My question would then be: where is the proper place for such a function?
ETA: at the request of Simon Wright, here's the part of the ARM I struggle with: http://www.ada-auth.org/standards/12rm/html/RM-3-11.html entries 9, 10/1 and 14:
For a construct that attempts to use a body, a check
(Elaboration_Check) is performed, as follows:
For a call to a (non-protected) subprogram that has an explicit body, a check is made that the body is already elaborated. This check
and the evaluations of any actual parameters of the call are done in
an arbitrary order.
...
The exception Program_Error is raised if any of these checks fails.
As far as I understand, the construct mytable : constant Table := etc. tries to use the body of reallyComplicatedFunction, so it must check whether it was elaborated or not. I assume - this is a weak point in my reasoning but this is what I understood - that elaboration of the body of reallyComplicatedFunction only occurs during the elaboration of the body of package Mystic, so my function won't be elaborated at the time it is called from the private part of the package specification. Nonetheless, I don't receive the Program_Error as promised when using (an instance of) the package.
ETA2: following a remark from trashgod, I've tried turning package Mystic into a non-generic one; made top_m into a visible constant and removed the genericity part. The compiler now catches the circularity I was worried about from the beginning and the program exits with Program_Error: access before elaboration. It's as if the body of a generic package was elaborated before the first instantiation, or rather before the elaboration of the specification of said package during instantiation. Since I'd expect Ada to cater to this kind of need (of hiding complex calculations needed to instantiate a package in the body of said package), I'd not be surprised if it worked as per the standard, but I don't recall reading anything like this anywhere and would like to know the exact rules. Something very smart is going on because if I make the body of the function dependent on type T, the compiler warns about 'call to Tt may occur before body is seen' at the point of package instantiation (I guess 'Tt' is some internality of type T), and when the program is run, it throws a Program_Error complaining about access before elaboration, pointing to the first place where an object of type T is instantiated by another function I have called by reallyComplicatedFunction for testing purposes.
Edit, reflecting the comment that explain why reallyComplicatedFunction should not be public.
If I understand correctly, the function does not really not depend on Mystic, but reallyComplicatedFunction should be private. In that case, I'd try putting it elsewhere, and keep the dependency on top_m. I have assumed that Table could also be moved, even though formally it is creating a dependence of reallyComplicatedFunction, Table being in its parameter profile.
To resolve, a new private place is created in a hierarchy, a private sibling gets the declarations and will only be used in the private part of original Mystic. Hence, private with in the latter's context clause.
package Top is end;
private generic
top_m : Positive;
package Top.Outsourced is
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
end Top.Outsourced;
private with Top.Outsourced;
generic
Top_M : Positive;
package Top.Mystic is
type T is private;
private
package Initializer is new Top.Outsourced (top_m);
subtype Table is Initializer.Table;
mytable : constant Table := Initializer.reallyComplicatedFunction (top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Top.Mystic;
package body Top.Outsourced is
function reallyComplicatedFunction(x : Positive) return Table is
Limit : Positive;
begin
Limit := Positive'Min (top_m, 1) + x/2;
return Result : Table (1 .. Limit);
end reallyComplicatedFunction;
end Top.Outsourced;
Assuming (since you didn't specify it) the array returned from reallyComplicatedFunction has the range 1..top_m, you could define a new subtype and use that as the range for both arrays:
subtype My_Range is Positive range 1..m_top
type Table is array (My_Range) of Positive;
type T is array (My_Range) of Natural;
and move both my_table and reallyComplicatedFunction inside the package body.

Ada Function Parameter as Access Type or Not

I am refactoring some code originally written using access types, but not yet tested. I found access types to be troublesome in Ada because they can only refer to dynamically allocated items, and referring to items defined at compile time is apparently not allowed. (This is Ada83.)
But now I come to a function like this one:
function Get_Next(stateInfo : State_Info_Access_Type) return integer;
I know that I can easily pass parameter "contents" of an access type rather than the access pointer itself, so I am considering writing this as
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
where State_Info_Type is the type that State_Info_Access_Type refers to.
With this refactor, for all intents and purposes I think I'm still really passing what amounts to an implicit pointer back to the contents (using the .all) syntax).
I want to refactor and test starting with the lowest level functions, working my way up the call chains. My goal is to push the access types out of the code as I go.
Am I understanding this correctly or am I missing something?
I think original author(s), and possibly OP are missing a point, that is, how Ada parameter modes work.
To quote #T.E.D
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Ada does this automatically, and leaves the parameter modes as a way of describing the flow of information (Its NOT the C style reference / value conundrum). See the useful wikibook.
What worries me is that the code you have inherited looks like the author has used the explicit access parameter type as a way of getting functions to have side effects (usually considered a bad thing in Ada - World).
My recommendation is to change your functions to:
function Get_Next(State_Info : in State_Info_Type) return Integer;
and see if the compiler tells you if you are trying to modify State_Info. If so, you may need to change your functions to procedures like this:
procedure Get_Next(State_Info : in out State_Info_Type;
Result : out Integer);
This explicitly shows the flow of information without needing to know the register size or the size of State_Info_Type.
As an aside Ada 2012 Will allow you to have functions that have in out parameters.
To quote #T.E.D,
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Since this code hasn’t yet been tested, I think you are completely right to rework what looks like code written with a C mindset. But, you oughtn’t to mention pointers at all; you suggested
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
but this would be better as
function Get_Next(stateInfo : State_Info_Type) return integer;
or even (IMO) as
function Get_Next(State_Info : State_Info_Type) return Integer;
to use more standard Ada styling! My editor (Emacs, but GPS can do this too) will change state_info into State_Info on the fly.
As an afterthought, you might be able to get rid of State_Info_Type_Pointer altogether. You mention .all, so I guess you’ve got
SITP : State_Info_Type_Pointer := new State_Info_Type;
... set up components
Next := Get_Next (SITP.all);
but what about
SIT : State_Info_Type;
... set up components
Next := Get_Next (SIT);
I wouldn't recommend this, but you can get pointers to variables in Ada 83 by using 'Address.
You can then use overlays (again this is all Ada83 stuff) to achieve access...
function something(int_address : Address) return integer
is
x : integer;
for x'address use int_address;
begin
-- play with x as you will.

Can Code be Protected From Rogue Callers In Ada?

I'm a fairly new Ada programmer. I have read the book by Barnes (twice I might add) and even managed to write a fair terminal program in Ada. My main language is C++ though.
I am currently wondering if there is a way to "protect" subroutine calls in Ada, perhaps in Ada 2012 (of which I know basically nothing). Let me explain what I mean (although in C++ terms).
Suppose you have a class Secret like this:
class Secret
{
private:
int secret_int;
public:
Set_Secret_Value( int i );
}
Now this is the usual stuff, dont expose secret_int, manipulate it only through access functions. However, the problem is that anybody with access to an object of type Secret can manipulate the value, whether that particular code section is supposed to do it or not. So the danger of rogue altering of secret_int has been reduced to anybody altering secret_int through the permitted functions, even if it happens in a code section that's not supposed to manipulate it.
To remedy that I came up with the following construct
class Secret
{
friend class Secret_Interface;
private:
int secret_int;
Set_Secret_Value( int i );
Super_Secret_Function();
};
class Secret_Interface
{
friend class Client;
private:
static Set_Secret_Value( Secret &rc_secret_object, int i )
{
rc_secret_object.Set_Secret( i );
}
};
class Client
{
Some_Function()
{
...
Secret_Interface::Set_Secret_Value( c_object, some-value );
...
}
}
Now the class Secret_Interface can determine which other classes can use it's private functions and by doing so, indirectly, the functions of class Secret that are exposed to Secret_Interface. This way class Secret still has private functions that can not be called by anybody outside the class, for instance function Super_Secret_Function().
Well I was wondering if anything of this sort is possible in Ada. Basically my desire is to be able to say:
Code A may only be executed by code B but not by anybody else
Thanks for any help.
Edit:
I add a diagram here with a program structure like I have in mind that shows that what I mean here is a transport of a data structure across a wide area of the software, definition, creation and use of a record should happen in code sections that are otherwise unrleated
I think the key is to realize that, unlike C++ and other languages, Ada's primary top-level unit is the package, and visibility control (i.e. public vs. private) is on a per-package basis, not a per-type (or per-class) basis. I'm not sure I'm saying that correctly, but hopefully things will be explained below.
One of the main purposes of friend in C++ is so that you can write two (or more) closely related classes that both take part in implementing one concept. In that case, it makes sense that the code in one class would be able to have more direct access to the code in another class, since they're working together. I assume that in your C++ example, Secret and Client have that kind of close relationship. If I understand C++ correctly, they do all have to be defined in the same source file; if you say friend class Client, then the Client class has to be defined somewhere later in the same source file (and it can't be defined earlier, because at that point the methods in Secret or Secret_Interface haven't yet been declared).
In Ada, you can simply define the types in the same package.
package P is
type Secret is tagged private;
type Client is tagged private;
-- define public operations for both types
private
type Secret is tagged record ... end record;
type Client is tagged record ... end record;
-- define private operations for either or both types
end P;
Now, the body of P will contain the actual code for the public and private operations of both types. All code in the package body of P has access to those things defined in P's private part, regardless of which type they operate on. And, in fact, all code has access to the full definitions of both types. This means that a procedure that operates on a Client can call a private operation that operates on a Secret, and in fact it can read and write a Secret's record components directly. (And vice versa.) This may seem bizarre to programmers used to the class paradigm used by most other OOP languages, but it works fine in Ada. (In fact, if you don't need Secret to be accessible to anything else besides the implementation of Client, the type and its operations can be defined in the private part of P, or the package body.) This arrangement doesn't violate the principles behind OOP (encapsulation, information hiding), as long as the two types are truly two pieces of the implementation of one coherent concept.
If that isn't what you want, i.e. if Secret and Client aren't that closely related, then I would need to see a larger example to find out just what kind of use case you're trying to implement.
MORE THOUGHTS: After looking over your diagram, I think that the way you're trying to solve the problem is inferior design--an anti-pattern, if you will. When you write a "module" (whatever that means--a class or package, or in some cases two or more closely related classes or packages cooperating with each other), the module defines how other modules may use it--what public operations it provides on its objects, and what those operations do.
But the module (let's call it M1) should work the same way, according to its contract, regardless of what other module calls it, and how. M1 will get a sequence of "messages" instructing it to perform certain tasks or return certain information; M1 should not care where those messages are coming from. In particular, M1 should not be making decisions about the structure of the clients that use it. By having M1 decree that "procedure XYZ can only be called from package ABC", M1 is imposing structural requirements on the clients that use it. This, I believe, causes M1 to be too tightly coupled to the rest of the program. It is not good design.
However, it may make sense for the module that uses M1 to exercise some sort of control like that, internally. Suppose we have a "module" M2 that actually uses a number of packages as part of its implementation. The "main" package in M2 (the one that clients of M2 use to get M2 to perform its task) uses M1 to create a new object, and then passes that object to several other packages that do the work. It seems like a reasonable design goal to find a way that M2 could pass that object to some packages or subprograms without giving them the ability to, say, update the object, but pass it to other packages or subprograms that would have that ability.
There are some solutions that would protect against most accidents. For example:
package M1 is
type Secret is tagged private;
procedure Harmless_Operation (X : in out Secret);
type Secret_With_Updater is new Secret with null record;
procedure Dangerous_Operation (X : in out Secret_With_Updater);
end M1;
Now, the packages that could take a "Secret" object but should not have the ability to update it would have procedures defined with Secret'Class parameters. M2 would create a Secret_With_Updater object; since this object type is in Secret'Class, it could be passed as a parameter to procedures with Secret'Class parameters. However, those procedures would not be able to call Dangerous_Operation on their parameters; that would not compile.
A package with a Secret'Class parameter could still call the dangerous operation with a type conversion:
procedure P (X : in out Secret'Class) is
begin
-- ...
M1.Secret_With_Updater(X).Dangerous_Operation;
-- ...
end P;
The language can't prevent this, because it can't make Secret_With_Updater visible to some packages but not others (without using a child package hierarchy). But it would be harder to do this accidentally. If you really wish to go further and prevent even this (if you think there will be a programmer whose understanding of good design principles is so poor that they'd be willing to write code like this), then you could go a little further:
package M1 is
type Secret is tagged private;
procedure Harmless_Operation (X : in out Secret);
type Secret_Acc is access all Secret;
type Secret_With_Updater is tagged private;
function Get_Secret (X : Secret_With_Updater) return Secret_Acc;
-- this will be "return X.S"
procedure Dangerous_Operation (X : in out Secret_With_Updater);
private
-- ...
type Secret_With_Updater is tagged record
S : Secret_Acc;
end record;
-- ...
end M1;
Then, to create a Secret, M2 would call something that creates a Secret_With_Updater that returns a record with an access to a Secret. It would then pass X.Get_Secret to those procedures which would not be allowed to call Dangerous_Operation, but X itself to those that would be allowed. (You might also be able to declare S : aliased Secret, declare Get_Secret to return access Secret, and implement it with return X.S'access. This may avoid a potential memory leak, but it may also run into accessibility-check issues. I haven't tried this.)
Anyway, perhaps some of these ideas could help accomplish what you want to accomplish without introducing unnecessary coupling by forcing M1 to know about the structure of the application that uses it. It's hard to tell because your description of the problem, even with the diagram, is still at too abstract a level for me to see what you really want to do.
You could do this by using child packages:
package Hidden is
private
A : Integer;
B : Integer;
end Hidden;
and then
package Hidden.Client_A_View is
function Get_A return Integer;
procedure Set_A (To : Integer);
end Hidden.Client_A_View;
Then, Client_A can write
with Hidden.Client_A_View;
procedure Client_A is
Tmp : Integer;
begin
Tmp := Hidden.Client_A_View.Get_A;
Hidden.Client_A_View.Set_A (Tmp + 1);
end Client_A;
Your question is extremely unclear (and all the C++ code doesn't help explaining what you need), but if your point is that you want a type to have some publicly accessible operations, and some private operations, then it is easily done:
package Example is
type Instance is private;
procedure Public_Operation (Item : in out Instance);
private
procedure Private_Operation (Item : in out Instance);
type Instance is ... -- whatever you need it to be
end Example;
The procedure Example.Private_Operation is accessible to children of Example. If you want an operation to be purely internal, you declare it only in the package body:
package body Example is
procedure Internal_Operation (Item : in out Instance);
...
end Example;
Well I was wondering if anything of this sort is possible in Ada. Basically my desire is to be able to say:
Code A may only be executed by code B but not by anybody else
If limited to language features, no.
Programmatically, code execution can be protected if the provider must be provided an approved "key" to allow execution of its services, and only authorized clients are supplied with such keys.
Devising the nature, generation, and security of such keys is left as an exercise for the reader.

Ada Actual for this must be a variable in out mode

I am making a program in Ada for Data Structures and Algorithms class.
My current problem is the error 'actual for "this" must be a variable'
I did some looking around and I read about it being because of in out mode, but I'm not entirely grasping why it's happening to me I guess.
The Examples I seen made sense but I guess since it's my coding I'm just not seeing it?
Procedure AddUnmarked(g:Grid; this:Linked_List_Coord.List_Type; c:Cell) is
cNorth : Cell := getCell(g, North(c));
cEast : Cell := getCell(g, East(c));
cSouth : Cell := getCell(g, South(c));
cWest : Cell := getCell(g, West(c));
Begin
if CellExists(g, cNorth) and not cNorth.IsMarked then
Linked_List_Coord.Append(this, cNorth.Coords);
elsif CellExists(g, cEast) and not cEast.IsMarked then
Linked_List_Coord.Append(this, cEast.Coords);
elsif CellExists(g, cSouth) and not cSouth.IsMarked then
Linked_List_Coord.Append(this, cSouth.Coords);
elsif CellExists(g, cWest) and not cWest.IsMarked then
Linked_List_Coord.Append(this, cWest.Coords);
end if;
End AddUnmarked;
before "this" is passed to the function it is a Linked_List of my self defined type Coord (2 integers). It is initialized and has had a Coordinate pair added to it before the list is passed to the function above in my code.
What it means is that the list cannot be modified unless you are passing it as a modifiable parameter, that is, in out.
To elaborate, think of LIST_TYPE as being a handle to a tagged-type object; in order to ensure that LIST_TYPE is valid you need to pass it in via an in parameter (or create/manipulate a local object), but to pass out your results you need an out parameter.
So, in order to do your operations on an already-existing object {and get the results back} you need in out.
In Ada, subroutine parameters all have a usage mode associated with them. The available modes are in, out, and in out*. If you don't specify a mode, (like you didn't in your code), then it defaults to in only.
The modes specify what you can do with that parameter on the inside of the subprogram. If you want to read a value passed in from outside the routine, it must have in on it. If you want to write to the parameter (and/or possibly have it read outside the routine), then it must have out on it.
Since none of your parameters have out on them, you cannot write to any of them.
(* - There's another possible mode: access, but that's an advanced topic).

Resources