Language Change Specification for Function Interface Proposal

LCS Number: LCS-2016-002
Version: 7
Date: 31-Oct-2016 (Ver 1)
xx-Xxx-2016 (Ver 2)
14-Dec-2016 (Ver 3)
20-Dec-2016 (Ver 4)
17-Feb-2017 (Ver 5)
20-Feb-2017 (Ver 6)
24-Feb-2017 (Ver 7)
Status:  
Author: Kevin Jennings (Ver 1 and 2)
Ryan Hinton (Ver 3)
Jim Lewis (Ver 5 & 6)
Email: KevinJennings
RyanHinton
Source Doc: FunctionInterface
Summary: Allow access and protected type parameters on function interfaces
Interacts with: LCS_2016_014

Voting Results: Cast your votes here

This is the Laisee Faire version.

Revision Notes

Revision 7

  • This is the Laisee Faire version.

Revision 6

  • Made access types in only. Hence, can read the pointer, but not update the pointer.
  • To change the data, one must copy the pointer.

Revision 5

  • Added last sentence for the paragraph on pure functions that is currently in the LRM. If we want to delete this it needs to be red with a line through it. I think it is needed and was an oversight.

Details of Language Change

LRM 4.2.2.1 Formal parameter lists

Page 21 near top, second paragraph

[author comment: text for composite of a protected type depends on LCS_2016_014 being approved].

Change as indicated by red font.

For those parameters with modes, the only modes that are allowed for formal parameters of a procedure are in, inout, and out. If the mode is in and no object class is explicitly specified, constant is assumed. If the mode is inout or out, and no object class is explicitly specified, variable is assumed.

[Editing Note: This is the Laisee Faire version. It allows the same parameters as procedures. If accepted, in the final version, this paragraph will be incorporated into the one above on procedures.]

For those parameters with modes, the only modes that are allowed for formal parameters of an impure function are in, inout, and out. If the mode is in and no object class is explicitly specified, constant is assumed. If the mode is inout or out, and no object class is explicitly specified, variable is assumed.

For those parameters with modes, the only mode that is allowed for formal parameters of a pure function is the mode in (whether this mode is specified explicitly or implicitly). The object class shall be constant, signal, or file. If no object class is explicitly given, constant is assumed.

NOTE -- Variable class parameters of access and protected types are allowed for procedures and impure functions.

-- Kevin Jennings - 2016-10-21 -- Ryan Hinton - 2016-12-12

Comments

Version 2 change: Add 'and protected type' to the one sentence change.

-- Kevin Jennings - Unknown date

Per Nov-17-2016 discussions, reviewed Ada-2012 LRM. I did not see example of how this LCS change corresponds with any Ada examples. Ada already allows for function parameters to be passed by reference and does not seem to have any concept of 'impure' functions that I could tell. Section 6.4 Subprogram Calls page 165 (193 in PDF) specifically says "A function_call denotes a constant, as defined in 6.5..."

-- Kevin Jennings - 2016-11-18

Protected types can only be used with object class "variable", but this class is not listed. By adding "pure" in front of function , there is no statement of the parameters mode for impure functions. It should at least also restrict everything to "in" and allow "inout" as an exception for protected types.

-- Patrick Lehmann - 2016-12-09

Version 3 change: added text to remove ambiguities noted by Patrick.

-- Ryan Hinton - 2016-12-12

As written, this LCS has the side-effect of allowing ANY inout-mode variable or signal parameter to an impure function. Is this what we want? (The inout mode is added to allow variables of protected types, which must be passed by reference as inout mode, see LRM 4.2.2.2, the short paragraph near the end of page 21.)

-- Ryan Hinton - 2016-12-12

Patrick did not suggest an ambiguity, what he noted was the lack of a restriction. To the question of "Is this what we want?" my response would be why not? Why do you (and Patrick too I think) feel that a restriction must be kept in place? If there is an actual technical reason why it should not be allowed, post that reason. If there is no reason, then leave it alone. The LCS, as originally written, I believe captures what the proposal writer has requested, I'm not so sure that your modification retains that. Changing my vote to abstain.

-- Kevin Jennings - 2016-12-14

