Header/header union/header stack operation on right values
Consider the following programs. Should we allow such kinds of operations?
header H {
bit<8> x;
}
union U {
H h;
}
H f() {
H h;
return h;
}
U g() {
U u;
return u;
}
H[1] h() {
H[1] s;
return s;
}
control c () {
apply {
f().isValid();
g().h.isValid();
h()[0].isValid();
f().setValid();
g().h.setValid();
h()[0].setValid();
}
}
Thanks @hackedy.
These particular programs don't look very useful, because the returned header is not saved anywhere and thus should not ever affect the final observable state of executing the program.
A more useful thing would be if the functions returned headers or header stacks, and those return values were assigned to other variables that DID have an effect on the final observable state of the program.
If we allow that last kind of program mentioned in this comment, then it seems that the programs you have written would be tricky or weird to disallow as illegal.
Andy. Take any of these booleans and add a final command that adds an emitted 1-byte header whose value is 0xFF if the it is true or a 0x00 if it is false.
The question is: do we want to allow isValid() on non-l-values?
I am maybe a little confused right now on the precise meaning of L-value and R-value. I hope the questions below might clarify where I'm confused.
Can we say that an expression like hdr.h (where hdr is a struct type with h as a member, and h has some header type) is an L-value or an R-value by itself, or only by the context where it appears in the program?
In the assignment hdr.h = { /* some fields here */ }; hdr.h is clearly an L-value.
In the assignment hdr.g = hdr.h;, hdr.h is clearly an R-value.
Is it specified that a call to a P4 function like f() always must represent an R-value, and can never represent an L-value? At least other languages like C++ let functions/methods return references which can be L-values, I think, but I'm perfectly OK if we say that P4 doesn't ever support that, at least not so far as of today.
If I write if (hdr.h.field1 == 5), I'd think that hdr.h.field1 is a R-value.
Similarly in the (partial) statement if (hdr.h == hdr.g) it seems to me that hdr.h is an R-value there.
Are you saying that if we write if (hdr.h.isValid()), that hdr.h is an L-value in that expression?
I think the point is "can be used as an lvalue". hdr.h can be used as an lvalue, while return values cannot be used as lvalues. hdr.h can also be used as an rvalue, either by evaluating to an lvalue and dereferencing it or directly evaluating to an rvalue. Do we expect to have an lvalue or rvalue when calling isValid()?
For calling isValid(), which has no side effects, it seems quite reasonable to support calling it on an R-value.
For calling setValid() or setInvalid(), which have side effects, it seems odd to me to allow calling them on R-values.
The values returned by these functions are dead unless they are copied to another value that can be used afterwards. So I am with Andy that any choice you make about these being valid or not, the constructs themselves are useless. Being useless, having them be prohibited may actually be useful.
I added a test program to this p4c issue because it gets a compiler bug when attempting to compile it: https://github.com/p4lang/p4c/issues/3001
Note that in that test program, the calls to .isValid() are not dead, and it seems reasonable to me if the language spec permitted such calls like f().isValid(), for the reasons stated in my earlier comment.
A possible approach is, while we allow writing hdr.isValid(), we interpret it as isValid(hdr). The function prototype is isValid<H>(in H hdr) and H must be a header. Then we can regulate whether or not it needs to be an lvalue.
Why do we need to interpret as isValid(hdr) to regulate whether or not it needs to be an lvalue?
Couldn't we just say that
FYI, p4c until recently gave a compiler bug for a statement like if (f().isValid()) ..., but Mihai made changes so that now it seems to compile correctly: https://github.com/p4lang/p4c/issues/3001
That is not necessarily an argument that it should be legal in the language spec, but I wanted to mention it here as additional facts in the discussion.
In the interest of tidying up the set of active issues on the P4 specification repository, I'm marking this as "stalled" and closing it. Of course, we can always re-open it in the future if there is interest in resurrecting it.