This is still a bit clunky as the interface is expecting parameters in UPLC form and we don't do any kind of verification. So it is easy to shoot oneself in the foot at the moment (for example, to apply an integer into something that should have received a data). To be improved later.
Without that, we have no way to distinguish between fully applied
validators and those that still require some hard-coded parameters.
Next steps is to make it easier to apply parameters to those, as well
as forbid the creation of addresses of validators that aren't fully
qualified.
* fix assert on pattern Var
* fix tuple index unwrapping closes#334
* allow wrapping when casting with let
* allow wrapping when casting via function call
I decided to invert how I'm doing it. I'm passing
in a new argument to unify in environment called
allow_cast: bool and essentially at various
unification sites I can control whether or not I
want to allow casting to even occur. So we can
assume it's false by default always and then we
turn it on in a few places vs. just opening the
flood gates and locking it down at various sites
as they come up# Please enter the commit message
for your changes. Lines starting
* you cannot cast FROM Data with a `let`
* you cannot cast FROM Data by passing
Data to none Data when calling a function
* you MUST use `assert` to cast from data
* you can cast INTO Data with a `let`
* you can cast INTO Data by passing none Data
to Data when calling a function
* You cannot assert cast Data without an
annotation
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 calculates a validator's address from validators found in a blueprint. It also provides a convenient way to attach a delegation part to the validator if needs be. The command is meant to provide a nice user experience and works 'out of the box' for projects that have only a single validator. Just call 'aiken address' to get the validator's address.
Note that the command-line doesn't provide any option to configure the target network. This automatically assumes testnet, and will until we deem the project ready for mainnet. Those brave enough to run an Aiken's program on mainnet will find a way anyway.
Here's a trick though: I got lazy (a bit) and did not write a full deserializer for Schema because this is busywork and not at all necessary at this stage. Instead, I've made the blueprint parameterized by a generic type <T>; which represents the type of the underlying blueprint's schema. When deserializing from JSON, we can default to 'Value' to get a free deserializer. Since all we're interested about is the program and the metadata (purpose and title) of a validator, it works nicely.
Serialization however expects a Blueprint<Schema>, and most of the functions operates over a Blueprint<Schema> anyway.
This will be useful to re-use this behavior in other structure that contains a Program<DeBruijn> without having to manually serialize or deserialize the entire structure.
In an ideal world, I should have handlded that directly at the conflicting commit in the rebase, but this would have bubbled up through all commits... which I wasn't really quite keen on going through. So here's an extra ugly commit that comes and 'fix the rebase'.
This is quite something, because now we have a testing pipeline that
can also be used for testing other compiler-related stuff such as the
type-checker or the code generator.
This also now introduce two levels of representable types (because it's needed at least for tuples):
Plutus Data (a.k.a Data) and UPLC primitives / constants (a.k.a Schema).
In practice, we don't want to specify blueprints that use direct UPLC primitives because there's little support for producing those in the ecosystem. So we should aim for producing only Data whenever we can. Yet we don't want to forbid it either in case people know what they're doing. Which means that we need to capture that difference well in the type modelling (in Rust and in the CIP-0057 specification).
I've also simplified the error type for now, just to provide some degree of feedback while working on this. I'll refine it later with proper errors.