There was typo with the LRM section which I have now changed to '4.2.2.1 Formal parameter lists' (was '4.2.1 General (Subprogram declarations)'). I have also removed the HTML from the table and tidied the format.

-- Brent Hayhoe - 2016-12-15

Do we want to allow impure functions to have out and inout signals and variables of a regular type? This is probably bad. ADA-1995 only allowed access types. I am not sure what happened in more recent versions. We could reintroduce a separate paragraph for impure functions that limited out and inout parameters to variables that have either an access type or protected type.

-- Jim Lewis - 2016-12-17

What I am thinking is a second paragraph which reads: For those parameters with modes, the only modes that are allowed for formal parameters of an impure function are in, inout, and out. If the mode is in and no object class is explicitly specified, constant is assumed. If the mode is inout or out, and no object class is explicitly specified, variable is assumed. If the mode is inout or out and the object class is specified, it shall be variable. If the mode is inout or out, the object shall have a type which is either an access type or a protected type.

The last sentence needs work.

-- Jim Lewis - 2016-12-17

First, why is it important that signals and variables of regular types be excluded? I agree it may be bad style, and I wouldn't use it unless it's the least bad of the available alternatives.

-- Ryan Hinton - 2016-12-19

These singulars sound wrong: "... or a composite of only an access type or a protected type." Maybe, "... or a composite type whose members are all either of an access or a protected type." will do?

-- Thomas Preusser - 2016-12-21

I think we also need to add and/or modify text in 9.3.4 that discusses function calls. Switching to a NO vote until this is resolved.

-- Ryan Hinton - 2016-12-29

This LCS goes beyond the original requirement of passing access and protected types to impure functions, which needs only an in mode. It allows a strangely restricted inout mode, but not an out mode. This seems arbitrary.

-- Peter Flake - 2016-12-29

Why does VHDL request inout mode for access types and protected types? Normally, objects (in other languages) are passed by reference (pointers). These pointers are input parameters. So the question is why does VHDL say that pointers are inout? I could imagine it is a compiler hint to detect impure/pure function parameter rule violations because VHDL has no "byref" / "byvalue" keywords.

-- Patrick Lehmann - 2016-12-31

@PatrickLehmann: There is a difference between passing by reference and passing of a pointer, which will actually passed by value.

In Java for example, there are only pointers and these are passed by value to the function. In VHDL, this will be the access values and these can be passed with mode in.

In C++ for example, you can also enforce that an object is passed by reference. A compiler may internally use pointers to achieve this, but the difference to normal pointers as above is that this internal pointer will never be null. And if the function / method is inlined, the pointer dereference can be optimized away.

Furthermore, C++ allows two variants to pass a reference:

1. const Type& ref -- this will be a reference to an object which cannot be modified within the function. That means, you can call only methods of Type which are declared as "const". In VHDL these would be pure functions (methods) of the protected type Type.

2. Type& ref -- this will be a reference to an object which can be modified within the function. In VHDL this allows to call all methods of the protected type Type.

EDIT: In the current LRM (of VHDL), no restrictions are defined regarding which methods can be called on an object of a protected type. Thus case 2 applies which requires passing the object with mode inout because the content of the (passed) object might be modified.

-- Martin Zabel - 2017-01-28

@all: Why does the proposed change does include this restriction:

"If the mode is inout, the object shall have a type which is either an access type, a protected type, or a composite of only an access type or a protected type."

This actually means that I cannot pass a variable of some scalar type as inout to an impure function. If I wrap this scalar object by a protected type, then I can pass it as inout and, of course, modify it using methods of the protected type. Thus, this restriction is pointless.

My suggestion is to remove this sentence.

-- Martin Zabel - 2017-01-28

@Peter the strange "inout" is due to VHDL requiring "inout" for pointers and protected types when used as a parameter of a procedure. This keeps consistent with that.

@MZ The intent of the proposal is similar to what ADA-95 did and only allow pointers and things like pointers (ie: protected types).

-- Jim Lewis - 2017-02-16

What prevents a function from having a parameter of type access is that the parameter must be of class constant. An access type cannot be of class constant.

The LCS allows an impure function to have a parameter of class variable. An access type can be of class variable and mode in. So mode inout should be restricted to protected types.

-- Peter Flake - 2017-02-17

