Authorize complete patterns as function args.

This is mainly a syntactic trick/sugar, but it's been pretty annoying
  to me for a while that we can't simply pattern-match/destructure
  single-variant constructors directly from the args list. A classic
  example is when writing property tests:

  ```ak
  test foo(params via both(bytearray(), int())) {
    let (bytes, ix) = params
    ...
  }
  ```

  Now can be replaced simply with:

  ```
  test foo((bytes, ix) via both(bytearray(), int())) {
    ...
  }
  ```

  If feels natural, especially coming from the JavaScript, Haskell or
  Rust worlds and is mostly convenient. Behind the scene, the compiler
  does nothing more than re-writing the AST as the first form, with
  pre-generated arg names. Then, we fully rely on the existing
  type-checking capabilities and thus, works in a seamless way as if we
  were just pattern matching inline.
This commit is contained in:
KtorZ
2024-06-07 15:23:33 +02:00
parent b6da42baf2
commit 858dfccc82
23 changed files with 944 additions and 68 deletions

View File

@@ -0,0 +1,45 @@
use aiken/fuzz
type Foo {
a0: Int,
a1: Bool,
}
fn foo_1(Foo { a0, .. }) -> Int {
a0 + 1
}
fn foo_2(Foo { a0, a1 } as foo) -> Int {
if a1 {
a0 + 1
} else {
foo.a0 - 1
}
}
validator(Foo { a0, .. }: Foo) {
fn foo_3(_data, _redeemer) {
a0 == 1
}
}
test example_1() {
foo_1(Foo { a0: 1, a1: False }) == 2
}
test example_2() {
foo_2(Foo { a0: 1, a1: False }) == 0
}
test example_3() {
foo_3(Foo { a0: 1, a1: False }, "", "")
}
test example_4() {
let foo_4 = fn(Foo { a1, .. }) { a1 }
foo_4(Foo { a0: 1, a1: True })
}
test example_5((a, b) via fuzz.both(fuzz.int(), fuzz.int())) {
a + b == b + a
}