|
LCS-2016-060 |
|
1 {06-Jan-2017} 2 {10-Jan-2017} |
|
10-Jan-2017 |
|
Voting |
|
Patrick Lehmann |
|
Main.PatrickLehmann |
|
New Predefined Attributes: 'actual, and 'formal |
|
Adds attributes to access attributes of an actual. |
'ACTUAL_SUBTYPE
to 'ACTUAL
.
P'ACTUAL | Kind: | Subtype |
Prefix: | Any prefix P that is an interface object. | |
Result: | The subtype of an actual associated to a formal. | |
Restrictions: | This attribute is allowed only as the prefix of the name of another attribute; for example, P'ACTUAL'LEFT. |
function foo(s: std_logic; v: std_logic_vector) return integer is variable a, b: integer; begin a := v'left; -- This is how one retrieves the left bound of a vector b := s'actual_subtype'left; -- This is how one retrieves the left bound of a scalar return(a); end function foo;The user will, I think, rightly look at this and question why in the world is there so much typing in order to get the left bound of a scalar when it is so straightforward to get it for a vector? They will also have a valid beef about lack of consistency. There was precedence in how to get the attributes of a vector, how come that same mathod wasn't chosen for scalars? The users (and the tool makers) ultimately bear whatever convenience or burden the LRM puts on them. I think that once a person understands what 'bounds' are, that one has a mental model of what it means to talk about the 'bounds of a scalar' and the 'bounds of a vector' and would probably find it intuitive to access the 'bounds' of scalars and vectors in the same way. The less frequent user would be rightly ticked off that they need to use different methods to get at what they consider to be the same type of thing...after having to go back to the 'Dummies' book to see once again how to get the left bound of a scalar again. My two cents is, if you vote for this proposal, I think you should be comfortable explaining your answer to an end user to the question "Is this really the best that can be done here? Really???" I'm not trying to get into a debate on this and, as I said it is non-technical, just putting it out there asking people to consider the end user's view and how this feature could very likely be perceived out in the world. I'm not trying to go all 'Marketing' on folks, but this one doesn't look pretty to an end user and it easily could have. Plus we are all end users as well, do you really want to be accessing scalars and vectors differently when you're writing code? --
v
is a constrained vector, which is mostly the case on entity port lists, then v'ACTUAL_SUBTYPE'LEFT
can refer to the actual's bounds, whereas v'LEFT
returns the bounds of the formal. Both values might be different.
The difference is not the handling of attributes for arrays and scalars. The difference is that array bounds can be moved in an assignment and association, whereas type ranges
can not be moved. But this is all independent on how you access the information. 'LEFT
for scalar and arrays is not semantically the same operation. It just happens that both
attributes have the same name, because they are defined on different types.
-- 'ACTUAL
should be restricted to interface objects
of scalar types or subtypes.
I think the description of the return value should be changed to that of O'SUBTYPE
:
"The fully constrained subtype that is the subtype of O, together with
constraints defining any index ranges that are determined by applica-
tion of the rules of 5.3.2.2. (If O is an alias for an object, then the
result is determined by the declaration of O, not that of the object.)"
Note: I prefer 'ACTUAL_SUBTYPE
.
-- constant
parameters. These can be associated with literals, which are formally typed as universal_(integer|real)
. Is there any sensible interpretation of the attributes accessible through 'actual
in this case?
-- signal S: natural range 3 to 8; constant Sleft: integer := S'actual'left; -- This is a new error condition since S is not an interface object. User needs to remember to NOT use 'actual here constant Sleft: integer := S'left; -- This will be allowed by LCS-2016-018.- Creates an unreported user design issue when code gets refactored because of sensitivity to context. Consider if the user decides to refactor their code a bit and move the 'Sleft' out of the architecture and into a procedure. Furthermore, the procedure is applicable to the full range of type natural. Copy/paste refactoring would likely produce:
signal S: natural range 3 to 8; ... Call the procedure foo as foo(S); ... procedure foo (signal S: natural) is constant Sleft: integer := S'left; -- This form is now 'wrong' since it will return 0 rather than the value 3 from the actual. constant Vleft: integer := V'left; -- This is correct and returns the value 7 from the actualThe above will compile without error but will not produce the same value of 3 for Sleft as it did before refactoring. Instead, the user must now modify their previously working code and instead use S'actual'left. But since there was no compiler error produced, the user is likely to have to debug in simulation to find the error. - Vector and scalar usage is different for no apparent reason to the end user.
signal S: natural range 3 to 8; signal V: std_ulogic_vector(7 downto 0); procedure foo (signal S: natural; V: std_ulogic_vector) is constant Sleft: integer := S'actual'left; -- Why is it that I need to say S'actual rather than S... constant Vleft: integer := V'left; -- when you could figure out what I wanted for a vector???Alternatives: Neither of these end user problems are encountered if LCS-2016-072a is implemented instead. - No new errors are produced - S'left will work properly in all of these contexts without the end user having to make any code adjustments and without having to know which context they are in. - No debug required when copy/pasted code is refactored and the code context changes and yet no errors are reported. I think the basic problem here is that folks are clinging to attributes and how they are used today and thinking that there must be something 'different' in the code in order to distinguish the new usage. What you should consider instead is what do you think the end user should expect to get when they say "Sleft = S'left"? Then ask why they should have to alter their code based on code context to get what they want? --
'LEFT
, just because the authors chose to use the same name for two different things. One is a scalar type's range boundary and the other one is an array index's range boundary.
PL: As far as I understand the LRM, objects are already classified in interface objects and locally declared objects, so it is not difficult to track if 'actual
is allowed.
-- 'actual
is to give you access to the situation before this conversion. And I am afraid, there is no such intuitive before in the case of constant literals. So as to avoid diversion among implementations, a clear specification is needed. Acceptable choices may be (a) to disallow 'actual
on constant parameters, (b) to make the actual subtype equivalent to the formal subtype or (c) to create an implicit one-element subtype of the formal whose range coincides with the exact constant value. As I am still short of a convincing use case, I do not know which of these choices fits best.
-- 'actual
is not as firmly defined as it may appear at a first glance (see above), specifications are required to eliminate uncertainty and prevent tool divergence. Without an illustrative example that helps to understand the usage scenario, those specification choices can only go wrong. That's why I have changed my vote to a straight no and would ask for postponing this LCS until real demand and well-understood usage patterns become available.
--