We do not actually every parse negative values in there, as a negative value is a combination of a 'Negate' and 'UInt' expression.
However, for patterns and constant, it'll be simpler to parse whole Int values as there's no ambiguity with arithmetic operations
there. To avoid confusion of having some 'Int' constructors containing only non-negative values, and some being on the whole range,
I've renamed the constructor to 'UInt' to make this more obvious.
This is simply a syntactic sugar which desugarize to a function call with two arguments mapped to the specified binary operator.
Only works for '>' at this stage as a PoC, extending to all binop in the next commit.
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.
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"
```
This is not supported by the code generation, so it's a bit of a lie
to have them in the language in the first place. There's arguably not
even any use for constant records, list and tuples to begin with. So
this cleans this up everywhere for the sake of moving forward with the
alpha release.
This now reduces constants to:
- Integer
- ByteArray
- String
Anything else can be declared via a function anyway. We can revisit
this choice later.... or not.
The goal is to handle this without bothering the code generation down the line. That is, we can handle it when transforming from the untyped AST to the typed one. That's why there's no 'TraceIfFalse' constructor in the typed AST. It has disappeared during type-check.
We want the lookup to yield a result when there's only a single
validator; and no title is provided. So that users can simply do
'aiken address' in their project if it's unambiguous. The validator's
name is only required to disambiguate between multiple validators.
I also noticed that the order of arguments in with_validator was
wrong. Somehow.
Todo is fundamentally just a trace and an error. The only reason we kept it as a separate element in the AST is for the formatter to work out whether it should format something back to a todo or something else.
However, this introduces redundancy in the code internally and makes the AIR more complicated than it needs to be. Both todo and errors can actually be represented as trace + errors, and we only need to record their preferred shape when parsing so that we can format them back to what's expected.
We now parse errors as a combination of a trace plus and error term. This is a baby step in order to simplify the code generation down the line and the internal representation of todo / errors.
This however enforces that the argument unifies to a `String`. So this
is more flexible than the previous form, but does fundamentally the
same thing.
Fixes#378.
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.
There's arguably no use case ever for that in the context of on-chain
Plutus. Strings are really just meant to be used for tracing. They
aren't meant to be manipulated as heavily as in classic programming
languages.