update grammar readme after master merge

This commit is contained in:
gluax 2021-05-05 13:18:13 -04:00
commit f4c9c2c1f0
5 changed files with 411 additions and 40 deletions

View File

@ -0,0 +1,44 @@
# Summary
This is an RFC to propose RFC format for Leo language.
# Motivation
Leo develops rapidly and changes to the language need to be stated clearly and presented to everyone. RFC is the perfect tool for turning chaos into order.
# Design
This section describes proposed solution.
## Store RFCs inside Leo repository.
At early stages it is for better to see changes with the code eliminating the need to keep track of a different repository.
## Use standard PR mechanics for submitting new RFCs
New RFCs should be submitted as a PRs into Leo repository. PRs should be correctly labeled for easier search. Yet they should not have number unless PR is accepted by leo maintainers.
## Increase approvals count for RFCs
RFCs may propose changes affecting multiple systems or projects. They also introduce new changes to the language design or structure. Because of that they should be watched more carefully by as many involved team members as possible. Increasing number of required approvals should help achieve this goal.
## Format
For bootstrapping new requests template is made and placed into RFC folder.
## Number
RFCs should receive number once they are accepted.
# Drawbacks
None.
# Effect on Ecosystem
None.
# Alternatives
Propose language changes in team channels or as GitHub issues.

View File

@ -0,0 +1,279 @@
# Leo RFC 001: Initial String Support
## Authors
- Max Bruce
- Collin Chin
- Alessandro Coglio
- Eric McCarthy
- Pratyush Mishra
- Jon Pavlik
- Damir Shamanaev
- Damon Sicore
- Howard Wu
## Status
DRAFT
# Summary
The purpose of this proposal is to provide initial support for strings in Leo.
Since strings are sequences of characters,
the proposal inextricably also involves characters.
This proposal is described as 'initial'
because it provides some basic features that we may extend in the future;
the initial features should be sufficiently simple and conservative
that they should not limit the design of the future features.
This proposal adds a new scalar type for characters
along with a new kind of literals to denote characters.
A string is then simply as an array of characters,
but this proposal also adds a new kind of literals to denote strings
more directly than via character array construction expressions.
Along with equality and inequality, which always apply to every Leo type,
this proposal also introduces operations for
_[TODO: Summarize initial set of built-in or library operations
on characters and strings.]_.
By not prescribing a new type for strings,
this initial proposal leaves the door open
to a future more flexible type of resizable strings.
# Motivation
Strings (and characters) are common in programming languages.
Use cases for Leo include
simple ones like URLs and token ticker symbols,
and more complex ones like Bech32 encoding,
edit distance in strings representing proteins,
and zero-knowledge proofs of occurrences or absences of patterns in textual logs.
_[TODO: Add more use cases if needed.]_
# Design
Since strings are sequences of characters,
a design for strings inextricably also involves a design for characters.
Thus, we first present a design for characters, then for strings.
After that, we discuss the relation with Leo's existing format strings.
We conclude this design section
with a discussion of possible future extensions.
## Characters
We add a new scalar type `char` for characters.
In accord with Leo's strong typing,
this new type is separate from all the other scalar types.
The set of values of type `char` is isomorphic to
the set of Unicode code points from 0 to 10FFFFh (both inclusive).
That is, we support Unicode characters, more precisely code points
(this may include some invalid code points,
but it is simpler to allow every code point in that range).
A character is an atomic entity:
there is no notion of Unicode encoding (e.g. UTF-8) that applies here.
We add a new kind of literals for characters,
consisting of single characters or escapes,
surrounded by single quotes.
Any single Unicode character except single quote is allowed,
e.g. `'a'`, `'*'`, and `'"'`.
Single quotes must be escaped with backslash, i.e. `'\''`;
backslashes must be escaped as well, i.e. `'\\'`
We allow other backslash escapes
for commonly used characters that are not otherwise easily denoted,
namely _[TODO: Decide which other escapes we want to allow, e.g. `'\n'`.]_
We also allow Unicode escapes of the form `'\u{X}'`,
where `X` is a sequence of one or more hex digits
(both uppercase and lowercase letters are allowed)
whose value must be between 0 and 10FFFFh.
Note that the literal character is assembled by the compiler---for
creating literals there is no need for the circuit to know
which codepoints are disallowed.
_[TODO: Do we want a different notation for Unicode escapes?
Note that the `{` `}` delimiters are motivated by the fact that
there may be a varying number of hex digits in this notation.]_
_[TODO: Which (initial) built-in or library operations
do we want to provide for `char` values?]_
## Strings
In this initial design proposal, we do not introduce any new type for strings.
Instead, we rely on the fact that Leo already has arrays,
and that arrays of characters can be regarded as strings.
Existing array operations, such as element and range access,
apply to these strings without the need of language extensions.
To ease the common use case of writing a string value in the code,
we add a new kind of literal for strings (i.e. character arrays),
consisting of a sequence of one or more single characters or escapes
surrounded by double quotes;
this is just syntactic sugar.
Any single Unicode character except double quote is allowed,
e.g. `""`, `"Aleo"`, `"it's"`, and `"x + y"`.
Double quotes must be escaped with backslash, e.g. `"say \"hi\""`;
backslashes must be escaped as well, e.g. `"c:\\dir"`.
We allow the same backslash escapes allowed for character literals
(see the section on characters above).
_[TODO: There is a difference in the treatment of single and double quotes:
the former are allowed in string literals but not character literals,
while the latter are allowed in character literals but not string literals;
this asymmetry is also present in Java.
However, for simplicity we may want to symmetrically disallow
both single and double quotes in both character and string literals.]_
We also allow the same Unicode escapes allowed in character literals,
(described in the section on characters above).
In any case, the type of a string literal is `[char; N]`,
where `N` is the length of the string measured in characters,
i.e. the size of the array.
Note that there is no notion of Unicode encoding (e.g. UTF-8)
that applies to string literals.
The rationale for not introducing a new type for strings initially,
and instead piggyback on the existing array types and operations,
is twofold.
First, it is an economical design
that lets us reuse the existing array machinery,
both at the language level (e.g. readily use array operations)
and at the R1CS compilation level
(see the section on compilation to R1CS below).
Second, it leaves the door open to providing,
in a future design iteration,
a richer type for strings,
as disccused in the section about future extensions below.
_[TODO: Which (initial) built-in or library operations
do we want to provide for `[char; N]` values that are not already
available with the existing array operations?]_
* `u8` to `[char; 2]` hexstring, .., `u128` to `[char; 32]` hexstring
* field element to `[char; 64]` hexstring. (Application can test leading zeros and slice them out if it needs to return, say, a 40-hex-digit string)
* _[TODO: more?]_
## Input and Output of Literal Characters and Strings
Since UTF-8 is a standard encoding, it would make sense for
the literal characters and strings in the `.in` file
to be automatically converted to UTF-32 by the Leo compiler.
However, the size of a string can be confusing, since multiple
Unicode code points can be composed into a single glyph which
then appears to be a single character. If a parameter of type `[char; 10]`
[if that is the syntax we decide on] is passed a literal string
of a different size, the error message should explain that the
size must be the number of codepoints needed to encode the string.
## Format Strings
Leo currently supports format strings as their own entity,
usable exclusively as first arguments of console print calls.
This proposal eliminates this very specific notion,
which is subsumed by the string literals described above.
In other words, a console print call
will simply take a string literal as first argument,
which will be interpreted as a format string
according to the semantics of console print calls.
The internal UTF-32 string will be translated to UTF-8 for output.
## Compilation to R1CS
So far the discussion has been independent from R1CS
(except for a brief reference when discussing the rationale behind the design).
This is intentional, because the syntax and semantics of Leo
should be understandable independently from the compilation of Leo to R1CS.
However, compilation to R1CS is a critical consideration
that affects the design of Leo.
This section discusses R1CS compilation considerations
for this proposal for characters and strings.
Values of type `char` can be represented directly as field elements,
since the prime of the field is (much) larger than 10FFFFh.
This is more efficient than using a bit representation of characters.
By construction, field elements that represent `char` values
are never above 10FFFFh.
Note that `field` and `char` remain separate types in Leo:
it is only in the compilation to R1CS
that everything is reduced to field elements.
Since strings are just arrays of characters,
there is nothing special about compiling strings to R1CS,
compared to other types of arrays.
In particular, the machinery to infer array sizes at compile time,
necessary for the flattening to R1CS,
applies to strings without exception.
String literals are just syntactic sugar for
suitable array inline construction expressions.
## Future Extensions
As alluded to in the section about design above,
for now we are avoiding the introduction of a string type,
isomorphic to but separate from character arrays,
because we may want to introduce later a more flexible type of strings,
in particular one that supports resizing.
This may be realized via a built-in or library circuit type
that includes a character array and a fill index.
This may be a special case of a built-in or library circuit type
for resizable vectors,
possibly realized via an array and a fill index.
This hypothetical type of resizable vectors
may have to be parameterized over the element type,
requiring an extension of the Leo type system
that is much more general than strings.
Because of the above considerations,
it seems premature to design a string type at this time,
provided that the simple initial design described in the section above
suffices to cover the initial use cases that motivate this RFC.
# Drawbacks
This proposal does not appear to bring any real drawbacks,
other than making the language inevitably slightly more complex.
But the need to support characters and strings justifies the extra complexity.
# Effect on Ecosystem
With the ability of Leo programs to process strings,
it may be useful to have external tools that convert Leo strings
to/from common formats, e.g. UTF-8.
# Alternatives
We could avoid the new `char` type altogether,
and instead rely on the existing `u32` to represent Unicode code points,
and provide character-oriented operations on `u32` values.
(Note that both `u8` and `u16` are too small for 10FFFFh,
and that signed integer types include negative integers
which are not Unicode code points:
this makes `u32` the obvious choice.)
However, many values of type `u32` are above 10FFFFh,
and many operations on `u32` do not really make sense on code points.
We would probably want a notation for character literals anyhow,
which could be (arguably mis)used for non-character unsigned integers.
All in all, introducing a new type for characters
is consistent with Leo's strong typing approach.
Furthermore, for compilation to R1CS, `u32`,
even if restricted to the number of bits needed for Unicode code points,
is less efficient than the field representation described earlier,
because `u32` requires a field element for each bit.
Instead of representing strings as character arrays,
we could introduce a new type `string`
whose values are finite sequences of zero or more characters.
These strings would be isomorphic to, but distinct form, character arrays.
However, for compilation to R1CS, it would be necessary to
perform the same kind of known-size analysis on strings
that is already performed on arrays,
possibly necessitating to include a size as part of the type, i.e. `string(N)`,
which is obviously isomorphic to `[char; N]`.
Thus, using character arrays avoids the duplication.
Furthermore, as noted in the section on future extensions,
this leaves the door open to
introducing a future type `string` for resizable strings.
Yet another option could be to use directly `field` to represent characters
and `[field; N]` to represent strings of `N` characters.
However, many values of type `field` are not valid Unicode code points,
and many field operations do not make sense for characters.
Thus, having a separate type `char` for characters seems better,
and more in accordance with Leo's strong typing.

