-
Notifications
You must be signed in to change notification settings - Fork 64
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
Adjust grammar to distinguish paranthesis and brace based initialization in C++ #399
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. I wonder if we should also allow initializers to be arbitrary identifiers? In C, we sometimes have an awkwardness like this:
state primes:int*({= NULL =});
or
state last_invoked:tag_t({= NEVER_TAG =});
This is a very interesting point. In Python, Also, tuples are immutable but lists are mutable, so, parameter lists (initialized in LF using |
I don't think that there is the same problem in Python. In Python, initialization is always done with Generally, I think it would be beneficial to support a more complex syntax for initialization values, so that we can write |
Right. My point was: what should we do about
At least for the Python target, I agree that this should be addressed in another PR. |
Perhaps I wouldn't overload the meaning of our initialization operator |
While I agree it should be a separate pull request, I would like to see our grammar be much more permissive about the initialization to eliminate the escaping with |
I documented this new feature in the C++ article in our wiki. |
Essentially, this MR extends the grammar to allow
{...}
for initializing state variables and parameters as an alternative to the current(...)
syntax. The validator ensures that this feature is only usable in the C++ target. See below for a more detailed explanation.There is a semantic difference in C++ between brace based initialization
{...}
and parenthesis based initialization(...)
. Generally speaking, the curly braces should be preferred whenever possible. I don't want to go into the details of this, but if you are interested, here is a discussion on stackoverflow. Now in my opinion C++ has messed up quite a bit, because it is not at all clear when it is possible to use the curly braces for initialization. The current policy in the LF C++ code generator is to always use the curly braces for initialization. This works well for simple examples, but causes problems in more complex scenarios, as curly braces can be ambiguous in C++ code...Let me make an example to illustrate the problem. Consider this state variable:
This variable will be initialized in the constructor of the generated reactor. In C++ we have two options for this initialization:
foo(4,2)
orfoo{4,2}
. Both will do very different things!foo(4,2)
calls the vector constructor 3) which "3) Constructs the container with count copies of elements with value value". So the resulting vector will be initialized to[2, 2, 2, 2]
. However, if we use the curly braces, a different constructor will be called as the braces are interpreted as an initializer list: "10) Constructs the container with the contents of the initializer list init.". Thus, the resulting vector will be set to[4, 2]
. This is equivalent to callingfoo({4, 2})
.Since the current policy in the LF C++ code generator is to always use curly braces, it is impossible to call a
std::vector
constructor other than the initializer list one. This is also a problem for many other classes. Now we could switch policies and always generate parenthesis based initializers. However, the curly braces have significant advantages over parenthesis, and it would be nice if we are able to use them where it is appropriate. Therefore, this MR introduces the{...}
syntax and gives the LF programmer full control over the initialization method to be used in the generated code.