While we agree on the idea of having some ways of emitting events, the
design hasn't been completely fleshed out and it is unclear whether
events should have a well-defined format independent of the framework
/ compiler and what this format should be.
So we need more time discussing and agreeing about what use case we
are actually trying to solve with that.
Irrespective of that, some cleanup was also needed on the UPLC side
anyway since the PR introduced a lot of needless duplications.
We'll piggyback on the tracing capabilities of the VM to provide labelling for prop tests. To ensure we do not interfere with normal traces, we only count traces that starts with a NUL byte as label. That convention is assumed to be known of the companion fuzz library that should then provide the labelling capabilities as a dedicated function.
The parameter is special as it takes no annotation but a 'via' keyword followed by an expression that should unify to a Fuzzer<a>, where Fuzzer<a> = fn(Seed) -> (Seed, a). The current commit only allow name identifiers for now. Ultimately, this may allow full expressions.
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...
This was trickier than expected as the expression parser, and in particular the bin-op parser will interpret negative patterns as a continuation of a binary operation and eventually choke on the next right-arrow symbol. This is due to how we actually completely erase newlines once we're done with the lexer. The newline separating when clause is actually semantically important. In principle, we could only parse an expression until the next newline.
Ideally, we would keep that newline in the list of token but it's difficult to figure out which newline to keep between two right arrows since a clause guard can be written over multiple lines. Though, since we know that this is only truly a problem for negative integers, we can use the same trick as for tuples and define a new 'NewLineMinus' token. That token CANNOT be part of a binop expression. That means it's impossible to write a binary operation with a minus over multiple lines, or more specifically, with the '-' symbol on a newline. This sounds like a fair limitation. What we get in exchange is less ambiguity when parsing patterns following expressions in when clause cases.
Another more cumbersome option could be to preserve the first newline encountered after a 'right-arrow' symbol and before any parenthesis or curly brace is found (which would otherwise signal the beginning of a new block). That requires to traverse, at least partially, the list of tokens twice. This feels unnecessary for now and until we do face a similar issue with a binary operator.
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'.
* add unary op
* parse, typecheck, and code gen it
* express boolean not as unary op as well, previously called negate
Co-authored-by: rvcas <x@rvcas.dev>