24
docs/rfc/__template.md Normal file
View File

@ -0,0 +1,24 @@
# Summary
What is the proposal?
# Motivation
What problems does it solve? What is the background?
# Design
What are the details of proposal?
# Drawbacks
What problems does this solution bring in?
# Effect on Ecosystem
How changes affect other projects and language ecosystem in general?
# Alternatives
What are the alternatives?

View File

@ -476,7 +476,7 @@ Line terminators form whitespace, along with spaces and horizontal tabs.
whitespace = space / horizontal-tab / newline
```
Go to: _[newline](#user-content-newline), [space](#user-content-space), [horizontal-tab](#user-content-horizontal-tab)_;
Go to: _[horizontal-tab](#user-content-horizontal-tab), [newline](#user-content-newline), [space](#user-content-space)_;
There are two kinds of comments in Leo, as in other languages.
@ -494,7 +494,7 @@ the ones used in the Java language reference.
comment = block-comment / end-of-line-comment
```
Go to: _[end-of-line-comment](#user-content-end-of-line-comment), [block-comment](#user-content-block-comment)_;
Go to: _[block-comment](#user-content-block-comment), [end-of-line-comment](#user-content-end-of-line-comment)_;
<a name="block-comment"></a>
@ -521,7 +521,7 @@ rest-of-block-comment-after-star = "/"
/ not-star-or-slash rest-of-block-comment
```
Go to: _[rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star-or-slash](#user-content-not-star-or-slash)_;
Go to: _[rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [rest-of-block-comment](#user-content-rest-of-block-comment), [not-star-or-slash](#user-content-not-star-or-slash)_;
<a name="end-of-line-comment"></a>
@ -596,16 +596,19 @@ lowercase-letter = %x61-7A ; a-z
letter = uppercase-letter / lowercase-letter
```
Go to: _[uppercase-letter](#user-content-uppercase-letter), [lowercase-letter](#user-content-lowercase-letter)_;
Go to: _[lowercase-letter](#user-content-lowercase-letter), [uppercase-letter](#user-content-uppercase-letter)_;
An identifier is a non-empty sequence of letters, digits, and underscores,
starting with a letter.
It must not be a keyword: this is an extra-grammatical constraint.
It must not be a keyword: this is an extra-grammatical requirement.
It must also not be or start with `aleo1`,
because that is used for address literals:
this is another extra-grammatical requirement.
<a name="identifier"></a>
```abnf
identifier = letter *( letter / digit / "_" ) ; but not a keyword
identifier = letter *( letter / digit / "_" ) ; but not a keyword or aleo1...
```
Go to: _[letter](#user-content-letter)_;
@ -639,7 +642,7 @@ format-string-element = not-double-quote-or-open-brace
/ format-string-container
```
Go to: _[not-double-quote-or-close-brace](#user-content-not-double-quote-or-close-brace), [not-double-quote-or-open-brace](#user-content-not-double-quote-or-open-brace), [format-string-container](#user-content-format-string-container)_;
Go to: _[not-double-quote-or-open-brace](#user-content-not-double-quote-or-open-brace), [not-double-quote-or-close-brace](#user-content-not-double-quote-or-close-brace), [format-string-container](#user-content-format-string-container)_;
<a name="format-string"></a>
@ -764,7 +767,7 @@ atomic-literal = untyped-literal
/ address-literal
```
Go to: _[address-literal](#user-content-address-literal), [untyped-literal](#user-content-untyped-literal), [unsigned-literal](#user-content-unsigned-literal), [signed-literal](#user-content-signed-literal), [field-literal](#user-content-field-literal), [boolean-literal](#user-content-boolean-literal), [product-group-literal](#user-content-product-group-literal)_;
Go to: _[unsigned-literal](#user-content-unsigned-literal), [boolean-literal](#user-content-boolean-literal), [product-group-literal](#user-content-product-group-literal), [signed-literal](#user-content-signed-literal), [address-literal](#user-content-address-literal), [field-literal](#user-content-field-literal), [untyped-literal](#user-content-untyped-literal)_;
After defining the (mostly) alphanumeric tokens above,
@ -809,7 +812,7 @@ token = keyword
/ symbol
```
Go to: _[format-string](#user-content-format-string), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [keyword](#user-content-keyword), [atomic-literal](#user-content-atomic-literal), [package-name](#user-content-package-name), [identifier](#user-content-identifier)_;
Go to: _[package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [atomic-literal](#user-content-atomic-literal), [format-string](#user-content-format-string), [identifier](#user-content-identifier), [keyword](#user-content-keyword)_;
@ -866,7 +869,7 @@ group-type = %s"group"
arithmetic-type = integer-type / field-type / group-type
```
Go to: _[field-type](#user-content-field-type), [integer-type](#user-content-integer-type), [group-type](#user-content-group-type)_;
Go to: _[integer-type](#user-content-integer-type), [field-type](#user-content-field-type), [group-type](#user-content-group-type)_;
The arithmetic types, along with the boolean and address types,
@ -887,7 +890,7 @@ address-type = %s"address"
scalar-type = boolean-type / arithmetic-type / address-type
```
Go to: _[arithmetic-type](#user-content-arithmetic-type), [boolean-type](#user-content-boolean-type), [address-type](#user-content-address-type)_;
Go to: _[address-type](#user-content-address-type), [arithmetic-type](#user-content-arithmetic-type), [boolean-type](#user-content-boolean-type)_;
Circuit types are denoted by identifiers and the keyword `Self`.
@ -948,7 +951,7 @@ i.e. types whose values contain (sub-)values
aggregate-type = tuple-type / array-type / circuit-type
```
Go to: _[tuple-type](#user-content-tuple-type), [circuit-type](#user-content-circuit-type), [array-type](#user-content-array-type)_;
Go to: _[array-type](#user-content-array-type), [circuit-type](#user-content-circuit-type), [tuple-type](#user-content-tuple-type)_;
Scalar and aggregate types form all the types.
@ -958,7 +961,7 @@ Scalar and aggregate types form all the types.
type = scalar-type / aggregate-type
```
Go to: _[scalar-type](#user-content-scalar-type), [aggregate-type](#user-content-aggregate-type)_;
Go to: _[aggregate-type](#user-content-aggregate-type), [scalar-type](#user-content-scalar-type)_;
The lexical grammar given earlier defines product group literals.
@ -1036,7 +1039,7 @@ primary-expression = identifier
/ circuit-expression
```
Go to: _[tuple-expression](#user-content-tuple-expression), [expression](#user-content-expression), [array-expression](#user-content-array-expression), [circuit-expression](#user-content-circuit-expression), [literal](#user-content-literal), [identifier](#user-content-identifier)_;
Go to: _[array-expression](#user-content-array-expression), [tuple-expression](#user-content-tuple-expression), [identifier](#user-content-identifier), [literal](#user-content-literal), [expression](#user-content-expression), [circuit-expression](#user-content-circuit-expression)_;
Tuple expressions construct tuples.
@ -1089,7 +1092,7 @@ Go to: _[expression](#user-content-expression)_;
array-repeat-construction = "[" expression ";" array-dimensions "]"
```
Go to: _[expression](#user-content-expression), [array-dimensions](#user-content-array-dimensions)_;
Go to: _[array-dimensions](#user-content-array-dimensions), [expression](#user-content-expression)_;
<a name="array-construction"></a>
@ -1133,7 +1136,7 @@ Go to: _[circuit-type](#user-content-circuit-type), [circuit-inline-element](#us
circuit-inline-element = identifier ":" expression / identifier
```
Go to: _[expression](#user-content-expression), [identifier](#user-content-identifier)_;
Go to: _[identifier](#user-content-identifier), [expression](#user-content-expression)_;
<a name="circuit-expression"></a>
@ -1184,7 +1187,7 @@ postfix-expression = primary-expression
/ postfix-expression "[" [expression] ".." [expression] "]"
```
Go to: _[natural](#user-content-natural), [function-arguments](#user-content-function-arguments), [postfix-expression](#user-content-postfix-expression), [circuit-type](#user-content-circuit-type), [identifier](#user-content-identifier), [expression](#user-content-expression), [primary-expression](#user-content-primary-expression)_;
Go to: _[circuit-type](#user-content-circuit-type), [expression](#user-content-expression), [function-arguments](#user-content-function-arguments), [identifier](#user-content-identifier), [natural](#user-content-natural), [primary-expression](#user-content-primary-expression), [postfix-expression](#user-content-postfix-expression)_;
Unary operators have the highest operator precedence.
@ -1224,7 +1227,7 @@ multiplicative-expression = exponential-expression
/ multiplicative-expression "/" exponential-expression
```
Go to: _[exponential-expression](#user-content-exponential-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [exponential-expression](#user-content-exponential-expression)_;
Then there are addition and subtraction, both left-assocative.
@ -1264,7 +1267,7 @@ equality-expression = ordering-expression
/ equality-expression "!=" ordering-expression
```
Go to: _[ordering-expression](#user-content-ordering-expression), [equality-expression](#user-content-equality-expression)_;
Go to: _[equality-expression](#user-content-equality-expression), [ordering-expression](#user-content-ordering-expression)_;
Next come conjunctive expressions, left-associative.
@ -1299,7 +1302,7 @@ conditional-expression = disjunctive-expression
":" conditional-expression
```
Go to: _[expression](#user-content-expression), [disjunctive-expression](#user-content-disjunctive-expression), [conditional-expression](#user-content-conditional-expression)_;
Go to: _[conditional-expression](#user-content-conditional-expression), [expression](#user-content-expression), [disjunctive-expression](#user-content-disjunctive-expression)_;
Those above are all the expressions.
@ -1332,7 +1335,7 @@ statement = expression-statement
/ block
```
Go to: _[conditional-statement](#user-content-conditional-statement), [console-statement](#user-content-console-statement), [variable-declaration](#user-content-variable-declaration), [expression-statement](#user-content-expression-statement), [assignment-statement](#user-content-assignment-statement), [block](#user-content-block), [loop-statement](#user-content-loop-statement), [return-statement](#user-content-return-statement), [constant-declaration](#user-content-constant-declaration)_;
Go to: _[console-statement](#user-content-console-statement), [expression-statement](#user-content-expression-statement), [return-statement](#user-content-return-statement), [loop-statement](#user-content-loop-statement), [assignment-statement](#user-content-assignment-statement), [variable-declaration](#user-content-variable-declaration), [constant-declaration](#user-content-constant-declaration), [block](#user-content-block), [conditional-statement](#user-content-conditional-statement)_;
<a name="block"></a>
@ -1361,21 +1364,31 @@ return-statement = %s"return" expression ";"
Go to: _[expression](#user-content-expression)_;
There are two kinds of variable definition statements,
There are variable declarations and constant declarations,
which only differ in the starting keyword.
The variables are either a single one or a tuple of two or more;
These declarations are also statements.
The names of the variables or constants are
either a single one or a tuple of two or more;
in all cases, there is just one optional type
and just one initializing expression.
<a name="variable-declaration"></a>
```abnf
variable-declaration = %s"let" identifier-or-identifiers [ ":" type ] "=" expression ";"
constant-declaration = %s"const" identifier-or-identifiers [ ":" type ] "=" expression ";"
variable-declaration = %s"let" identifier-or-identifiers [ ":" type ]
"=" expression ";"
```
Go to: _[type](#user-content-type), [expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_;
Go to: _[expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type)_;
<a name="constant-declaration"></a>
```abnf
constant-declaration = %s"const" identifier-or-identifiers [ ":" type ]
"=" expression ";"
```
Go to: _[expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type)_;
<a name="identifier-or-identifiers"></a>
```abnf
@ -1407,7 +1420,7 @@ conditional-statement = branch
/ branch %s"else" conditional-statement
```
Go to: _[conditional-statement](#user-content-conditional-statement), [branch](#user-content-branch), [block](#user-content-block)_;
Go to: _[branch](#user-content-branch), [block](#user-content-block), [conditional-statement](#user-content-conditional-statement)_;
A loop statement implicitly defines a loop variable
@ -1419,7 +1432,7 @@ The body is a block.
loop-statement = %s"for" identifier %s"in" expression ".." expression block
```
Go to: _[identifier](#user-content-identifier), [expression](#user-content-expression), [block](#user-content-block)_;
Go to: _[expression](#user-content-expression), [identifier](#user-content-identifier), [block](#user-content-block)_;
An assignment statement is straightforward.
@ -1436,7 +1449,7 @@ assignment-operator = "=" / "+=" / "-=" / "*=" / "/=" / "**="
assignment-statement = expression assignment-operator expression ";"
```
Go to: _[expression](#user-content-expression), [assignment-operator](#user-content-assignment-operator)_;
Go to: _[assignment-operator](#user-content-assignment-operator), [expression](#user-content-expression)_;
Console statements start with the `console` keyword,
@ -1505,7 +1518,7 @@ annotation = annotation-name
[ "(" identifier *( "," identifier ) ")" ]
```
Go to: _[identifier](#user-content-identifier), [annotation-name](#user-content-annotation-name)_;
Go to: _[annotation-name](#user-content-annotation-name), [identifier](#user-content-identifier)_;
A function declaration defines a function.
@ -1522,7 +1535,7 @@ function-declaration = *annotation %s"function" identifier
block
```
Go to: _[function-parameters](#user-content-function-parameters), [type](#user-content-type), [identifier](#user-content-identifier), [block](#user-content-block)_;
Go to: _[identifier](#user-content-identifier), [type](#user-content-type), [function-parameters](#user-content-function-parameters), [block](#user-content-block)_;
<a name="function-parameters"></a>
@ -1599,7 +1612,7 @@ to be followed by a comma, for convenience.
<a name="import-declaration"></a>
```abnf
import-declaration = %s"import" package-path
import-declaration = %s"import" package-path ";"
```
Go to: _[package-path](#user-content-package-path)_;
@ -1617,6 +1630,8 @@ Go to: _[identifier](#user-content-identifier), [package-path](#user-content-pac
Finally, we define a file as a sequence of zero or more declarations.
We allow constant declarations at the top level, for global constants.
Currently variable declarations are disallowed at the top level.
<a name="declaration"></a>
```abnf
@ -1626,7 +1641,7 @@ declaration = import-declaration
/ constant-declaration
```
Go to: _[circuit-declaration](#user-content-circuit-declaration), [constant-declaration](#user-content-constant-declaration), [import-declaration](#user-content-import-declaration), [function-declaration](#user-content-function-declaration)_;
Go to: _[circuit-declaration](#user-content-circuit-declaration), [constant-declaration](#user-content-constant-declaration), [function-declaration](#user-content-function-declaration), [import-declaration](#user-content-import-declaration)_;
<a name="file"></a>

View File

@ -435,9 +435,12 @@ letter = uppercase-letter / lowercase-letter
; An identifier is a non-empty sequence of letters, digits, and underscores,
; starting with a letter.
; It must not be a keyword: this is an extra-grammatical constraint.
; It must not be a keyword: this is an extra-grammatical requirement.
; It must also not be or start with `aleo1`,
; because that is used for address literals:
; this is another extra-grammatical requirement.
identifier = letter *( letter / digit / "_" ) ; but not a keyword
identifier = letter *( letter / digit / "_" ) ; but not a keyword or aleo1...
; A package name consists of one or more segments separated by single dashes,
; where each segment is a non-empty sequence of lowercase letters and digits.
@ -845,15 +848,19 @@ expression-statement = expression ";"
return-statement = %s"return" expression ";"
; There are two kinds of variable definition statements,
; There are variable declarations and constant declarations,
; which only differ in the starting keyword.
; The variables are either a single one or a tuple of two or more;
; These declarations are also statements.
; The names of the variables or constants are
; either a single one or a tuple of two or more;
; in all cases, there is just one optional type
; and just one initializing expression.
variable-declaration = %s"let" identifier-or-identifiers [ ":" type ] "=" expression ";"
constant-declaration = %s"const" identifier-or-identifiers [ ":" type ] "=" expression ";"
variable-declaration = %s"let" identifier-or-identifiers [ ":" type ]
"=" expression ";"
constant-declaration = %s"const" identifier-or-identifiers [ ":" type ]
"=" expression ";"
identifier-or-identifiers = identifier
/ "(" identifier 1*( "," identifier ) ")"
@ -958,7 +965,7 @@ circuit-declaration = *annotation %s"circuit" identifier
; Note that we allow the last element of the parenthesized list
; to be followed by a comma, for convenience.
import-declaration = %s"import" package-path
import-declaration = %s"import" package-path ";"
package-path = "*"
/ identifier [ %s"as" identifier ]
@ -966,6 +973,8 @@ package-path = "*"
/ "(" package-path *( "," package-path ) [","] ")"
; Finally, we define a file as a sequence of zero or more declarations.
; We allow constant declarations at the top level, for global constants.
; Currently variable declarations are disallowed at the top level.
declaration = import-declaration
/ function-declaration