diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fcba714..55e7fc40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - **aiken**: New `-S` flag on `check` and `build` that blocks the printing of warnings but it still shows the total warning count. @rvcas - **aiken-lang**: Allow types to be used as namespaces for constructors. Importing each constructor variants independently is no longer required in neither pattern-matches nor value construction. One can simply use the type name as a prefix/namespace now. @KtorZ +- **aiken-lang**: Allow capture on constructor calls. @KtorZ ### Changed diff --git a/crates/aiken-lang/src/parser/expr/record.rs b/crates/aiken-lang/src/parser/expr/record.rs index 2e654f69..02f53369 100644 --- a/crates/aiken-lang/src/parser/expr/record.rs +++ b/crates/aiken-lang/src/parser/expr/record.rs @@ -29,24 +29,16 @@ pub fn parser( .then_ignore(just(Token::Colon)) .then(choice(( r.clone(), - select! {Token::DiscardName {name} => name }.validate( - |_name, span, emit| { - emit(ParseError::expected_input_found( - span, - None, - Some(error::Pattern::Discard), - )); - - UntypedExpr::Var { - location: span, - name: ast::CAPTURE_VARIABLE.to_string(), - } + choice((select! {Token::DiscardName {name} => name }.map_with_span( + |name, span| UntypedExpr::Var { + location: span, + name, }, - ), + ),)), ))) .map_with_span(|(label, value), span| ast::CallArg { location: span, - value, + value: Some(value), label: Some(label), }), choice(( @@ -111,7 +103,7 @@ pub fn parser( ) .map(|(value, name)| ast::CallArg { location: value.location(), - value, + value: Some(value), label: Some(name), }), )) @@ -144,24 +136,16 @@ pub fn parser( .or_not() .then(choice(( r.clone(), - select! {Token::DiscardName {name} => name }.validate( - |_name, span, emit| { - emit(ParseError::expected_input_found( - span, - None, - Some(error::Pattern::Discard), - )); - - UntypedExpr::Var { - location: span, - name: ast::CAPTURE_VARIABLE.to_string(), - } - }, - ), + select! {Token::DiscardName {name} => name }.map_with_span(|name, span| { + UntypedExpr::Var { + location: span, + name, + } + }), ))) .map(|(_label, value)| ast::CallArg { location: value.location(), - value, + value: Some(value), label: None, }) .separated_by(just(Token::Comma)) @@ -208,11 +192,7 @@ pub fn parser( }, }; - UntypedExpr::Call { - arguments, - fun: Box::new(fun), - location: span, - } + fun.call(arguments, span) }, ) } diff --git a/examples/acceptance_tests/121/aiken.toml b/examples/acceptance_tests/121/aiken.toml new file mode 100644 index 00000000..4f7f7fee --- /dev/null +++ b/examples/acceptance_tests/121/aiken.toml @@ -0,0 +1,9 @@ +name = "aiken-lang/121" +version = "0.0.0" +license = "Apache-2.0" +description = "Aiken contracts for project 'aiken-lang/121'" + +[repository] +user = "aiken-lang" +project = "121" +platform = "github" diff --git a/examples/acceptance_tests/121/lib/tests.ak b/examples/acceptance_tests/121/lib/tests.ak new file mode 100644 index 00000000..a69da0f1 --- /dev/null +++ b/examples/acceptance_tests/121/lib/tests.ak @@ -0,0 +1,34 @@ +pub type Foo { + i: Int, + b: Bool, +} + +const give_i: fn(Int) -> Foo = Foo { i: _, b: True } + +const give_b: fn(Bool) -> Foo = Foo(1337, _) + +fn foo_i(i: Int) -> fn(Bool) -> Foo { + Foo { i: i, b: _bool } +} + +fn foo_b(b: Bool) -> fn(Int) -> Foo { + Foo(_, b) +} + +test test_1() { + let bar = foo_i(14) + and { + foo_i(42)(True) == Foo(42, True), + bar(False) == Foo { i: 14, b: False }, + give_i(1337) == Foo { i: 1337, b: True }, + } +} + +test test_2() { + let bar = foo_b(False) + and { + foo_b(True)(42) == Foo(42, True), + bar(14) == Foo { i: 14, b: False }, + give_b(False) == Foo { i: 1337, b: False }, + } +}