Bumped into this randomly. We do correctly parse escape sequence, but
the format would simply but the unescaped string back on save. Now it
properly re-escapes strings before flushing them back. I also removed
the escape sequence for 'backspace' and 'new page' form feed as I
don't see any use case for those in an Aiken program really...
Isolated doc comments causes the compiler to panic with:
```
'no consecutive empty lines'
```
This is reproducible when doc comments are wrapped in sandwich between
comments and newlines.
This leads to more consistent formatting across entire Aiken programs.
Before that commit, only long expressions would be formatted on a
newline, causing non-consistent formatting and additional reading
barrier when looking at source code.
Programs also now take more vertical space, which is better for more
friendly diffing in version control systems (especially git).
Rules are now as follows:
- If a pipeline contains a newline, then the entire pipeline is formatted over multiple lines.
- If it doesn't, then it's formatted as a single-line UNLESS it cannot fit; in which case, we fallback to multiline again.
This has been bothering me and the more I thought of it the more I
disliked the idea of a warning. The rationale being that in this very
context, there's absolutely no ambiguity. So it is only frustrating
that the parser is even able to make the exact suggestion of what
should be fixed, but still fails.
I can imagine it is going to be very common for people to type:
```
trace "foo"
```
...yet terribly frustrating if they have to remember each time that
this should actually be a string. Because of the `trace`, `todo` and
`error` keywords, we know exactly the surrounding context and what to
expect here. So we can work it nicely.
However, the formatter will re-format it to:
```
trace @"foo"
```
Just for the sake of remaining consistent with the type-system. This
way, we still only manipulate `String` in the AST, but we conveniently
parse a double-quote utf-8 literal when coupled with one of the
specific keywords.
I believe that's the best of both worlds.
The core observation is that **in the context of Aiken** (i.e. on-chain logic)
people do not generally want to use String. Instead, they want
bytearrays.
So, it should be easy to produce bytearrays when needed and it should
be the default. Before this commit, `"foo"` would parse as a `String`.
Now, it parses as a `ByteArray`, whose bytes are the UTF-8 bytes
encoding of "foo".
Now, to make this change really "fool-proof", we now want to:
- [ ] Emit a parse error if we parse a UTF-8 bytearray literal in
place where we would expect a `String`. For example, `trace`,
`error` and `todo` can only be followed by a `String`.
So when we see something like:
```
trace "foo"
```
we know it's a mistake and we can suggest users to use:
```
trace @"foo"
```
instead.
- [ ] Emit a warning if we ever see a bytearray literals UTF-8, which
is either 56 or 64 character long and is a valid hexadecimal string.
For example:
```
let policy_id = "29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c6"
```
This is _most certainly_ a mistake, as this generates a ByteArray of
56 bytes, which is effectively the hex-encoding of the provided string.
In this scenario, we want to warn the user and inform them they probably meant to use:
```
let policy_id = #"29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c6"
```
Interestingly enough, chumsky seems to fail when given a 'choice' with
more than 25 elements. That's why this commit groups together some of
the choices as another nested 'choice'.
Not sure what this special case was trying to achieve, but it's not right. There's no need to handle function call with a single argument differently than the others.
Whoopsie... || and && were treated with the same precedence, causing very surprising behavior down the line.
I noticed this because of the auto-formatter adding parenthesis where it really shouldn't. The problem came actually from the parser and how it constructed the AST.
Weirdly enough, we got the parsing wrong for byte literals in expressions (but did okay in constants). But got the formatting wrong in constants (yet did okay for formatting expressions). I've factored out the code in both cases to avoid the duplication that led to this in the first place. Plus added test coverage to make sure this doesn't happen in the future.
This changes allow to use parenthesis `(` `)` to encapsulate
expressions in addition to braces `{` `}` used to define blocks.
The main use-case is for arithmetic and boolean expressions for which
developers are used to using parenthesis. For example:
```
{ 14 + 42 } * 1337
```
can now be written as:
```
( 14 + 42 ) * 1337
```
This may sound straightforward at first but wasn't necessarily trivial
in Aiken given that (a) everything is an expression, (b) whitespaces
do not generally matter and (c) there's no symbol indicating the end
of a 'statement' (because there's no statement).
Thus, we have to properly disambiguate between:
```
let foo = bar(14 + 42)
```
and
```
let foo = bar
(14 + 42)
```
Before this commit, the latter would be interpreted as a function call
and would lead to a somewhat puzzling error. Now, the newline serves
as a delimiting symbol. The trade-off being that for a function call,
the left parenthesis has to be on the same line as the function name
identifier -- which is a fair trade off. So this is still allowed:
```
let foo = bar(
14 + 42
)
```
As there's very little ambiguity about it.
This fixes#236 and would seemingly allow us to get rid of the leading
`#` in front of tuples.