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:
@@ -2539,3 +2539,37 @@ fn mutually_recursive_1() {
|
||||
|
||||
assert!(check(parse(source_code)).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fn_single_variant_pattern() {
|
||||
let source_code = r#"
|
||||
pub type Foo {
|
||||
a: Int
|
||||
}
|
||||
|
||||
pub fn foo(Foo { a }) {
|
||||
a + 1
|
||||
}
|
||||
"#;
|
||||
|
||||
assert!(dbg!(check(parse(source_code))).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fn_multi_variant_pattern() {
|
||||
let source_code = r#"
|
||||
type Foo {
|
||||
A { a: Int }
|
||||
B { b: Int }
|
||||
}
|
||||
|
||||
pub fn foo(A { a }) {
|
||||
a + 1
|
||||
}
|
||||
"#;
|
||||
|
||||
assert!(matches!(
|
||||
dbg!(check_validator(parse(source_code))),
|
||||
Err((_, Error::NotExhaustivePatternMatch { .. }))
|
||||
))
|
||||
}
|
||||
|
||||
@@ -883,3 +883,68 @@ fn format_pairs() {
|
||||
}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_fn_pattern() {
|
||||
assert_format!(
|
||||
r#"
|
||||
pub fn foo(Foo { a, b, .. }) {
|
||||
todo
|
||||
}
|
||||
|
||||
pub fn bar([Bar] : List<Bar>) {
|
||||
todo
|
||||
}
|
||||
|
||||
pub fn baz((Baz, Baz) as x) {
|
||||
todo
|
||||
}
|
||||
|
||||
pub fn fiz(Pair(fst, snd) as x: Pair<Int, Int>) {
|
||||
todo
|
||||
}
|
||||
|
||||
test buz((a, b) via some_fuzzer()) {
|
||||
todo
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_anon_fn_pattern() {
|
||||
assert_format!(
|
||||
r#"
|
||||
pub fn main() {
|
||||
let foo = fn (Foo { a, b, .. }) { todo }
|
||||
let bar = fn ([Bar] : List<Bar>) { todo }
|
||||
let baz = fn ((Baz, Baz) as x) { todo }
|
||||
let fiz = fn (Pair(fst, snd) as x: Pair<Int, Int>) { todo }
|
||||
todo
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_validator_pattern() {
|
||||
assert_format!(
|
||||
r#"
|
||||
validator(Foo { a, b, .. }) {
|
||||
fn foo() { todo }
|
||||
}
|
||||
|
||||
validator([Bar] : List<Bar>) {
|
||||
fn bar() { todo }
|
||||
}
|
||||
|
||||
validator((Baz, Baz) as x) {
|
||||
fn baz() { todo }
|
||||
}
|
||||
|
||||
validator((fst, snd) as x: Pair<Int, Int>) {
|
||||
fn fiz() { todo }
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/tests/format.rs
|
||||
description: "Code:\n\npub fn main() {\n let foo = fn (Foo { a, b, .. }) { todo }\n let bar = fn ([Bar] : List<Bar>) { todo }\n let baz = fn ((Baz, Baz) as x) { todo }\n let fiz = fn (Pair(fst, snd) as x: Pair<Int, Int>) { todo }\n todo\n}\n"
|
||||
---
|
||||
pub fn main() {
|
||||
let foo =
|
||||
fn(Foo { a, b, .. }) {
|
||||
todo
|
||||
}
|
||||
let bar =
|
||||
fn([Bar]: List<Bar>) {
|
||||
todo
|
||||
}
|
||||
let baz =
|
||||
fn((Baz, Baz) as x) {
|
||||
todo
|
||||
}
|
||||
let fiz =
|
||||
fn(Pair(fst, snd) as x: Pair<Int, Int>) {
|
||||
todo
|
||||
}
|
||||
todo
|
||||
}
|
||||
23
crates/aiken-lang/src/tests/snapshots/format_fn_pattern.snap
Normal file
23
crates/aiken-lang/src/tests/snapshots/format_fn_pattern.snap
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/tests/format.rs
|
||||
description: "Code:\n\npub fn foo(Foo { a, b, .. }) {\n todo\n}\n\npub fn bar([Bar] : List<Bar>) {\n todo\n}\n\npub fn baz((Baz, Baz) as x) {\n todo\n}\n\npub fn fiz(Pair(fst, snd) as x: Pair<Int, Int>) {\n todo\n}\n\ntest buz((a, b) via some_fuzzer()) {\n todo\n}\n"
|
||||
---
|
||||
pub fn foo(Foo { a, b, .. }) {
|
||||
todo
|
||||
}
|
||||
|
||||
pub fn bar([Bar]: List<Bar>) {
|
||||
todo
|
||||
}
|
||||
|
||||
pub fn baz((Baz, Baz) as x) {
|
||||
todo
|
||||
}
|
||||
|
||||
pub fn fiz(Pair(fst, snd) as x: Pair<Int, Int>) {
|
||||
todo
|
||||
}
|
||||
|
||||
test buz((a, b) via some_fuzzer()) {
|
||||
todo
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/tests/format.rs
|
||||
description: "Code:\n\nvalidator(Foo { a, b, .. }) {\n fn foo() { todo }\n}\n\nvalidator([Bar] : List<Bar>) {\n fn bar() { todo }\n}\n\nvalidator((Baz, Baz) as x) {\n fn baz() { todo }\n}\n\nvalidator((fst, snd) as x: Pair<Int, Int>) {\n fn fiz() { todo }\n}\n"
|
||||
---
|
||||
validator(Foo { a, b, .. }) {
|
||||
fn foo() {
|
||||
todo
|
||||
}
|
||||
}
|
||||
|
||||
validator([Bar]: List<Bar>) {
|
||||
fn bar() {
|
||||
todo
|
||||
}
|
||||
}
|
||||
|
||||
validator((Baz, Baz) as x) {
|
||||
fn baz() {
|
||||
todo
|
||||
}
|
||||
}
|
||||
|
||||
validator((fst, snd) as x: Pair<Int, Int>) {
|
||||
fn fiz() {
|
||||
todo
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user