@PeterFlake: You said: An access type can be of class variable and mode in. So mode inout should be restricted to protected types.

I'm would agree on that, but a variable of an access type and of mode in would disallow to update the designated object by the access value, see also clause 6.5.2. Here is a short VHDL-2008 example which must use a procedure, of course:

entity e is
end entity;

architecture a of e is
  type IntPtr is access integer;
  
  procedure p(variable x : in IntPtr) is
  begin
    x.all := x.all + 1;          -- NOT ALLOWED
  end procedure;
  
begin

  process
    variable a : IntPtr := new integer'(0);
  begin
    report "a = "& integer'image(a.all);
    p(a);
    report "a = "& integer'image(a.all);
    wait;
  end process;
  
end architecture;

EDIT: Thus, if we allow variables for impure functions with:

  • any mode for protected types --- the actual mode is of no care if any method should be callable on the variable---,
  • mode in for any other feasible type,
then the impure function can update a protected type object, but nothing else which has been passed in. This would still be curios, see also my comment on 2017-01-28.

-- Martin Zabel - 2017-02-17

@TODO: As also mentioned by Ryan, clause 9.3.4 needs to be updated because it states (in the middle of page 136):

Evaluation of a function call includes evaluation of the actual parameter expressions specified in the call and evaluation of the default expressions associated with formal parameters of the function that do not have actual parameters associated with them. In both cases, the resulting value shall belong to the subtype of the associated formal parameter. [...] The function body is executed using the actual parameter values and default expression values as the values of the corresponding formal parameters.

But, for protected types (PT) a reference must be passed in. (in Jim's view there would be no value at all. In my view, such a method call would not copy the value of the PT object.)

And for a variable with mode inout of any type other than a PT, the final value must be copied back into the associated actual parameter (variable).

See also clause 14.6.

-- Martin Zabel - 2017-02-17

@Martin I think we can agree that this proposal makes what a function and procedure does with its parameters much more similar.

So I look in 9.3.4 function calls on page 136. Now I look at the corresponding paragraph of 10.7 procedure calls also the last paragraph that spans pages 163 and 164. Swap the word function for procedure. Swap evaluated (functions are part of an expression that is evaluated) for the word executed (procedures are statements that are executed). At this point the text is identical.

Since the paragraphs are identical except for changing function to procedure and evaluated to executed, I conclude that no changes are needed to 9.3.4.

I reviewed 14.6. It only used the word subprogram. Hence, what it says applies to both procedures and functions equally.

Hence, no edits are needed to 9.3.4 or 14.6.

-- Jim Lewis - 2017-02-17

@Peter, I amend my statement about inout. inout is required for protected types. It is not required for access types. The language permits any mode for access types. This proposal allows access types to be either in or inout. The restriction for protected types being inout is not here either it is in 4.2.2.2, page 21, 2nd to last paragraph.

-- Jim Lewis - 2017-02-17

Posted version 5. Added sentence to end of "pure" functions that is part of the LRM and accidentally got left out.

-- Jim Lewis - 2017-02-17

@Jim. You are right. I was confused by the wording in this sentence:

Evaluation of a function call includes evaluation of the actual parameter expressions specified in the call [...]

I thought this means that every actual is treated as an expressions. But, it actually says that: if the actual is an expression, it will be evaluated. Sorry for any inconvenience.

JL: I think we can agree that this proposal makes what a function and procedure does with its parameters much more similar.

Yes, I agree. But why then not just splitting subprograms into these two classes:

  • procedures and impure functions why may have parameters of class variable and of an access or protected type (independent of any mode),
  • pure functions which shall not have parameters of class variable, and thus no parameters of an access or protected type.

This was actually done in Version 3. Even you voted Yes on this version, but left a comment later on (2016-17-12) which reads:

Do we want to allow impure functions to have out and inout signals and variables of a regular type? This is probably bad. ADA-1995 only allowed access types. I am not sure what happened in more recent versions. We could reintroduce a separate paragraph for impure functions that limited out and inout parameters to variables that have either an access type or protected type.

And then you changed the text to Version 4. But, you didn't answered the question from Ryan, neither before nor later on: First, why is it important that signals and variables of regular types be excluded? I agree it may be bad style, and I wouldn't use it unless it's the least bad of the available alternatives. (Ryan Hinton, 2016-12-12)

So, as long as this question is not answered by you or any other person in a convincing way, I will vote against Version 4 / 5. The restrictions put into version 4 / 5 are just arbitrary, see also my comment on 2017-01-28 and also Peter's comment on 2016-12-29 which seems to backup his No vote.

-- Martin Zabel - 2017-02-18

@MZ. Both VHDL and ADA have the intention to be safe languages. As we allow AT and PT on functions, we weaken that. To allow any old type, throws away too much of the original design intent. If you tried to thrww out strong typing, you would have many people after you. To me, this is like that.

-- Jim Lewis - 2017-02-18

From Peter Flake: The issue as far as I am concerned is that an inout access type can be modified in the function and then would have to be copied back to the actual (4.2.2.2). In other words inout applies to the pointer not to the object pointed to. If this mechanism exists for pointers, why not for any scalar? The issue does not apply to protected types.

@TODO, hence, I conclude that access types should be mode in.

Perhaps this means we should allow protected types to have the mode in and this proposal only allow functions to have mode in.

-- Jim Lewis - 2017-02-18

@Jim: Then let's take a look on the Ada 95 LRM:

Ada 95, Clause 6.1

The formal parameters of a function, if any, shall have the mode in.

Ada 95, Clause 6.2 When a parameter is passed by reference, the formal parameter denotes (a view of) the object denoted by the actual parameter; reads and updates of the formal parameter directly reference the actual parameter object.

A type is a by-reference type if it is a descendant of one of the following:

  • [...]
  • a task or protected type;
  • [...]

A parameter of a by-reference type is passed by reference.

NOTES: A formal parameter of mode in is a constant view (see 3.3); it cannot be updated within the subprogram_body.

Ada 95, Clause 3.3

An object is either a constant object or a variable object. The value of a constant object cannot be changed between its initialization and its finalization, whereas the value of a variable object can be changed. Similarly, a view of an object is either a constant or a variable. A constant view of a variable object cannot be used to modify the value of the variable. The terms constant and variable by themselves refer to constant and variable views of objects.

The value of an object is read when the value of any part of the object is evaluated, or when the value of an enclosing object is evaluated. The value of a variable is updated when an assignment is performed to any part of the variable, or when an assignment is performed to an enclosing object.

Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent constants:

  • [...]
  • a formal parameter or generic formal object of mode in;
  • [...]

Ada 95, Clause 9.5.1

Within the body of a protected function (or a function declared immediately within a protected_body), the current instance of the enclosing protected unit is defined to be a constant (that is, its subcomponents may be read but not updated). Within the body of a protected procedure (or a procedure declared immediately within a protected_body), and within an entry_body, the current instance is defined to be a variable (updating is permitted).

Thus, you can call only protected functions on a formal parameter of mode in because such a function cannot update the protected object.

The C++ equivalent is that you can only call const functions on parameter with signature const Type& ref as already explained in my comment from 2017-01-28.

There is no direct equivalent in VHDL because:

  • Pure functions of protected types can only access constant objects (or type declarations) of the shared data to ensure that each method call returns the same result given the same parameters. Thus, they are more restricted then the protected functions of Ada.
  • Impure functions and procedures can update the shared data.

What I expect from a safe language:

  • If the mode is in, then the object shall be only read, i.e., only pure or const functions of the PT can be called on the object, see below.
  • If the mode is inout, then the object can be read or updated, i.e., any functions and procedures of the PT can be called on the object, see below.
  • Pure functions of a PT, shall only read (evaluate) constant objects of the shared data.
  • Const functions of a PT, shall only read the shared data (this concept is not available in VHDL, but in Ada 95 or C++).
  • Impure functions and procedures of a PT, can also update the shared data.
  • Pure functions shall only have parameters of mode in.
  • Impure functions and procedure can have parameters of any mode.

Comment edited on 2017-02-18 11:38 pm CET

-- Martin Zabel - 2017-02-18

Revision 6. To address Peter's concern about being able to change the value of the pointer when an access type object is inout, I changed it so only protected types are inout

-- Jim Lewis - 2017-02-21

Topic revision: r8 - 2020-02-17 - 15:34:39 - JimLewis
 
Copyright © 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback