-
Notifications
You must be signed in to change notification settings - Fork 82
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
Namespaces and imports #718
Comments
@jafingerhut there is also (d) |
Yes, glad you mentioned that variant, too, since I forgot it, and because |
Yes, python is a good model. |
Should we pick up the Modularity WG sub-group and bang out a quick proposal together? (Maybe just the three of us?) I'll even be in CA much of the next week if we want to do it in person... :-) |
Apologies for missing you in person, given the invitation. I would be open to doing a sub-group meeting focused on this topic. Given my lack of knowledge of more sophisticated module systems from other programming languages, my initial proposal here is focused on what I understand better, i.e. visibility or non-visibility of object names (object here meant to include things like P4_16 function definitions, extern objects, extern functions, etc.), which seems like it at least covers concerns about name conflicts. @mbudiu-vmw Your concern with nested modules isn't clear to me yet, perhaps because I'm not sure what you mean by the term. Perhaps you mean a scenario like the following? Someone writes a module M2. Someone else writes a module M1 that imports some names from module M2. Yet another person writes a P4 program that imports M1, and thus also imports M2. You want it to be possible to allow some selected names from M2 to thus be visible from within the P4 program, without having to explicitly import M2 as well? If that is the scenario you are considering, it seems to me that perhaps the following code sketch would enable this? Skeleton of the definition of module M2:
Skeleton of the definition of the P4 program:
The above examples presume that all names in a module are "public", i.e. are allowed to be imported. One could also of course define a mechanism for a module to explicitly list which of its names can be imported by others, and define it to be an error to attempt to import any other names from that module (i.e. they would be "private" by default). |
You are right. A few of us met in person and brainstormed, and we reached the conclusion that we have to continue to support a significant part of the preprocessor functionality, including |
Sorry I missed the brainstorming meetings, and thus may be treading old ground with this comment, that misses some requirements that you have identified but aren't explicitly stated in comments here yet. Please feel free to add comments describing any such requirements that this comment's proposal misses. One way to add a 'namespace' mechanism to P4 that still allows the use of #include preprocessor directives, is to imagine that for the time being, P4 programs after running through the preprocessor would still be "one big source file", then define namespace/module syntax that would have meaning within that one big source file, to separate namespaces from each other. I think that C++ for example allows multiple namespaces to be defined, and declarations/definitions made inside of each one, inside of one source file, too. As a concrete example of some possible syntax, see this sample P4 program that includes a file "header_lengths.p4" that defines a namespace named "header_lengths": https://github.com/jafingerhut/p4-guide/blob/master/namespaces/sample1.p4#L3-L30 Here is the contents of header_lengths.p4: https://github.com/jafingerhut/p4-guide/blob/master/namespaces/header_lengths.p4 After the preprocessor runs, all of those #include's in sample1.p4 are expanded, and you have one big source file, which may optionally define any number of "namespace" blocks inside of it. Later code can refer to earlier namespaces (unless someone thinks it is important to allow cycles of reference between namespaces, but hopefully that isn't necessary for the idea to be useful). |
Carrot: Just imagine if we never had to have a discussion in a LDWG meeting again about adding a new function/action/etc. could break existing user programs that use that name! Of course, we would have to bikeshed over the names of namespaces, and whether something should be added to an existing namespace, or a new one. Still, it seems like progress. |
I don't think modules need to declare namespaces. The ones who import the modules can declare namespaces, confining them into a namespace of their choice. In this way there are no conflicts, because the users choose the namespaces, and can use different namespaces for different modules. This is better than C++, and more like Python. |
What features or capabilities do people want from a P4_16 module system? Is adding namespaces orthogonal to a module system, or intertwined in some way? if they are considered independent, is adding namespaces useful enough on its own as a separate step? |
I actually think that namespaces as existing in C++ are a bad design. We don't really need them. |
Mihai, do you expect that a P4_16 module system would provide some kind of isolation of newly defined names, so that discussions like we have in a LDWG meeting about new standard function names can break previous programs, could be a thing of the past? If a module system does not provide such benefits, why not some form of namespaces that would make them a thing of the past? I should be cautious in saying that despite my code examples using the syntax "namespace { ... }", I know very little about the namespace feature in C++ and am not trying to imply by that syntax that we should copy the C++ design. |
Yes, absolutely. The Python model seems useful. When you import something you can move it to its own namespace. You don't construct namespaces, they are constructed when you import something else. This way the one who imports can control all names, not the one who declares them. You can also rename symbols when you import. |
Perhaps I should not really call them "namespaces". What happens is that you give a new name to something when you import it. You can, for example, add a prefix to all names that you import. |
All top-level declarations from file.p4 would now be renamed prefixed with The hard part is keeping all the existing constructs |
So my proposal with The main reason I ask is whether someone has the idea that "a P4_16 module system" has some other features they want to come with it, e.g. module interfaces, contracts, etc. If not, i.e. if the primary feature we want from it is to let people define whatever names they want in their own namespace, and anyone else declaring that same name in another namespace can be independent of that, then I think we get something useful out of it. There is still the issue that namespace names themselves can conflict. The best solution I know of for that is Java's package naming convention, where people are suggested to create globally unique namespace names using reversed DNS names, e.g. org.p4.psa.v1 or com.cisco.csa |
With the "import" solution in python names will never conflict, because you import them with any name you like. |
If you try to copy Python's import features exactly, then you can make names conflict, but the important thing is that as long as you avoid implementing Python's Python Python Python's The one I would definitely anti-recommend from Python is |
We should also have something like |
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. |
Personnel
Design
Implementation
p4-spec
: Draft module system #798; see also Namespaces and imports #718p4c
:Process
p4-spec
:p4c
:Apologies if this is a duplicate of some other issue. Happy to close this and replace it with something else if that is preferred for long-term tracking.
I just wanted to record one idea mentioned in the language design WG earlier today, in case it turns out to be of interest for a P4_16 module / namespace system.
I will give syntax examples from Python, simply because I am more familiar with that and less with others, but hopefully the ideas are clear.
Python allows several ways to import a package, of which I will possibly leave some out since I may not know them all:
(a)
import <package_name>
enables the "caller" to use names inside of<package_name>
with a syntax like<package_name>.<name_inside_package>
. You cannot use<name_inside_package>
without the prefix.(b)
import <package_name> as <alias_name>
enables the caller to use names inside of<package_name>
with the syntax<alias_name>.<name_inside_package>
. The reason it exists in addition to the previous option is that the caller can choose to make<alias_name>
much shorter than<package_name>
. The caller is responsible for ensuring that multiple<alias_name>
's to not collide with each other.(c)
from <package_name> import *
enables the caller to use names inside of<package_name>
with the syntax<name_inside_package>
, with no prefix required. Any local names that happen to be the same as a name inside of the package are subject to the normal language rules for shadowing or redefinition.If P4_16 enabled operations like (a) and (b), but not (c), then it has the property that either
<package_name>.
or<alias_name>.
prefixes are always required when referring to a name inside of another package. They can be short because<alias_name>
's can be short, but they must be present.Some people consider this an advantage, in that it makes it clear on a casual reading which names are from other packages, and which are local. If you allow option (c), then it is not clear when you read a name
foo
whether it is in this package, or one of 1 up to N other packages for which you have donefrom <package_name> import *
.Requiring the prefixes also means that later versions of packages can introduce new names, and be guaranteed that they will not collide with names in the code that imports the package.
Anyway, nothing earth-shattering here, and I know some people probably dislike having to type prefixes, but I personally like requiring them simply for a code reader to easily determine which package that names come from.
The text was updated successfully, but these errors were encountered: