Replies: 1 comment
-
I updated Clément's post providing more details on why the change is needed and what exactly we envision for the different targets. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
This is a spec draft to rationalize the changes in #544. Please comment if you disagree, need more details, or agree. With consensus on this spec it will be easier to finish #544.
Motivation
Our current syntax for expressions and variable initialization is rather limited. Currently, expressions can only be values, which means literals, time values, target code, or parameter reverences. This is the corresponding grammar rule:
This neglects the fact that expressions in our target languages can be much more complex. For instance, in Python and Rust
[1, 2, 3]
is a valid expression denoting a list of integers. While technically all target language expressions are supported within the target code delimiters{=...=}
, we should make an effort to support the most common expressions natively.With a more powerful expression syntax, we also need to revise our syntax for variable initialization. Currently, state variables and parameters are initialized like follows:
Where
<init>
can be aValue
or a comma separated sequence ofValue
s.This syntax has various problems:
=
is used for initialization.(1, 2, 3)
one would need to writestate foo((1, 2, 3))
. It would be much clearer to write insteadstate foo = (1, 2, 3)
.state foo(1, 2, 3)
) and our targets make different interpretation. In C and Python, the incentive appears to be to interpret the sequence as a list of values. However, it is entirely unclear what a list of values is in the target language (e.g. tuple vs. list in Python). An extended expression syntax would empower the programmers to specify the precise list type they need. In C++, the sequence of Values is interpreted very differently. It is used as an argument list and each given value is passed to the constructor of the variable type.Specification
Initializer Syntax
The grammar for both parameters and state variables should support the following initialization syntaxes:
name: <type> ()
orname: <type> (<expr>)
orname: <type> (<expr>, <expr>, ...)
name: <type> {}
orname: <type> {<expr>}
orname: <type> {<expr>, <expr>, ...}
name: <type> = <expr>
Depending on the target, the validator imposes various restrictions:
foo: int(42)
->int foo(42);
foo: int{42}
->int foo{42};
foo: int = 42
->int foo = 42;
This distinction is very important in C++, as each variant has a slightly different meaning. The last variant is currently not supported, but is particularly important as the assignment operator can be overloaded.
Expression Syntax
These are possible syntax extensions for what stands for an
<expr>
in the above.C/C++:
{}
or{<expr>}
or{<expr>, <expr>, ...}
.name = <expr>
Python:
(<expr>,)
or(<expr>, <expr>, ...)
.[]
, or[<expr>]
or[<expr>, <expr>, ...]
{}
, or{<key>: <expr>}
or{<key>: <expr>, <key>: <expr>, ...}
Rust:
Name{<key>: <expr>, <key>: <expr>, ...}
Typescript:
All languages:
name[<expr>]
name()
orname(<expr>)
orname(<expr>, <expr>, ...)
Note that this list is not complete. There is much more we could support, but we should probably take it step by step.
The grammar rules should be designed such that they allow all these different expression styles without making assumptions about their nature in the target language. We need validator rules to reject styles that are not supported by a given target language. Further, we will need a class in the code generator that takes care of interpreting expressions and that can be overloaded for the various targets.
Beta Was this translation helpful? Give feedback.
All reactions