Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add specification for named parameters #599

Closed
wants to merge 2 commits into from

Conversation

cc10512
Copy link
Contributor

@cc10512 cc10512 commented Mar 25, 2018

Fixes #598

Copy link
Contributor

@ChrisDodd ChrisDodd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very clear on the difference between _ and None. Does the former mean that caller need not provide the value while the latter means something else?

If `_` is provided as the default value the compiler will initialize the
optional parameter with an appropriate value.

In addition, we define the value `None`as a keyword to specify a parameter for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding None as a keyword is going to break any program that already uses None as a name anywhere.

Copy link
Contributor Author

@cc10512 cc10512 Mar 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that could be a problem. However, I have seen no uses of None in the entire body of p4_16 code that I have access to.
In addition, we should be able to detect the context and have the defined meaning only when used as an argument "initializer".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't think we need to have a None default value. We don't need it for anything.
It is much simpler to just an annotation of @optional on parameters that do not need to have a value specified, as it is today. However, we can only allow such parameters for objects that are interpreted by the back-end, e.g., package or extern constructor parameters.
We can have default parameter values, but they have to have the right type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear to me why would you prefer an annotation over explicitly stating the optionality in the language. Just because we currently have an experimental feature implemented in the compiler? I can promise that we implement the new feature instead.

Line 1477 states that all optional parameters are applicable to objects not exposed to the control plane. If it is not coming across, please suggest different wording.

