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,28 @@
# This file was generated by Aiken
# You typically do not need to edit this file
[[requirements]]
name = "aiken-lang/stdlib"
version = "main"
source = "github"
[[requirements]]
name = "aiken-lang/fuzz"
version = "main"
source = "github"
[[packages]]
name = "aiken-lang/stdlib"
version = "main"
requirements = []
source = "github"
[[packages]]
name = "aiken-lang/fuzz"
version = "main"
requirements = []
source = "github"
[etags]
"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1717767691, nanos_since_epoch = 206091000 }, "98cf81aa68f9ccf68bc5aba9be06d06cb1db6e8eff60b668ed5e8ddf3588206b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1717767690, nanos_since_epoch = 920449000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"]

View File

@@ -0,0 +1,21 @@
name = "aiken-lang/104"
version = "0.0.0"
compiler = "v1.0.29-alpha"
plutus = "v2"
license = "Apache-2.0"
description = "Aiken contracts for project 'aiken-lang/104'"
[repository]
user = "aiken-lang"
project = "104"
platform = "github"
[[dependencies]]
name = "aiken-lang/stdlib"
version = "main"
source = "github"
[[dependencies]]
name = "aiken-lang/fuzz"
version = "main"
source = "github"

View File

@@ -0,0 +1,80 @@
{
"preamble": {
"title": "aiken-lang/104",
"description": "Aiken contracts for project 'aiken-lang/104'",
"version": "0.0.0",
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.29-alpha+257bd23"
},
"license": "Apache-2.0"
},
"validators": [
{
"title": "tests.foo_3",
"redeemer": {
"title": "_data",
"schema": {
"$ref": "#/definitions/Data"
}
},
"parameters": [
{
"title": "th_arg",
"schema": {
"$ref": "#/definitions/tests~1Foo"
}
}
],
"compiledCode": "582401000032323222253330043370e6eb4c018c014dd5001a400429309b2b2b9a5573cae841",
"hash": "047dafbc61fb4a550a28398bde3680c48ff2000cf1022efc883124cd"
}
],
"definitions": {
"Bool": {
"title": "Bool",
"anyOf": [
{
"title": "False",
"dataType": "constructor",
"index": 0,
"fields": []
},
{
"title": "True",
"dataType": "constructor",
"index": 1,
"fields": []
}
]
},
"Data": {
"title": "Data",
"description": "Any Plutus data."
},
"Int": {
"dataType": "integer"
},
"tests/Foo": {
"title": "Foo",
"anyOf": [
{
"title": "Foo",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "a0",
"$ref": "#/definitions/Int"
},
{
"title": "a1",
"$ref": "#/definitions/Bool"
}
]
}
]
}
}
}

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
}