Ada Function Parameter as Access Type or Not

1.4k views Asked by At

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?

3

There are 3 answers

2
NWS On BEST ANSWER

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.

1
Simon Wright On

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);
2
Dale Stanbrough On

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.