In addition, we define the value `None`as a keyword to specify a parameter for
which there should be no default value. The programmer must specifically
provide a value for a parameter initialized with `None`, Otherwise, for an
invocation that does not specify a value, the compiler may assume that all uses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the programmer must specifically provide a value for the parameter, how can there be an invocation that does not specify a value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use None, we assume that that parameter is not used at all. With a '_' (default value) we assume a default value described in the table (empty controls and parsers, default instances of externs, or zero valued ints, headers, structs, metadata.

@mihaibudiu
Copy link
Contributor

mihaibudiu commented Apr 23, 2018

I wrote a very compact summary of calls with named arguments, which I hope handles all of the use cases described in this PR:

    Named arguments
  1. P4 entities that can be called or instantiated:

Called:

  • extern functions
  • methods of extern objects
  • controls (called from other controls)
  • parsers (called from other parsers)
  • actions (directly called from controls; from table entry initializers)

Instantiated

  • controls (instantiated in other controls or packages)
  • parsers (instantiated in other parsers or packages)
  • packages (instantiated at top-level or other packages)
  • extern objects (through constructors)
  1. Goal: P4 should allow function-like calls to be made by specifying
    the argument Names.

  2. Examples: given the following declarations:

extern void f(in bit<32> a, out bit<16> b);
extern C {
     C(bit<32> size);
     bit<16> get(in bit<32> index, in bool b);
}

parser parserProto<H>(packet_in p, out H h);
control controlProto<H, M>(inout H h, inout M m);
package pack<H>(parserProto<H> p, controlProto<H, _> c);

3.1. Current syntax:

parser p(packet_in p, out MyH h)(bool b) {
     ....
}

parser p1(packet_in pkt, out MyH h) {
     p(true) pinst;
     state start {
          pinst.apply(pkt, h);
          transition next;
     }
}

control c(inout MyH h, inout MyM m)(bool b) {
     ...
}

control c1(inout MyH h, inout MyM m) {
     c(true) cinst;
     C(10) extC;

     apply {
           c.apply(h, m);
           bit<32> x;
           bit<16> z;
           f(x, z);
           z = extC.get(x, true);
     }
}

pack(p1, c1) main;

3.2. New syntax:

parser p1(packet_in pkt, out MyH h) {
     p(b = true) pinst;
     state start {
          pinst.apply(p = pkt, h = h);
          transition next;
     }
}

control c1(inout MyH h, inout MyM m) {
     c(b = true) cinst;
     C(size = 10) extC;

     apply {
           c.apply(h = h, m = m);
           bit<32> x;
           bit<16> z;
           f(a = x, b = z);
           z = extC.get(index = x, b = true);
     }
}

pack(p = p1, c = c1) main;
  1. Rules:

4.1. Previously calls used to be of the form:

identifier(expression list)

Now we will also allow

identifier( (paramName = expression) list )

4.2. Argument names must correspond to parameter names. Arguments can
be supplied in any order if they are named. Arguments are evaluated
left-to-right in the order they show up in the call (and not in the
order that the parameters show up).

4.3. A call can have either all argument names supplied or none.
Mixing names with positional is not supported.

4.4 Overloading: overloaded objects are allowed if any call can be
unambiguously resolved using the number of arguments (if positional)
or argument names (if arguments are passed by name).

  1. Optional parameters

A parameter can be annotated as optional using @optional:

extern void g(in bit<32> a, @optional in bool b);

g(10);  // legal
g(10, true);  // legal
g(a = 10);  // legal
g(a = 10; b = true);  // legal

If all optional parameter are at the end, then object can be called
using positional or named arguments, otherwise it can only be called
using named arguments.

Optional parameters can only appear for the following objects:

  • packages
  • extern functions
  • extern methods
  • extern object constructors

Justification: the implementations of these objects is not done in P4.
For packages and constructors the compiler will evaluate the call as
if the missing optional arguments have a special distinguished value
"NONE". For functions and methods the compiler will generate the
proper call or signal an error.

  1. Default parameter values

A parameter can be annotated with a default value of the correct type:

extern void h(in bit<32> a, in bool b = true);

h(10);  // same as h(10, true);
h(a = 10);  // same as h(10, true);
h(a = 10, b = true);

struct Empty {}
control nothing(inout Empty h, inout Empty m) {
   apply {}
}

package pack<H, M>(@optional parserProto p,  // optional parameter
                   controlProto c = nothing()); // default parameter value


pack() main;   // parser is NONE, control is an instance of nothing()

Default parameter values can appear in all declarations that appear in section 1.

If all default parameter values are at the end the object can be
called using positional or named arguments, otherwise it can only be
called usign named arguments.

6.1. Combining default values and optional parameters

The same parameter cannot be both optional and have a default value.

An object with both default parameters values and optional parameters
can only be called using named arguments.

extern void i(@optional in bit<32> a, in bool b = true);

i();  // legal, same as i(b = true);
i(b = true);  // legal
i(a = 10);  // legal, same as b(a = 10, b = true);
i(a = 10, b = true);   // legal
i(10);   // illegal: must used named arguments
i(10, true);   // illegal: must use named arguments

@mihaibudiu
Copy link
Contributor

There are few key points:

  • allow named arguments
  • overloading is allowed as long as the compiler can disambiguate any call
  • optional parameters only work for values where the compiler knows what code to generate
  • instead of using a NONE default value, mark the parameter as @optional. The NONE value is only something that is internal to the compiler, and not exposed in P4.

@ChrisDodd
Copy link
Contributor

Do we really need both @optional and default parameters? They seem to mostly fill the same niche. @optional really only makes sense for extern functions/methods, as we have no syntax for determining if an optional argument was supplied or not in anything that has a body. It currently has an additional related meaning for abstract methods (they can be defined in an instance with a method that does not include the optional argument), which is different from the meaning anywhere else.

@mihaibudiu
Copy link
Contributor

The difference between the two is that an optional parameter may not be given any value (i.e. will have the value NONE). This machinery avoids having a special value for NONE in the language.

@mihaibudiu
Copy link
Contributor

But indeed, it looks a bit ugly. If we had a nice version of NONE we would not need optional anymore.

@jnfoster
Copy link
Collaborator

I think this can be closed as it is superseded by #626

@jnfoster jnfoster closed this May 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants